Compare commits

..

219 Commits

Author SHA1 Message Date
Josef Heinen 0d17aa0093 gr: removed println statement 2017-06-17 22:11:57 +02:00
Michael K. Borregaard df729cd0f6 hotfix-FixedPointNumbers in require 2017-06-07 17:08:06 +02:00
Michael Krabbe Borregaard 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 Krabbe Borregaard 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 Borregaard 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 Schwabeneder 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 Borregaard 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 Borregaard 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 Borregaard 6a23202e89 Merge pull request #825 from ma-laforge/hdf5plots
Re-integrate HDF5 plots.
2017-06-06 12:36:46 +02:00
Josef Heinen 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 Schwabeneder 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 Schwabeneder 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 Schwabeneder 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 Borregaard 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 Borregaard 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 Borregaard 84406f0823 Fixed writing error. 2017-06-01 17:10:03 +02:00
Michael Krabbe Borregaard 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 Borregaard 7805f3f85b Merge pull request #862 from JuliaPlots/sd/fix_signals
fix glvisualize backend
2017-06-01 11:51:09 +02:00
Daniel Schwabeneder 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 Heinen 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 Borregaard 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 Heinen 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 Heinen 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 Heinen 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 Borregaard af7d332453 Merge pull request #859 from innerlee/patch-1
Update backends.jl
2017-05-23 15:43:33 +02:00
lizz 5439c3a3ce Update backends.jl 2017-05-23 21:41:31 +08:00
Michael Krabbe Borregaard 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 Borregaard 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 Borregaard 712d2011c3 Merge pull request #843 from mkborregaard/change_default_backend
Change default backends
2017-05-22 12:04:46 +02:00
Daniel Schwabeneder 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 Borregaard 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 Borregaard 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 Borregaard 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 Borregaard 72c506b62b Merge pull request #845 from ChrisRackauckas/patch-2
Add JSON to REQUIRE
2017-05-19 17:52:38 +02:00
Christopher Rackauckas f09dfb7035 Update REQUIRE 2017-05-19 07:56:36 -07:00
Daniel Schwabeneder 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 Borregaard 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 Schwabeneder 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 Borregaard 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 Schwabeneder 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 Borregaard 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 Borregaard 864dddb1ff Merge pull request #806 from dpsanders/0.6_deprecations
0.6 deprecations
2017-05-13 08:55:17 +02:00
Michael Krabbe Borregaard 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 Borregaard 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 Schwabeneder 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
Michael Krabbe Borregaard 601f24a006 Merge pull request #816 from mkborregaard/master
Up minor version number
2017-05-11 14:00:47 +02:00
Michael K. Borregaard 160b2bf03a Up minor version number 2017-05-11 14:00:29 +02:00
Michael Krabbe Borregaard 944163e889 Merge pull request #815 from mkborregaard/master
Updates for release 0.11
2017-05-11 13:41:13 +02:00
Michael K. Borregaard 8656fe002a Add minimum version numbers to PlotUtils and PlotThemes 2017-05-11 13:40:39 +02:00
Michael K. Borregaard d5e50983d8 Move rgba_string to PlotUtils
requested by Tony Kelman
2017-05-11 13:40:10 +02:00
Michael Krabbe Borregaard f3d31a62db Merge pull request #814 from ChrisRackauckas/patch-2
Fix plotpane notice
2017-05-11 09:48:15 +02:00
Christopher Rackauckas ee15b2c166 Fix plotpane notice
PlotlyJS actually plots to the plot pane, so the text was misleading.
2017-05-11 00:31:30 -07:00
Michael Krabbe Borregaard 4d84ab155a Merge pull request #812 from JonathanAnderson/JonathanAnderson-patch-1
Update gr.jl inline display to match GR.jl
2017-05-10 13:28:29 +02:00
Michael Krabbe Borregaard accc063db8 Merge pull request #811 from fuzzybear3965/master
increase plotly bottom margin to 20px; fixes #810
2017-05-10 13:24:08 +02:00
fuzzybear3965 b88d26ce77 increase bottom margin to 20px; fixes #810 2017-05-09 12:29:35 -04:00
Michael Krabbe Borregaard 886386508c Merge pull request #809 from mkborregaard/master
Amend news.md
2017-05-09 09:32:26 +02:00
Michael K. Borregaard d893034f47 Amend news.md 2017-05-09 09:31:40 +02:00
Josef Heinen f4b798765d Merge pull request #807 from jheinen/master
gr: use correct colorbar scaling
2017-05-08 23:39:09 +02:00
Josef Heinen 5e6a9da3ed gr: use correct colorbar scaling 2017-05-08 14:36:25 -07: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
Michael Krabbe Borregaard 598211c349 Merge pull request #802 from oschulz/bins-default-auto
Change default for bins to :auto (meaning 30 bins)
2017-05-08 11:39:58 +02:00
Oliver Schulz 7843821109 Change default for bins to :auto (meaning 30 bins) 2017-05-08 11:37:02 +02:00
Michael Krabbe Borregaard 96f3baca41 Merge pull request #800 from oschulz/barplot-fix
Barplot fix
2017-05-08 10:49:14 +02:00
Oliver Schulz 67b4157e25 Improve data preprocessing for bar and histogram plots
Fixes broken bar-plots with non-numeric a-axes
2017-05-06 15:00:31 +02:00
Oliver Schulz a523903c15 Remove remnant debugging output 2017-05-06 14:58:48 +02:00
Josef Heinen 92e9fa2084 Merge pull request #798 from jheinen/master
gr: fixed linewidth bug (lw=0)
2017-05-04 16:31:43 +02:00
Josef Heinen c75e1df190 gr: fixed linewidth bug (lw=0) 2017-05-04 16:28:49 +02:00
Michael Krabbe Borregaard 79bf45b823 Merge pull request #795 from sebastianpech/master
Add pgfplots support for zcolor and colorbar
2017-05-04 16:18:26 +02:00
Daniel Schwabeneder 58989465f4 Merge pull request #793 from daschw/ds-ticks-reduction
Avoid reducing the number of ticks set by the user
2017-05-04 16:17:57 +02:00
Daniel Schwabeneder 1e6b442c6c Merge pull request #794 from daschw/ds-pyplot-colorbar
Avoid PyPlot colorbar label cropping
2017-05-04 16:17:17 +02:00
Michael Krabbe Borregaard 33addf4449 Merge pull request #758 from mcawte/master
Added an animation with subplots example
2017-05-04 13:43:27 +02:00
Michael Krabbe Borregaard c5fed9524a Merge pull request #790 from huckl3b3rry87/pull-request/2e732993
changed warning in imagemagick
2017-05-04 13:42:30 +02:00
Michael Krabbe Borregaard cbfadde43c Merge pull request #769 from blegat/surfaceclims
Use clims with :surface for PyPlot
2017-05-04 13:19:10 +02:00
Michael Krabbe Borregaard cebe1eedeb Merge pull request #797 from mkborregaard/updatenews
Update News.md
2017-05-04 13:17:06 +02:00
Michael K. Borregaard c22a9e51a1 Update News.md 2017-05-04 13:15:05 +02:00
Michael Krabbe Borregaard e41022c7be Merge pull request #787 from oschulz/new-hist-impl
Rewrite of histogram recipes, using StatsBase.histogram
2017-05-04 12:33:42 +02:00
Oliver Schulz 56a9389023 Fix log-scale for 1D bar/bin/histogram series types 2017-05-04 10:02:07 +02:00
Oliver Schulz 1188230641 Change histogram implementation, use StatsPlots, add new histogram styles
New series recipes for binned data:

* barbins
* scatterbins
* stepbins

New series recipes for histogram:

* barhist (histogram is now an alias for this)
* scatterhist
* stephist

Supports plotting 1D and 2D StatsBase histograms, seriestype can be set to
bar(bins), scatter(bins) or step(bins).

Also adds support for some common auto-binning modes:

