Compare commits

..
136 Commits
Author SHA1 Message Date
Michael Krabbe BorregaardandGitHub 228d3af1fa Merge pull request #922 from mkborregaard/make-tkelman-happy
remove all 0.5-compliant uses of the transpose operator
2017-06-11 22:26:53 +02:00
Michael K. Borregaard a1df325051 Remove all 0.5-compliant uses of the transpose operator (')
A horrible change, but one required by the metadata maintainers.
2017-06-11 22:25:15 +02:00
Daniel SchwabenederandGitHub 8e6fdfac3c Merge pull request #921 from daschw/ds-precompile
reactivate precompilation on master
2017-06-10 23:36:57 +02:00
Daniel Schwabeneder 9a1afb2376 reactivate precompilation 2017-06-10 23:13:03 +02:00
Michael K. Borregaard e9ab8c4dac require RecipesBase 0.2.0 2017-06-09 22:57:23 +02:00
Michael Krabbe BorregaardandGitHub 1d98acc407 deactivate precompilation for release 2017-06-09 22:04:48 +02:00
Michael Krabbe BorregaardandGitHub 034613b50c Merge pull request #804 from ChrisRackauckas/_cycle
Change cycle => _cycle
2017-06-09 20:09:26 +02:00
Michael Krabbe BorregaardandGitHub 282e611ef7 Merge pull request #803 from ChrisRackauckas/recipes_change
RecipesBase change: all recipes usable from RecipesBase
2017-06-09 20:09:15 +02:00
ChrisRackauckas 49fc903334 fix last cycle 2017-06-09 08:43:01 -07:00
ChrisRackauckas 44b6157f17 cycle => _cycle 2017-06-09 08:43:01 -07:00
ChrisRackauckas 0a8d3f9251 animate from RecipesBase 2017-06-09 08:42:00 -07:00
ChrisRackauckas ac505ede44 move abstract types and make PlotRecipe on abstract type 2017-06-09 08:42:00 -07:00
ChrisRackauckas 4770f8b580 Merge remote-tracking branch 'ChrisRackauckas/master' into patch-1 2017-06-09 08:41:26 -07:00
Christopher RackauckasandChrisRackauckas 67e5598d28 Move the @userplot recipes
https://github.com/JuliaPlots/RecipesBase.jl/pull/16
2017-06-09 08:41:26 -07:00
ChrisRackauckas 554d7ab887 remove @shorthands 2017-06-09 08:41:26 -07:00
Michael K. Borregaard 40734bf90e Revert "turn off precompilation for release"
This reverts commit 66d9c79bef.
2017-06-09 16:00:39 +02:00
Michael Krabbe BorregaardandGitHub 3e720f8bae Merge pull request #919 from mkborregaard/ready-for-release
turn off precompilation for release
2017-06-09 15:58:38 +02:00
Michael K. Borregaard 66d9c79bef turn off precompilation for release 2017-06-09 15:58:09 +02:00
Michael Krabbe BorregaardandGitHub 89a5e5d57a Merge pull request #914 from mkborregaard/change-ignorenan-case
ignoreNaN => ignorenan
2017-06-08 12:54:47 +02:00
Michael K. Borregaard 8f6b0c50d6 ignoreNaN => ignorenan 2017-06-08 12:54:25 +02:00
Michael Krabbe BorregaardandGitHub d85dfaf38a Merge pull request #913 from mkborregaard/fix-broadcast
update Base..* to 0.6 syntax
2017-06-08 11:13:08 +02:00
Michael K. Borregaard 8511152982 update Base..* to 0.6 syntax 2017-06-08 10:56:12 +02:00
Michael Krabbe BorregaardandGitHub 40f9a51d4f Merge pull request #909 from mkborregaard/reactivate-precompilation
reactivate precompilation
2017-06-08 10:47:56 +02:00
Daniel SchwabenederandGitHub 30ad6d93bc Merge pull request #908 from daschw/ds-tests-2
Make tests pass on 0.6 2
2017-06-08 10:27:04 +02:00
Josef HeinenandGitHub 770d907fb8 Merge pull request #910 from jheinen/master
gr: removed println statement
2017-06-07 18:18:11 -07:00
Josef Heinen 46cdbacf0b gr: removed println statement 2017-06-07 18:15:43 -07:00
Michael K. Borregaard c0a8adc167 reactivate precompilation 2017-06-08 00:55:23 +02:00
Daniel Schwabeneder 4dd176a7f2 add @eval in image_comparision_tests and replaced transpose in testexample 13 2017-06-08 00:19:36 +02:00
Michael Krabbe BorregaardandGitHub eac9023b9a Merge pull request #904 from mkborregaard/Change-test-versions-to-release
Use ImageMagick release
2017-06-08 00:09:41 +02:00
Michael Krabbe BorregaardandGitHub a4c403286d Merge pull request #906 from mkborregaard/change-to-0.6
Up requirement to julia 0.6
2017-06-07 23:59:21 +02:00
Michael K. Borregaard 3a2ee0fc72 Fix some deprecations 2017-06-07 23:55:30 +02:00
Michael K. Borregaard f097fb57b5 Fix some deprecation warnings 2017-06-07 23:55:30 +02:00
Michael K. Borregaard 7415a362c4 reactivate precompilation 2017-06-07 23:55:30 +02:00
Michael K. Borregaard 8a7b7f5c9b Up requirement to 0.6 2017-06-07 23:55:30 +02:00
Michael Krabbe BorregaardandGitHub 4ce35ef352 Merge pull request #894 from mkborregaard/legendtitle_example
Adds legendtitle to example 12
2017-06-07 23:54:39 +02:00
Michael K. Borregaard a12f601b9c add legendtitle to example 2017-06-07 23:54:05 +02:00
Michael K. Borregaard 4106161aa8 add colon 2017-06-07 23:54:05 +02:00
Michael K. Borregaard 58c2f35bcf reinclude Plots 2017-06-07 23:54:05 +02:00
Michael K. Borregaard c41839a816 Add legendtitle to example 13 2017-06-07 23:54:05 +02:00
Michael K. Borregaard df729cd0f6 hotfix-FixedPointNumbers in require 2017-06-07 17:08:06 +02:00
Michael Krabbe BorregaardandGitHub 230ab34fe9 Merge pull request #905 from mkborregaard/fix-version-number-fixedsizearrays
Up FixedSizeArrays requirement to 0.3
2017-06-07 17:00:03 +02:00
Michael K. Borregaard 51fabab7b7 Up FixedSizeArrays requirement to 0.3 2017-06-07 16:59:20 +02:00
Michael K. Borregaard c7a13a4641 Use ImageMagick release 2017-06-07 16:54:24 +02:00
Michael Krabbe BorregaardandGitHub f855386bf1 Merge pull request #903 from mkborregaard/ready-for-0.11.3
get ready for 0.11.3 release
2017-06-07 16:07:21 +02:00
Michael K. Borregaard b8d1d9d7f1 Turn off precompilation for release 2017-06-07 16:06:04 +02:00
Michael K. Borregaard a22412d39d Update News.md with 0.11.3 2017-06-07 16:05:51 +02:00
Michael K. Borregaard f8bc9ba476 update version number in tests 2017-06-07 16:05:35 +02:00
Michael Krabbe BorregaardandGitHub fe83937368 Merge pull request #870 from wfrgra/legend
add ability to specify legend placement to gr backend
2017-06-07 15:44:00 +02:00
Daniel SchwabenederandGitHub 3def6265c4 Merge pull request #886 from daschw/ds-spy
Changed spy recipe and added spy example to tests (fix #883)
2017-06-07 11:16:06 +02:00
Michael Krabbe BorregaardandGitHub d9f7c19344 Merge pull request #900 from mkborregaard/amend-histogram-docs
amend bins description, fixes #898
2017-06-07 11:02:31 +02:00
Michael K. Borregaard db1dd618ea Add example with linspace 2017-06-07 11:01:47 +02:00
Michael K. Borregaard 132306fef1 amend bins description 2017-06-07 08:02:18 +02:00
Daniel Schwabeneder 18d29a0c7c changed markershape to :dtriangle in spy example 2017-06-06 22:51:34 +02:00
Michael Krabbe BorregaardandGitHub 4125fa75dd Merge pull request #893 from mkborregaard/fix-example12-transpose
fix-example12-transpose
2017-06-06 14:48:59 +02:00
Michael K. Borregaard bad7772b15 fix-example12-transpose 2017-06-06 14:45:30 +02:00
Michael Krabbe BorregaardandGitHub 6a23202e89 Merge pull request #825 from ma-laforge/hdf5plots
Re-integrate HDF5 plots.
2017-06-06 12:36:46 +02:00
Josef HeinenandGitHub 21c384fcdd Merge pull request #888 from jheinen/master
gr: added support for legend title
2017-06-04 10:04:15 +02:00
Josef Heinen b140fddebd gr: added support for legend title 2017-06-04 10:02:20 +02:00
Daniel SchwabenederandGitHub 24ea1c4847 Merge pull request #887 from daschw/ds-pyplot-legendtitle
Added legend_title attribute for Pylot backend
2017-06-04 09:29:50 +02:00
Daniel Schwabeneder 9d115fc02e added space in arg_desc 2017-06-03 13:49:06 +02:00
Daniel Schwabeneder 5e7756810d changed default attribute to legendtitle 2017-06-03 13:47:24 +02:00
Daniel SchwabenederandGitHub c65abd19ae Merge pull request #885 from daschw/gr-legend-markers
Changed GR legend markers for plots with fillrange
2017-06-03 13:39:05 +02:00
Daniel Schwabeneder 1a07c39fad changed spy plot example 2017-06-03 13:27:38 +02:00
Daniel Schwabeneder ee23cb2185 grid --> false in spy recipe, removed info, added example 2017-06-03 01:14:25 +02:00
Daniel Schwabeneder ee5617c6b8 added attribute for pyplot backend 2017-06-02 18:55:47 +02:00
Daniel Schwabeneder dc757cbf6c changed gr legend markers for fillrange 2017-06-02 17:39:25 +02:00
Daniel Schwabeneder 3d3ec2a194 add info about default markersize in spy recipe 2017-06-02 17:18:01 +02:00
Daniel SchwabenederandGitHub d2e79f33a3 Merge pull request #884 from daschw/ds-maketestspass
Make tests pass for GR and PyPlot 2 (fix #670 and #838)
2017-06-02 16:23:23 +02:00
Daniel Schwabeneder 6156228c89 install xfonts-75dpi for whtmltox 2017-06-02 15:07:17 +02:00
Daniel Schwabeneder 90f7e370f3 make tests pass for gr and pyplot cf. #877 2017-06-02 14:58:49 +02:00
Michael Krabbe BorregaardandGitHub 92688f03a8 Merge pull request #881 from mkborregaard/change-NaNMath-implementation
change NaNMath implementation
2017-06-01 22:28:02 +02:00
Michael K. Borregaard 80d0d6ecc8 Change NaNMath implementation
We needed some functions to forward to Base methods, e.g. when non-`AbstractArray{<:AbstractFloat}` was passed
2017-06-01 22:19:38 +02:00
Michael Krabbe BorregaardandGitHub d29df4289e RFC: Ignore NaNs on 0.6 (like on 0.5): fixes #796 (#876)
Replaces min, max, minimum, mean, maximum and extrema with NaNMath versions in places where NaNs can occur.

To avoid returning NaN when there are NaNs in the Vector

* Also add maximum and minimum

* define _-prefaced versions of mean, maximum, minimum, extrema

* variable arg numbers for Base methods

* Different implementation of the override

* remove underscore from 2-arg versions of maximum

* some forgotten extrema -> _extrema

* Fix bug in _extrema definition

* edit comment

* replace min and max with _min and _max

* Base NaN-compliant functions on NaNMath


replace _min and _max with NaNMath versions

* Use NaNMath explicitly everywhere

* remove unneccesary NaNMath calls

* Ensure ceil does not error on NaN

* Added one more maximum in gr
2017-06-01 19:17:28 +02:00
Michael Krabbe BorregaardandGitHub 84406f0823 Fixed writing error. 2017-06-01 17:10:03 +02:00
Michael Krabbe BorregaardandGitHub 380907af8d Merge pull request #879 from mkborregaard/change-glvisualize-string
Change installation message
2017-06-01 11:56:20 +02:00
Michael K. Borregaard 0e308d9f50 Change installation message 2017-06-01 11:55:43 +02:00
Michael Krabbe BorregaardandGitHub 7805f3f85b Merge pull request #862 from JuliaPlots/sd/fix_signals
fix glvisualize backend
2017-06-01 11:51:09 +02:00
Daniel SchwabenederandGitHub e04d13323d Merge pull request #878 from oschulz/debug-info-cleanup
Remove remnant debug output about binning
2017-05-31 23:27:21 +02:00
Oliver Schulz 6e8bfe1ea6 Remove remnant debug output about binning 2017-05-31 23:07:10 +02:00
Josef HeinenandGitHub 3baceb9dc4 Merge pull request #874 from jheinen/master
gr: fixed several bugs
2017-05-30 10:31:17 +02:00
Josef Heinen abf8ca2dc7 gr: fixed several bugs
- use correct image orientation
- added missing marker keywords
- improved alignment of axes labels
- corrected scaling of polar coordinates
- slightly shrink pie chart viewport
2017-05-30 10:29:31 +02:00
Michael Krabbe BorregaardandGitHub 2a0a5f2d08 Merge pull request #868 from staticfloat/updated_ci_url
Update CI URLs to point to new caching infrastructure
2017-05-29 09:05:40 +02:00
Josef HeinenandGitHub d45b228461 Merge pull request #871 from jheinen/master
gr: fix problems with axes display
2017-05-28 16:25:52 +02:00
Josef Heinen 231e11715f gr: fix problems with axes display 2017-05-28 16:23:21 +02:00
wgrant d6f1120dfc add ability to specify legend placement to gr backend 2017-05-27 16:46:38 +10:00
Josef HeinenandGitHub 7471bc791c Merge pull request #869 from jheinen/master
gr: corrected size of shape markers
2017-05-26 15:02:05 +02:00
Josef Heinen effcffff8a gr: corrected size of shape markers 2017-05-26 14:59:30 +02:00
Josef HeinenandGitHub 76186cab97 Merge pull request #863 from jheinen/master
gr: improve viewport size for 3D plots
2017-05-24 11:21:27 +02:00
Josef Heinen 4756e04e25 gr: improve viewport size for 3D plots 2017-05-24 11:19:43 +02:00
SimonDanisch 5b73f1e56c remove clean up code, switch to renderloop 2017-05-23 16:41:18 +02:00
Michael Krabbe BorregaardandGitHub af7d332453 Merge pull request #859 from innerlee/patch-1
Update backends.jl
2017-05-23 15:43:33 +02:00
lizzandGitHub 5439c3a3ce Update backends.jl 2017-05-23 21:41:31 +08:00
Michael Krabbe BorregaardandGitHub 6c4b6bbfbe Merge pull request #858 from mkborregaard/hotfix-glvisualizetext
Fix missing brackets
2017-05-23 10:51:26 +02:00
Michael K. Borregaard 53719e5a8e Fix missing brackets 2017-05-23 10:51:00 +02:00
Michael Krabbe BorregaardandGitHub aed34c3b9b Merge pull request #857 from mkborregaard/glvisualize_tert
Replace `text` with `glvisualize_text`
2017-05-23 10:23:53 +02:00
Michael K. Borregaard a5482453ce Replace text with glvisualize_text
glvisualize defined a `text` function that shadowed a method of Plots exported `text` function
2017-05-23 10:23:20 +02:00
Michael Krabbe BorregaardandGitHub 712d2011c3 Merge pull request #843 from mkborregaard/change_default_backend
Change default backends
2017-05-22 12:04:46 +02:00
Daniel SchwabenederandGitHub 0e6942a182 Merge pull request #853 from daschw/ds-ticks-tuple
fix passing ticks tuple on 0.6
2017-05-22 08:05:04 +02:00
Daniel Schwabeneder ce169edd08 fix passing ticks tuple on 0.6 2017-05-21 23:58:20 +02:00
Michael K. Borregaard e283c6557b Change default backends 2017-05-21 12:44:18 +02:00
Michael Krabbe BorregaardandGitHub e8da23c3e7 Merge pull request #852 from mkborregaard/remove-conda-messag
Remove conda update message
2017-05-21 11:30:51 +02:00
Michael K. Borregaard 08d7bee224 Remove conda update message
These instructions led to installing a deprecated matplotlib version
2017-05-21 11:30:11 +02:00
Michael Krabbe BorregaardandGitHub 16c95c6deb Merge pull request #848 from darwindarak/dd/pyplot-worldage
RFC: fix world-age problem in PyPlot initialization
2017-05-21 10:55:19 +02:00
Michael Krabbe BorregaardandGitHub 1d03e97721 Merge pull request #849 from dlfivefifty/pull-request/9abcba37
Fix plot(::Matrix{RGB{Float64}}) in plotly backend
2017-05-21 09:38:55 +02:00
Sheehan Olver 9abcba3753 Fix plot(::Matrix{RGB{Float64}}) in plotly backend 2017-05-21 16:53:28 +10:00
Darwin Darakananda b501c9bf4b fix world-age problem in PyPlot initialization 2017-05-20 15:39:26 -07:00
Michael Krabbe BorregaardandGitHub 72c506b62b Merge pull request #845 from ChrisRackauckas/patch-2
Add JSON to REQUIRE
2017-05-19 17:52:38 +02:00
Christopher RackauckasandGitHub f09dfb7035 Update REQUIRE 2017-05-19 07:56:36 -07:00
Daniel SchwabenederandGitHub 05eb687ca4 Merge pull request #834 from daschw/ds-testing
Move new PlotExample to the end for VRT testing
2017-05-17 08:32:12 +02:00
Elliot Saba 99e4408da4 Update CI URLs to point to new caching infrastructure 2017-05-16 17:25:27 -07:00
MA Laforge 64dd69f550 Improve robustness
More generic Array support.
Add support for ColorGradient.
Don't crash if plot specifies GridLayout.
(Does not properly restore info on layout).
2017-05-16 19:21:35 -04:00
MA Laforge 8b8de6bcd3 Move where backends.jl is included.
Must ensure all types required by HDF5 plots are defined.
2017-05-16 19:20:55 -04:00
MA Laforge b920ee8550 Re-integrate HDF5 plots.
Made code compatible with Julia v0.6.
Parametric types no longer <: DataType (now <: Type).
Add workaround to initialize Dict with "Type" keys.
2017-05-16 19:19:35 -04:00
Daniel Schwabeneder 89cd67792b update numbers of skipped examples in VRT 2017-05-16 21:46:11 +02:00
Daniel Schwabeneder 1f7ecb969c move new PlotExample to the end for VRT 2017-05-16 21:43:22 +02:00
Daniel Schwabeneder d4ef1761e4 change skipped images because of new example 2017-05-16 21:32:57 +02:00
Michael Krabbe BorregaardandGitHub dc01cc5c8e Merge pull request #832 from mkborregaard/master
Revert "changed xor in gr.jl"
2017-05-16 20:39:50 +02:00
Michael K. Borregaard db341f1814 Revert "changed xor in gr.jl"
This reverts commit 5c54722626.
2017-05-16 20:38:37 +02:00
Daniel SchwabenederandGitHub 06e469f059 Merge pull request #831 from daschw/ds-pyplot-fill
fix filling stepstyle on pyplot
2017-05-16 19:45:16 +02:00
Michael Krabbe BorregaardandGitHub 9ec1e674d0 Merge pull request #830 from mkborregaard/fix-xor-0.6
changed xor in gr.jl for 0.6
2017-05-16 11:29:17 +02:00
Michael K. Borregaard 5c54722626 changed xor in gr.jl 2017-05-16 11:28:38 +02:00
Daniel SchwabenederandGitHub 0a92b13263 Merge pull request #827 from oschulz/no-hist-autolims
Remove ylims default setting for bar and histogram plots
2017-05-16 07:58:58 +02:00
Daniel Schwabeneder 2fbc3c954a fix filling stepstyle on pyplot 2017-05-16 07:32:14 +02:00
Oliver Schulz 746f96cdcd Remove ylims default setting for bar and histogram plots
Setting `ylims -> ...` doesn't play well with multiple series and cannot
be properly overridden by user.
2017-05-15 23:26:30 +02:00
Michael Krabbe BorregaardandGitHub ee9d78b190 Merge pull request #824 from daschw/ds-0.5-compat
Fix precompilation on 0.5: Fixes #823
2017-05-14 22:23:08 +02:00
Daniel Schwabeneder 0e6a02b810 make precompilation work on o.5 2017-05-13 23:46:29 +02:00
Michael Krabbe BorregaardandGitHub 864dddb1ff Merge pull request #806 from dpsanders/0.6_deprecations
0.6 deprecations
2017-05-13 08:55:17 +02:00
Michael Krabbe BorregaardandGitHub 321495f253 Merge pull request #820 from mkborregaard/Switch-precompilation-on
Switch back on
2017-05-12 11:47:33 +02:00
Michael K. Borregaard eced31e3d7 Update version number in tests 2017-05-12 11:46:51 +02:00
Michael K. Borregaard 4b8dc06ddb Switch precompilation back on 2017-05-12 11:45:46 +02:00
Michael Krabbe BorregaardandGitHub ff3ba18b15 Merge pull request #819 from mkborregaard/switch_off_precompile
Switch off precompilation for release
2017-05-12 11:42:51 +02:00
Michael K. Borregaard d24f327342 Switch off precompilation for release 2017-05-12 11:42:26 +02:00
Daniel SchwabenederandGitHub d801a2789e Merge pull request #818 from daschw/ds-testing
update version number for testing
2017-05-12 09:08:27 +02:00
Daniel Schwabeneder b8c8c49176 update version number for testing 2017-05-11 22:45:04 +02:00
David Sanders 10f214fbb4 Change typealias to const 2017-05-08 15:20:21 -05:00
David Sanders 698d583d1d Fix world-age problem with IJulia 2017-05-08 15:16:21 -05:00
33 changed files with 1120 additions and 452 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ os:
- linux
# - osx
julia:
- 0.5
- 0.6
matrix:
allow_failures:
- julia: nightly
+16 -2
View File
@@ -10,7 +10,21 @@
---
## 0.11 (current master/dev)
## 0.12 (current master/dev)
- 0.6 only
#### 0.11.3
- add HDF5 backend
- GR replaces PyPlot as first-choice backend
- support for legend position in GR
- smaller markers in GR
- better viewport size in GR
- fix glvisualize support
- remove bug with three-argument method of `text`
- `legendtitle` attribute added
- add test for `spy`
#### 0.11.0
@@ -364,7 +378,7 @@
- z-axis keywords
- 3D indexing overhaul: `push!`, `append!` support
- matplotlib colormap constants (`:inferno` is the new default colormap for Plots)
- `typealias KW Dict{Symbol,Any}` used in place of splatting in many places
- `const KW = Dict{Symbol,Any}` used in place of splatting in many places
- png generation for plotly backend using wkhtmltoimage
- `normalize` and `weights` keywords
- background/foreground subcategories for fine-tuning of looks
+5 -2
View File
@@ -1,10 +1,13 @@
julia 0.5
julia 0.6-pre
RecipesBase
RecipesBase 0.2.0
PlotUtils 0.4.1
PlotThemes 0.1.3
Reexport
FixedSizeArrays
FixedPointNumbers 0.3
Measures
Showoff
StatsBase 0.14.0
JSON
NaNMath
+6 -5
View File
@@ -1,9 +1,9 @@
environment:
matrix:
- JULIAVERSION: "julialang/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe"
- JULIAVERSION: "julialang/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe"
- JULIAVERSION: "julianightlies/bin/winnt/x86/julia-latest-win32.exe"
- JULIAVERSION: "julianightlies/bin/winnt/x64/julia-latest-win64.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
notifications:
- provider: Email
@@ -12,13 +12,14 @@ notifications:
on_build_status_changed: false
install:
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
# If there's a newer build queued for the same PR, cancel this one
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
throw "There are newer queued builds for this pull request, failing early." }
# Download most recent Julia Windows binary
- ps: (new-object net.webclient).DownloadFile($("http://s3.amazonaws.com/"+$env:JULIAVERSION), "C:\projects\julia-binary.exe")
- ps: (new-object net.webclient).DownloadFile($env:JULIA_URL, "C:\projects\julia-binary.exe")
# Run installer silently, output to C:\projects\julia
- C:\projects\julia-binary.exe /S /D=C:\projects\julia
+28 -16
View File
@@ -1,10 +1,11 @@
__precompile__(true)
__precompile__(false)
module Plots
using Reexport
using FixedSizeArrays
@reexport using RecipesBase
import RecipesBase: plot, animate
using Base.Meta
@reexport using PlotUtils
@reexport using PlotThemes
@@ -30,9 +31,6 @@ export
with,
twinx,
@userplot,
@shorthands,
pie,
pie!,
plot3d,
@@ -106,9 +104,33 @@ export
# ---------------------------------------------------------
import NaNMath # define functions that ignores NaNs. To overcome the destructive effects of https://github.com/JuliaLang/julia/pull/12563
ignorenan_minimum{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.minimum(x)
ignorenan_minimum(x) = Base.minimum(x)
ignorenan_maximum{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.maximum(x)
ignorenan_maximum(x) = Base.maximum(x)
ignorenan_mean{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.mean(x)
ignorenan_mean(x) = Base.mean(x)
ignorenan_extrema{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.extrema(x)
ignorenan_extrema(x) = Base.extrema(x)
# ---------------------------------------------------------
# to cater for block matrices, Base.transpose is recursive.
# This makes it impossible to create row vectors of String and Symbol with the transpose operator.
# This solves this issue, internally in Plots at least.
# commented out on the insistence of the METADATA maintainers
#Base.transpose(x::Symbol) = x
#Base.transpose(x::String) = x
# ---------------------------------------------------------
import Measures
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h
typealias BBox Measures.Absolute2DBox
const BBox = Measures.Absolute2DBox
export BBox, BoundingBox, mm, cm, inch, pt, px, pct, w, h
# ---------------------------------------------------------
@@ -118,7 +140,6 @@ include("utils.jl")
include("components.jl")
include("axes.jl")
include("args.jl")
include("backends.jl")
include("themes.jl")
include("plot.jl")
include("pipeline.jl")
@@ -131,20 +152,11 @@ include("output.jl")
include("examples.jl")
include("arg_desc.jl")
include("plotattr.jl")
include("backends.jl")
# ---------------------------------------------------------
# define and export shorthand plotting method definitions
macro shorthands(funcname::Symbol)
funcname2 = Symbol(funcname, "!")
esc(quote
export $funcname, $funcname2
$funcname(args...; kw...) = plot(args...; kw..., seriestype = $(quot(funcname)))
$funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(quot(funcname)))
end)
end
@shorthands scatter
@shorthands bar
@shorthands barh
+2 -1
View File
@@ -21,7 +21,7 @@ const _arg_desc = KW(
:markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)",
:markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.",
:markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.",
:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto. For histogram-types, defines the number of bins, or the edges, of the histogram, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd)",
:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto. For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `linspace(extrema(x)..., 25)`",
:smooth => "Bool. Add a regression line?",
:group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.",
:x => "Various. Input data. First Dimension",
@@ -80,6 +80,7 @@ const _arg_desc = KW(
:foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.",
:color_palette => "Vector of colors (cycle through) or color gradient (generate list from gradient) or `:auto` (generate a color list using `Colors.distiguishable_colors` and custom seed colors chosen to contrast with the background). The color palette is a color list from which series colors are automatically chosen.",
:legend => "Bool (show the legend?) or Symbol (legend position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:inside`, `:legend`, `:topright`, `:topleft`, `:bottomleft`, `:bottomright` (note: only some may be supported in each backend)",
:legendtitle => "String or nothing (default). Sets the legend title.",
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
:legendfont => "Font. Font of legend items.",
+2
View File
@@ -251,6 +251,7 @@ const _subplot_defaults = KW(
:foreground_color_title => :match, # title color
:color_palette => :auto,
:legend => :best,
:legendtitle => nothing,
:colorbar => :legend,
:clims => :auto,
:legendfont => font(8),
@@ -439,6 +440,7 @@ add_aliases(:zticks, :ztick)
add_aliases(:zrotation, :zrot, :zr)
add_aliases(:fill_z, :fillz, :fz, :surfacecolor, :surfacecolour, :sc, :surfcolor, :surfcolour)
add_aliases(:legend, :leg, :key)
add_aliases(:legendtitle, :legend_title, :labeltitle, :label_title, :leg_title, :key_title)
add_aliases(:colorbar, :cb, :cbar, :colorkey)
add_aliases(:clims, :clim, :cbarlims, :cbar_lims, :climits, :color_limits)
add_aliases(:smooth, :regression, :reg)
+12 -12
View File
@@ -118,7 +118,7 @@ Base.show(io::IO, axis::Axis) = dumpdict(axis.d, "Axis", true)
# Base.getindex(axis::Axis, k::Symbol) = getindex(axis.d, k)
Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.d, v, ks...)
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.d, k)
Base.extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
ignorenan_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
const _scale_funcs = Dict{Symbol,Function}(
@@ -229,7 +229,7 @@ function get_ticks(axis::Axis)
elseif typeof(ticks) <: AVec
# override ticks, but get the labels
optimal_ticks_and_labels(axis, ticks)
elseif typeof(ticks) <: NTuple{2}
elseif typeof(ticks) <: NTuple{2, Any}
# assuming we're passed (ticks, labels)
ticks
else
@@ -260,8 +260,8 @@ end
function expand_extrema!(ex::Extrema, v::Number)
ex.emin = min(v, ex.emin)
ex.emax = max(v, ex.emax)
ex.emin = NaNMath.min(v, ex.emin)
ex.emax = NaNMath.max(v, ex.emax)
ex
end
@@ -276,8 +276,8 @@ expand_extrema!(axis::Axis, ::Bool) = axis[:extrema]
function expand_extrema!{MIN<:Number,MAX<:Number}(axis::Axis, v::Tuple{MIN,MAX})
ex = axis[:extrema]
ex.emin = min(v[1], ex.emin)
ex.emax = max(v[2], ex.emax)
ex.emin = NaNMath.min(v[1], ex.emin)
ex.emax = NaNMath.max(v[2], ex.emax)
ex
end
function expand_extrema!{N<:Number}(axis::Axis, v::AVec{N})
@@ -349,11 +349,11 @@ function expand_extrema!(sp::Subplot, d::KW)
bw = d[:bar_width]
if bw == nothing
bw = d[:bar_width] = mean(diff(data))
bw = d[:bar_width] = ignorenan_mean(diff(data))
end
axis = sp.attr[Symbol(dsym, :axis)]
expand_extrema!(axis, maximum(data) + 0.5maximum(bw))
expand_extrema!(axis, minimum(data) - 0.5minimum(bw))
expand_extrema!(axis, ignorenan_maximum(data) + 0.5maximum(bw))
expand_extrema!(axis, ignorenan_minimum(data) - 0.5minimum(bw))
end
end
@@ -368,8 +368,8 @@ end
# push the limits out slightly
function widen(lmin, lmax)
span = lmax - lmin
# eps = max(1e-16, min(1e-2span, 1e-10))
eps = max(1e-16, 0.03span)
# eps = NaNMath.max(1e-16, min(1e-2span, 1e-10))
eps = NaNMath.max(1e-16, 0.03span)
lmin-eps, lmax+eps
end
@@ -425,7 +425,7 @@ function discrete_value!(axis::Axis, dv)
# @show axis[:discrete_map], axis[:discrete_values], dv
if cv_idx == -1
ex = axis[:extrema]
cv = max(0.5, ex.emax + 1.0)
cv = NaNMath.max(0.5, ex.emax + 1.0)
expand_extrema!(axis, cv)
push!(axis[:discrete_values], dv)
push!(axis[:continuous_values], cv)
+2 -1
View File
@@ -148,7 +148,7 @@ function pickDefaultBackend()
# the ordering/inclusion of this package list is my semi-arbitrary guess at
# which one someone will want to use if they have the package installed...accounting for
# features, speed, and robustness
for pkgstr in ("PyPlot", "GR", "PlotlyJS", "Immerse", "Gadfly", "UnicodePlots")
for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR", "GLVisualize")
if Pkg.installed(pkgstr) != nothing
return backend(Symbol(lowercase(pkgstr)))
end
@@ -277,6 +277,7 @@ end
@init_backend GLVisualize
@init_backend PGFPlots
@init_backend InspectDR
@init_backend HDF5
# ---------------------------------------------------------
+28 -71
View File
@@ -77,14 +77,9 @@ end
function add_backend_string(b::GLVisualizeBackend)
"""
For those incredibly brave souls who assume full responsibility for what happens next...
There's an easy way to get what you need for the GLVisualize backend to work (until Pkg3 is usable):
Pkg.clone("https://github.com/tbreloff/MetaPkg.jl")
using MetaPkg
meta_checkout("MetaGL")
See the MetaPkg readme for details...
if !Plots.is_installed("GLVisualize")
Pkg.add("GLVisualize")
end
"""
end
@@ -98,41 +93,6 @@ end
# end
const _glplot_deletes = []
function close_child_signals!(screen)
for child in screen.children
for (k, s) in child.inputs
empty!(s.actions)
end
for (k, cam) in child.cameras
for f in fieldnames(cam)
s = getfield(cam, f)
if isa(s, Signal)
close(s, false)
end
end
end
empty!(child.cameras)
close_child_signals!(child)
end
return
end
function empty_screen!(screen)
if isempty(_glplot_deletes)
close_child_signals!(screen)
empty!(screen)
empty!(screen.cameras)
for (k, s) in screen.inputs
empty!(s.actions)
end
empty!(screen)
else
for del_signal in _glplot_deletes
push!(del_signal, true) # trigger delete
end
empty!(_glplot_deletes)
end
nothing
end
function get_plot_screen(list::Vector, name, result = [])
for elem in list
@@ -158,7 +118,7 @@ function create_window(plt::Plot{GLVisualizeBackend}, visible)
resolution = plt[:size],
visible = visible
)
@async GLWindow.waiting_renderloop(parent_screen)
@async GLWindow.renderloop(parent_screen)
GLVisualize.add_screen(parent_screen)
end
# now lets get ourselves a permanent Plotting screen
@@ -169,9 +129,6 @@ function create_window(plt::Plot{GLVisualizeBackend}, visible)
parent, area = map(GLWindow.zeroposition, parent.area),
name = name
)
for (k, s) in screen.inputs # copy signals, so we can clean them up better
screen.inputs[k] = map(identity, s)
end
screen
elseif length(plot_screens) == 1
plot_screens[1]
@@ -181,7 +138,7 @@ function create_window(plt::Plot{GLVisualizeBackend}, visible)
error("multiple Plot screens. Please don't use any screen with the name $name")
end
# Since we own this window, we can do deep cleansing
empty_screen!(screen)
empty!(screen)
plt.o = screen
GLWindow.set_visibility!(screen, visible)
resize!(screen, plt[:size]...)
@@ -347,7 +304,7 @@ function extract_any_color(d, kw_args)
kw_args[:color_norm] = Vec2f0(clims)
end
elseif clims == :auto
kw_args[:color_norm] = Vec2f0(extrema(d[:y]))
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(d[:y]))
end
end
else
@@ -358,7 +315,7 @@ function extract_any_color(d, kw_args)
kw_args[:color_norm] = Vec2f0(clims)
end
elseif clims == :auto
kw_args[:color_norm] = Vec2f0(extrema(d[:y]))
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(d[:y]))
else
error("Unsupported limits: $clims")
end
@@ -410,14 +367,14 @@ end
dist(a, b) = abs(a-b)
mindist(x, a, b) = min(dist(a, x), dist(b, x))
mindist(x, a, b) = NaNMath.min(dist(a, x), dist(b, x))
function gappy(x, ps)
n = length(ps)
x <= first(ps) && return first(ps) - x
for j=1:(n-1)
p0 = ps[j]
p1 = ps[min(j+1, n)]
p1 = ps[NaNMath.min(j+1, n)]
if p0 <= x && p1 >= x
return mindist(x, p0, p1) * (isodd(j) ? 1 : -1)
end
@@ -525,7 +482,7 @@ function hover(to_hover, to_display, window)
end
function extract_extrema(d, kw_args)
xmin, xmax = extrema(d[:x]); ymin, ymax = extrema(d[:y])
xmin, xmax = ignorenan_extrema(d[:x]); ymin, ymax = ignorenan_extrema(d[:y])
kw_args[:primitive] = GeometryTypes.SimpleRectangle{Float32}(xmin, ymin, xmax-xmin, ymax-ymin)
nothing
end
@@ -552,7 +509,7 @@ function extract_colornorm(d, kw_args)
else
d[:y]
end
kw_args[:color_norm] = Vec2f0(extrema(z))
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(z))
kw_args[:intensity] = map(Float32, collect(z))
end
end
@@ -692,7 +649,7 @@ function draw_ticks(
text, positions, offsets
end
function text(position, text, kw_args)
function glvisualize_text(position, text, kw_args)
text_align = alignment2num(text.font)
startpos = Vec2f0(position)
atlas = GLVisualize.get_texture_atlas()
@@ -769,7 +726,7 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
kw = Dict(:model => text_model(font, xy), :scale_primitive => true)
extract_font(font, kw)
t = PlotText(sp[:title], font)
push!(axis_vis, text(xy, t, kw))
push!(axis_vis, glvisualize_text(xy, t, kw))
end
if xaxis[:guide] != ""
tf = xaxis[:guidefont]; color = gl_color(xaxis[:foreground_color_guide])
@@ -778,7 +735,7 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
kw = Dict(:model => text_model(font, xy), :scale_primitive => true)
t = PlotText(xaxis[:guide], font)
extract_font(font, kw)
push!(axis_vis, text(xy, t, kw))
push!(axis_vis, glvisualize_text(xy, t, kw))
end
if yaxis[:guide] != ""
@@ -788,7 +745,7 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
kw = Dict(:model => text_model(font, xy), :scale_primitive=>true)
t = PlotText(yaxis[:guide], font)
extract_font(font, kw)
push!(axis_vis, text(xy, t, kw))
push!(axis_vis, glvisualize_text(xy, t, kw))
end
axis_vis
@@ -824,9 +781,9 @@ function gl_bar(d, kw_args)
# compute half-width of bars
bw = nothing
hw = if bw == nothing
mean(diff(x))
ignorenan_mean(diff(x))
else
Float64[cycle(bw,i)*0.5 for i=1:length(x)]
Float64[_cycle(bw,i)*0.5 for i=1:length(x)]
end
# make fillto a vector... default fills to 0
@@ -840,7 +797,7 @@ function gl_bar(d, kw_args)
sx, sy = m[1,1], m[2,2]
for i=1:ny
center = x[i]
hwi = abs(cycle(hw,i)); yi = y[i]; fi = cycle(fillto,i)
hwi = abs(_cycle(hw,i)); yi = y[i]; fi = _cycle(fillto,i)
if Plots.isvertical(d)
sz = (hwi*sx, yi*sy)
else
@@ -876,7 +833,7 @@ function gl_boxplot(d, kw_args)
sx, sy = m[1,1], m[2,2]
for (i,glabel) in enumerate(glabels)
# filter y
values = y[filter(i -> cycle(x,i) == glabel, 1:length(y))]
values = y[filter(i -> _cycle(x,i) == glabel, 1:length(y))]
# compute quantiles
q1,q2,q3,q4,q5 = quantile(values, linspace(0,1,5))
# notch
@@ -889,7 +846,7 @@ function gl_boxplot(d, kw_args)
# make the shape
center = Plots.discrete_value!(d[:subplot][:xaxis], glabel)[1]
hw = d[:bar_width] == nothing ? Plots._box_halfwidth*2 : cycle(d[:bar_width], i)
hw = d[:bar_width] == nothing ? Plots._box_halfwidth*2 : _cycle(d[:bar_width], i)
l, m, r = center - hw/2, center, center + hw/2
# internal nodes for notches
@@ -907,7 +864,7 @@ function gl_boxplot(d, kw_args)
end
# change q1 and q5 to show outliers
# using maximum and minimum values inside the limits
q1, q5 = extrema(inside)
q1, q5 = ignorenan_extrema(inside)
end
# Box
if notch
@@ -988,7 +945,7 @@ function scale_for_annotations!(series::Series, scaletype::Symbol = :pixels)
msw, msh = anns.scalefactor
offsets = Array(Vec2f0, length(anns.strs))
series[:markersize] = map(1:length(anns.strs)) do i
str = cycle(anns.strs, i)
str = _cycle(anns.strs, i)
# get the width and height of the string (in mm)
sw, sh = text_size(str, anns.font.pointsize)
@@ -1101,7 +1058,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
kw = copy(kw_args)
fr = d[:fillrange]
ps = if all(x-> x >= 0, diff(d[:x])) # if is monotonic
vcat(points, Point2f0[(points[i][1], cycle(fr, i)) for i=length(points):-1:1])
vcat(points, Point2f0[(points[i][1], _cycle(fr, i)) for i=length(points):-1:1])
else
points
end
@@ -1167,7 +1124,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
txt_args = Dict{Symbol, Any}(:model => eye(GLAbstraction.Mat4f0))
x, y = Reactive.value(model_m) * Vec{4, Float32}(x, y, 0, 1)
extract_font(font, txt_args)
t = text(Point2f0(x, y), PlotText(str, font), txt_args)
t = glvisualize_text(Point2f0(x, y), PlotText(str, font), txt_args)
GLVisualize._view(t, sp_screen, camera = :perspective)
end
@@ -1274,7 +1231,7 @@ function gl_scatter(points, kw_args)
if haskey(kw_args, :stroke_width)
s = Reactive.value(kw_args[:scale])
sw = kw_args[:stroke_width]
if sw*5 > cycle(Reactive.value(s), 1)[1] # restrict marker stroke to 1/10th of scale (and handle arrays of scales)
if sw*5 > _cycle(Reactive.value(s), 1)[1] # restrict marker stroke to 1/10th of scale (and handle arrays of scales)
kw_args[:stroke_width] = s[1] / 5f0
end
end
@@ -1361,7 +1318,7 @@ function gl_contour(x, y, z, kw_args)
T = eltype(z)
levels = Contour.contours(map(T, x), map(T, y), z, h)
result = Point2f0[]
zmin, zmax = get(kw_args, :limits, Vec2f0(extrema(z)))
zmin, zmax = get(kw_args, :limits, Vec2f0(ignorenan_extrema(z)))
cmap = get(kw_args, :color_map, get(kw_args, :color, RGBA{Float32}(0,0,0,1)))
colors = RGBA{Float32}[]
for c in levels.contours
@@ -1382,7 +1339,7 @@ end
function gl_heatmap(x,y,z, kw_args)
get!(kw_args, :color_norm, Vec2f0(extrema(z)))
get!(kw_args, :color_norm, Vec2f0(ignorenan_extrema(z)))
get!(kw_args, :color_map, Plots.make_gradient(cgrad()))
delete!(kw_args, :intensity)
I = GLVisualize.Intensity{1, Float32}
@@ -1479,7 +1436,7 @@ function make_label(sp, series, i)
kw = Dict(:model => text_model(font, xy), :scale_primitive=>false)
extract_font(font, kw)
t = PlotText(labeltext, font)
push!(result, text(xy, t, kw))
push!(result, glvisualize_text(xy, t, kw))
GLAbstraction.Context(result...), i
end
+91 -57
View File
@@ -20,7 +20,7 @@ const _gr_attr = merge_with_base_supported([
:title, :window_title,
:guide, :lims, :ticks, :scale, :flip,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:grid, :legend, :legendtitle, :colorbar,
:marker_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -76,6 +76,8 @@ const gr_markertype = KW(
:diamond => -13,
:utriangle => -3,
:dtriangle => -5,
:ltriangle => -18,
:rtriangle => -17,
:pentagon => -21,
:hexagon => -22,
:heptagon => -23,
@@ -122,10 +124,10 @@ function gr_getcolorind(c)
convert(Int, GR.inqcolorfromrgb(red(c), green(c), blue(c)))
end
gr_set_linecolor(c) = GR.setlinecolorind(gr_getcolorind(cycle(c,1)))
gr_set_fillcolor(c) = GR.setfillcolorind(gr_getcolorind(cycle(c,1)))
gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(cycle(c,1)))
gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(cycle(c,1)))
gr_set_linecolor(c) = GR.setlinecolorind(gr_getcolorind(_cycle(c,1)))
gr_set_fillcolor(c) = GR.setfillcolorind(gr_getcolorind(_cycle(c,1)))
gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(_cycle(c,1)))
gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c,1)))
# --------------------------------------------------------------------------------------
@@ -262,7 +264,7 @@ end
normalize_zvals(zv::Void) = zv
function normalize_zvals(zv::AVec)
vmin, vmax = extrema(zv)
vmin, vmax = ignorenan_extrema(zv)
if vmin == vmax
zeros(length(zv))
else
@@ -277,10 +279,11 @@ function gr_draw_marker(xi, yi, msize, shape::Shape)
sx, sy = coords(shape)
# convert to ndc coords (percentages of window)
GR.selntran(0)
w, h = gr_plot_size
f = msize / (w + h)
xi, yi = GR.wctondc(xi, yi)
ms_ndc_x, ms_ndc_y = gr_pixels_to_ndc(msize, msize)
GR.fillarea(xi .+ sx .* ms_ndc_x,
yi .+ sy .* ms_ndc_y)
GR.fillarea(xi .+ sx .* f,
yi .+ sy .* f)
GR.selntran(1)
end
@@ -298,23 +301,23 @@ function gr_draw_markers(series::Series, x, y, msize, mz)
shapes = series[:markershape]
if shapes != :none
for i=1:length(x)
msi = cycle(msize, i)
shape = cycle(shapes, i)
msi = _cycle(msize, i)
shape = _cycle(shapes, i)
cfunc = isa(shape, Shape) ? gr_set_fillcolor : gr_set_markercolor
cfuncind = isa(shape, Shape) ? GR.setfillcolorind : GR.setmarkercolorind
# draw a filled in shape, slightly bigger, to estimate a stroke
if series[:markerstrokewidth] > 0
cfunc(cycle(series[:markerstrokecolor], i)) #, series[:markerstrokealpha])
cfunc(_cycle(series[:markerstrokecolor], i)) #, series[:markerstrokealpha])
gr_draw_marker(x[i], y[i], msi + series[:markerstrokewidth], shape)
end
# draw the shape
if mz == nothing
cfunc(cycle(series[:markercolor], i)) #, series[:markeralpha])
cfunc(_cycle(series[:markercolor], i)) #, series[:markeralpha])
else
# pick a color from the pre-loaded gradient
ci = round(Int, 1000 + cycle(mz, i) * 255)
ci = round(Int, 1000 + _cycle(mz, i) * 255)
cfuncind(ci)
GR.settransparency(_gr_gradient_alpha[ci-999])
end
@@ -383,20 +386,28 @@ const viewport_plotarea = zeros(4)
# the size of the current plot in pixels
const gr_plot_size = zeros(2)
function gr_viewport_from_bbox(bb::BoundingBox, w, h, viewport_canvas)
function gr_viewport_from_bbox(sp::Subplot{GRBackend}, bb::BoundingBox, w, h, viewport_canvas)
viewport = zeros(4)
viewport[1] = viewport_canvas[2] * (left(bb) / w)
viewport[2] = viewport_canvas[2] * (right(bb) / w)
viewport[3] = viewport_canvas[4] * (1.0 - bottom(bb) / h)
viewport[4] = viewport_canvas[4] * (1.0 - top(bb) / h)
if is3d(sp)
vp = viewport[:]
extent = min(vp[2] - vp[1], vp[4] - vp[3])
viewport[1] = 0.5 * (vp[1] + vp[2] - extent)
viewport[2] = 0.5 * (vp[1] + vp[2] + extent)
viewport[3] = 0.5 * (vp[3] + vp[4] - extent)
viewport[4] = 0.5 * (vp[3] + vp[4] + extent)
end
viewport
end
# change so we're focused on the viewport area
function gr_set_viewport_cmap(sp::Subplot)
GR.setviewport(
viewport_plotarea[2] + (is3d(sp) ? 0.04 : 0.02),
viewport_plotarea[2] + (is3d(sp) ? 0.07 : 0.05),
viewport_plotarea[2] + (is3d(sp) ? 0.07 : 0.02),
viewport_plotarea[2] + (is3d(sp) ? 0.10 : 0.05),
viewport_plotarea[3],
viewport_plotarea[4]
)
@@ -417,7 +428,7 @@ function gr_set_viewport_polar()
ymax -= 0.05 * (xmax - xmin)
xcenter = 0.5 * (xmin + xmax)
ycenter = 0.5 * (ymin + ymax)
r = 0.5 * min(xmax - xmin, ymax - ymin)
r = 0.5 * NaNMath.min(xmax - xmin, ymax - ymin)
GR.setviewport(xcenter -r, xcenter + r, ycenter - r, ycenter + r)
GR.setwindow(-1, 1, -1, 1)
r
@@ -434,16 +445,34 @@ end
gr_view_xcenter() = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2])
gr_view_ycenter() = 0.5 * (viewport_plotarea[3] + viewport_plotarea[4])
gr_view_xdiff() = viewport_plotarea[2] - viewport_plotarea[1]
gr_view_ydiff() = viewport_plotarea[4] - viewport_plotarea[3]
function gr_pixels_to_ndc(x_pixels, y_pixels)
w,h = gr_plot_size
totx = w * gr_view_xdiff()
toty = h * gr_view_ydiff()
x_pixels / totx, y_pixels / toty
function gr_legend_pos(s::Symbol,w,h)
str = string(s)
if str == "best"
str = "topright"
end
if contains(str,"right")
xpos = viewport_plotarea[2] - 0.05 - w
elseif contains(str,"left")
xpos = viewport_plotarea[1] + 0.11
else
xpos = (viewport_plotarea[2]-viewport_plotarea[1])/2 - w/2 +.04
end
if contains(str,"top")
ypos = viewport_plotarea[4] - 0.06
elseif contains(str,"bottom")
ypos = viewport_plotarea[3] + h + 0.06
else
ypos = (viewport_plotarea[4]-viewport_plotarea[3])/2 + h/2
end
(xpos,ypos)
end
function gr_legend_pos{S<:Real, T<:Real}(v::Tuple{S,T},w,h)
xpos = v[1] * (viewport_plotarea[2] - viewport_plotarea[1]) + viewport_plotarea[1]
ypos = v[2] * (viewport_plotarea[4] - viewport_plotarea[3]) + viewport_plotarea[3]
(xpos,ypos)
end
# --------------------------------------------------------------------------------------
@@ -504,10 +533,15 @@ function gr_display(plt::Plot)
end
function _update_min_padding!(sp::Subplot{GRBackend})
sp.minpad = (10mm,2mm,2mm,8mm)
end
function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# the viewports for this subplot
viewport_subplot = gr_viewport_from_bbox(bbox(sp), w, h, viewport_canvas)
viewport_plotarea[:] = gr_viewport_from_bbox(plotarea(sp), w, h, viewport_canvas)
viewport_subplot = gr_viewport_from_bbox(sp, bbox(sp), w, h, viewport_canvas)
viewport_plotarea[:] = gr_viewport_from_bbox(sp, plotarea(sp), w, h, viewport_canvas)
# get data limits
data_lims = gr_xy_axislims(sp)
@@ -632,7 +666,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif ispolar(sp)
r = gr_set_viewport_polar()
rmin, rmax = GR.adjustrange(minimum(r), maximum(r))
rmin, rmax = GR.adjustrange(ignorenan_minimum(r), ignorenan_maximum(r))
# rmin, rmax = axis_limits(sp[:yaxis])
gr_polaraxes(rmin, rmax)
@@ -656,7 +690,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# spine (border) and tick marks
gr_set_line(1, :solid, sp[:xaxis][:foreground_color_axis])
GR.setclip(0)
gr_polyline(coords(spine_segs)...)
GR.setclip(1)
if !(xticks in (nothing, false))
# x labels
@@ -669,9 +705,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
rotation = sp[:xaxis][:rotation])
for (cv, dv) in zip(xticks...)
# use xor ($) to get the right y coords
xi, yi = GR.wctondc(cv, (flip $ mirror) ? ymax : ymin)
xi, yi = GR.wctondc(cv, xor(flip, mirror) ? ymax : ymin)
# @show cv dv ymin xi yi flip mirror (flip $ mirror)
gr_text(xi, yi + (mirror ? 1 : -1) * 2e-3, string(dv))
gr_text(xi, yi + (mirror ? 1 : -1) * 5e-3, string(dv))
end
end
@@ -686,24 +722,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
rotation = sp[:yaxis][:rotation])
for (cv, dv) in zip(yticks...)
# use xor ($) to get the right y coords
xi, yi = GR.wctondc((flip $ mirror) ? xmax : xmin, cv)
xi, yi = GR.wctondc(xor(flip, mirror) ? xmax : xmin, cv)
# @show cv dv xmin xi yi
gr_text(xi + (mirror ? 1 : -1) * 2e-3, yi, string(dv))
gr_text(xi + (mirror ? 1 : -1) * 1e-2, yi, string(dv))
end
end
# window_diag = sqrt(gr_view_xdiff()^2 + gr_view_ydiff()^2)
# ticksize = 0.0075 * window_diag
# if outside_ticks
# ticksize = -ticksize
# end
# # TODO: this should be done for each axis separately
# gr_set_linecolor(xaxis[:foreground_color_axis])
# x1, x2 = xaxis[:flip] ? (xmax,xmin) : (xmin,xmax)
# y1, y2 = yaxis[:flip] ? (ymax,ymin) : (ymin,ymax)
# GR.axes(xtick, ytick, x1, y1, 1, 1, ticksize)
# GR.axes(xtick, ytick, x2, y2, -1, -1, -ticksize)
end
# end
@@ -785,9 +808,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
for (i,rng) in enumerate(iter_segments(series[:x], series[:y]))
if length(rng) > 1
gr_set_fillcolor(cycle(series[:fillcolor], i))
fx = cycle(x, vcat(rng, reverse(rng)))
fy = vcat(cycle(fr_from,rng), cycle(fr_to,reverse(rng)))
gr_set_fillcolor(_cycle(series[:fillcolor], i))
fx = _cycle(x, vcat(rng, reverse(rng)))
fy = vcat(_cycle(fr_from,rng), _cycle(fr_to,reverse(rng)))
# @show i rng fx fy
GR.fillarea(fx, fy)
end
@@ -828,7 +851,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# create the colorbar of contour levels
if sp[:colorbar] != :none
gr_set_viewport_cmap(sp)
l = round(Int32, 1000 + (h - minimum(h)) / (maximum(h) - minimum(h)) * 255)
l = round(Int32, 1000 + (h - ignorenan_minimum(h)) / (ignorenan_maximum(h) - ignorenan_minimum(h)) * 255)
GR.setwindow(xmin, xmax, zmin, zmax)
GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l)
ztick = 0.5 * GR.tick(zmin, zmax)
@@ -886,7 +909,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.selntran(0)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
xmin, xmax, ymin, ymax = viewport_plotarea
ymax -= 0.05 * (xmax - xmin)
ymax -= 0.1 * (xmax - xmin)
xcenter = 0.5 * (xmin + xmax)
ycenter = 0.5 * (ymin + ymax)
if xmax - xmin > ymax - ymin
@@ -939,18 +962,18 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
x, y = series[:x][rng], series[:y][rng]
# draw the interior
gr_set_fill(cycle(series[:fillcolor], i))
gr_set_fill(_cycle(series[:fillcolor], i))
GR.fillarea(x, y)
# draw the shapes
gr_set_line(series[:linewidth], :solid, cycle(series[:linecolor], i))
gr_set_line(series[:linewidth], :solid, _cycle(series[:linecolor], i))
GR.polyline(x, y)
end
end
elseif st == :image
z = transpose_z(series, series[:z].surf, true)
z = transpose_z(series, series[:z].surf, true)'
w, h = size(z)
if eltype(z) <: Colors.AbstractGray
grey = round(UInt8, float(z) * 255)
@@ -984,6 +1007,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
w = 0
i = 0
n = 0
if sp[:legendtitle] != nothing
tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle]))
w = tbx[3] - tbx[1]
n += 1
end
for series in series_list(sp)
should_add_to_legend(series) || continue
n += 1
@@ -997,9 +1025,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
w = max(w, tbx[3] - tbx[1])
end
if w > 0
xpos = viewport_plotarea[2] - 0.05 - w
ypos = viewport_plotarea[4] - 0.06
dy = _gr_point_mult[1] * sp[:legendfont].pointsize * 1.75
h = dy*n
(xpos,ypos) = gr_legend_pos(sp[:legend],w,h)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
gr_set_fillcolor(sp[:background_color_legend])
GR.fillrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
@@ -1007,13 +1035,19 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.setlinewidth(1)
GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
i = 0
if sp[:legendtitle] != nothing
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
gr_set_textcolor(sp[:foreground_color_legend])
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
ypos -= dy
end
for series in series_list(sp)
should_add_to_legend(series) || continue
st = series[:seriestype]
gr_set_line(series[:linewidth], series[:linestyle], series[:linecolor]) #, series[:linealpha])
if st == :path
if st == :path && series[:fillrange] == nothing
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])
elseif st == :shape
elseif st == :shape || series[:fillrange] != nothing
gr_set_fill(series[:fillcolor]) #, series[:fillalpha])
l, r = xpos-0.07, xpos-0.01
b, t = ypos-0.4dy, ypos+0.4dy
+655
View File
@@ -0,0 +1,655 @@
#HDF5 Plots: Save/replay plots to/from HDF5
#-------------------------------------------------------------------------------
#==Usage
===============================================================================
Write to .hdf5 file using:
p = plot(...)
Plots.hdf5plot_write(p, "plotsave.hdf5")
Read from .hdf5 file using:
pyplot() #Must first select backend
pread = Plots.hdf5plot_read("plotsave.hdf5")
display(pread)
==#
#==TODO
===============================================================================
1. Support more features
- SeriesAnnotations & GridLayout known to be missing.
3. Improve error handling.
- Will likely crash if file format is off.
2. Save data in a folder parallel to "plot".
- Will make it easier for users to locate data.
- Use HDF5 reference to link data?
3. Develop an actual versioned file format.
- Should have some form of backward compatibility.
- Should be reliable for archival purposes.
==#
import FixedPointNumbers: N0f8 #In core Julia
#Dispatch types:
immutable HDF5PlotNative; end #Indentifies a data element that can natively be handled by HDF5
immutable HDF5CTuple; end #Identifies a "complex" tuple structure
type HDF5Plot_PlotRef
ref::Union{Plot, Void}
end
#==Useful constants
===============================================================================#
const _hdf5_plotroot = "plot"
const _hdf5_dataroot = "data" #TODO: Eventually move data to different root (easier to locate)?
const _hdf5plot_datatypeid = "TYPE" #Attribute identifying type
const _hdf5plot_countid = "COUNT" #Attribute for storing count
#Dict has problems using "Types" as keys. Initialize in "_initialize_backend":
const HDF5PLOT_MAP_STR2TELEM = Dict{String, Type}()
const HDF5PLOT_MAP_TELEM2STR = Dict{Type, String}()
#Don't really like this global variable... Very hacky
const HDF5PLOT_PLOTREF = HDF5Plot_PlotRef(nothing)
#Simple sub-structures that can just be written out using _hdf5plot_gwritefields:
const HDF5PLOT_SIMPLESUBSTRUCT = Union{Font, BoundingBox,
GridLayout, RootLayout, ColorGradient, SeriesAnnotations, PlotText
}
#==
===============================================================================#
const _hdf5_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
:label,
:linecolor, :linestyle, :linewidth, :linealpha,
:markershape, :markercolor, :markersize, :markeralpha,
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
:fillrange, :fillcolor, :fillalpha,
:bins, :bar_width, :bar_edges, :bar_position,
:title, :title_location, :titlefont,
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
:orientation,
:overwrite_figure,
:polar,
:normalize, :weights,
:contours, :aspect_ratio,
:match_dimensions,
:clims,
:inset_subplots,
:dpi,
:colorbar_title,
])
const _hdf5_seriestype = [
:path, :steppre, :steppost, :shape,
:scatter, :hexbin, #:histogram2d, :histogram,
# :bar,
:heatmap, :pie, :image,
:contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe
]
const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot]
const _hdf5_marker = vcat(_allMarkers, :pixel)
const _hdf5_scale = [:identity, :ln, :log2, :log10]
is_marker_supported(::HDF5Backend, shape::Shape) = true
function add_backend_string(::HDF5Backend)
"""
if !Plots.is_installed("HDF5")
Pkg.add("HDF5")
end
"""
end
#==Helper functions
===============================================================================#
_hdf5_plotelempath(subpath::String) = "$_hdf5_plotroot/$subpath"
_hdf5_datapath(subpath::String) = "$_hdf5_dataroot/$subpath"
_hdf5_map_str2telem(k::String) = HDF5PLOT_MAP_STR2TELEM[k]
_hdf5_map_str2telem(v::Vector) = HDF5PLOT_MAP_STR2TELEM[v[1]]
function _hdf5_merge!(dest::Dict, src::Dict)
for (k, v) in src
if isa(v, Axis)
_hdf5_merge!(dest[k].d, v.d)
else
dest[k] = v
end
end
return
end
#==
===============================================================================#
function _initialize_backend(::HDF5Backend)
@eval begin
import HDF5
export HDF5
if length(HDF5PLOT_MAP_TELEM2STR) < 1
#Possible element types of high-level data types:
const telem2str = Dict{String, Type}(
"NATIVE" => HDF5PlotNative,
"VOID" => Void,
"BOOL" => Bool,
"SYMBOL" => Symbol,
"TUPLE" => Tuple,
"CTUPLE" => HDF5CTuple, #Tuple of complex structures
"RGBA" => ARGB{N0f8},
"EXTREMA" => Extrema,
"LENGTH" => Length,
"ARRAY" => Array, #Dict won't allow Array to be key in HDF5PLOT_MAP_TELEM2STR
#Sub-structure types:
"FONT" => Font,
"BOUNDINGBOX" => BoundingBox,
"GRIDLAYOUT" => GridLayout,
"ROOTLAYOUT" => RootLayout,
"SERIESANNOTATIONS" => SeriesAnnotations,
# "PLOTTEXT" => PlotText,
"COLORGRADIENT" => ColorGradient,
"AXIS" => Axis,
"SUBPLOT" => Subplot,
"NULLABLE" => Nullable,
)
merge!(HDF5PLOT_MAP_STR2TELEM, telem2str)
merge!(HDF5PLOT_MAP_TELEM2STR, Dict{Type, String}(v=>k for (k,v) in HDF5PLOT_MAP_STR2TELEM))
end
end
end
# ---------------------------------------------------------------------------
# Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{HDF5Backend})
#Do nothing
end
# ---------------------------------------------------------------------------
# # this is called early in the pipeline, use it to make the plot current or something
# function _prepare_plot_object(plt::Plot{HDF5Backend})
# end
# ---------------------------------------------------------------------------
# Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{HDF5Backend}, sp::Subplot{HDF5Backend})
#Do nothing
end
# ---------------------------------------------------------------------------
# Add one series to the underlying backend object.
# Called once per series
# NOTE: Seems to be called when user calls plot()... even if backend
# plot, sp.o has not yet been constructed...
function _series_added(plt::Plot{HDF5Backend}, series::Series)
#Do nothing
end
# ---------------------------------------------------------------------------
# When series data is added/changed, this callback can do dynamic updates to the backend object.
# note: if the backend rebuilds the plot from scratch on display, then you might not do anything here.
function _series_updated(plt::Plot{HDF5Backend}, series::Series)
#Do nothing
end
# ---------------------------------------------------------------------------
# called just before updating layout bounding boxes... in case you need to prep
# for the calcs
function _before_layout_calcs(plt::Plot{HDF5Backend})
#Do nothing
end
# ----------------------------------------------------------------
# Set the (left, top, right, bottom) minimum padding around the plot area
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{HDF5Backend})
#Do nothing
end
# ----------------------------------------------------------------
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations])
function _update_plot_object(plt::Plot{HDF5Backend})
#Do nothing
end
# ----------------------------------------------------------------
_show(io::IO, mime::MIME"text/plain", plt::Plot{HDF5Backend}) = nothing #Don't show
# ----------------------------------------------------------------
# Display/show the plot (open a GUI window, or browser page, for example).
function _display(plt::Plot{HDF5Backend})
msg = "HDF5 interface does not support `display()` function."
msg *= "\nUse `Plots.hdf5plot_write(::String)` method to write to .HDF5 \"plot\" file instead."
warn(msg)
return
end
#==HDF5 write functions
===============================================================================#
function _hdf5plot_writetype(grp, k::String, tstr::Array{String})
d = HDF5.d_open(grp, k)
HDF5.a_write(d, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writetype(grp, k::String, T::Type)
tstr = HDF5PLOT_MAP_TELEM2STR[T]
d = HDF5.d_open(grp, k)
HDF5.a_write(d, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_overwritetype(grp, k::String, T::Type)
tstr = HDF5PLOT_MAP_TELEM2STR[T]
d = HDF5.d_open(grp, k)
HDF5.a_delete(d, _hdf5plot_datatypeid)
HDF5.a_write(d, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writetype(grp, T::Type) #Write directly to group
tstr = HDF5PLOT_MAP_TELEM2STR[T]
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_overwritetype(grp, T::Type) #Write directly to group
tstr = HDF5PLOT_MAP_TELEM2STR[T]
HDF5.a_delete(grp, _hdf5plot_datatypeid)
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writetype{T<:Any}(grp, ::Type{Array{T}})
tstr = HDF5PLOT_MAP_TELEM2STR[Array] #ANY
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writetype{T<:BoundingBox}(grp, ::Type{T})
tstr = HDF5PLOT_MAP_TELEM2STR[BoundingBox]
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writecount(grp, n::Int) #Write directly to group
HDF5.a_write(grp, _hdf5plot_countid, n)
end
function _hdf5plot_gwritefields(grp, k::String, v)
grp = HDF5.g_create(grp, k)
for _k in fieldnames(v)
_v = getfield(v, _k)
kstr = string(_k)
_hdf5plot_gwrite(grp, kstr, _v)
end
_hdf5plot_writetype(grp, typeof(v))
return
end
# Write data
# ----------------------------------------------------------------
function _hdf5plot_gwrite(grp, k::String, v) #Default
grp[k] = v
_hdf5plot_writetype(grp, k, HDF5PlotNative)
end
function _hdf5plot_gwrite{T<:Number}(grp, k::String, v::Array{T}) #Default for arrays
grp[k] = v
_hdf5plot_writetype(grp, k, HDF5PlotNative)
end
#=
function _hdf5plot_gwrite(grp, k::String, v::Array{Any})
# @show grp, k
warn("Cannot write Array: $k=$v")
end
=#
function _hdf5plot_gwrite(grp, k::String, v::Void)
grp[k] = 0
_hdf5plot_writetype(grp, k, Void)
end
function _hdf5plot_gwrite(grp, k::String, v::Bool)
grp[k] = Int(v)
_hdf5plot_writetype(grp, k, Bool)
end
function _hdf5plot_gwrite(grp, k::String, v::Symbol)
grp[k] = string(v)
_hdf5plot_writetype(grp, k, Symbol)
end
function _hdf5plot_gwrite(grp, k::String, v::Tuple)
varr = [v...]
elt = eltype(varr)
# if isleaftype(elt)
_hdf5plot_gwrite(grp, k, varr)
if elt <: Number
#We just wrote a simple dataset
_hdf5plot_overwritetype(grp, k, Tuple)
else #Used a more complex scheme (using subgroups):
_hdf5plot_overwritetype(grp[k], HDF5CTuple)
end
#NOTE: _hdf5plot_overwritetype overwrites "Array" type with "Tuple".
end
function _hdf5plot_gwrite(grp, k::String, d::Dict)
# warn("Cannot write dict: $k=$d")
end
function _hdf5plot_gwrite(grp, k::String, v::Range)
_hdf5plot_gwrite(grp, k, collect(v)) #For now
end
function _hdf5plot_gwrite(grp, k::String, v::ARGB{N0f8})
grp[k] = [v.r.i, v.g.i, v.b.i, v.alpha.i]
_hdf5plot_writetype(grp, k, ARGB{N0f8})
end
function _hdf5plot_gwrite(grp, k::String, v::Colorant)
_hdf5plot_gwrite(grp, k, ARGB{N0f8}(v))
end
#Custom vector (when not using simple numeric type):
function _hdf5plot_gwritearray{T}(grp, k::String, v::Array{T})
if "annotations" == k;
return #Hack. Does not yet support annotations.
end
vgrp = HDF5.g_create(grp, k)
_hdf5plot_writetype(vgrp, Array) #ANY
sz = size(v)
for iter in eachindex(v)
coord = ind2sub(sz, iter)
elem = v[iter]
idxstr = join(coord, "_")
_hdf5plot_gwrite(vgrp, "v$idxstr", v[iter])
end
_hdf5plot_gwrite(vgrp, "dim", [sz...])
return
end
_hdf5plot_gwrite(grp, k::String, v::Array) =
_hdf5plot_gwritearray(grp, k, v)
function _hdf5plot_gwrite(grp, k::String, v::Extrema)
grp[k] = [v.emin, v.emax]
_hdf5plot_writetype(grp, k, Extrema)
end
function _hdf5plot_gwrite{T}(grp, k::String, v::Length{T})
grp[k] = v.value
_hdf5plot_writetype(grp, k, [HDF5PLOT_MAP_TELEM2STR[Length], string(T)])
end
# Write more complex structures:
# ----------------------------------------------------------------
function _hdf5plot_gwrite(grp, k::String, v::Plot)
#Don't write plot references
end
function _hdf5plot_gwrite(grp, k::String, v::HDF5PLOT_SIMPLESUBSTRUCT)
_hdf5plot_gwritefields(grp, k, v)
return
end
function _hdf5plot_gwrite(grp, k::String, v::Axis)
grp = HDF5.g_create(grp, k)
for (_k, _v) in v.d
kstr = string(_k)
_hdf5plot_gwrite(grp, kstr, _v)
end
_hdf5plot_writetype(grp, Axis)
return
end
#TODO: "Properly" support Nullable using _hdf5plot_writetype?
function _hdf5plot_gwrite(grp, k::String, v::Nullable)
if isnull(v)
_hdf5plot_gwrite(grp, k, nothing)
else
_hdf5plot_gwrite(grp, k, v.value)
end
return
end
function _hdf5plot_gwrite(grp, k::String, v::SeriesAnnotations)
#Currently no support for SeriesAnnotations
return
end
function _hdf5plot_gwrite(grp, k::String, v::Subplot)
grp = HDF5.g_create(grp, k)
_hdf5plot_gwrite(grp, "index", v[:subplot_index])
_hdf5plot_writetype(grp, Subplot)
return
end
function _hdf5plot_write(grp, d::Dict)
for (k, v) in d
kstr = string(k)
_hdf5plot_gwrite(grp, kstr, v)
end
return
end
# Write main plot structures:
# ----------------------------------------------------------------
function _hdf5plot_write(sp::Subplot{HDF5Backend}, subpath::String, f)
f = f::HDF5.HDF5File #Assert
grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/attr"))
_hdf5plot_write(grp, sp.attr)
grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list"))
_hdf5plot_writecount(grp, length(sp.series_list))
for (i, series) in enumerate(sp.series_list)
grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list/series$i"))
_hdf5plot_write(grp, series.d)
end
return
end
function _hdf5plot_write(plt::Plot{HDF5Backend}, f)
f = f::HDF5.HDF5File #Assert
grp = HDF5.g_create(f, _hdf5_plotelempath("attr"))
_hdf5plot_write(grp, plt.attr)
grp = HDF5.g_create(f, _hdf5_plotelempath("subplots"))
_hdf5plot_writecount(grp, length(plt.subplots))
for (i, sp) in enumerate(plt.subplots)
_hdf5plot_write(sp, "subplots/subplot$i", f)
end
return
end
function hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString)
HDF5.h5open(path, "w") do file
_hdf5plot_write(plt, file)
end
end
hdf5plot_write(path::AbstractString) = hdf5plot_write(current(), path)
#==HDF5 playback (read) functions
===============================================================================#
function _hdf5plot_readcount(grp) #Read directly from group
return HDF5.a_read(grp, _hdf5plot_countid)
end
_hdf5plot_convert(T::Type{HDF5PlotNative}, v) = v
_hdf5plot_convert(T::Type{Void}, v) = nothing
_hdf5plot_convert(T::Type{Bool}, v) = (v!=0)
_hdf5plot_convert(T::Type{Symbol}, v) = Symbol(v)
_hdf5plot_convert(T::Type{Tuple}, v) = tuple(v...) #With Vector{T<:Number}
function _hdf5plot_convert(T::Type{ARGB{N0f8}}, v)
r, g, b, a = reinterpret(N0f8, v)
return Colors.ARGB{N0f8}(r, g, b, a)
end
_hdf5plot_convert(T::Type{Extrema}, v) = Extrema(v[1], v[2])
# Read data structures:
# ----------------------------------------------------------------
function _hdf5plot_read(grp, k::String, T::Type, dtid)
v = HDF5.d_read(grp, k)
return _hdf5plot_convert(T, v)
end
function _hdf5plot_read(grp, k::String, T::Type{Length}, dtid::Vector)
v = HDF5.d_read(grp, k)
TU = Symbol(dtid[2])
T = typeof(v)
return Length{TU,T}(v)
end
# Read more complex data structures:
# ----------------------------------------------------------------
function _hdf5plot_read(grp, k::String, T::Type{Font}, dtid)
grp = HDF5.g_open(grp, k)
family = _hdf5plot_read(grp, "family")
pointsize = _hdf5plot_read(grp, "pointsize")
halign = _hdf5plot_read(grp, "halign")
valign = _hdf5plot_read(grp, "valign")
rotation = _hdf5plot_read(grp, "rotation")
color = _hdf5plot_read(grp, "color")
return Font(family, pointsize, halign, valign, rotation, color)
end
function _hdf5plot_read(grp, k::String, T::Type{Array}, dtid) #ANY
grp = HDF5.g_open(grp, k)
sz = _hdf5plot_read(grp, "dim")
if [0] == sz; return []; end
sz = tuple(sz...)
result = Array{Any}(sz)
for iter in eachindex(result)
coord = ind2sub(sz, iter)
idxstr = join(coord, "_")
result[iter] = _hdf5plot_read(grp, "v$idxstr")
end
#Hack: Implicitly make Julia detect element type.
# (Should probably write it explicitly to file)
result = [result[iter] for iter in eachindex(result)] #Potentially make more specific
return reshape(result, sz)
end
function _hdf5plot_read(grp, k::String, T::Type{HDF5CTuple}, dtid)
v = _hdf5plot_read(grp, k, Array, dtid)
return tuple(v...)
end
function _hdf5plot_read(grp, k::String, T::Type{ColorGradient}, dtid)
grp = HDF5.g_open(grp, k)
colors = _hdf5plot_read(grp, "colors")
values = _hdf5plot_read(grp, "values")
return ColorGradient(colors, values)
end
function _hdf5plot_read(grp, k::String, T::Type{BoundingBox}, dtid)
grp = HDF5.g_open(grp, k)
x0 = _hdf5plot_read(grp, "x0")
a = _hdf5plot_read(grp, "a")
return BoundingBox(x0, a)
end
_hdf5plot_read(grp, k::String, T::Type{RootLayout}, dtid) = RootLayout()
function _hdf5plot_read(grp, k::String, T::Type{GridLayout}, dtid)
grp = HDF5.g_open(grp, k)
# parent = _hdf5plot_read(grp, "parent")
parent = RootLayout()
minpad = _hdf5plot_read(grp, "minpad")
bbox = _hdf5plot_read(grp, "bbox")
grid = _hdf5plot_read(grp, "grid")
widths = _hdf5plot_read(grp, "widths")
heights = _hdf5plot_read(grp, "heights")
attr = KW() #TODO support attr: _hdf5plot_read(grp, "attr")
return GridLayout(parent, minpad, bbox, grid, widths, heights, attr)
end
function _hdf5plot_read(grp, k::String, T::Type{Axis}, dtid)
grp = HDF5.g_open(grp, k)
kwlist = KW()
_hdf5plot_read(grp, kwlist)
return Axis([], kwlist)
end
function _hdf5plot_read(grp, k::String, T::Type{Subplot}, dtid)
grp = HDF5.g_open(grp, k)
idx = _hdf5plot_read(grp, "index")
return HDF5PLOT_PLOTREF.ref.subplots[idx]
end
function _hdf5plot_read(grp, k::String)
dtid = HDF5.a_read(grp[k], _hdf5plot_datatypeid)
T = _hdf5_map_str2telem(dtid) #expect exception
return _hdf5plot_read(grp, k, T, dtid)
end
#Read in values in group to populate d:
function _hdf5plot_read(grp, d::Dict)
gnames = names(grp)
for k in gnames
try
v = _hdf5plot_read(grp, k)
d[Symbol(k)] = v
catch e
@show e
@show grp
warn("Could not read field $k")
end
end
return
end
# Read main plot structures:
# ----------------------------------------------------------------
function _hdf5plot_read(sp::Subplot, subpath::String, f)
f = f::HDF5.HDF5File #Assert
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr"))
kwlist = KW()
_hdf5plot_read(grp, kwlist)
_hdf5_merge!(sp.attr, kwlist)
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list"))
nseries = _hdf5plot_readcount(grp)
for i in 1:nseries
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list/series$i"))
kwlist = KW()
_hdf5plot_read(grp, kwlist)
plot!(sp, kwlist[:x], kwlist[:y]) #Add data & create data structures
_hdf5_merge!(sp.series_list[end].d, kwlist)
end
return
end
function _hdf5plot_read(plt::Plot, f)
f = f::HDF5.HDF5File #Assert
#Assumpltion: subplots are already allocated (plt.subplots)
HDF5PLOT_PLOTREF.ref = plt #Used when reading "layout"
grp = HDF5.g_open(f, _hdf5_plotelempath("attr"))
_hdf5plot_read(grp, plt.attr)
for (i, sp) in enumerate(plt.subplots)
_hdf5plot_read(sp, "subplots/subplot$i", f)
end
return
end
function hdf5plot_read(path::AbstractString)
plt = nothing
HDF5.h5open(path, "r") do file
grp = HDF5.g_open(file, _hdf5_plotelempath("subplots"))
n = _hdf5plot_readcount(grp)
plt = plot(layout=n) #Get reference to a new plot
_hdf5plot_read(plt, file)
end
return plt
end
#Last line
+5 -5
View File
@@ -265,8 +265,8 @@ For st in :shape:
nmax = i
if length(rng) > 1
linewidth = series[:linewidth]
linecolor = _inspectdr_mapcolor(cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(cycle(series[:fillcolor], i))
linecolor = _inspectdr_mapcolor(_cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(_cycle(series[:fillcolor], i))
line = InspectDR.line(
style=:solid, width=linewidth, color=linecolor
)
@@ -280,8 +280,8 @@ For st in :shape:
i = (nmax >= 2? div(nmax, 2): nmax) #Must pick one set of colors for legend
if i > 1 #Add dummy waveform for legend entry:
linewidth = series[:linewidth]
linecolor = _inspectdr_mapcolor(cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(cycle(series[:fillcolor], i))
linecolor = _inspectdr_mapcolor(_cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(_cycle(series[:fillcolor], i))
wfrm = InspectDR.add(plot, Float64[], Float64[], id=series[:label])
wfrm.line = InspectDR.line(
style=:none, width=linewidth, #linewidth affects glyph
@@ -349,7 +349,7 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
ymin, ymax = axis_limits(yaxis)
if ispolar(sp)
#Plots.jl appears to give (xmin,xmax) ≜ (Θmin,Θmax) & (ymin,ymax) ≜ (rmin,rmax)
rmax = max(abs(ymin), abs(ymax))
rmax = NaNMath.max(abs(ymin), abs(ymax))
xmin, xmax = -rmax, rmax
ymin, ymax = -rmax, rmax
end
+4 -4
View File
@@ -546,7 +546,7 @@ function plotly_series(plt::Plot, series::Series)
else
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
grad = as_gradient(series[:markercolor], series[:markeralpha])
zmin, zmax = extrema(series[:marker_z])
zmin, zmax = ignorenan_extrema(series[:marker_z])
zrange = zmax == zmin ? 1 : zmax - zmin # if all marker_z values are the same, plot all markers same color (avoids division by zero in next line)
[rgba_string(grad[(zi - zmin) / zrange]) for zi in series[:marker_z]]
end
@@ -600,18 +600,18 @@ function plotly_series_shapes(plt::Plot, series::Series)
:x => vcat(x[rng], x[rng[1]]),
:y => vcat(y[rng], y[rng[1]]),
:fill => "tozeroy",
:fillcolor => rgba_string(cycle(series[:fillcolor], i)),
:fillcolor => rgba_string(_cycle(series[:fillcolor], i)),
))
if series[:markerstrokewidth] > 0
d_out[:line] = KW(
:color => rgba_string(cycle(series[:linecolor], i)),
:color => rgba_string(_cycle(series[:linecolor], i)),
:width => series[:linewidth],
:dash => string(series[:linestyle]),
)
end
d_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
plotly_polar!(d_out, series)
plotly_hover!(d_out, cycle(series[:hover], i))
plotly_hover!(d_out, _cycle(series[:hover], i))
push!(d_outs, d_out)
end
d_outs
+29 -24
View File
@@ -17,7 +17,7 @@ const _pyplot_attr = merge_with_base_supported([
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:grid, :legend, :legendtitle, :colorbar,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
@@ -55,8 +55,6 @@ function add_backend_string(::PyPlotBackend)
withenv("PYTHON" => "") do
Pkg.build("PyPlot")
end
import Conda
Conda.add("qt=4.8.5")
# now restart julia!
"""
@@ -84,10 +82,10 @@ function _initialize_backend(::PyPlotBackend)
const pytransforms = PyPlot.pywrap(PyPlot.pyimport("matplotlib.transforms"))
const pycollections = PyPlot.pywrap(PyPlot.pyimport("matplotlib.collections"))
const pyart3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d.art3d"))
end
# we don't want every command to update the figure
PyPlot.ioff()
# we don't want every command to update the figure
PyPlot.ioff()
end
end
# --------------------------------------------------------------------------------------
@@ -221,6 +219,12 @@ function py_stepstyle(seriestype::Symbol)
return "default"
end
function py_fillstepstyle(seriestype::Symbol)
seriestype == :steppost && return "post"
seriestype == :steppre && return "pre"
return nothing
end
# # untested... return a FontProperties object from a Plots.Font
# function py_font(font::Font)
# pyfont.pymember("FontProperties")(
@@ -491,10 +495,10 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
handle = if is3d(st)
for rng in iter_segments(x, y, z)
length(rng) < 2 && continue
push!(segments, [(cycle(x,i),cycle(y,i),cycle(z,i)) for i in rng])
push!(segments, [(_cycle(x,i),_cycle(y,i),_cycle(z,i)) for i in rng])
end
# for i=1:n
# segments[i] = [(cycle(x,i), cycle(y,i), cycle(z,i)), (cycle(x,i+1), cycle(y,i+1), cycle(z,i+1))]
# segments[i] = [(_cycle(x,i), _cycle(y,i), _cycle(z,i)), (_cycle(x,i+1), _cycle(y,i+1), _cycle(z,i+1))]
# end
lc = pyart3d.Line3DCollection(segments; kw...)
lc[:set_array](lz)
@@ -503,10 +507,10 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
else
for rng in iter_segments(x, y)
length(rng) < 2 && continue
push!(segments, [(cycle(x,i),cycle(y,i)) for i in rng])
push!(segments, [(_cycle(x,i),_cycle(y,i)) for i in rng])
end
# for i=1:n
# segments[i] = [(cycle(x,i), cycle(y,i)), (cycle(x,i+1), cycle(y,i+1))]
# segments[i] = [(_cycle(x,i), _cycle(y,i)), (_cycle(x,i+1), _cycle(y,i+1))]
# end
lc = pycollections.LineCollection(segments; kw...)
lc[:set_array](lz)
@@ -577,16 +581,16 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
lw = py_dpi_scale(plt, series[:markerstrokewidth])
for i=1:length(y)
extrakw[:c] = if series[:marker_z] == nothing
py_color_fix(py_color(cycle(series[:markercolor],i)), x)
py_color_fix(py_color(_cycle(series[:markercolor],i)), x)
else
extrakw[:c]
end
push!(handle, ax[:scatter](cycle(x,i), cycle(y,i);
push!(handle, ax[:scatter](_cycle(x,i), _cycle(y,i);
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
marker = py_marker(cycle(shapes,i)),
s = py_dpi_scale(plt, cycle(series[:markersize],i) .^ 2),
marker = py_marker(_cycle(shapes,i)),
s = py_dpi_scale(plt, _cycle(series[:markersize],i) .^ 2),
edgecolors = msc,
linewidths = lw,
extrakw...
@@ -701,11 +705,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# contours on the axis planes
if series[:contours]
for (zdir,mat) in (("x",x), ("y",y), ("z",z))
offset = (zdir == "y" ? maximum : minimum)(mat)
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat)
handle = ax[:contourf](x, y, z, levelargs...;
zdir = zdir,
cmap = py_fillcolormap(series),
offset = (zdir == "y" ? maximum : minimum)(mat) # where to draw the contour plane
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) # where to draw the contour plane
)
push!(handles, handle)
needs_colorbar = true
@@ -774,7 +778,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
clims = sp[:clims]
zmin, zmax = extrema(z)
zmin, zmax = ignorenan_extrema(z)
extrakw[:vmin] = (is_2tuple(clims) && isfinite(clims[1])) ? clims[1] : zmin
extrakw[:vmax] = (is_2tuple(clims) && isfinite(clims[2])) ? clims[2] : zmax
@@ -798,8 +802,8 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
path;
label = series[:label],
zorder = series[:series_plotindex],
edgecolor = py_color(cycle(series[:linecolor], i)),
facecolor = py_color(cycle(series[:fillcolor], i)),
edgecolor = py_color(_cycle(series[:linecolor], i)),
facecolor = py_color(_cycle(series[:fillcolor], i)),
linewidth = py_dpi_scale(plt, series[:linewidth]),
fill = true
)
@@ -868,7 +872,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
dim1, expand_data(fillrange[1], n), expand_data(fillrange[2], n)
end
handle = ax[f](args...;
handle = ax[f](args..., trues(n), false, py_fillstepstyle(st);
zorder = series[:series_plotindex],
facecolor = py_fillcolor(series),
linewidths = 0
@@ -922,14 +926,14 @@ function py_compute_axis_minval(axis::Axis)
for series in series_list(sp)
v = series.d[axis[:letter]]
if !isempty(v)
minval = min(minval, minimum(abs(v)))
minval = NaNMath.min(minval, ignorenan_minimum(abs(v)))
end
end
end
# now if the axis limits go to a smaller abs value, use that instead
vmin, vmax = axis_limits(axis)
minval = min(minval, abs(vmin), abs(vmax))
minval = NaNMath.min(minval, abs(vmin), abs(vmax))
minval
end
@@ -950,7 +954,7 @@ function py_set_scale(ax, axis::Axis)
elseif scale == :log10
10
end
kw[Symbol(:linthresh,letter)] = max(1e-16, py_compute_axis_minval(axis))
kw[Symbol(:linthresh,letter)] = NaNMath.max(1e-16, py_compute_axis_minval(axis))
"symlog"
end
func(arg; kw...)
@@ -1162,7 +1166,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
# add a line/marker and a label
push!(handles, if series[:seriestype] == :shape
PyPlot.plt[:Line2D]((0,1),(0,0),
color = py_color(cycle(series[:fillcolor],1)),
color = py_color(_cycle(series[:fillcolor],1)),
linewidth = py_dpi_scale(plt, 4)
)
else
@@ -1183,6 +1187,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
# framealpha = 0.6
)
leg[:set_zorder](1000)
sp[:legendtitle] != nothing && leg[:set_title](sp[:legendtitle])
fgcolor = py_color(sp[:foreground_color_legend])
for txt in leg[:get_texts]()
+11 -11
View File
@@ -1,7 +1,7 @@
typealias P2 FixedSizeArrays.Vec{2,Float64}
typealias P3 FixedSizeArrays.Vec{3,Float64}
const P2 = FixedSizeArrays.Vec{2,Float64}
const P3 = FixedSizeArrays.Vec{3,Float64}
nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b))
nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b))
@@ -446,7 +446,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
msw,msh = anns.scalefactor
msize = Float64[]
shapes = Shape[begin
str = cycle(anns.strs,i)
str = _cycle(anns.strs,i)
# get the width and height of the string (in mm)
sw, sh = text_size(str, anns.font.pointsize)
@@ -462,7 +462,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
# and then re-scale a copy of baseshape to match the w/h ratio
maxscale = max(xscale, yscale)
push!(msize, maxscale)
baseshape = cycle(get(anns.baseshape),i)
baseshape = _cycle(get(anns.baseshape),i)
shape = scale(baseshape, msw*xscale/maxscale, msh*yscale/maxscale, (0,0))
end for i=1:length(anns.strs)]
series[:markershape] = shapes
@@ -479,13 +479,13 @@ end
Base.start(ea::EachAnn) = 1
Base.done(ea::EachAnn, i) = ea.anns == nothing || isempty(ea.anns.strs) || i > length(ea.y)
function Base.next(ea::EachAnn, i)
tmp = cycle(ea.anns.strs,i)
tmp = _cycle(ea.anns.strs,i)
str,fnt = if isa(tmp, PlotText)
tmp.str, tmp.font
else
tmp, ea.anns.font
end
((cycle(ea.x,i), cycle(ea.y,i), str, fnt), i+1)
((_cycle(ea.x,i), _cycle(ea.y,i), str, fnt), i+1)
end
annotations(::Void) = []
@@ -501,13 +501,13 @@ immutable ZValues
zrange::Tuple{Float64,Float64}
end
function zvalues{T<:Real}(values::AVec{T}, zrange::Tuple{T,T} = (minimum(values), maximum(values)))
function zvalues{T<:Real}(values::AVec{T}, zrange::Tuple{T,T} = (ignorenan_minimum(values), ignorenan_maximum(values)))
ZValues(collect(float(values)), map(Float64, zrange))
end
# -----------------------------------------------------------------------
abstract AbstractSurface
abstract type AbstractSurface end
"represents a contour or surface mesh"
immutable Surface{M<:AMat} <: AbstractSurface
@@ -645,8 +645,8 @@ function (bc::BezierCurve)(t::Real)
p
end
Base.mean(x::Real, y::Real) = 0.5*(x+y)
Base.mean{N,T<:Real}(ps::FixedSizeArrays.Vec{N,T}...) = sum(ps) / length(ps)
# mean(x::Real, y::Real) = 0.5*(x+y) #commented out as I cannot see this used anywhere and it overwrites a Base method with different functionality
# mean{N,T<:Real}(ps::FixedSizeArrays.Vec{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array
@deprecate curve_points coords
@@ -659,7 +659,7 @@ function directed_curve(args...; kw...)
end
function extrema_plus_buffer(v, buffmult = 0.2)
vmin,vmax = extrema(v)
vmin,vmax = ignorenan_extrema(v)
vdiff = vmax-vmin
buffer = vdiff * buffmult
vmin - buffer, vmax + buffer
+1 -1
View File
@@ -84,7 +84,7 @@ function make_polygon(geom::ShapeGeometry, xs::AbstractArray, ys::AbstractArray,
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in cycle(geom.vertices, i)]
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in _cycle(geom.vertices, i)]
end
Gadfly.polygon(polys, geom.tag)
end
+1 -1
View File
@@ -1,5 +1,5 @@
abstract ColorScheme
abstract type ColorScheme end
Base.getindex(scheme::ColorScheme, i::Integer) = getColor(scheme, i)
+1 -1
View File
@@ -5,7 +5,7 @@
# This should cut down on boilerplate code and allow more focused dispatch on type
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
typealias FuncOrFuncs @compat(Union{Function, AVec{Function}})
const FuncOrFuncs = @compat(Union{Function, AVec{Function}})
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
+36 -27
View File
@@ -41,7 +41,7 @@ PlotExample("Colors",
[:(begin
y = rand(100)
plot(0:10:100,rand(11,4),lab="lines",w=3,palette=:grays,fill=0, α=0.6)
scatter!(y, zcolor=abs(y-.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs(y-0.5)+4, lab="grad")
scatter!(y, zcolor=abs.(y-.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs.(y-0.5)+4, lab="grad")
end)]
),
@@ -115,20 +115,22 @@ PlotExample("Line types",
PlotExample("Line styles",
"",
[:(begin
styles = filter(s -> s in Plots.supported_styles(), [:solid, :dash, :dot, :dashdot, :dashdotdot])'
styles = filter(s -> s in Plots.supported_styles(), [:solid, :dash, :dot, :dashdot, :dashdotdot])
styles = reshape(styles, 1, length(styles)) # Julia 0.6 unfortunately gives an error when transposing symbol vectors
n = length(styles)
y = cumsum(randn(20,n),1)
plot(y, line = (5, styles), label = map(string,styles))
plot(y, line = (5, styles), label = map(string,styles), legendtitle = "linestyle")
end)]
),
PlotExample("Marker types",
"",
[:(begin
markers = filter(m -> m in Plots.supported_markers(), Plots._shape_keys)'
markers = filter(m -> m in Plots.supported_markers(), Plots._shape_keys)
markers = reshape(markers, 1, length(markers))
n = length(markers)
x = linspace(0,10,n+2)[2:end-1]
y = repmat(reverse(x)', n, 1)
y = repmat(reshape(reverse(x),1,:), n, 1)
scatter(x, y, m=(8,:auto), lab=map(string,markers), bg=:linen, xlim=(0,10), ylim=(0,10))
end)]
),
@@ -172,24 +174,6 @@ PlotExample("",
end)]
),
PlotExample("Animation with subplots",
"The `layout` macro can be used to create an animation with subplots.",
[:(begin
l = @layout([[a; b] c])
p = plot(plot([sin,cos],1,leg=false),
scatter([atan,cos],1,leg=false),
plot(log,1,xlims=(1,10π),ylims=(0,5),leg=false),layout=l)
anim = Animation()
for x = linspace(1,10π,100)
plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)]))
frame(anim)
end
end)]
),
PlotExample("Open/High/Low/Close",
"Create an OHLC chart. Pass in a list of (open,high,low,close) tuples as your `y` argument. This uses recipes to first convert the tuples to OHLC objects, and subsequently create a :path series with the appropriate line segments.",
[:(begin
@@ -232,7 +216,7 @@ PlotExample("Contours",
x = 1:0.5:20
y = 1:0.5:10
f(x,y) = (3x+y^2)*abs(sin(x)+cos(y))
X = repmat(x', length(y), 1)
X = repmat(reshape(x,1,:), length(y), 1)
Y = repmat(y, 1, length(x))
Z = map(f, X, Y)
p1 = contour(x, y, f, fill=true)
@@ -286,7 +270,7 @@ PlotExample("Polar Plots",
"",
[:(begin
Θ = linspace(0,1.5π,100)
r = abs(0.1randn(100)+sin(3Θ))
r = abs.(0.1randn(100)+sin.(3Θ))
plot(Θ, r, proj=:polar, m=2)
end)]
),
@@ -296,7 +280,7 @@ PlotExample("Heatmap, categorical axes, and aspect_ratio",
[:(begin
xs = [string("x",i) for i=1:10]
ys = [string("y",i) for i=1:4]
z = float((1:4)*(1:10)')
z = float((1:4)*reshape(1:10,1,:))
heatmap(xs, ys, z, aspect_ratio=1)
end)]
),
@@ -318,7 +302,32 @@ PlotExample("Boxplot and Violin series recipes",
violin(singers, :VoicePart, :Height, line = 0, fill = (0.2, :blue))
boxplot!(singers, :VoicePart, :Height, line = (2,:black), fill = (0.3, :orange))
end)]
)
),
PlotExample("Animation with subplots",
"The `layout` macro can be used to create an animation with subplots.",
[:(begin
l = @layout([[a; b] c])
p = plot(plot([sin,cos],1,leg=false),
scatter([atan,cos],1,leg=false),
plot(log,1,xlims=(1,10π),ylims=(0,5),leg=false),layout=l)
anim = Animation()
for x = linspace(1,10π,100)
plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)]))
frame(anim)
end
end)]
),
PlotExample("Spy",
"For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat` has various different nonzero values, a colorbar is added. The colorbar can be disabled with `legend = nothing`. As always, the marker shape and size can be changed with `spy(mat, markersize = 3, markershape = :star)`",
[:(begin
a = spdiagm((ones(50), ones(49), ones(49), ones(40), ones(40)),(0, 1, -1, 10, -10))
b = spdiagm((1:50, 1:49, 1:49, 1:40, 1:40),(0, 1, -1, 10, -10))
plot(spy(a, markershape = :dtriangle), spy(b), markersize = 3, title = ["Unique nonzeros" "Different nonzeros"])
end)]
),
]
+3 -3
View File
@@ -9,8 +9,8 @@ to_pixels(m::AbsoluteLength) = m.value / 0.254
const _cbar_width = 5mm
Base.:.*(m::Measure, n::Number) = m * n
Base.:.*(n::Number, m::Measure) = m * n
Base.broadcast(::typeof(Base.:.*), m::Measure, n::Number) = m * n
Base.broadcast(::typeof(Base.:.*), m::Number, n::Measure) = m * n
Base.:-(m::Measure, a::AbstractArray) = map(ai -> m - ai, a)
Base.:-(a::AbstractArray, m::Measure) = map(ai -> ai - m, a)
Base.zero(::Type{typeof(mm)}) = 0mm
@@ -704,7 +704,7 @@ function link_axes!(axes::Axis...)
a1 = axes[1]
for i=2:length(axes)
a2 = axes[i]
expand_extrema!(a1, extrema(a2))
expand_extrema!(a1, ignorenan_extrema(a2))
for k in (:extrema, :discrete_values, :continuous_values, :discrete_map)
a2[k] = a1[k]
end
+1 -1
View File
@@ -271,7 +271,7 @@ function setup_ijulia()
show(io, MIME("text/html"), plt)
end
end
set_ijulia_output("text/html")
@eval set_ijulia_output("text/html")
end
end
+2 -2
View File
@@ -153,7 +153,7 @@ function _add_smooth_kw(kw_list::Vector{KW}, kw::KW)
if get(kw, :smooth, false)
x, y = kw[:x], kw[:y]
β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y)
sx = [minimum(x), maximum(x)]
sx = [ignorenan_minimum(x), ignorenan_maximum(x)]
sy = β * sx + α
push!(kw_list, merge(copy(kw), KW(
:seriestype => :path,
@@ -262,7 +262,7 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
for kw in kw_list
# get the Subplot object to which the series belongs.
sps = get(kw, :subplot, :auto)
sp = get_subplot(plt, cycle(sps == :auto ? plt.subplots : plt.subplots[sps], command_idx(kw_list,kw)))
sp = get_subplot(plt, _cycle(sps == :auto ? plt.subplots : plt.subplots[sps], command_idx(kw_list,kw)))
kw[:subplot] = sp
# extract subplot/axis attributes from kw and add to sp_attr
+1 -1
View File
@@ -60,7 +60,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
# build our plot vector from the args
n = length(plts_tail) + 1
plts = Array(Plot, n)
plts = Array{Plot}(n)
plts[1] = plt1
for (i,plt) in enumerate(plts_tail)
plts[i+1] = plt
+48 -118
View File
@@ -1,53 +1,4 @@
"""
You can easily define your own plotting recipes with convenience methods:
```
@userplot type GroupHist
args
end
@recipe function f(gh::GroupHist)
# set some attributes, add some series, using gh.args as input
end
# now you can plot like:
grouphist(rand(1000,4))
```
"""
macro userplot(expr)
_userplot(expr)
end
function _userplot(expr::Expr)
if expr.head != :type
errror("Must call userplot on a type/immutable expression. Got: $expr")
end
typename = expr.args[2]
funcname = Symbol(lowercase(string(typename)))
funcname2 = Symbol(funcname, "!")
# return a code block with the type definition and convenience plotting methods
esc(quote
$expr
export $funcname, $funcname2
$funcname(args...; kw...) = plot($typename(args); kw...)
$funcname2(args...; kw...) = plot!($typename(args); kw...)
end)
end
function _userplot(sym::Symbol)
_userplot(:(type $sym
args
end))
end
# ----------------------------------------------------------------------------------
const _series_recipe_deps = Dict()
function series_recipe_dependencies(st::Symbol, deps::Symbol...)
@@ -96,7 +47,7 @@ end
num_series(x::AMat) = size(x,2)
num_series(x) = 1
RecipesBase.apply_recipe{T}(d::KW, ::Type{T}, plt::Plot) = throw(MethodError("Unmatched plot recipe: $T"))
RecipesBase.apply_recipe{T}(d::KW, ::Type{T}, plt::AbstractPlot) = throw(MethodError("Unmatched plot recipe: $T"))
# ---------------------------------------------------------------------------
@@ -225,14 +176,14 @@ end
fr = if yaxis[:scale] == :identity
0.0
else
min(axis_limits(yaxis)[1], minimum(y))
NaNMath.min(axis_limits(yaxis)[1], ignorenan_minimum(y))
end
end
newx, newy = zeros(3n), zeros(3n)
for i=1:n
rng = 3i-2:3i
newx[rng] = [x[i], x[i], NaN]
newy[rng] = [cycle(fr,i), y[i], NaN]
newy[rng] = [_cycle(fr,i), y[i], NaN]
end
x := newx
y := newy
@@ -284,16 +235,16 @@ end
for rng in iter_segments(args...)
length(rng) < 2 && continue
ts = linspace(0, 1, npoints)
nanappend!(newx, map(t -> bezier_value(cycle(x,rng), t), ts))
nanappend!(newy, map(t -> bezier_value(cycle(y,rng), t), ts))
nanappend!(newx, map(t -> bezier_value(_cycle(x,rng), t), ts))
nanappend!(newy, map(t -> bezier_value(_cycle(y,rng), t), ts))
if z != nothing
nanappend!(newz, map(t -> bezier_value(cycle(z,rng), t), ts))
nanappend!(newz, map(t -> bezier_value(_cycle(z,rng), t), ts))
end
if fr != nothing
nanappend!(newfr, map(t -> bezier_value(cycle(fr,rng), t), ts))
nanappend!(newfr, map(t -> bezier_value(_cycle(fr,rng), t), ts))
end
# if lz != nothing
# lzrng = cycle(lz, rng) # the line_z's for this segment
# lzrng = _cycle(lz, rng) # the line_z's for this segment
# push!(newlz, 0.0)
# append!(newlz, map(t -> lzrng[1+floor(Int, t * (length(rng)-1))], ts))
# end
@@ -323,7 +274,7 @@ end
# create a bar plot as a filled step function
@recipe function f(::Type{Val{:bar}}, x, y, z)
procx, procy, xscale, yscale, baseline, wautolims = _preprocess_barlike(d, x, y)
procx, procy, xscale, yscale, baseline = _preprocess_barlike(d, x, y)
nx, ny = length(procx), length(procy)
axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis]
cv = [discrete_value!(axis, xi)[1] for xi=procx]
@@ -338,9 +289,9 @@ end
# compute half-width of bars
bw = d[:bar_width]
hw = if bw == nothing
0.5mean(diff(procx))
0.5ignorenan_mean(diff(procx))
else
Float64[0.5cycle(bw,i) for i=1:length(procx)]
Float64[0.5_cycle(bw,i) for i=1:length(procx)]
end
# make fillto a vector... default fills to 0
@@ -358,15 +309,15 @@ end
yi = procy[i]
if !isnan(yi)
center = procx[i]
hwi = cycle(hw,i)
fi = cycle(fillto,i)
hwi = _cycle(hw,i)
fi = _cycle(fillto,i)
push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi)
push!(yseg, yi, fi, fi, yi, yi)
end
end
# widen limits out a bit
expand_extrema!(axis, widen(extrema(xseg.pts)...))
expand_extrema!(axis, widen(ignorenan_extrema(xseg.pts)...))
# switch back
if !isvertical(d)
@@ -380,7 +331,6 @@ end
x := xseg.pts
y := yseg.pts
seriestype := :shape
ylims --> wautolims
()
end
@deps bar shape
@@ -412,41 +362,20 @@ function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol)
end
end
function _binbarlike_autolims{T<:Real}(min_value::T, max_value::T, scale::Symbol)
lo = if (scale in _logScales)
_binbarlike_baseline(min_value, scale)
else
min(min_value * T(1.1), zero(T))
end::T
hi = if !isnan(max_value)
if (scale in _logScales)
max_value * T(_logScaleBases[scale]^log10(2))
else
max(max_value * T(1.1), zero(T))
end
else
one(T)
end::T
(lo, hi)
end
function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol)
w_adj = _scale_adjusted_values(T, w, wscale)
w_min = minimum(w_adj)
w_max = maximum(w_adj)
w_min = ignorenan_minimum(w_adj)
w_max = ignorenan_maximum(w_adj)
baseline = _binbarlike_baseline(w_min, wscale)
autolims = _binbarlike_autolims(w_min, w_max,wscale)
w_adj, baseline, autolims
w_adj, baseline
end
function _preprocess_barlike(d, x, y)
xscale = get(d, :xscale, :identity)
yscale = get(d, :yscale, :identity)
weights, baseline, wautolims = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale)
x, weights, xscale, yscale, baseline, wautolims
weights, baseline = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale)
x, weights, xscale, yscale, baseline
end
function _preprocess_binlike(d, x, y)
@@ -454,13 +383,13 @@ function _preprocess_binlike(d, x, y)
yscale = get(d, :yscale, :identity)
T = float(promote_type(eltype(x), eltype(y)))
edge = T.(x)
weights, baseline, wautolims = _preprocess_binbarlike_weights(T, y, yscale)
edge, weights, xscale, yscale, baseline, wautolims
weights, baseline = _preprocess_binbarlike_weights(T, y, yscale)
edge, weights, xscale, yscale, baseline
end
@recipe function f(::Type{Val{:barbins}}, x, y, z)
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
if (d[:bar_width] == nothing)
bar_width := diff(edge)
end
@@ -473,7 +402,7 @@ end
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
xerror := diff(edge)/2
x := _bin_centers(edge)
y := weights
@@ -538,7 +467,7 @@ end
@recipe function f(::Type{Val{:stepbins}}, x, y, z)
axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis]
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale)
if !isvertical(d)
@@ -564,17 +493,15 @@ end
x := xpts
y := ypts
seriestype := :path
ylims --> wautolims
()
end
Plots.@deps stepbins path
function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto)
_cl(x) = max(ceil(Int, x), 1)
_cl(x) = ceil(Int, NaNMath.max(x, one(x)))
_iqr(v) = quantile(v, 0.75) - quantile(v, 0.25)
_span(v) = maximum(v) - minimum(v)
_span(v) = ignorenan_maximum(v) - ignorenan_minimum(v)
n_samples = length(linearindices(first(vs)))
# Estimator for number of samples in one row/column of bins along each axis:
@@ -613,7 +540,6 @@ _hist_norm_mode(mode::Symbol) = mode
_hist_norm_mode(mode::Bool) = mode ? :pdf : :none
function _make_hist{N}(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing)
info("binning = $binning")
edges = _hist_edges(vs, binning)
h = float( weights == nothing ?
StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) :
@@ -668,7 +594,7 @@ end
if d[:seriestype] == :scatterbins
# Workaround, error bars currently not set correctly by scatterbins
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, h.edges[1], h.weights)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights)
xerror --> diff(h.edges[1])/2
seriestype := :scatter
(Plots._bin_centers(edge), weights)
@@ -694,7 +620,7 @@ end
edge_x, edge_y, weights = x, y, z.surf
float_weights = float(weights)
if is(float_weights, weights)
if float_weights === weights
float_weights = deepcopy(float_weights)
end
for (i, c) in enumerate(float_weights)
@@ -780,9 +706,9 @@ function error_coords(xorig, yorig, ebar)
x, y = Array(float_extended_type(xorig), 0), Array(Float64, 0)
# for each point, create a line segment from the bottom to the top of the errorbar
for i = 1:max(length(xorig), length(yorig))
xi = cycle(xorig, i)
yi = cycle(yorig, i)
ebi = cycle(ebar, i)
xi = _cycle(xorig, i)
yi = _cycle(yorig, i)
ebi = _cycle(ebar, i)
nanappend!(x, [xi, xi])
e1, e2 = if istuple(ebi)
first(ebi), last(ebi)
@@ -835,11 +761,11 @@ function quiver_using_arrows(d::KW)
x, y = zeros(0), zeros(0)
for i = 1:max(length(xorig), length(yorig))
# get the starting position
xi = cycle(xorig, i)
yi = cycle(yorig, i)
xi = _cycle(xorig, i)
yi = _cycle(yorig, i)
# get the velocity
vi = cycle(velocity, i)
vi = _cycle(velocity, i)
vx, vy = if istuple(vi)
first(vi), last(vi)
elseif isscalar(vi)
@@ -872,12 +798,12 @@ function quiver_using_hack(d::KW)
for i = 1:max(length(xorig), length(yorig))
# get the starting position
xi = cycle(xorig, i)
yi = cycle(yorig, i)
xi = _cycle(xorig, i)
yi = _cycle(yorig, i)
p = P2(xi, yi)
# get the velocity
vi = cycle(velocity, i)
vi = _cycle(velocity, i)
vx, vy = if istuple(vi)
first(vi), last(vi)
elseif isscalar(vi)
@@ -944,7 +870,7 @@ end
# get the joined vector
function get_xy(v::AVec{OHLC}, x = 1:length(v))
xdiff = 0.3mean(abs(diff(x)))
xdiff = 0.3ignorenan_mean(abs.(diff(x)))
x_out, y_out = zeros(0), zeros(0)
for (i,ohlc) in enumerate(v)
ox,oy = get_xy(ohlc, x[i], xdiff)
@@ -985,7 +911,7 @@ end
# "Sparsity plot... heatmap of non-zero values of a matrix"
# function spy{T<:Real}(z::AMat{T}; kw...)
# mat = map(zi->float(zi!=0), z)'
# mat = reshape(map(zi->float(zi!=0), z),1,:)
# xn, yn = size(mat)
# heatmap(mat; leg=false, yflip=true, aspect_ratio=:equal,
# xlim=(0.5, xn+0.5), ylim=(0.5, yn+0.5),
@@ -1001,6 +927,9 @@ end
@assert length(g.args) == 1 && typeof(g.args[1]) <: AbstractMatrix
seriestype := :spy
mat = g.args[1]
if length(unique(mat[mat .!= 0])) < 2
legend --> nothing
end
n,m = size(mat)
Plots.SliceIt, 1:m, 1:n, Surface(mat)
end
@@ -1009,8 +938,8 @@ end
yflip := true
aspect_ratio := 1
rs, cs, zs = findnz(z.surf)
xlim := extrema(cs)
ylim := extrema(rs)
xlim := ignorenan_extrema(cs)
ylim := ignorenan_extrema(rs)
if d[:markershape] == :none
markershape := :circle
end
@@ -1024,6 +953,7 @@ end
y := rs
z := nothing
seriestype := :scatter
grid --> false
()
end
@@ -1031,7 +961,7 @@ end
"Adds a+bx... straight line over the current plot"
function abline!(plt::Plot, a, b; kw...)
plot!(plt, [extrema(plt)...], x -> b + a*x; kw...)
plot!(plt, [ignorenan_extrema(plt)...], x -> b + a*x; kw...)
end
abline!(args...; kw...) = abline!(current(), args...; kw...)
@@ -1075,7 +1005,7 @@ end
end
library = PlotUtils.color_libraries[cl.args[1]]
z = sqrt.((1:15)*(1:20)')
z = sqrt.((1:15)*reshape(1:20,1,:))
seriestype := :heatmap
ticks := nothing
@@ -1099,7 +1029,7 @@ end
if !(length(grad.args) == 1 && isa(grad.args[1], Symbol))
error("showgradient takes the name of a color gradient as a Symbol")
end
z = sqrt.((1:15)*(1:20)')
z = sqrt.((1:15)*reshape(1:20,1,:))
seriestype := :heatmap
ticks := nothing
legend := false
+3 -2
View File
@@ -6,7 +6,7 @@
# This should cut down on boilerplate code and allow more focused dispatch on type
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
typealias FuncOrFuncs{F} Union{F, Vector{F}, Matrix{F}}
const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}}
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
@@ -317,9 +317,10 @@ end
# # images - colors
@recipe function f{T<:Colorant}(mat::AMat{T})
n, m = size(mat)
if is_seriestype_supported(:image)
seriestype := :image
n, m = size(mat)
SliceIt, 1:m, 1:n, Surface(mat)
else
seriestype := :heatmap
+1 -1
View File
@@ -32,7 +32,7 @@ get_subplot(plt::Plot, k) = plt.spmap[k]
get_subplot(series::Series) = series.d[:subplot]
get_subplot_index(plt::Plot, idx::Integer) = Int(idx)
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(_ -> _ === sp, plt.subplots)
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(x -> x === sp, plt.subplots)
series_list(sp::Subplot) = sp.series_list # filter(series -> series.d[:subplot] === sp, sp.plt.series_list)
+4 -8
View File
@@ -2,16 +2,12 @@
# TODO: I declare lots of types here because of the lacking ability to do forward declarations in current Julia
# I should move these to the relevant files when something like "extern" is implemented
typealias AVec AbstractVector
typealias AMat AbstractMatrix
typealias KW Dict{Symbol,Any}
const AVec = AbstractVector
const AMat = AbstractMatrix
const KW = Dict{Symbol,Any}
immutable PlotsDisplay <: Display end
abstract AbstractBackend
abstract AbstractPlot{T<:AbstractBackend}
abstract AbstractLayout
# -----------------------------------------------------------
immutable InputWrapper{T}
@@ -62,7 +58,7 @@ Extrema() = Extrema(Inf, -Inf)
# -----------------------------------------------------------
typealias SubplotMap Dict{Any, Subplot}
const SubplotMap = Dict{Any, Subplot}
# -----------------------------------------------------------
+31 -31
View File
@@ -3,7 +3,7 @@ calcMidpoints(edges::AbstractVector) = Float64[0.5 * (edges[i] + edges[i+1]) for
"Make histogram-like bins of data"
function binData(data, nbins)
lo, hi = extrema(data)
lo, hi = ignorenan_extrema(data)
edges = collect(linspace(lo, hi, nbins+1))
midpoints = calcMidpoints(edges)
buckets = Int[max(2, min(searchsortedfirst(edges, x), length(edges)))-1 for x in data]
@@ -109,7 +109,7 @@ function regressionXY(x, y)
β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y)
# make a line segment
regx = [minimum(x), maximum(x)]
regx = [ignorenan_minimum(x), ignorenan_maximum(x)]
regy = β * regx + α
regx, regy
end
@@ -192,7 +192,7 @@ function iter_segments(args...)
end
# helpers to figure out if there are NaN values in a list of array types
anynan(i::Int, args::Tuple) = any(a -> !isfinite(cycle(a,i)), args)
anynan(i::Int, args::Tuple) = any(a -> !isfinite(_cycle(a,i)), args)
anynan(istart::Int, iend::Int, args::Tuple) = any(i -> anynan(i, args), istart:iend)
allnan(istart::Int, iend::Int, args::Tuple) = all(i -> anynan(i, args), istart:iend)
@@ -243,19 +243,19 @@ notimpl() = error("This has not been implemented yet")
isnothing(x::Void) = true
isnothing(x) = false
cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
_cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
_cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
cycle(v, idx::Int) = v
_cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
_cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
_cycle(v, idx::Int) = v
cycle(v::AVec, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
cycle(v::AMat, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
cycle(v, indices::AVec{Int}) = fill(v, length(indices))
_cycle(v::AVec, indices::AVec{Int}) = map(i -> _cycle(v,i), indices)
_cycle(v::AMat, indices::AVec{Int}) = map(i -> _cycle(v,i), indices)
_cycle(v, indices::AVec{Int}) = fill(v, length(indices))
cycle(grad::ColorGradient, idx::Int) = cycle(grad.colors, idx)
cycle(grad::ColorGradient, indices::AVec{Int}) = cycle(grad.colors, indices)
_cycle(grad::ColorGradient, idx::Int) = _cycle(grad.colors, idx)
_cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices)
makevec(v::AVec) = v
makevec{T}(v::T) = T[v]
@@ -283,16 +283,16 @@ unzip{T}(xyuv::FixedSizeArrays.Vec{4,T}) = T[xyuv[1]], T[xyuv[2]], T[xyuv[
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
function _expand_limits(lims, x)
try
e1, e2 = extrema(x)
lims[1] = min(lims[1], e1)
lims[2] = max(lims[2], e2)
e1, e2 = ignorenan_extrema(x)
lims[1] = NaNMath.min(lims[1], e1)
lims[2] = NaNMath.max(lims[2], e2)
# catch err
# warn(err)
end
nothing
end
expand_data(v, n::Integer) = [cycle(v, i) for i=1:n]
expand_data(v, n::Integer) = [_cycle(v, i) for i=1:n]
# if the type exists in a list, replace the first occurence. otherwise add it to the end
function addOrReplace(v::AbstractVector, t::DataType, args...; kw...)
@@ -324,7 +324,7 @@ function replaceAliases!(d::KW, aliases::Dict{Symbol,Symbol})
end
end
createSegments(z) = collect(repmat(z',2,1))[2:end]
createSegments(z) = collect(repmat(reshape(z,1,:),2,1))[2:end]
Base.first(c::Colorant) = c
Base.first(x::Symbol) = x
@@ -334,29 +334,29 @@ sortedkeys(d::Dict) = sort(collect(keys(d)))
"create an (n+1) list of the outsides of heatmap rectangles"
function heatmap_edges(v::AVec)
vmin, vmax = extrema(v)
vmin, vmax = ignorenan_extrema(v)
extra = 0.5 * (vmax-vmin) / (length(v)-1)
vcat(vmin-extra, 0.5 * (v[1:end-1] + v[2:end]), vmax+extra)
end
function calc_r_extrema(x, y)
xmin, xmax = extrema(x)
ymin, ymax = extrema(y)
r = 0.5 * min(xmax - xmin, ymax - ymin)
extrema(r)
xmin, xmax = ignorenan_extrema(x)
ymin, ymax = ignorenan_extrema(y)
r = 0.5 * NaNMath.min(xmax - xmin, ymax - ymin)
ignorenan_extrema(r)
end
function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y))
rmin, rmax = r_extrema
phi, r = x, y
r = 0.5 * (r - rmin) / (rmax - rmin)
r = (r - rmin) / (rmax - rmin)
n = max(length(phi), length(r))
x = zeros(n)
y = zeros(n)
for i in 1:n
x[i] = cycle(r,i) * cos(cycle(phi,i))
y[i] = cycle(r,i) * sin(cycle(phi,i))
x[i] = _cycle(r,i) * cos.(_cycle(phi,i))
y[i] = _cycle(r,i) * sin.(_cycle(phi,i))
end
x, y
end
@@ -469,7 +469,7 @@ ok(tup::Tuple) = ok(tup...)
# compute one side of a fill range from a ribbon
function make_fillrange_side(y, rib)
frs = zeros(length(y))
for (i, (yi, ri)) in enumerate(zip(y, Base.cycle(rib)))
for (i, (yi, ri)) in enumerate(zip(y, Base.Iterators.cycle(rib)))
frs[i] = yi + ri
end
frs
@@ -645,7 +645,7 @@ end
# used in updating an existing series
extendSeriesByOne(v::UnitRange{Int}, n::Int = 1) = isempty(v) ? (1:n) : (minimum(v):maximum(v)+n)
extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + maximum(v))
extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + ignorenan_maximum(v))
extendSeriesData{T}(v::Range{T}, z::Real) = extendSeriesData(float(collect(v)), z)
extendSeriesData{T}(v::Range{T}, z::AVec) = extendSeriesData(float(collect(v)), z)
extendSeriesData{T}(v::AVec{T}, z::Real) = (push!(v, convert(T, z)); v)
@@ -871,9 +871,9 @@ mm2px(mm::Real) = float(px / MM_PER_PX)
"Smallest x in plot"
xmin(plt::Plot) = minimum([minimum(series.d[:x]) for series in plt.series_list])
xmin(plt::Plot) = ignorenan_minimum([ignorenan_minimum(series.d[:x]) for series in plt.series_list])
"Largest x in plot"
xmax(plt::Plot) = maximum([maximum(series.d[:x]) for series in plt.series_list])
xmax(plt::Plot) = ignorenan_maximum([ignorenan_maximum(series.d[:x]) for series in plt.series_list])
"Extrema of x-values in plot"
Base.extrema(plt::Plot) = (xmin(plt), xmax(plt))
ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))
+2 -2
View File
@@ -24,7 +24,7 @@ default(size=(500,300))
# TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
const _current_plots_version = v"0.9.6"
const _current_plots_version = v"0.12.0"
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
@@ -99,7 +99,7 @@ function image_comparison_facts(pkg::Symbol;
for i in 1:length(Plots._examples)
i in skip && continue
if only == nothing || i in only
@fact image_comparison_tests(pkg, i, debug=debug, sigma=sigma, eps=eps) |> success --> true
@fact @eval(image_comparison_tests(Symbol(String(Symbol($pkg))[7:end]), $i, debug=$debug, sigma=$sigma, eps=$eps)) |> success --> true
end
end
end
+5 -3
View File
@@ -5,9 +5,11 @@ set -ex
sudo apt-get -qq update
# sudo apt-get install -y wkhtmltopdf
sudo apt-get install -y xfonts-75dpi
wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2/wkhtmltox-0.12.2_linux-trusty-amd64.deb
sudo dpkg -i wkhtmltox-0.12.2_linux-trusty-amd64.deb
sudo apt-get install -y xfonts-75dpi xfonts-base
wget https://downloads.wkhtmltopdf.org/0.12/0.12.2/wkhtmltox-0.12.2_linux-precise-amd64.deb
sudo dpkg -i wkhtmltox-0.12.2_linux-precise-amd64.deb
# wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2/wkhtmltox-0.12.2_linux-trusty-amd64.deb
# sudo dpkg -i wkhtmltox-0.12.2_linux-trusty-amd64.deb
wkhtmltoimage http://www.google.com test.png
ls
+74 -32
View File
@@ -7,41 +7,78 @@ srand(1234)
default(show=false, reuse=true)
img_eps = isinteractive() ? 1e-2 : 10e-2
# facts("Gadfly") do
# @fact gadfly() --> Plots.GadflyBackend()
# @fact backend() --> Plots.GadflyBackend()
#
# @fact typeof(plot(1:10)) --> Plots.Plot{Plots.GadflyBackend}
# @fact plot(Int[1,2,3], rand(3)) --> not(nothing)
# @fact plot(sort(rand(10)), rand(Int, 10, 3)) --> not(nothing)
# @fact plot!(rand(10,3), rand(10,3)) --> not(nothing)
#
# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], eps=img_eps)
# end
facts("GR") do
@fact gr() --> Plots.GRBackend()
@fact backend() --> Plots.GRBackend()
image_comparison_facts(:gr, eps=img_eps)
end
facts("PyPlot") do
@fact pyplot() --> Plots.PyPlotBackend()
@fact backend() --> Plots.PyPlotBackend()
image_comparison_facts(:pyplot, skip=[6,25,30], eps=img_eps)
image_comparison_facts(:pyplot, eps=img_eps)
end
facts("GR") do
@fact gr() --> Plots.GRBackend()
@fact backend() --> Plots.GRBackend()
facts("UnicodePlots") do
@fact unicodeplots() --> Plots.UnicodePlotsBackend()
@fact backend() --> Plots.UnicodePlotsBackend()
if is_linux() && isinteractive()
image_comparison_facts(:gr, skip=[2,25,30], eps=img_eps)
end
# lets just make sure it runs without error
@fact isa(plot(rand(10)), Plots.Plot) --> true
end
facts("Plotly") do
@fact plotly() --> Plots.PlotlyBackend()
@fact backend() --> Plots.PlotlyBackend()
# The plotlyjs testimages return a connection error on travis:
# connect: connection refused (ECONNREFUSED)
# # until png generation is reliable on OSX, just test on linux
# @static is_linux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], eps=img_eps)
end
# facts("PlotlyJS") do
# @fact plotlyjs() --> Plots.PlotlyJSBackend()
# @fact backend() --> Plots.PlotlyJSBackend()
#
# if is_linux() && isinteractive()
# image_comparison_facts(:plotlyjs,
# skip=[
# 2, # animation (skipped for speed)
# 27, # (polar plots) takes very long / not working
# 31, # animation (skipped for speed)
# ],
# eps=img_eps)
# end
# end
# InspectDR returns that error on travis:
# ERROR: LoadError: InitError: Cannot open display:
# in Gtk.GLib.GError(::Gtk.##229#230) at /home/travis/.julia/v0.5/Gtk/src/GLib/gerror.jl:17
# facts("InspectDR") do
# @fact inspectdr() --> Plots.InspectDRBackend()
# @fact backend() --> Plots.InspectDRBackend()
#
# image_comparison_facts(:inspectdr,
# skip=[
# 2, # animation
# 6, # heatmap not defined
# 10, # heatmap not defined
# 22, # contour not defined
# 23, # pie not defined
# 27, # polar plot not working
# 28, # heatmap not defined
# 31, # animation
# ],
# eps=img_eps)
# end
# facts("Plotly") do
# @fact plotly() --> Plots.PlotlyBackend()
# @fact backend() --> Plots.PlotlyBackend()
#
# # # until png generation is reliable on OSX, just test on linux
# # @static is_linux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], eps=img_eps)
# end
# facts("Immerse") do
@@ -62,13 +99,18 @@ end
# end
facts("UnicodePlots") do
@fact unicodeplots() --> Plots.UnicodePlotsBackend()
@fact backend() --> Plots.UnicodePlotsBackend()
# facts("Gadfly") do
# @fact gadfly() --> Plots.GadflyBackend()
# @fact backend() --> Plots.GadflyBackend()
#
# @fact typeof(plot(1:10)) --> Plots.Plot{Plots.GadflyBackend}
# @fact plot(Int[1,2,3], rand(3)) --> not(nothing)
# @fact plot(sort(rand(10)), rand(Int, 10, 3)) --> not(nothing)
# @fact plot!(rand(10,3), rand(10,3)) --> not(nothing)
#
# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], eps=img_eps)
# end
# lets just make sure it runs without error
@fact isa(plot(rand(10)), Plots.Plot) --> true
end
@@ -78,12 +120,12 @@ facts("Axes") do
@fact typeof(axis) --> Plots.Axis
@fact Plots.discrete_value!(axis, "HI") --> (0.5, 1)
@fact Plots.discrete_value!(axis, :yo) --> (1.5, 2)
@fact extrema(axis) --> (0.5,1.5)
@fact Plots.ignorenan_extrema(axis) --> (0.5,1.5)
@fact axis[:discrete_map] --> Dict{Any,Any}(:yo => 2, "HI" => 1)
Plots.discrete_value!(axis, ["x$i" for i=1:5])
Plots.discrete_value!(axis, ["x$i" for i=0:2])
@fact extrema(axis) --> (0.5, 7.5)
@fact Plots.ignorenan_extrema(axis) --> (0.5, 7.5)
end
+9 -6
View File
@@ -1,8 +1,8 @@
# Pkg.clone("ImageMagick")
# Pkg.build("ImageMagick")
Pkg.add("ImageMagick")
Pkg.build("ImageMagick")
# Pkg.clone("GR")
# Pkg.build("GR")
Pkg.clone("GR")
Pkg.build("GR")
Pkg.clone("https://github.com/JuliaPlots/PlotReferenceImages.jl.git")
@@ -11,11 +11,12 @@ Pkg.clone("https://github.com/JuliaPlots/PlotReferenceImages.jl.git")
Pkg.clone("StatPlots")
Pkg.checkout("PlotUtils")
# Pkg.clone("https://github.com/JunoLab/Blink.jl.git")
# Pkg.clone("Blink")
# Pkg.build("Blink")
# import Blink
# Blink.AtomShell.install()
# Pkg.clone("https://github.com/spencerlyon2/PlotlyJS.jl.git")
# Pkg.add("Rsvg")
# Pkg.add("PlotlyJS")
# Pkg.checkout("RecipesBase")
# Pkg.clone("VisualRegressionTests")
@@ -25,4 +26,6 @@ ENV["PYTHON"] = ""
Pkg.add("PyPlot")
Pkg.build("PyPlot")
# Pkg.add("InspectDR")
Pkg.test("Plots"; coverage=false)