* :sturges, :auto - Sturges' formula
* :sqrt - Square-root choice
* :rice - Rice Rule
* :scott - Scott's normal reference rule
* :fd - Freedman–Diaconis rule

Maybe these could be contributed to StatsBase at some point.

Error bars currently don't work correctly for scatterbins and scatterhist,
due to problem with manipulating error bars in a series recipe, but do work
for "plot(h::StatsBase.Histogram, seriestype = :scatter)" (works around
the problem by calling scatter directly, it seems that error bars can be
manipulated correctly in a type recipe).
2017-05-04 10:02:07 +02:00
Michael Krabbe Borregaard e760b42560 Merge pull request #789 from huckl3b3rry87/pull-request/5e5e1850
deleted old warning for conda
2017-05-04 09:55:31 +02:00
Huckleberry Febbo 627c03193a Merge branch 'master' into pull-request/5e5e1850 2017-05-03 16:00:06 -04:00
Sebastian Pech 0f837f3438 Add pgfplots support for zcolor and colorbar 2017-05-03 10:46:25 +02:00
Daniel Schwabeneder af072da0b0 avoid auto-reduction of user-defined ticks 2017-05-02 21:10:43 +02:00
Daniel Schwabeneder c4f3b93da5 increase rightpad for colorbars 2017-05-02 20:36:33 +02:00
Michael Krabbe Borregaard 906f11ed76 Merge pull request #782 from oschulz/fix-pylot-conda-handling
Prevent inadvertent Conda ROOTENV initialization
2017-05-02 16:10:46 +02:00
Huckleberry Febbo 2e7329931c changed warning in imagemagick 2017-05-01 11:14:38 -04:00
Huckleberry Febbo 5e5e1850ac deleted old warning for conda 2017-05-01 11:04:39 -04:00
Oliver Schulz 6b250d1ab6 Prevent inadvertent Conda ROOTENV initialization
Conda._installed_packages_dict() always runs Conda._install_conda(),
even when using an external conda installation (e.g. via Anaconda).
2017-04-27 17:50:27 +02:00
Michael Krabbe Borregaard 1ee6affcb3 Merge pull request #777 from Godisemo/patch-1
Add colorbar_title attr to plotly(js) backends
2017-04-24 11:54:22 +02:00
Godisemo 7a1dd0db29 Add colorbar_title attr to plotly(js) backends
fixes issue #773
2017-04-20 17:40:05 +02:00
Michael Krabbe Borregaard e41918569b Merge pull request #776 from JuliaPlots/revert-747-hdf5plots
Revert "Initial implementation for HDF5 plots."
2017-04-20 00:08:44 +02:00
Michael Krabbe Borregaard ec6f75b59e Revert "Initial implementation for HDF5 plots." 2017-04-19 16:14:48 +02:00
Michael Krabbe Borregaard ec595c23e5 Merge pull request #747 from ma-laforge/hdf5plots
Initial implementation for HDF5 plots.
2017-04-19 06:26:52 +02:00
Michael Krabbe Borregaard 2c5a37d38e Merge pull request #746 from ma-laforge/inspectdr
Layout fix: Update plot.bb in _update_plot_object.
2017-04-18 20:55:21 +02:00
Michael Krabbe Borregaard 3ec61cd012 Merge pull request #771 from blegat/travis
Update Travis badge
2017-04-18 20:23:02 +02:00
Michael Krabbe Borregaard a3b4b9c8b2 Merge pull request #774 from ChrisRackauckas/complex
Recipe for handing arrays of complex values
2017-04-18 20:17:35 +02:00
Jonathan Anderson 5166d16406 Update gr.jl inline display to match GR.jl
I wanted to switch from using GR directly to using Plots, but the inline plots were not working for me.

The following change is sufficient to generate inline plots in iterm for me
https://github.com/jheinen/GR.jl/blob/0f167b2be921a0014c405f760a1e1bc22b222751/src/GR.jl#L3014

julia> versioninfo()
Julia Version 0.6.0-pre.beta.187
Commit 55c97fb* (2017-04-17 23:06 UTC)
Platform Info:
  OS: Linux (x86_64-redhat-linux)
  CPU: Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, haswell)
julia> using TerminalExtensions
julia> using Plots
julia> gr(display_type=:inline);
julia> z=[sin(sqrt(x^2+y^2)) for x in linspace(-2π,2π,50), y in linspace(-2π,2π,50)];
julia> contour(z)
2017-04-18 10:32:07 -05:00
ChrisRackauckas 3e7dd9bb77 tone down recipe 2017-04-17 22:15:13 -07:00
Simon 0ab57b3d76 Merge pull request #772 from blegat/fix770
Fix #770
2017-04-17 14:10:12 +02:00
ChrisRackauckas 0be0824207 (complex) type recipe 2017-04-16 13:14:12 -07:00
ChrisRackauckas 7def4e8e73 add transformation option 2017-04-16 13:01:51 -07:00
Michael Krabbe Borregaard 2397c78e9f Merge pull request #762 from mkborregaard/vectorfield_alias
add vectorfield alias to quiver: Closes #760
2017-04-16 19:37:04 +02:00
ChrisRackauckas 9a59df793d coloring setup 2017-04-15 17:00:00 -07:00
ChrisRackauckas 1852ba99b3 force real x 2017-04-15 13:16:40 -07:00
ChrisRackauckas 0d665c661f complex recipe 2017-04-15 13:14:14 -07:00
Benoît Legat f11828075b Fix #770 2017-04-13 22:20:03 +02:00
Benoît Legat 9a1efefbd4 Update Travis badge 2017-04-13 22:17:34 +02:00
Benoît Legat 066ff96b58 Use clims with :surface for PyPlot 2017-04-13 19:58:31 +02:00
Josef Heinen 7d8b00d1b9 Merge pull request #768 from jheinen/master
gr: expand extrema for heatmap() axes
2017-04-13 10:54:04 +02:00
Josef Heinen 5d4f3182fc gr: expand extrema for heatmap() axes 2017-04-13 10:51:03 +02:00
Josef Heinen b8d80f5285 Merge pull request #767 from jheinen/master
gr: use correct line width
2017-04-10 17:18:39 +02:00
Josef Heinen ccb9df2a08 gr: use correct line width 2017-04-10 14:56:38 +02:00
Josef Heinen c3ae9e1ee2 Merge pull request #764 from JuliaPlots/dev
gr: use correct marker size
2017-04-10 12:59:39 +02:00
Josef Heinen abcc4b6739 Merge pull request #763 from jheinen/dev
gr: use correct colorbar() routine
2017-04-10 12:58:10 +02:00
Josef Heinen dd3f65496a gr: use correct marker size 2017-04-10 12:54:57 +02:00
Michael K. Borregaard 2d69fc39de add vectorfield alias to quiver 2017-04-08 13:14:56 +02:00
Michael Krabbe Borregaard 731cac4262 Merge pull request #752 from daschw/ds-datetime-ticks
restore bar_width behavior for date x axis
2017-04-06 16:13:09 +02:00
Michael Cawte b4846bd5d5 Added an animation with subplots example 2017-04-06 11:58:50 +12:00
Josef Heinen fac39344f4 Merge pull request #754 from jheinen/dev
gr: use correct colorbar() routine
2017-03-31 16:28:18 +02:00
Josef Heinen ffb9878893 gr: use correct colorbar() routine 2017-03-31 16:26:29 +02:00
Daniel Schwabeneder 034a1af649 restore bar_width behavior for date x axis 2017-03-29 23:20:30 +02:00
MA Laforge 06fd894f79 Initial implementation for HDF5 plots. 2017-03-27 10:04:30 -04:00
MA Laforge 5731648479 Layout fix: Update plot.bb in _update_plot_object. 2017-03-25 17:51:33 -04:00
Tom Breloff 1ebc2cb9c1 Merge pull request #731 from mkborregaard/fix-colors-with-marker_z
fix plotly error on marker_z
2017-03-15 12:14:44 -04:00
Tom Breloff 0bd76ef7a4 Merge pull request #729 from JuliaPlots/sd/dev
newest changes
2017-03-15 12:14:30 -04:00
Tom Breloff ea15f7746d Merge pull request #720 from daschw/pull-request/f2235abf
Added logic to choose *round* DateTime tick positions
2017-03-15 12:14:12 -04:00
Michael K. Borregaard ed102269e7 fix error on marker_z 2017-03-14 22:47:43 +01:00
Daniel Schwabeneder 76e1f4720b avoid ignoring ticks set by the user 2017-03-13 16:05:30 +01:00
Tom Breloff 2317b77314 Merge pull request #721 from mkborregaard/fix-pyplot-grid
set dotted grid lines for pyplot
2017-03-13 09:54:43 -04:00
Michael Krabbe Borregaard 1a7bb10a22 Merge pull request #718 from anowacki/0.6-scale-fix
Remove import of Base.scale(!); fixes #687
2017-03-11 08:13:23 +01:00
Michael Krabbe Borregaard 0732006d5a Merge pull request #727 from mkborregaard/fix-linecolor-for-density
remove density from like_histogram
2017-03-10 23:53:48 +01:00
Michael K. Borregaard fb2e12089f remove density from like_histogram 2017-03-10 23:53:00 +01:00
Michael K. Borregaard 7a0e03b374 set dotted grid lines for pyplot 2017-03-07 08:04:15 +01:00
Daniel Schwabeneder f2235abf08 Added logic to choose *round* DateTime tick positions 2017-03-06 23:52:59 +01:00
Andy Nowacki 5435ce20a9 Remove import of Base.scale(!); fixes #687
Base.scale and Base.scale! were deprecated in v0.5 and removed in
v0.6-pre.alpha.  Removing their import permits use on v0.6- and
is fine since we REQUIRE v0.5 and above.
2017-03-06 10:25:21 +00:00
Michael Krabbe Borregaard 124f1fe701 Merge pull request #716 from mkborregaard/fix-gr_inqtext
define default behaviour for symbol in gr_text
2017-03-04 15:13:36 +01:00
Michael K. Borregaard 37e2c18c3c define default behaviour for symbol in gr_text 2017-03-03 12:15:23 +01:00
Michael Krabbe Borregaard 032f5a5dab Merge pull request #692 from mkborregaard/showlibrary
Update Plots to use color libraries
2017-03-02 22:04:10 +01:00
Michael K. Borregaard 7e41a2f40d sort colors 2017-03-01 22:18:34 +01:00
Tom Breloff 8b90eb37c5 Merge pull request #711 from mkborregaard/fix-pyplot-deprecation-warning
fix set_axis_bgcolor
2017-03-01 10:32:28 -05:00
Tom Breloff ff797b11d1 Merge pull request #703 from lwabeke/FreeBSDfix
FreeBSDfix
2017-03-01 10:32:08 -05:00
Tom Breloff 31c665a837 Merge pull request #706 from ma-laforge/inspectdr
InspectDR: Reflect changes to support delta markers.
2017-03-01 10:06:27 -05:00
Tom Breloff 68c39697a6 Merge remote-tracking branch 'origin/dev' 2017-02-28 13:52:08 -05:00
Michael K. Borregaard 6f8881b610 set defaults to sequential 2017-02-28 12:43:06 +01:00
Michael K. Borregaard 1b468ba5d8 fix gr.text on showgradient 2017-02-28 12:35:08 +01:00
Michael K. Borregaard 7aca2b1584 fix set_axis_bgcolor 2017-02-28 09:15:32 +01:00
Michael K. Borregaard 41e56b1f2e put PlotThemes in :misc 2017-02-28 07:56:00 +01:00
Michael K. Borregaard cad96e652f fix error on gr 2017-02-27 22:45:14 +01:00
Michael Krabbe Borregaard c7bde0ff19 Merge pull request #1 from mkborregaard/theme-works-with-colorlibraries
Theme works with colorlibraries
2017-02-27 21:52:52 +01:00
Michael K. Borregaard 6b94bbac2d updated function names 2017-02-27 21:52:22 +01:00
Michael K. Borregaard f7de9fbea4 Merge branch 'JuliaPlots/master' into showlibrary 2017-02-27 21:48:33 +01:00
Michael K. Borregaard 5465479e57 Put themes in Plots library 2017-02-27 21:47:12 +01:00
Josef Heinen cd3ce86dbb Merge pull request #710 from jheinen/dev
Fixed image bug
2017-02-27 14:15:41 +01:00
Josef Heinen b109025fac Fixed image bug 2017-02-27 14:13:16 +01:00
Michael K. Borregaard 6e74411a8e Merge branch 'JuliaPlots/master' into theme-works-with-colorlibraries 2017-02-26 20:43:09 +01:00
Michael K. Borregaard 6c51982793 fix theme default 2017-02-26 20:43:04 +01:00
Michael Krabbe Borregaard 8f841cdea4 Merge pull request #709 from JuliaPlots/fix-uneven
Fix uneven
2017-02-26 20:39:35 +01:00
Michael K. Borregaard eab4cfdf2d allow color libraries to be used in PlotThemes 2017-02-26 17:23:43 +01:00
MA Laforge b0dabaafe8 InspectDR: Reflect changes to support delta markers. 2017-02-25 11:33:24 -05:00
Leon Wabeke 9e1d551173 Commit to address issue #681
Change to address issue #681
Untested change
2017-02-24 12:19:20 +02:00
Leon Wabeke 2d61b413d6 Merge remote-tracking branch 'JuliaPlots/master' 2017-02-24 12:13:05 +02:00
Michael K. Borregaard b7536f129b Revert "replaced boxes with symmetrical squares"
This reverts commit 28b026c9ad.
2017-02-22 11:52:54 +01:00
Michael K. Borregaard 28b026c9ad replaced boxes with symmetrical squares 2017-02-22 11:49:31 +01:00
Michael K. Borregaard d4b7bfbe1d Added a recipe to show a single gradient 2017-02-22 11:48:37 +01:00
Michael K. Borregaard 4b2ce036e8 change numbers 2017-02-21 22:49:15 +01:00
Michael K. Borregaard 2a350df5eb plot recipe to show color libraries 2017-02-21 22:44:32 +01:00
SimonDanisch c93e2b80ca fixes for GLVisualize 2017-02-07 18:28:22 -05:00
SimonDanisch fdadfa3a80 small changes 2017-01-24 02:42:20 +01:00
SimonDanisch 45b5922d01 dont rely on postempty, img transpose not necessary anymore 2017-01-20 19:07:20 +01:00
34 changed files with 1357 additions and 340 deletions
+49 -4
View File
@@ -3,14 +3,59 @@
#### notes on release changes, ongoing development, and future planned work
- All new development should target 0.9!
- Minor version 0.8 is the last one to support Julia 0.4!!
- All new development should target 0.12!
- Minor version 0.11 is the last one to support Julia 0.5!!
- Critical bugfixes only
- `backports` branch is for Julia 0.4
---
## 0.9 (current master/dev)
## 0.11 (current master/dev)
#### 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
- julia 0.6 compatibility
- matplotlib 0.2.0 compatibility
- add inspectdr backend
- improved histogram functionality:
- added a `:stephist` and `:scatterhist` series type as well as ``:barhist` (the default)
- support for log scale axes with histograms
- support for plotting `StatsBase.Histogram`
- allowing bins to be specified as `:sturges`, `:rice`, `:scott` or :fd
- allow `normalization` to be specified as :density (for unequal bins) or :pdf (sum to 1)
- add a `plotattr` function to access documentation for Plots attribute
- add `fill_z` attribute for pyplot
- add colorbar_title to plotlyjs
- enable standalone window for plotlyjs
- improved support for pgfplots, ticks rotation, clims, series_annotations
- restore colorbars for GR
- better axis labels for heatmap in GR
- better marker sizes in GR
- fix color representation in GR
- update GR legend
- fix image bug on GR
- fix glvisualize dependencies
- set dotted grid lines for pyplot
- several improvements to inspectdr
- improved tick positions for TimeType x axes
- support for improved color gradient capability in PlotUtils
- add a showlibrary recipe to display color libraries
- add a showgradient recipe to display color gradients
- add `vectorfield` as an alias for `quiver`
- use `PlotUtils.adaptedgrid` for functions
#### 0.9.5
@@ -331,7 +376,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
+1 -1
View File
@@ -1,6 +1,6 @@
# Plots
[![Build Status](https://travis-ci.org/tbreloff/Plots.jl.svg?branch=master)](https://travis-ci.org/tbreloff/Plots.jl)
[![Build Status](https://travis-ci.org/JuliaPlots/Plots.jl.svg?branch=master)](https://travis-ci.org/JuliaPlots/Plots.jl)
[![Join the chat at https://gitter.im/tbreloff/Plots.jl](https://badges.gitter.im/tbreloff/Plots.jl.svg)](https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<!-- [![Plots](http://pkg.julialang.org/badges/Plots_0.3.svg)](http://pkg.julialang.org/?pkg=Plots&ver=0.3) -->
<!-- [![Plots](http://pkg.julialang.org/badges/Plots_0.4.svg)](http://pkg.julialang.org/?pkg=Plots&ver=0.4) -->
+6 -3
View File
@@ -1,10 +1,13 @@
julia 0.5
RecipesBase
PlotUtils
PlotThemes
PlotUtils 0.4.1
PlotThemes 0.1.3
Reexport
FixedSizeArrays
FixedPointNumbers 0.3
Measures
Showoff
StatsBase
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
+15 -3
View File
@@ -1,4 +1,4 @@
__precompile__(true)
__precompile__(false)
module Plots
@@ -106,9 +106,21 @@ 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)
# ---------------------------------------------------------
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 +130,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,6 +142,7 @@ include("output.jl")
include("examples.jl")
include("arg_desc.jl")
include("plotattr.jl")
include("backends.jl")
# ---------------------------------------------------------
+2 -1
View File
@@ -80,7 +80,8 @@ function buildanimation(animdir::AbstractString, fn::AbstractString;
catch err
warn("""Tried to create gif using convert (ImageMagick), but got error: $err
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`.
You may also need to install the imagemagick c++ library through your operating system.
Will try ffmpeg, but it's lower quality...)""")
# low quality
+3 -2
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. For histogram-types, defines the number of bins, or the edges, of the histogram.",
: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",
@@ -40,7 +40,7 @@ const _arg_desc = KW(
:ribbon => "Number or AbstractVector. Creates a fillrange around the data points.",
:quiver => "AbstractVector or 2-Tuple of vectors. The directional vectors U,V which specify velocity/gradient vectors for a quiver plot.",
:arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.",
:normalize => "Bool. Should normalize histogram types? Trying for area == 1.",
:normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a PDF with integral of 1) and :density (only normalize in respect to bin sizes).",
:weights => "AbstractVector. Used in histogram types for weighted counts.",
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
:match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.",
@@ -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.",
+11 -4
View File
@@ -35,7 +35,9 @@ const _3dTypes = [
]
const _allTypes = vcat([
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:heatmap, :hexbin, :histogram, :histogram2d, :histogram3d, :density, :bar, :hline, :vline,
:heatmap, :hexbin, :barbins, :barhist, :histogram, :scatterbins,
:scatterhist, :stepbins, :stephist, :bins2d, :histogram2d, :histogram3d,
:density, :bar, :hline, :vline,
:contour, :pie, :shape, :image
], _3dTypes)
@@ -65,6 +67,7 @@ const _typeAliases = Dict{Symbol,Symbol}(
:polygon => :shape,
:box => :boxplot,
:velocity => :quiver,
:vectorfield => :quiver,
:gradient => :quiver,
:img => :image,
:imshow => :image,
@@ -77,7 +80,7 @@ const _typeAliases = Dict{Symbol,Symbol}(
add_non_underscore_aliases!(_typeAliases)
like_histogram(seriestype::Symbol) = seriestype in (:histogram, :barhist, :barbins, :density)
like_histogram(seriestype::Symbol) = seriestype in (:histogram, :barhist, :barbins)
like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :steppost)
like_surface(seriestype::Symbol) = seriestype in (:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image)
@@ -153,6 +156,8 @@ const _markerAliases = Dict{Symbol,Symbol}(
)
const _allScales = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
const _logScales = [:ln, :log2, :log10]
const _logScaleBases = Dict(:ln => e, :log2 => 2.0, :log10 => 10.0)
const _scaleAliases = Dict{Symbol,Symbol}(
:none => :identity,
:log => :log10,
@@ -180,7 +185,7 @@ const _series_defaults = KW(
:markerstrokewidth => 1,
:markerstrokecolor => :match,
:markerstrokealpha => nothing,
:bins => 30, # number of bins for hists
:bins => :auto, # number of bins for hists
:smooth => false, # regression line?
:group => nothing, # groupby vector
:x => nothing,
@@ -246,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),
@@ -434,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)
@@ -445,7 +452,7 @@ add_aliases(:color_palette, :palette)
add_aliases(:overwrite_figure, :clf, :clearfig, :overwrite, :reuse)
add_aliases(:xerror, :xerr, :xerrorbar)
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
add_aliases(:quiver, :velocity, :quiver2d, :gradient)
add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield)
add_aliases(:normalize, :norm, :normed, :normalized)
add_aliases(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio)
add_aliases(:match_dimensions, :transpose, :transpose_z)
+37 -13
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}(
@@ -156,6 +156,30 @@ function optimal_ticks_and_labels(axis::Axis, ticks = nothing)
scale = axis[:scale]
sf = scalefunc(scale)
# If the axis input was a Date or DateTime use a special logic to find
# "round" Date(Time)s as ticks
# This bypasses the rest of optimal_ticks_and_labels, because
# optimize_datetime_ticks returns ticks AND labels: the label format (Date
# or DateTime) is chosen based on the time span between amin and amax
# rather than on the input format
# TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime
if ticks == nothing && scale == :identity
if axis[:formatter] == dateformatter
# optimize_datetime_ticks returns ticks and labels(!) based on
# integers/floats corresponding to the DateTime type. Thus, the axes
# limits, which resulted from converting the Date type to integers,
# are converted to 'DateTime integers' (actually floats) before
# being passed to optimize_datetime_ticks.
# (convert(Int, convert(DateTime, convert(Date, i))) == 87600000*i)
ticks, labels = optimize_datetime_ticks(864e5 * amin, 864e5 * amax;
k_min = 2, k_max = 4)
# Now the ticks are converted back to floats corresponding to Dates.
return ticks / 864e5, labels
elseif axis[:formatter] == datetimeformatter
return optimize_datetime_ticks(amin, amax; k_min = 2, k_max = 4)
end
end
# get a list of well-laid-out ticks
scaled_ticks = if ticks == nothing
optimize_ticks(
@@ -205,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
@@ -214,7 +238,7 @@ function get_ticks(axis::Axis)
# @show ticks dvals cv dv
# TODO: better/smarter cutoff values for sampling ticks
if length(cv) > 30
if length(cv) > 30 && ticks == :auto
rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)]
cv[rng], dv[rng]
else
@@ -236,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
@@ -252,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})
@@ -325,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
@@ -344,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
@@ -401,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
# ---------------------------------------------------------
+34 -78
View File
@@ -1,4 +1,4 @@
``#=
#=
TODO
* move all gl_ methods to GLPlot
* integrate GLPlot UI
@@ -7,7 +7,6 @@ TODO
* polar plots
* labes and axis
* fix units in all visuals (e.g dotted lines, marker scale, surfaces)
* why is there so little unicode supported in the font!??!?
=#
const _glvisualize_attr = merge_with_base_supported([
@@ -78,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
@@ -99,46 +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 poll_reactive()
# run_till_now blocks when message queue is empty!
Base.n_avail(Reactive._messages) > 0 && Reactive.run_till_now()
end
function get_plot_screen(list::Vector, name, result = [])
for elem in list
@@ -155,38 +109,36 @@ function get_plot_screen(screen, name, result = [])
end
function create_window(plt::Plot{GLVisualizeBackend}, visible)
name = Symbol("Plots.jl")
name = Symbol("__Plots.jl")
# make sure we have any screen open
if isempty(GLVisualize.get_screens())
# create a fresh, new screen
parent_screen = GLVisualize.glscreen(
"Plot",
"Plots",
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
plot_screens = get_plot_screen(GLVisualize.get_screens(), name)
plot_screens = get_plot_screen(GLVisualize.current_screen(), name)
screen = if isempty(plot_screens) # no screen with `name`
parent = GLVisualize.current_screen()
screen = GLWindow.Screen(
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]
else
# okay this is silly! Lets see if we can. There is an ID we could use
# will not be fine for more than 255 screens though -.-.
error("multiple Plot screens. Please don't use any screen with the name Plots.jl")
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]...)
@@ -352,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
@@ -363,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
@@ -415,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
@@ -530,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
@@ -557,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
@@ -697,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()
@@ -774,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])
@@ -783,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] != ""
@@ -793,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
@@ -829,7 +781,7 @@ 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)]
end
@@ -912,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
@@ -1141,8 +1093,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
vis = gl_bar(d, kw_args)
elseif st == :image
extract_extrema(d, kw_args)
z = transpose_z(series, d[:z].surf, false)
vis = GL.gl_image(z, kw_args)
vis = GL.gl_image(d[:z].surf, kw_args)
elseif st == :boxplot
extract_c(d, kw_args, :fill)
vis = gl_boxplot(d, kw_args)
@@ -1173,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
@@ -1182,7 +1133,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
if _3d
GLAbstraction.center!(sp_screen)
end
Reactive.post_empty()
GLAbstraction.post_empty()
yield()
end
end
@@ -1367,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
@@ -1388,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}
@@ -1422,6 +1373,8 @@ function label_scatter(d, w, ho)
color = get(kw, :color, nothing)
kw[:color] = isa(color, Array) ? first(color) : color
end
strcolor = get(kw, :stroke_color, RGBA{Float32}(0,0,0,0))
kw[:stroke_color] = isa(strcolor, Array) ? first(strcolor) : strcolor
p = get(kw, :primitive, GeometryTypes.Circle)
if isa(p, GLNormalMesh)
bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p))
@@ -1436,6 +1389,9 @@ function label_scatter(d, w, ho)
kw[:scale] = Vec3f0(w/2)
delete!(kw, :offset)
end
if isa(p, Array)
kw[:primitive] = GeometryTypes.Circle
end
GL.gl_scatter(Point2f0[(w/2, ho)], kw)
end
@@ -1480,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
+93 -52
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,
@@ -172,6 +174,8 @@ function gr_polyline(x, y, func = GR.polyline; arrowside=:none)
end
end
gr_inqtext(x, y, s::Symbol) = gr_inqtext(x, y, string(s))
function gr_inqtext(x, y, s)
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.inqtextext(x, y, s[2:end-1])
@@ -182,6 +186,8 @@ function gr_inqtext(x, y, s)
end
end
gr_text(x, y, s::Symbol) = gr_text(x, y, string(s))
function gr_text(x, y, s)
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
GR.mathtex(x, y, s[2:end-1])
@@ -258,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
@@ -273,17 +279,19 @@ 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
# draw ONE symbol marker
function gr_draw_marker(xi, yi, msize::Number, shape::Symbol)
GR.setmarkertype(gr_markertype[shape])
GR.setmarkersize(0.3msize)
w, h = gr_plot_size
GR.setmarkersize(0.3msize / ((w + h) * 0.001))
GR.polymarker([xi], [yi])
end
@@ -330,9 +338,10 @@ end
# ---------------------------------------------------------
function gr_set_line(w, style, c) #, a)
function gr_set_line(lw, style, c) #, a)
GR.setlinetype(gr_linetype[style])
GR.setlinewidth(w)
w, h = gr_plot_size
GR.setlinewidth(max(0, lw / ((w + h) * 0.001)))
gr_set_linecolor(c) #, a)
end
@@ -377,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]
)
@@ -411,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
@@ -421,23 +438,41 @@ end
function gr_colorbar(sp::Subplot)
if sp[:colorbar] != :none
gr_set_viewport_cmap(sp)
GR.colormap()
GR.colorbar()
gr_set_viewport_plotarea()
end
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
# --------------------------------------------------------------------------------------
@@ -498,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)
@@ -545,6 +585,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if st == :heatmap
outside_ticks = true
x, y = heatmap_edges(series[:x]), heatmap_edges(series[:y])
expand_extrema!(sp[:xaxis], x)
expand_extrema!(sp[:yaxis], y)
data_lims = gr_xy_axislims(sp)
end
end
@@ -622,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)
@@ -646,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
@@ -661,7 +707,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# use xor ($) to get the right y coords
xi, yi = GR.wctondc(cv, (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
@@ -678,22 +724,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# use xor ($) to get the right y coords
xi, yi = GR.wctondc((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
@@ -759,10 +792,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# recompute data
if typeof(z) <: Surface
# if st == :heatmap
# expand_extrema!(sp[:xaxis], (x[1]-0.5*(x[2]-x[1]), x[end]+0.5*(x[end]-x[end-1])))
# expand_extrema!(sp[:yaxis], (y[1]-0.5*(y[2]-y[1]), y[end]+0.5*(y[end]-y[end-1])))
# end
z = vec(transpose_z(series, z.surf, false))
elseif ispolar(sp)
if frng != nothing
@@ -807,12 +836,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
isfinite(clims[1]) && (zmin = clims[1])
isfinite(clims[2]) && (zmax = clims[2])
end
GR.setspace(zmin, zmax, 0, 90)
if typeof(series[:levels]) <: Array
h = series[:levels]
else
h = linspace(zmin, zmax, series[:levels])
end
GR.setspace(zmin, zmax, 0, 90)
if series[:fillrange] != nothing
GR.surface(x, y, z, GR.OPTION_CELL_ARRAY)
else
@@ -822,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)
@@ -850,6 +879,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
isfinite(clims[1]) && (zmin = clims[1])
isfinite(clims[2]) && (zmax = clims[2])
end
GR.setspace(zmin, zmax, 0, 90)
grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad()
colors = [grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)] for zi=z]
rgba = map(c -> UInt32( round(Int, alpha(c) * 255) << 24 +
@@ -879,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
@@ -943,8 +973,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :image
z = transpose_z(series, series[:z].surf, true)
h, w = size(z)
z = transpose_z(series, series[:z].surf, true)'
w, h = size(z)
if eltype(z) <: Colors.AbstractGray
grey = round(UInt8, float(z) * 255)
rgba = map(c -> UInt32( 0xff000000 + Int(c)<<16 + Int(c)<<8 + Int(c) ), grey)
@@ -977,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
@@ -990,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)
@@ -1000,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
@@ -1103,7 +1144,7 @@ function _display(plt::Plot{GRBackend})
ENV["GKS_FILEPATH"] = filepath
gr_display(plt)
GR.emergencyclosegks()
content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(readbytes, filepath)), "\a")
content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(read, filepath)), "\a")
println(content)
rm(filepath)
else
+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
+8 -10
View File
@@ -213,14 +213,10 @@ end
# Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend})
plot = sp.o
#Don't do anything without a "subplot" object: Will process later.
if nothing == plot; return; end
plot.data = []
plot.markers = [] #Clear old markers
plot.atext = [] #Clear old annotation
plot.apline = [] #Clear old poly lines
plot.userannot = [] #Clear old markers/text annotation/polyline "annotation"
return plot
end
@@ -277,7 +273,7 @@ For st in :shape:
apline = InspectDR.PolylineAnnotation(
x[rng], y[rng], line=line, fillcolor=fillcolor
)
push!(plot.apline, apline)
InspectDR.add(plot, apline)
end
end
@@ -353,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
@@ -415,8 +411,6 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend})
plot = sp.o
_initialize_subplot(plt, sp)
_inspectdr_setupsubplot(sp)
graphbb = _inspectdr_to_pixels(plotarea(sp))
plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb)
# add the annotations
for ann in sp[:annotations]
@@ -471,7 +465,11 @@ function _update_plot_object(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end
#TODO: should plotbb be computed here??
for (i, sp) in enumerate(plt.subplots)
graphbb = _inspectdr_to_pixels(plotarea(sp))
plot = mplot.subplots[i]
plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb)
end
gplot = _inspectdr_getgui(plt.o)
if nothing == gplot; return; end
+51 -4
View File
@@ -22,8 +22,8 @@ const _pgfplots_attr = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend,
# :colorbar,
# :marker_z, :levels,
:colorbar,
:marker_z, #:levels,
# :ribbon, :quiver, :arrow,
# :orientation,
# :overwrite_figure,
@@ -98,6 +98,8 @@ const _pgf_series_extrastyle = KW(
:xsticks => "xcomb",
)
# PGFPlots uses the anchors to define orientations for example to align left
# one needs to use the right edge as anchor
const _pgf_annotation_halign = KW(
:center => "",
:left => "right",
@@ -107,11 +109,24 @@ const _pgf_annotation_halign = KW(
# --------------------------------------------------------------------------------------
# takes in color,alpha, and returns color and alpha appropriate for pgf style
function pgf_color(c)
function pgf_color(c::Colorant)
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", red(c), green(c), blue(c))
cstr, alpha(c)
end
function pgf_color(grad::ColorGradient)
# Can't handle ColorGradient here, fallback to defaults.
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", 0.0, 0.60560316,0.97868012)
cstr, 1
end
# Generates a colormap for pgfplots based on a ColorGradient
function pgf_colormap(grad::ColorGradient)
join(map(grad.colors) do c
@sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c),blue(c))
end,", ")
end
function pgf_fillstyle(d::KW)
cstr,a = pgf_color(d[:fillcolor])
"fill = $cstr, fill opacity=$a"
@@ -162,7 +177,6 @@ function pgf_series(sp::Subplot, series::Series)
st = d[:seriestype]
style = []
kw = KW()
push!(style, pgf_linestyle(d))
push!(style, pgf_marker(d))
@@ -182,6 +196,10 @@ function pgf_series(sp::Subplot, series::Series)
d[:z].surf, d[:x], d[:y]
elseif is3d(st)
d[:x], d[:y], d[:z]
elseif d[:marker_z] != nothing
# If a marker_z is used pass it as third coordinate to a 2D plot.
# See "Scatter Plots" in PGFPlots documentation
d[:x], d[:y], d[:marker_z]
else
d[:x], d[:y]
end
@@ -274,6 +292,7 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
# Obtain the total height of the plot by extracting the maximal bottom
# coordinate from the bounding box.
total_height = bottom(bbox(plt.layout))
for sp in plt.subplots
# first build the PGFPlots.Axis object
style = ["unbounded coords=jump"]
@@ -319,6 +338,34 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
if sp[:projection] == :polar
axisf = PGFPlots.PolarAxis
end
# Search series for any gradient. In case one series uses a gradient set
# the colorbar and colomap.
# The reasoning behind doing this on the axis level is that pgfplots
# colorbar seems to only works on axis level and needs the proper colormap for
# correctly displaying it.
# It's also possible to assign the colormap to the series itself but
# then the colormap needs to be added twice, once for the axis and once for the
# series.
# As it is likely that all series within the same axis use the same
# colormap this should not cause any problem.
for series in series_list(sp)
for col in (:markercolor, :fillcolor)
if typeof(series.d[col]) == ColorGradient
push!(style,"colormap={plots}{$(pgf_colormap(series.d[col]))}")
if sp[:colorbar] == :none
kw[:colorbar] = "false"
else
kw[:colorbar] = "true"
end
# goto is needed to break out of col and series for
@goto colorbar_end
end
end
end
@label colorbar_end
o = axisf(; style = style, kw...)
# add the series object to the PGFPlots.Axis
+12 -5
View File
@@ -19,7 +19,7 @@ const _plotly_attr = merge_with_base_supported([
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:grid, :legend, :colorbar, :colorbar_title,
:marker_z, :fill_z, :levels,
:ribbon, :quiver,
:orientation,
@@ -269,7 +269,7 @@ function plotly_layout(plt::Plot)
w, h = plt[:size]
d_out[:width], d_out[:height] = w, h
d_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside])
d_out[:margin] = KW(:l=>0, :b=>0, :r=>0, :t=>20)
d_out[:margin] = KW(:l=>0, :b=>20, :r=>0, :t=>20)
d_out[:annotations] = KW[]
@@ -409,6 +409,10 @@ plotly_surface_data(series::Series, a::AbstractVector) = a
plotly_surface_data(series::Series, a::AbstractMatrix) = transpose_z(series, a, false)
plotly_surface_data(series::Series, a::Surface) = plotly_surface_data(series, a.surf)
#ensures that a gradient is called if a single color is supplied where a gradient is needed (e.g. if a series recipe defines marker_z)
as_gradient(grad::ColorGradient, α) = grad
as_gradient(grad, α) = cgrad(alpha = α)
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
function plotly_series(plt::Plot, series::Series)
st = series[:seriestype]
@@ -439,6 +443,8 @@ function plotly_series(plt::Plot, series::Series)
end
end
d_out[:colorbar] = KW(:title => sp[:colorbar_title])
clims = sp[:clims]
if is_2tuple(clims)
d_out[:zmin], d_out[:zmax] = clims
@@ -539,9 +545,10 @@ function plotly_series(plt::Plot, series::Series)
rgba_string(series[:markercolor])
else
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
grad = series[:markercolor]
zmin, zmax = extrema(series[:marker_z])
[rgba_string(grad[(zi - zmin) / (zmax - zmin)]) for zi in series[:marker_z]]
grad = as_gradient(series[:markercolor], series[:markeralpha])
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
end
+26 -26
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,20 +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"))
# we don't want every command to update the figure
PyPlot.ioff()
end
if is_linux()
@eval begin
# avoid Conda update that causes Segfault with qt >=4.8.6 on Ubuntu https://github.com/JuliaPy/PyPlot.jl/issues/234
import Conda
kw = Conda._installed_packages_dict()
if (!haskey(kw,"qt") || (qt_version=get(kw,"qt",0)[1]!=v"4.8.5"))
print("\n If the code has a Segmentation fault error switch to qt v4.8.5 by pasting the following code into julia: \n \n")
print(add_backend_string(PyPlotBackend()))
end
end
end
# we don't want every command to update the figure
PyPlot.ioff()
end
# --------------------------------------------------------------------------------------
@@ -231,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")(
@@ -683,6 +677,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
end
z = transpose_z(series, z)
if st == :surface
clims = sp[:clims]
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
if series[:fill_z] != nothing
# the surface colors are different than z-value
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
@@ -706,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
@@ -779,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
@@ -873,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
@@ -927,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
@@ -955,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...)
@@ -1059,7 +1058,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
end
if sp[:grid]
fgcolor = py_color(sp[:foreground_color_grid])
pyaxis[:grid](true, color = fgcolor)
pyaxis[:grid](true, color = fgcolor, linestyle = ":")
ax[:set_axisbelow](true)
end
py_set_axis_colors(ax, axis)
@@ -1075,7 +1074,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
py_add_legend(plt, sp, ax)
# this sets the bg color inside the grid
ax[:set_axis_bgcolor](py_color(sp[:background_color_inside]))
ax[:set_facecolor](py_color(sp[:background_color_inside]))
end
py_drawfig(fig)
end
@@ -1107,7 +1106,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend})
# optionally add the width of colorbar labels and colorbar to rightpad
if haskey(sp.attr, :cbar_ax)
bb = py_bbox(sp.attr[:cbar_handle][:ax][:get_yticklabels]())
sp.attr[:cbar_width] = _cbar_width + width(bb) + 1mm + (sp[:colorbar_title] == "" ? 0px : 30px)
sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px)
rightpad = rightpad + sp.attr[:cbar_width]
end
@@ -1188,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]()
+1 -1
View File
@@ -23,7 +23,7 @@ function open_browser_window(filename::AbstractString)
@static if is_apple()
return run(`open $(filename)`)
end
@static if is_linux()
@static if is_linux() || is_bsd() # is_bsd() addition is as yet untested, but based on suggestion in https://github.com/JuliaPlots/Plots.jl/issues/681
return run(`xdg-open $(filename)`)
end
@static if is_windows()
+9 -9
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))
@@ -174,7 +174,7 @@ function center(shape::Shape)
Cx / 6A, Cy / 6A
end
function Base.scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
sx, sy = coords(shape)
cx, cy = c
for i=1:length(sx)
@@ -184,7 +184,7 @@ function Base.scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
shape
end
function Base.scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
function scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
shapecopy = deepcopy(shape)
scale!(shapecopy, x, y, c)
end
@@ -501,7 +501,7 @@ 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
@@ -521,7 +521,7 @@ Base.Array(surf::Surface) = surf.surf
for f in (:length, :size)
@eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...)
end
Base.copy(surf::Surface) = Surface{typeof(surf.surf)}(copy(surf.surf))
Base.copy(surf::Surface) = Surface(copy(surf.surf))
Base.eltype{T}(surf::Surface{T}) = eltype(T)
function expand_extrema!(a::Axis, surf::Surface)
@@ -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
@@ -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))
+28 -2
View File
@@ -115,7 +115,8 @@ 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))
@@ -300,7 +301,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)]
),
]
+1 -1
View File
@@ -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
+2 -2
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
@@ -318,7 +318,7 @@ function setup_atom()
# special handling for plotly... use PlotsDisplay
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyBackend})
display(Plots.PlotsDisplay(), plt)
s = "PlotPane turned off. The plotly and plotlyjs backends cannot render in the PlotPane due to javascript issues."
s = "PlotPane turned off. The plotly backend cannot render in the PlotPane due to javascript issues. Plotlyjs is similar to plotly and is compatible with the plot pane."
Media.render(pane, Atom.div(Atom.HTML(s)))
end
end
+9 -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,
@@ -277,6 +277,13 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
attr[Symbol(letter,k)] = v
end
end
for k in (:scale,), letter in (:x,:y,:z)
# Series recipes may need access to this information
lk = Symbol(letter,k)
if haskey(attr, lk)
kw[lk] = attr[lk]
end
end
end
sp_attrs[sp] = attr
end
@@ -357,7 +364,7 @@ function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol)
expand_extrema!(sp[:xaxis], (0,w))
expand_extrema!(sp[:yaxis], (0,h))
sp[:yaxis].d[:flip] = true
elseif !(st in (:pie, :histogram, :histogram2d))
elseif !(st in (:pie, :histogram, :bins2d, :histogram2d))
expand_extrema!(sp, d)
end
end
+194 -60
View File
@@ -225,7 +225,7 @@ 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)
@@ -323,10 +323,11 @@ end
# create a bar plot as a filled step function
@recipe function f(::Type{Val{:bar}}, x, y, z)
nx, ny = length(x), length(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=x]
x = if nx == ny
cv = [discrete_value!(axis, xi)[1] for xi=procx]
procx = if nx == ny
cv
elseif nx == ny + 1
0.5diff(cv) + cv[1:end-1]
@@ -337,9 +338,9 @@ end
# compute half-width of bars
bw = d[:bar_width]
hw = if bw == nothing
0.5mean(diff(x))
0.5ignoreNaN_mean(diff(procx))
else
Float64[0.5cycle(bw,i) for i=1:length(x)]
Float64[0.5cycle(bw,i) for i=1:length(procx)]
end
# make fillto a vector... default fills to 0
@@ -347,20 +348,25 @@ end
if fillto == nothing
fillto = 0
end
if (yscale in _logScales) && !all(_is_positive, fillto)
fillto = map(x -> _is_positive(x) ? typeof(baseline)(x) : baseline, fillto)
end
# create the bar shapes by adding x/y segments
xseg, yseg = Segments(), Segments()
for i=1:ny
center = x[i]
hwi = cycle(hw,i)
yi = y[i]
fi = cycle(fillto,i)
push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi)
push!(yseg, yi, fi, fi, yi, yi)
yi = procy[i]
if !isnan(yi)
center = procx[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)
@@ -384,9 +390,55 @@ end
_bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2
_is_positive(x) = (x > 0) && !(x 0)
_positive_else_nan{T}(::Type{T}, x::Real) = _is_positive(x) ? T(x) : T(NaN)
function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector, scale::Symbol)
if scale in _logScales
[_positive_else_nan(T, x) for x in V]
else
[T(x) for x in V]
end
end
function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol)
if (scale in _logScales)
!isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3)
else
zero(T)
end
end
function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol)
w_adj = _scale_adjusted_values(T, w, wscale)
w_min = ignoreNaN_minimum(w_adj)
w_max = ignoreNaN_maximum(w_adj)
baseline = _binbarlike_baseline(w_min, wscale)
w_adj, baseline
end
function _preprocess_barlike(d, x, y)
xscale = get(d, :xscale, :identity)
yscale = get(d, :yscale, :identity)
weights, baseline = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale)
x, weights, xscale, yscale, baseline
end
function _preprocess_binlike(d, x, y)
xscale = get(d, :xscale, :identity)
yscale = get(d, :yscale, :identity)
T = float(promote_type(eltype(x), eltype(y)))
edge = T.(x)
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 = x, y
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
if (d[:bar_width] == nothing)
bar_width := diff(edge)
end
@@ -395,11 +447,11 @@ _bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2
seriestype := :bar
()
end
@deps barbins bins
@deps barbins bar
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
edge, weights = x, y
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
xerror := diff(edge)/2
x := _bin_centers(edge)
y := weights
@@ -409,43 +461,65 @@ end
@deps scatterbins scatter
function _stepbins_path(edge, weights)
function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::Symbol)
log_scale_x = xscale in _logScales
log_scale_y = yscale in _logScales
nbins = length(linearindices(weights))
if length(linearindices(edge)) != nbins + 1
error("Edge vector must be 1 longer than weight vector")
end
x = eltype(edge)[]
y = eltype(weights)[]
it_e, it_w = start(edge), start(weights)
px, it_e = next(edge, it_e)
py = zero(eltype(weights))
a, it_e = next(edge, it_e)
last_w = eltype(weights)(NaN)
i = 1
while (!done(edge, it_e) && !done(edge, it_e))
b, it_e = next(edge, it_e)
w, it_w = next(weights, it_w)
npathpts = 2 * nbins + 2
x = Vector{eltype(px)}(npathpts)
y = Vector{eltype(py)}(npathpts)
if (log_scale_x && a 0)
a = b/_logScaleBases[xscale]^3
end
x[1], y[1] = px, py
i = 2
while (i < npathpts - 1)
py, it_w = next(weights, it_w)
x[i], y[i] = px, py
i += 1
px, it_e = next(edge, it_e)
x[i], y[i] = px, py
i += 1
if isnan(w)
if !isnan(last_w)
push!(x, a)
push!(y, baseline)
end
else
if isnan(last_w)
push!(x, a)
push!(y, baseline)
end
push!(x, a)
push!(y, w)
push!(x, b)
push!(y, w)
end
a = b
last_w = w
end
if (last_w != baseline)
push!(x, a)
push!(y, baseline)
end
assert(i == npathpts)
x[end], y[end] = px, zero(py)
(x, y)
end
@recipe function f(::Type{Val{:stepbins}}, x, y, z)
edge, weights = x, y
@recipe function f(::Type{Val{:stepbins}}, x, y, z)
axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis]
xpts, ypts = _stepbins_path(edge, weights)
if !Plots.isvertical(d)
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale)
if !isvertical(d)
xpts, ypts = ypts, xpts
end
@@ -453,7 +527,7 @@ end
if d[:markershape] != :none
@series begin
seriestype := :scatter
x := Plots._bin_centers(edge)
x := _bin_centers(edge)
y := weights
fillrange := nothing
label := ""
@@ -468,16 +542,15 @@ end
x := xpts
y := ypts
seriestype := :path
ylims --> [0, 1.1 * maximum(weights)]
()
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:
@@ -485,9 +558,11 @@ function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode
v = vs[dim]
if mode == :sqrt # Square-root choice
if mode == :auto
30
elseif mode == :sqrt # Square-root choice
_cl(sqrt(n))
elseif mode == :sturges || mode ==:auto # Sturges' formula
elseif mode == :sturges # Sturges' formula
_cl(log2(n)) + 1
elseif mode == :rice # Rice Rule
_cl(2 * n^(1/3))
@@ -497,7 +572,7 @@ function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode
_cl(_span(v) / (2 * _iqr(v) / n^(1/3)))
else
error("Unknown auto-binning mode $mode")
end
end::Int
end
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) = StatsBase.histrange(vs[dim], binning, :left)
@@ -511,13 +586,13 @@ _hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, Abs
map(dim -> _hist_edge(vs, dim, binning), (1:N...))
_hist_norm_mode(mode::Symbol) = mode
_hist_norm_mode(mode::Bool) = mode ? :norm : :none
_hist_norm_mode(mode::Bool) = mode ? :pdf : :none
function _make_hist{N}(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing)
edges = _hist_edges(vs, binning)
h = float( weights == nothing ?
StatsBase.fit(StatsBase.Histogram, vs, edges) :
StatsBase.fit(StatsBase.Histogram, vs, weights, edges)
StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) :
StatsBase.fit(StatsBase.Histogram, vs, weights, edges, closed = :left)
)
normalize!(h, mode = _hist_norm_mode(normed))
end
@@ -568,9 +643,10 @@ end
if d[:seriestype] == :scatterbins
# Workaround, error bars currently not set correctly by scatterbins
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights)
xerror --> diff(h.edges[1])/2
seriestype := :scatter
(Plots._bin_centers(h.edges[1]), h.weights)
(Plots._bin_centers(edge), weights)
else
(h.edges[1], h.weights)
end
@@ -843,7 +919,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)
@@ -900,6 +976,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
@@ -908,8 +987,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
@@ -923,6 +1002,7 @@ end
y := rs
z := nothing
seriestype := :scatter
grid --> false
()
end
@@ -930,7 +1010,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...)
@@ -939,16 +1019,70 @@ abline!(args...; kw...) = abline!(current(), args...; kw...)
# -------------------------------------------------
# Dates
@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int,dt), dt -> string(convert(Date,dt)))
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int,dt), dt -> string(convert(DateTime,dt)))
dateformatter(dt) = string(convert(Date, dt))
datetimeformatter(dt) = string(convert(DateTime, dt))
@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int, dt), dateformatter)
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int, dt), datetimeformatter)
# -------------------------------------------------
# Complex Numbers
@userplot ComplexPlot
@recipe function f(cp::ComplexPlot)
xguide --> "Real Part"
yguide --> "Imaginary Part"
seriestype --> :scatter
real(cp.args[1]), imag(cp.args[1])
@recipe function f{T<:Number}(A::Array{Complex{T}})
xguide --> "Re(x)"
yguide --> "Im(x)"
real.(A), imag.(A)
end
# Splits a complex matrix to its real and complex parts
# Reals defaults solid, imaginary defaults dashed
# Label defaults are changed to match the real-imaginary reference / indexing
@recipe function f{T<:Real,T2}(x::AbstractArray{T},y::Array{Complex{T2}})
ylabel --> "Re(y)"
zlabel --> "Im(y)"
x,real.(y),imag.(y)
end
# --------------------------------------------------
# Color Gradients
@userplot ShowLibrary
@recipe function f(cl::ShowLibrary)
if !(length(cl.args) == 1 && isa(cl.args[1], Symbol))
error("showlibrary takes the name of a color library as a Symbol")
end
library = PlotUtils.color_libraries[cl.args[1]]
z = sqrt.((1:15)*(1:20)')
seriestype := :heatmap
ticks := nothing
legend := false
layout --> length(library.lib)
i = 0
for grad in sort(collect(keys(library.lib)))
@series begin
seriescolor := cgrad(grad, cl.args[1])
title := string(grad)
subplot := i += 1
z
end
end
end
@userplot ShowGradient
@recipe function f(grad::ShowGradient)
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)')
seriestype := :heatmap
ticks := nothing
legend := false
seriescolor := grad.args[1]
title := string(grad.args[1])
z
end
+2 -1
View File
@@ -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
@@ -39,7 +39,7 @@ series_list(sp::Subplot) = sp.series_list # filter(series -> series.d[:subplot]
function should_add_to_legend(series::Series)
series.d[:primary] && series.d[:label] != "" &&
!(series.d[:seriestype] in (
:hexbin,:histogram2d,:hline,:vline,
:hexbin,:bins2d,:histogram2d,:hline,:vline,
:contour,:contourf,:contour3d,:surface,:wireframe,
:heatmap, :pie, :image
))
+4 -2
View File
@@ -2,7 +2,8 @@
function theme(s::Symbol; kw...)
# reset?
if s == :none || s == :default
PlotUtils._default_gradient[] = :inferno
PlotUtils.clibrary(:Plots)
PlotUtils.default_cgrad(default = :sequential, sequential = :inferno)
default(;
bg = :white,
bglegend = :match,
@@ -23,7 +24,8 @@ function theme(s::Symbol; kw...)
# update the default gradient and other defaults
thm = PlotThemes._themes[s]
if thm.gradient != nothing
PlotUtils._default_gradient[] = PlotThemes.gradient_name(s)
PlotUtils.clibrary(:misc)
PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s))
end
default(;
bg = thm.bg_secondary,
+4 -4
View File
@@ -2,9 +2,9 @@
# 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
@@ -62,7 +62,7 @@ Extrema() = Extrema(Inf, -Inf)
# -----------------------------------------------------------
typealias SubplotMap Dict{Any, Subplot}
const SubplotMap = Dict{Any, Subplot}
# -----------------------------------------------------------
+15 -15
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
@@ -283,9 +283,9 @@ 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
@@ -334,23 +334,23 @@ 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)
@@ -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
@@ -13,7 +13,7 @@ try
end
using Plots
# using Plots # reexported by StatPlots
using StatPlots
using FactCheck
using Glob
@@ -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.11.3"
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
+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
+59 -16
View File
@@ -19,31 +19,74 @@ img_eps = isinteractive() ? 1e-2 : 10e-2
# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], 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)
end
facts("GR") do
@fact gr() --> Plots.GRBackend()
@fact backend() --> Plots.GRBackend()
if is_linux() && isinteractive()
image_comparison_facts(:gr, skip=[2,25,30], eps=img_eps)
end
image_comparison_facts(:gr, 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)
facts("PyPlot") do
@fact pyplot() --> Plots.PyPlotBackend()
@fact backend() --> Plots.PyPlotBackend()
image_comparison_facts(:pyplot, eps=img_eps)
end
# The plotlyjs testimages return a connection error on travis:
# connect: connection refused (ECONNREFUSED)
# 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
# @fact immerse() --> Plots.ImmerseBackend()
# @fact backend() --> Plots.ImmerseBackend()
@@ -78,12 +121,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.clone("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)