Compare commits

..

197 Commits

Author SHA1 Message Date
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
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
Michael Krabbe Borregaard 34c0361d1a Merge pull request #707 from mkborregaard/new-histogram
fix uneven bins
2017-02-26 08:33:30 +01:00
Michael K. Borregaard 24c27737c1 fix uneven bins 2017-02-26 08:32:52 +01:00
MA Laforge b0dabaafe8 InspectDR: Reflect changes to support delta markers. 2017-02-25 11:33:24 -05:00
Tom Breloff 9472c0c5e5 skip pyplot image test 2017-02-24 15:19:41 -05:00
Tom Breloff 89fe3c9150 Merge remote-tracking branch 'origin/dev' 2017-02-24 11:02:50 -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
Tom Breloff aec08c74e0 Merge pull request #697 from lwabeke/add_clims_for_plotly
Attempt to add support for clims to plotly backend
2017-02-22 11:02:45 -05:00
Tom Breloff 48e8cb5eb1 Merge pull request #698 from joshday/jd_gr_label
Change GR label for scatterplot
2017-02-22 10:58:49 -05:00
Josh Day fd947ab887 only one, smaller gr marker 2017-02-22 10:40:16 -05:00
Leon Wabeke 5395b41852 Attempt to add support for clims to plotly backend
Added support for clims, seems to work on heatmap, surface and contour.
On surface zlims be still be set to be different from clims.
2017-02-22 15:57:41 +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
Tom Breloff bdc815066e Merge remote-tracking branch 'origin/dev' 2017-02-21 12:12:35 -05:00
Tom Breloff 44f4f22fdd Merge pull request #683 from sebastianpech/master
Fix halign for annotations in pgfplots backend
2017-02-14 15:11:28 -05:00
Sebastian Pech 5ae2044d02 Fix halign for annotations in pgfplots backend
PGFPlot uses inverted right and left parameters.
2017-02-14 21:04:13 +01:00
Tom Breloff 5e80a05f32 Merge pull request #679 from jheinen/dev
gr: added support for hexbin plots
2017-02-14 14:20:27 -05:00
Josef Heinen eb7534d319 gr: corrected alignment of rotated axes labels 2017-02-14 09:55:46 +01:00
Josef Heinen 471b09bd6c gr: added support for hexbin plots 2017-02-10 11:24:48 +01:00
Tom Breloff a4549cbfa2 Merge pull request #674 from mkborregaard/better-docs
WIP: lookup attributes at the console
2017-02-09 09:09:18 -05:00
Michael K. Borregaard d663267cde improved println call 2017-02-09 11:12:46 +01:00
Michael K. Borregaard 35a56962fc more concise output 2017-02-09 10:40:08 +01:00
Michael K. Borregaard 82161e60bc removed unnecessary Plots qualifier 2017-02-09 00:12:16 +01:00
Michael K. Borregaard 51a47cb2b1 Added basic support for searching attributes at the console 2017-02-08 23:51:15 +01:00
Michael K. Borregaard 9804debe86 Merge remote-tracking branch 'JuliaPlots/master' 2017-02-08 17:22:33 +01:00
SimonDanisch c93e2b80ca fixes for GLVisualize 2017-02-07 18:28:22 -05:00
Tom Breloff 1555876280 Merge pull request #669 from YongHee-Kim/master
enable standalone window for plotlyjs() backend
2017-02-06 09:40:43 -05:00
Tom Breloff 1d08e6619b Merge pull request #668 from ma-laforge/inspectdr
Make compatible with InspectDR v0.1.4.
2017-02-06 09:10:27 -05:00
YongHee Kim 0880487be2 enable standalone window for plotlyjs() backen 2017-02-06 21:29:41 +09:00
Tom Breloff 2ac4ffc576 Merge pull request #663 from fuzzybear3965/master
path spaces fix stolen from http://stackoverflow.com/a/13692919
2017-02-03 10:24:36 -05:00
Tom Breloff 7b2a0a92c4 Merge pull request #667 from sebastianpech/master
Fix/Extend pgfplots functions
2017-02-03 10:23:02 -05:00
Sebastian Pech d883274586 Fix comments 2017-02-03 08:25:55 +01:00
Sebastian Pech 803de95367 Merge branch 'master' of https://github.com/JuliaPlots/Plots.jl 2017-02-03 08:22:23 +01:00
MA Laforge 3ca39728d8 Make compatible with InspectDR v0.1.4. 2017-02-02 20:38:34 -05:00
Sebastian Pech 1111000217 Add support for ticks rotation 2017-02-02 17:39:34 +01:00
Sebastian Pech dd505fedcc Add support for polar axis 2017-02-02 16:43:30 +01:00
Sebastian Pech 48ff2fb8b8 Merge branch 'master' of https://github.com/JuliaPlots/Plots.jl 2017-02-02 16:06:59 +01:00
Sebastian Pech d5eafad48e Add annotations and series_annotations to pgfplots 2017-02-02 16:05:17 +01:00
John Rinehart 2e1c86c0c7 path spaces fix stolen from http://stackoverflow.com/a/13692919
Spaces in Windows paths resulted in improper DOS command. Fix designed
according to the above-referenced StackOverflow post.
2017-01-31 23:57:29 -05:00
Tom Breloff c728bf52b8 Merge pull request #662 from ma-laforge/inspectdr
Fix inversion in padding.
2017-01-28 11:55:11 -05:00
MA Laforge 95a26f5080 Fix inversion in padding. 2017-01-28 11:47:10 -05:00
Sebastian Pech 85eaef6aa9 Merge branch 'master' of https://github.com/JuliaPlots/Plots.jl 2017-01-26 15:19:57 +01:00
Tom Breloff dee160f2b8 Merge pull request #656 from ma-laforge/inspectdr
Add support for layout & plot size.
2017-01-25 11:47:58 -05:00
Tom Breloff 6d38e52321 Merge pull request #659 from ma-laforge/pyplot_qtinit
Fix exception calling backend() in _initialize_backend().
2017-01-25 11:47:31 -05:00
MA Laforge caed94328f Fix exception calling backend() in _initialize_backend(). 2017-01-25 11:40:47 -05:00
MA Laforge ebf92d3033 Add support for layout & plot size.
Also:
Add basic support for polar plots.
Add support for plot title & background color of entire figure.
2017-01-23 21:25:55 -05:00
SimonDanisch fdadfa3a80 small changes 2017-01-24 02:42:20 +01:00
Sebastian Pech f8b84185ac Add rounding and obtain plot height from layout bbox 2017-01-23 14:28:26 +01:00
Sebastian Pech caf86686dd Fix yshift of subplots.
Calculation of coordinate transformation from bb to pgf did not consider the
height of the plot.
2017-01-23 13:56:40 +01:00
Sebastian Pech bcd5d9ef90 Fix issue where every series is plotted with a fillcolor 2017-01-22 16:57:28 +01:00
SimonDanisch 45b5922d01 dont rely on postempty, img transpose not necessary anymore 2017-01-20 19:07:20 +01:00
Sebastian Pech 1a91eacdcb Enable histogram plotting in pgfplot 2017-01-20 15:26:54 +01:00
Tom Breloff 0421fe9a82 Merge pull request #651 from huckl3b3rry87/pull-request/43a21364
Pull request/43a21364
2017-01-19 22:02:55 -05:00
Huckleberry Febbo 43a213643b changed code so it does not automatically change qt version 2017-01-19 18:04:09 -05:00
Huckleberry Febbo cd8939fe0b finished fixing segfault issue when qt>v4.8.5 on Ubuntu using pyplot 2017-01-19 17:32:37 -05:00
Huckleberry Febbo c250d7c073 working on fixing pyplot issue for ubuntu 2017-01-19 14:45:16 -05:00
Tom Breloff 3b570edea1 added back precompilation 2017-01-13 09:33:02 -05:00
Tom Breloff 199a3306db fix support for fill_z in pyplot 2017-01-11 10:37:54 -05:00
Tom Breloff 3236e06fb9 wrap_surfaces for 3 matrices 2017-01-10 11:35:57 -05:00
Tom Breloff 492618ae67 Merge pull request #641 from tbreloff/surfacecolor
Add fill_z attribute and plotly impl
2017-01-09 16:17:49 -05:00
Naoki Saito c5737db4f5 Add fill_z attribute and plotly impl 2017-01-09 16:03:14 -05:00
Tom Breloff 40b49b9873 Merge pull request #631 from ma-laforge/inspectdr
Inspectdr
2017-01-09 15:18:04 -05:00
MA Laforge 1fa34574e8 More fixes requested by Tom:
Add add_backend_string().
Remove un-necessary test: true == plt[:show].
2017-01-09 15:14:39 -05:00
Michael K. Borregaard 4c2db68037 Merge remote-tracking branch 'tbreloff/master' 2017-01-09 11:42:33 -07:00
Tom Breloff 1c522159df Merge remote-tracking branch 'origin/master' into dev 2017-01-09 13:22:07 -05:00
Tom Breloff 967dca7912 Merge remote-tracking branch 'origin/dev' into dev 2017-01-09 13:20:18 -05:00
Tom Breloff 7d66c502f4 support tex in pgfplots; closes #637 2017-01-09 13:19:37 -05:00
Tom Breloff 9b9e2fe6cd Merge pull request #636 from jheinen/dev
gr: use GKSwstype environment (required for QML)
2017-01-09 12:07:09 -05:00
Tom Breloff 47ee0a4c97 Merge pull request #633 from tbreloff/dev
fix arrays of funcs; closes #632
2017-01-09 12:06:45 -05:00
Tom Breloff f10bda463c Merge pull request #635 from anowacki/nowacki/default-font-family
Use `sans-serif` as default font family (fix #593)
2017-01-09 12:05:53 -05:00
Josef Heinen 72d336265b gr: use GKSwstype environment (required for QML) 2017-01-06 19:48:41 +01:00
Andy Nowacki a087a6694b Use sans-serif as default font family (fix #593)
Rather than specifying a specific typeface, set the font
*family* in the `family` field of `Font` as `sans-serif`
by default.

Fixes #593.
2017-01-06 16:45:40 +00:00
Michael K. Borregaard 5eaf6b2adc Merge remote-tracking branch 'tbreloff/master' 2017-01-06 14:50:11 +01:00
Thomas Breloff 57840a37d0 fix for func assert 2017-01-05 15:44:56 -07:00
Thomas Breloff aedcb372f6 forgot utils.jl 2017-01-05 15:30:34 -07:00
Thomas Breloff 7f554d3c84 fix arrays of funcs; closes #632 2017-01-05 15:25:08 -07:00
MA Laforge edf1daa7d7 Improve gui handling & remove global state.
Also:
Add AVec support for colors.
Move init code back to _initialize_backend.
2017-01-05 14:39:50 -05:00
Thomas Breloff f554bf925e try catch for func recipe, move adapted_grid to f,xmin,xmax recipe; closes #610; closes #621 2017-01-05 10:18:47 -07:00
Tom Breloff 9676309ba2 Merge pull request #623 from KristofferC/kc/plot_adapt
use adapted_grid from PlotUtilities for single functions
2017-01-05 09:56:37 -07:00
MA Laforge c78444fc24 Improve support for Shapes, markers & colors.
Details:
Control font & background color.
Support arbitrary marker shapes.
Support more pre-defined markers.
Support Shapes in plots.
Support ln-plots.

Also:
Fix ncolumns.
Update supported section.
2017-01-04 17:41:05 -05:00
Michael K. Borregaard 4ab51d4bfa Merge remote-tracking branch 'tbreloff/master' 2017-01-02 10:16:07 +01:00
MA Laforge e381c13dc6 Initial support for InspectDR. 2016-12-31 15:41:11 -05:00
Kristoffer Carlsson ec31898f25 use adapted_grid from PlotUtilities for single functions 2016-12-25 00:38:58 +01:00
Tom Breloff a88d78a2e9 Merge pull request #604 from pabloferz/pz/plotlyjs
Proper "id" synchronization of plotlyjs plots
2016-12-24 19:05:44 +01:00
Tom Breloff 92430afba9 Merge pull request #618 from ChrisRackauckas/patch-2
Fix precompile disable
2016-12-24 19:04:38 +01:00
Christopher Rackauckas 8f60a4df8d Fix precompile disable 2016-12-19 14:49:44 -08:00
Michael K. Borregaard 08c9e627ab Merge remote-tracking branch 'tbreloff/master' 2016-12-16 10:10:39 +01:00
Pablo Zubieta 46ad076751 Proper id synchronization of plotlyjs plots 2016-12-10 23:49:17 -06:00
28 changed files with 1354 additions and 199 deletions
+36 -3
View File
@@ -3,14 +3,47 @@
#### 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.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
+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) -->
+1
View File
@@ -7,3 +7,4 @@ Reexport
FixedSizeArrays
Measures
Showoff
StatsBase 0.14.0
+9 -1
View File
@@ -1,3 +1,4 @@
__precompile__(true)
module Plots
@@ -8,6 +9,7 @@ using Base.Meta
@reexport using PlotUtils
@reexport using PlotThemes
import Showoff
import StatsBase
export
grid,
@@ -98,7 +100,9 @@ export
center,
P2,
P3,
BezierCurve
BezierCurve,
plotattr
# ---------------------------------------------------------
@@ -126,6 +130,7 @@ include("animation.jl")
include("output.jl")
include("examples.jl")
include("arg_desc.jl")
include("plotattr.jl")
# ---------------------------------------------------------
@@ -144,6 +149,9 @@ end
@shorthands bar
@shorthands barh
@shorthands histogram
@shorthands barhist
@shorthands stephist
@shorthands scatterhist
@shorthands histogram2d
@shorthands density
@shorthands heatmap
+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 number of bins, or the edges, of the histogram, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd)",
: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",
@@ -29,6 +29,7 @@ const _arg_desc = KW(
:z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.",
:marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.",
:line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).",
:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.",
:levels => "Integer, NTuple{2,Integer}. Number of levels (or x-levels/y-levels) for a contour type.",
:orientation => "Symbol. Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).",
:bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)",
@@ -39,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`.",
+12 -5
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, :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,
@@ -188,6 +193,7 @@ const _series_defaults = KW(
:z => nothing, # depth for contour, surface, etc
:marker_z => nothing, # value for color scale
:line_z => nothing,
:fill_z => nothing,
:levels => 15,
:orientation => :vertical,
:bar_position => :overlay, # for bar plots and histograms: could also be stack (stack up) or dodge (side by side)
@@ -431,6 +437,7 @@ add_aliases(:zguide, :zlabel, :zlab, :zl)
add_aliases(:zlims, :zlim, :zlimit, :zlimits)
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(:colorbar, :cb, :cbar, :colorkey)
add_aliases(:clims, :clim, :cbarlims, :cbar_lims, :climits, :color_limits)
@@ -443,7 +450,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)
@@ -1258,7 +1265,7 @@ function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
end
# scatter plots don't have a line, but must have a shape
if d[:seriestype] in (:scatter, :scatter3d)
if d[:seriestype] in (:scatter, :scatterbins, :scatterhist, :scatter3d)
d[:linewidth] = 0
if d[:markershape] == :none
d[:markershape] = :circle
+25 -1
View File
@@ -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(
@@ -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
+1
View File
@@ -276,6 +276,7 @@ end
@init_backend GR
@init_backend GLVisualize
@init_backend PGFPlots
@init_backend InspectDR
# ---------------------------------------------------------
+13 -14
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([
@@ -134,11 +133,6 @@ function empty_screen!(screen)
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,19 +149,20 @@ 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)
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(
@@ -183,7 +178,7 @@ function create_window(plt::Plot{GLVisualizeBackend}, visible)
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)
@@ -1141,8 +1136,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)
@@ -1182,7 +1176,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
if _3d
GLAbstraction.center!(sp_screen)
end
Reactive.post_empty()
GLAbstraction.post_empty()
yield()
end
end
@@ -1422,6 +1416,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 +1432,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
+25 -16
View File
@@ -172,6 +172,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 +184,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])
@@ -283,7 +287,8 @@ 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 +335,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
@@ -421,7 +427,7 @@ 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
@@ -545,6 +551,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
@@ -653,6 +663,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
flip = sp[:yaxis][:flip]
mirror = sp[:xaxis][:mirror]
gr_set_font(sp[:xaxis][:tickfont],
halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2],
valign = (mirror ? :bottom : :top),
color = sp[:xaxis][:foreground_color_axis],
rotation = sp[:xaxis][:rotation])
@@ -670,6 +681,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
mirror = sp[:yaxis][:mirror]
gr_set_font(sp[:yaxis][:tickfont],
halign = (mirror ? :left : :right),
valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2],
color = sp[:yaxis][:foreground_color_axis],
rotation = sp[:yaxis][:rotation])
for (cv, dv) in zip(yticks...)
@@ -757,10 +769,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
@@ -805,12 +813,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
@@ -848,6 +856,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 +
@@ -942,7 +951,7 @@ 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)
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)
@@ -1015,7 +1024,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if series[:markershape] != :none
gr_draw_markers(series, xpos-[0.06,0.02], [ypos,ypos], 10, nothing)
gr_draw_markers(series, xpos - .035, ypos, 6, nothing)
end
if typeof(series[:label]) <: Array
@@ -1077,14 +1086,14 @@ else
"use_default"
end
const _gr_wstype = Ref(get(ENV, "GKS_WSTYPE", _gr_wstype_default))
const _gr_wstype = Ref(get(ENV, "GKSwstype", _gr_wstype_default))
gr_set_output(wstype::String) = (_gr_wstype[] = wstype)
for (mime, fmt) in _gr_mimeformats
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GRBackend})
GR.emergencyclosegks()
filepath = tempname() * "." * $fmt
ENV["GKS_WSTYPE"] = $fmt
ENV["GKSwstype"] = $fmt
ENV["GKS_FILEPATH"] = filepath
gr_display(plt)
GR.emergencyclosegks()
@@ -1097,17 +1106,17 @@ function _display(plt::Plot{GRBackend})
if plt[:display_type] == :inline
GR.emergencyclosegks()
filepath = tempname() * ".pdf"
ENV["GKS_WSTYPE"] = "pdf"
ENV["GKSwstype"] = "pdf"
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
ENV["GKS_DOUBLE_BUF"] = true
if _gr_wstype[] != "use_default"
ENV["GKS_WSTYPE"] = _gr_wstype[]
ENV["GKSwstype"] = _gr_wstype[]
end
gr_display(plt)
end
+529
View File
@@ -0,0 +1,529 @@
# https://github.com/ma-laforge/InspectDR.jl
#=TODO:
Tweak scale factor for width & other sizes
Not supported by InspectDR:
:foreground_color_grid
:foreground_color_border
:polar,
Add in functionality to Plots.jl:
:aspect_ratio,
=#
# ---------------------------------------------------------------------------
#TODO: remove features
const _inspectdr_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,
:markerstrokestyle, #Causes warning not to have it... what is this?
:fillcolor, :fillalpha, #:fillrange,
# :bins, :bar_width, :bar_edges, :bar_position,
:title, :title_location, :titlefont,
:window_title,
:guide, :lims, :scale, #:ticks, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, #:colorbar,
# :marker_z,
# :line_z,
# :levels,
# :ribbon, :quiver, :arrow,
# :orientation,
:overwrite_figure,
:polar,
# :normalize, :weights,
# :contours, :aspect_ratio,
:match_dimensions,
# :clims,
# :inset_subplots,
:dpi,
# :colorbar_title,
])
const _inspectdr_style = [:auto, :solid, :dash, :dot, :dashdot]
const _inspectdr_seriestype = [
:path, :scatter, :shape #, :steppre, :steppost
]
#see: _allMarkers, _shape_keys
const _inspectdr_marker = Symbol[
:none, :auto,
:circle, :rect, :diamond,
:cross, :xcross,
:utriangle, :dtriangle, :rtriangle, :ltriangle,
:pentagon, :hexagon, :heptagon, :octagon,
:star4, :star5, :star6, :star7, :star8,
:vline, :hline, :+, :x,
]
const _inspectdr_scale = [:identity, :ln, :log2, :log10]
is_marker_supported(::InspectDRBackend, shape::Shape) = true
_inspectdr_to_pixels(bb::BoundingBox) =
InspectDR.BoundingBox(to_pixels(left(bb)), to_pixels(right(bb)), to_pixels(top(bb)), to_pixels(bottom(bb)))
#Do we avoid Map to avoid possible pre-comile issues?
function _inspectdr_mapglyph(s::Symbol)
s == :rect && return :square
return s
end
function _inspectdr_mapglyph(s::Shape)
x, y = coords(s)
return InspectDR.GlyphPolyline(x, y)
end
# py_marker(markers::AVec) = map(py_marker, markers)
function _inspectdr_mapglyph(markers::AVec)
warn("Vectors of markers are currently unsupported in InspectDR.")
_inspectdr_mapglyph(markers[1])
end
_inspectdr_mapglyphsize(v::Real) = v
function _inspectdr_mapglyphsize(v::Vector)
warn("Vectors of marker sizes are currently unsupported in InspectDR.")
_inspectdr_mapglyphsize(v[1])
end
_inspectdr_mapcolor(v::Colorant) = v
function _inspectdr_mapcolor(g::PlotUtils.ColorGradient)
warn("Color gradients are currently unsupported in InspectDR.")
#Pick middle color:
_inspectdr_mapcolor(g.colors[div(1+end,2)])
end
function _inspectdr_mapcolor(v::AVec)
warn("Vectors of colors are currently unsupported in InspectDR.")
#Pick middle color:
_inspectdr_mapcolor(v[div(1+end,2)])
end
#Hack: suggested point size does not seem adequate relative to plot size, for some reason.
_inspectdr_mapptsize(v) = 1.5*v
function _inspectdr_add_annotations(plot, x, y, val)
#What kind of annotation is this?
end
#plot::InspectDR.Plot2D
function _inspectdr_add_annotations(plot, x, y, val::PlotText)
vmap = Dict{Symbol, Symbol}(:top=>:t, :bottom=>:b) #:vcenter
hmap = Dict{Symbol, Symbol}(:left=>:l, :right=>:r) #:hcenter
align = Symbol(get(vmap, val.font.valign, :c), get(hmap, val.font.halign, :c))
fnt = InspectDR.Font(val.font.family, val.font.pointsize,
color =_inspectdr_mapcolor(val.font.color)
)
ann = InspectDR.atext(val.str, x=x, y=y,
font=fnt, angle=val.font.rotation, align=align
)
InspectDR.add(plot, ann)
return
end
# ---------------------------------------------------------------------------
function _inspectdr_getscale(s::Symbol, yaxis::Bool)
#TODO: Support :asinh, :sqrt
kwargs = yaxis? (:tgtmajor=>8, :tgtminor=>2): () #More grid lines on y-axis
if :log2 == s
return InspectDR.AxisScale(:log2; kwargs...)
elseif :log10 == s
return InspectDR.AxisScale(:log10; kwargs...)
elseif :ln == s
return InspectDR.AxisScale(:ln; kwargs...)
else #identity
return InspectDR.AxisScale(:lin; kwargs...)
end
end
# ---------------------------------------------------------------------------
function add_backend_string(::InspectDRBackend)
"""
if !Plots.is_installed("InspectDR")
Pkg.add("InspectDR")
end
"""
end
function _initialize_backend(::InspectDRBackend; kw...)
@eval begin
import InspectDR
export InspectDR
#Glyph used when plotting "Shape"s:
const INSPECTDR_GLYPH_SHAPE = InspectDR.GlyphPolyline(
2*InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y
)
type InspecDRPlotRef
mplot::Union{Void, InspectDR.Multiplot}
gui::Union{Void, InspectDR.GtkPlot}
end
_inspectdr_getmplot(::Any) = nothing
_inspectdr_getmplot(r::InspecDRPlotRef) = r.mplot
_inspectdr_getgui(::Any) = nothing
_inspectdr_getgui(gplot::InspectDR.GtkPlot) = (gplot.destroyed? nothing: gplot)
_inspectdr_getgui(r::InspecDRPlotRef) = _inspectdr_getgui(r.gui)
end
end
# ---------------------------------------------------------------------------
# Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o)
gplot = _inspectdr_getgui(plt.o)
#:overwrite_figure: want to reuse current figure
if plt[:overwrite_figure] && mplot != nothing
mplot.subplots = [] #Reset
if gplot != nothing #Ensure still references current plot
gplot.src = mplot
end
else #want new one:
mplot = InspectDR.Multiplot()
gplot = nothing #Will be created later
end
#break link with old subplots
for sp in plt.subplots
sp.o = nothing
end
return InspecDRPlotRef(mplot, gplot)
end
# ---------------------------------------------------------------------------
# # this is called early in the pipeline, use it to make the plot current or something
# function _prepare_plot_object(plt::Plot{InspectDRBackend})
# 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.userannot = [] #Clear old markers/text annotation/polyline "annotation"
return plot
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{InspectDRBackend}, series::Series)
st = series[:seriestype]
sp = series[:subplot]
plot = sp.o
#Don't do anything without a "subplot" object: Will process later.
if nothing == plot; return; end
_vectorize(v) = isa(v, Vector)? v: collect(v) #InspectDR only supports vectors
x = _vectorize(series[:x]); y = _vectorize(series[:y])
#No support for polar grid... but can still perform polar transformation:
if ispolar(sp)
Θ = x; r = y
x = r.*cos(Θ); y = r.*sin(Θ)
end
# doesn't handle mismatched x/y - wrap data (pyplot behaviour):
nx = length(x); ny = length(y)
if nx < ny
series[:x] = Float64[x[mod1(i,nx)] for i=1:ny]
elseif ny > nx
series[:y] = Float64[y[mod1(i,ny)] for i=1:nx]
end
#= TODO: Eventually support
series[:fillcolor] #I think this is fill under line
zorder = series[:series_plotindex]
For st in :shape:
zorder = series[:series_plotindex],
=#
if st in (:shape,)
nmax = 0
for (i,rng) in enumerate(iter_segments(x, y))
nmax = i
if length(rng) > 1
linewidth = series[:linewidth]
linecolor = _inspectdr_mapcolor(cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(cycle(series[:fillcolor], i))
line = InspectDR.line(
style=:solid, width=linewidth, color=linecolor
)
apline = InspectDR.PolylineAnnotation(
x[rng], y[rng], line=line, fillcolor=fillcolor
)
InspectDR.add(plot, apline)
end
end
i = (nmax >= 2? div(nmax, 2): nmax) #Must pick one set of colors for legend
if i > 1 #Add dummy waveform for legend entry:
linewidth = series[:linewidth]
linecolor = _inspectdr_mapcolor(cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(cycle(series[:fillcolor], i))
wfrm = InspectDR.add(plot, Float64[], Float64[], id=series[:label])
wfrm.line = InspectDR.line(
style=:none, width=linewidth, #linewidth affects glyph
)
wfrm.glyph = InspectDR.glyph(
shape = INSPECTDR_GLYPH_SHAPE, size = 8,
color = linecolor, fillcolor = fillcolor
)
end
elseif st in (:path, :scatter) #, :steppre, :steppost)
#NOTE: In Plots.jl, :scatter plots have 0-linewidths (I think).
linewidth = series[:linewidth]
#More efficient & allows some support for markerstrokewidth:
_style = (0==linewidth? :none: series[:linestyle])
wfrm = InspectDR.add(plot, x, y, id=series[:label])
wfrm.line = InspectDR.line(
style = _style,
width = series[:linewidth],
color = series[:linecolor],
)
#InspectDR does not control markerstrokewidth independently.
if :none == _style
#Use this property only if no line is displayed:
wfrm.line.width = series[:markerstrokewidth]
end
wfrm.glyph = InspectDR.glyph(
shape = _inspectdr_mapglyph(series[:markershape]),
size = _inspectdr_mapglyphsize(series[:markersize]),
color = _inspectdr_mapcolor(series[:markerstrokecolor]),
fillcolor = _inspectdr_mapcolor(series[:markercolor]),
)
end
# this is all we need to add the series_annotations text
anns = series[:series_annotations]
for (xi,yi,str,fnt) in EachAnn(anns, x, y)
_inspectdr_add_annotations(plot, xi, yi, PlotText(str, fnt))
end
return
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{InspectDRBackend}, series::Series)
#Nothing to do
end
# ---------------------------------------------------------------------------
function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
const gridon = InspectDR.GridRect(vmajor=true, hmajor=true)
const gridoff = InspectDR.GridRect()
const plot = sp.o
const strip = plot.strips[1] #Only 1 strip supported with Plots.jl
#No independent control of grid???
strip.grid = sp[:grid]? gridon: gridoff
xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
plot.xscale = _inspectdr_getscale(xaxis[:scale], false)
strip.yscale = _inspectdr_getscale(yaxis[:scale], true)
xmin, xmax = axis_limits(xaxis)
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))
xmin, xmax = -rmax, rmax
ymin, ymax = -rmax, rmax
end
plot.xext = InspectDR.PExtents1D() #reset
strip.yext = InspectDR.PExtents1D() #reset
plot.xext_full = InspectDR.PExtents1D(xmin, xmax)
strip.yext_full = InspectDR.PExtents1D(ymin, ymax)
a = plot.annotation
a.title = sp[:title]
a.xlabel = xaxis[:guide]; a.ylabels = [yaxis[:guide]]
l = plot.layout
l.frame.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot])
l.framedata.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
l.framedata.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
l.fnttitle = InspectDR.Font(sp[:titlefont].family,
_inspectdr_mapptsize(sp[:titlefont].pointsize),
color = _inspectdr_mapcolor(sp[:foreground_color_title])
)
#Cannot independently control fonts of axes with InspectDR:
l.fntaxlabel = InspectDR.Font(xaxis[:guidefont].family,
_inspectdr_mapptsize(xaxis[:guidefont].pointsize),
color = _inspectdr_mapcolor(xaxis[:foreground_color_guide])
)
l.fntticklabel = InspectDR.Font(xaxis[:tickfont].family,
_inspectdr_mapptsize(xaxis[:tickfont].pointsize),
color = _inspectdr_mapcolor(xaxis[:foreground_color_text])
)
leg = l.legend
leg.enabled = (sp[:legend] != :none)
#leg.width = 150 #TODO: compute???
leg.font = InspectDR.Font(sp[:legendfont].family,
_inspectdr_mapptsize(sp[:legendfont].pointsize),
color = _inspectdr_mapcolor(sp[:foreground_color_legend])
)
leg.frame.fillcolor = _inspectdr_mapcolor(sp[:background_color_legend])
end
# called just before updating layout bounding boxes... in case you need to prep
# for the calcs
function _before_layout_calcs(plt::Plot{InspectDRBackend})
const mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end
mplot.title = plt[:plot_title]
if "" == mplot.title
#Don't use window_title... probably not what you want.
#mplot.title = plt[:window_title]
end
mplot.frame.fillcolor = _inspectdr_mapcolor(plt[:background_color_outside])
resize!(mplot.subplots, length(plt.subplots))
nsubplots = length(plt.subplots)
for (i, sp) in enumerate(plt.subplots)
if !isassigned(mplot.subplots, i)
mplot.subplots[i] = InspectDR.Plot2D()
end
sp.o = mplot.subplots[i]
plot = sp.o
_initialize_subplot(plt, sp)
_inspectdr_setupsubplot(sp)
# add the annotations
for ann in sp[:annotations]
_inspectdr_add_annotations(plot, ann...)
end
end
#Do not yet support absolute plot positionning.
#Just try to make things look more-or less ok:
if nsubplots <= 1
mplot.ncolumns = 1
elseif nsubplots <= 4
mplot.ncolumns = 2
elseif nsubplots <= 6
mplot.ncolumns = 3
elseif nsubplots <= 12
mplot.ncolumns = 4
else
mplot.ncolumns = 5
end
for series in plt.series_list
_series_added(plt, series)
end
return
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{InspectDRBackend})
plot = sp.o
if !isa(plot, InspectDR.Plot2D); return sp.minpad; end
#Computing plotbounds with 0-BoundingBox returns required padding:
bb = InspectDR.plotbounds(plot.layout, InspectDR.BoundingBox(0,0,0,0))
#NOTE: plotbounds always pads for titles, legends, etc. even if not in use.
#TODO: possibly zero-out items not in use??
# add in the user-specified margin to InspectDR padding:
leftpad = abs(bb.xmin)*px + sp[:left_margin]
toppad = abs(bb.ymin)*px + sp[:top_margin]
rightpad = abs(bb.xmax)*px + sp[:right_margin]
bottompad = abs(bb.ymax)*px + sp[:bottom_margin]
sp.minpad = (leftpad, toppad, rightpad, bottompad)
end
# ----------------------------------------------------------------
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations])
function _update_plot_object(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end
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
gplot.src = mplot #Ensure still references current plot
InspectDR.refresh(gplot)
return
end
# ----------------------------------------------------------------
const _inspectdr_mimeformats_dpi = Dict(
"image/png" => "png"
)
const _inspectdr_mimeformats_nodpi = Dict(
"image/svg+xml" => "svg",
"application/eps" => "eps",
"image/eps" => "eps",
# "application/postscript" => "ps", #TODO: support once Cairo supports PSSurface
"application/pdf" => "pdf"
)
_inspectdr_show(io::IO, mime::MIME, ::Void, w, h) =
throw(ErrorException("Cannot show(::IO, ...) plot - not yet generated"))
function _inspectdr_show(io::IO, mime::MIME, mplot, w, h)
InspectDR._show(io, mime, mplot, Float64(w), Float64(h))
end
for (mime, fmt) in _inspectdr_mimeformats_dpi
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
dpi = plt[:dpi]#TODO: support
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o), plt[:size]...)
end
end
for (mime, fmt) in _inspectdr_mimeformats_nodpi
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o), plt[:size]...)
end
end
_show(io::IO, mime::MIME"text/plain", plt::Plot{InspectDRBackend}) = nothing #Don't show
# ----------------------------------------------------------------
# Display/show the plot (open a GUI window, or browser page, for example).
function _display(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end
gplot = _inspectdr_getgui(plt.o)
if nothing == gplot
gplot = display(InspectDR.GtkDisplay(), mplot)
else
#redundant... Plots.jl will call _update_plot_object:
#InspectDR.refresh(gplot)
end
plt.o = InspecDRPlotRef(mplot, gplot)
return gplot
end
+108 -13
View File
@@ -3,7 +3,7 @@
# significant contributions by: @pkofod
const _pgfplots_attr = merge_with_base_supported([
# :annotations,
:annotations,
# :background_color_legend,
:background_color_inside,
# :background_color_outside,
@@ -22,17 +22,17 @@ 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,
# :polar,
:polar,
# :normalize, :weights, :contours,
:aspect_ratio,
# :match_dimensions,
])
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour]
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape]
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon] #vcat(_allMarkers, Shape)
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
@@ -98,14 +98,35 @@ 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",
:right => "left"
)
# --------------------------------------------------------------------------------------
# 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"
@@ -136,6 +157,19 @@ function pgf_marker(d::KW)
}"""
end
function pgf_add_annotation!(o,x,y,val)
# Construct the style string.
# Currently supports color and orientation
cstr,a = pgf_color(val.font.color)
push!(o, PGFPlots.Plots.Node(val.str, # Annotation Text
x, y,
style="""
$(get(_pgf_annotation_halign,val.font.halign,"")),
color=$cstr, draw opacity=$(convert(Float16,a)),
rotate=$(val.font.rotation)
"""))
end
# --------------------------------------------------------------------------------------
function pgf_series(sp::Subplot, series::Series)
@@ -143,11 +177,10 @@ function pgf_series(sp::Subplot, series::Series)
st = d[:seriestype]
style = []
kw = KW()
push!(style, pgf_linestyle(d))
push!(style, pgf_marker(d))
if d[:fillrange] != nothing
if d[:fillrange] != nothing || st in (:shape,)
push!(style, pgf_fillstyle(d))
end
@@ -163,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
@@ -211,6 +248,9 @@ function pgf_axis(sp::Subplot, letter)
# axis guide
kw[Symbol(letter,:label)] = axis[:guide]
# Add ticklabel rotations
push!(style, "$(letter)ticklabel style={rotate = $(axis[:rotation])}")
# flip/reverse?
axis[:flip] && push!(style, "$letter dir=reverse")
@@ -249,8 +289,12 @@ end
function _update_plot_object(plt::Plot{PGFPlotsBackend})
plt.o = PGFPlots.Axis[]
# 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
# first build the PGFPlots.Axis object
style = ["unbounded coords=jump"]
kw = KW()
@@ -265,10 +309,12 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
# bounding box values are in mm
# note: bb origin is top-left, pgf is bottom-left
# A round on 2 decimal places should be enough precision for 300 dpi
# plots.
bb = bbox(sp)
push!(style, """
xshift = $(left(bb).value)mm,
yshift = $((height(bb) - (bottom(bb))).value)mm,
yshift = $(round((total_height - (bottom(bb))).value,2))mm,
axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])}
""")
kw[:width] = "$(width(bb).value)mm"
@@ -288,19 +334,62 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
kw[:legendPos] = _pgfplots_legend_pos[legpos]
end
o = PGFPlots.Axis(; style = style, kw...)
axisf = PGFPlots.Axis
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
for series in series_list(sp)
push!(o, pgf_series(sp, series))
# add series annotations
anns = series[:series_annotations]
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y])
pgf_add_annotation!(o, xi, yi, PlotText(str, fnt))
end
end
# add the annotations
for ann in sp[:annotations]
pgf_add_annotation!(o,ann...)
end
# add the PGFPlots.Axis to the list
push!(plt.o, o)
end
end
function _show(io::IO, mime::MIME"image/svg+xml", plt::Plot{PGFPlotsBackend})
show(io, mime, plt.o)
end
@@ -314,12 +403,18 @@ function _show(io::IO, mime::MIME"application/pdf", plt::Plot{PGFPlotsBackend})
PGFPlots.save(PGFPlots.PDF(fn), pgfplt)
# read it into io
write(io, readall(open(fn)))
write(io, readstring(open(fn)))
# cleanup
PGFPlots.cleanup(plt.o)
end
function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend})
fn = tempname()*".tex"
PGFPlots.save(fn, backend_object(plt), include_preamble=false)
write(io, readstring(open(fn)))
end
function _display(plt::Plot{PGFPlotsBackend})
# prepare the object
pgfplt = PGFPlots.plot(plt.o)
+25 -5
View File
@@ -19,8 +19,8 @@ const _plotly_attr = merge_with_base_supported([
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :levels,
:grid, :legend, :colorbar, :colorbar_title,
:marker_z, :fill_z, :levels,
:ribbon, :quiver,
:orientation,
# :overwrite_figure,
@@ -31,6 +31,7 @@ const _plotly_attr = merge_with_base_supported([
:hover,
:inset_subplots,
:bar_width,
:clims,
])
const _plotly_seriestype = [
@@ -268,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[]
@@ -371,6 +372,7 @@ end
plotly_colorscale(c, α) = plotly_colorscale(cgrad(alpha=α), α)
# plotly_colorscale(c, alpha = nothing) = plotly_colorscale(cgrad(), alpha)
const _plotly_markers = KW(
:rect => "square",
:xcross => "x",
@@ -407,6 +409,13 @@ 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 = α)
# allows passing a ColorGradient where a single color is expected - the other backends allow this
PlotUtils.rgba_string(cg::ColorGradient) = rgba_string(cg[1])
# 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]
@@ -437,6 +446,13 @@ 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
end
# set the "type"
if st in (:path, :scatter, :scattergl)
d_out[:type] = st==:scattergl ? "scattergl" : "scatter"
@@ -488,6 +504,9 @@ function plotly_series(plt::Plot, series::Series)
d_out[:contours] = KW(:x => wirelines, :y => wirelines, :z => wirelines)
else
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
if series[:fill_z] != nothing
d_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
end
elseif st == :pie
@@ -529,9 +548,10 @@ function plotly_series(plt::Plot, series::Series)
rgba_string(series[:markercolor])
else
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
grad = series[:markercolor]
grad = as_gradient(series[:markercolor], series[:markeralpha])
zmin, zmax = extrema(series[:marker_z])
[rgba_string(grad[(zi - zmin) / (zmax - zmin)]) for zi in 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
+13 -3
View File
@@ -86,8 +86,8 @@ end
# ----------------------------------------------------------------
function _show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend})
if Plots.isijulia()
print(io, PlotlyJS.html_body(plt.o))
if isijulia() && !_use_remote[]
write(io, PlotlyJS.html_body(PlotlyJS.JupyterPlot(plt.o)))
else
show(io, MIME("text/html"), plt.o)
end
@@ -102,8 +102,18 @@ _show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hac
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "pdf")
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "eps")
function write_temp_html(plt::Plot{PlotlyJSBackend})
filename = string(tempname(), ".html")
savefig(plt, filename)
filename
end
function _display(plt::Plot{PlotlyJSBackend})
display(plt.o)
if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
display(plt.o)
else
standalone_html_window(plt)
end
end
+19 -16
View File
@@ -18,8 +18,7 @@ const _pyplot_attr = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z,
:line_z,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
:orientation,
@@ -56,6 +55,10 @@ function add_backend_string(::PyPlotBackend)
withenv("PYTHON" => "") do
Pkg.build("PyPlot")
end
import Conda
Conda.add("qt=4.8.5")
# now restart julia!
"""
end
@@ -124,8 +127,8 @@ end
py_colormap(c) = py_colormap(cgrad())
function py_shading(c, z, α=nothing)
cmap = py_colormap(c, α)
function py_shading(c, z)
cmap = py_colormap(c)
ls = pycolors.pymember("LightSource")(270,45)
ls[:shade](z, cmap, vert_exag=0.1, blend_mode="soft")
end
@@ -668,21 +671,21 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
x = repmat(x', length(y), 1)
y = repmat(y, 1, length(series[:x]))
end
# z = z'
z = transpose_z(series, z)
if st == :surface
if series[:marker_z] != nothing
extrakw[:facecolors] = py_shading(series[:fillcolor], series[:marker_z], series[:fillalpha])
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))
extrakw[:shade] = false
clims = sp[:clims]
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
else
extrakw[:cmap] = py_fillcolormap(series)
needs_colorbar = true
end
needs_colorbar = true
end
handle = ax[st == :surface ? :plot_surface : :plot_wireframe](x, y, z;
label = series[:label],
@@ -1051,7 +1054,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)
@@ -1067,7 +1070,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
@@ -1099,7 +1102,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
+2 -2
View File
@@ -23,11 +23,11 @@ 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()
return run(`$(ENV["COMSPEC"]) /c start $(filename)`)
return run(`$(ENV["COMSPEC"]) /c start "" "$(filename)"`)
end
warn("Unknown OS... cannot open browser window.")
end
+4 -4
View File
@@ -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
@@ -248,7 +248,7 @@ end
function font(args...)
# defaults
family = "Helvetica"
family = "sans-serif"
pointsize = 14
halign = :hcenter
valign = :vcenter
@@ -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)
+18
View File
@@ -172,6 +172,24 @@ PlotExample("",
end)]
),
PlotExample("Animation with subplots",
"The `layout` macro can be used to create an animation with subplots.",
[:(begin
l = @layout([[a; b] c])
p = plot(plot([sin,cos],1,leg=false),
scatter([atan,cos],1,leg=false),
plot(log,1,xlims=(1,10π),ylims=(0,5),leg=false),layout=l)
anim = Animation()
for x = linspace(1,10π,100)
plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)]))
frame(anim)
end
end)]
),
PlotExample("Open/High/Low/Close",
"Create an OHLC chart. Pass in a list of (open,high,low,close) tuples as your `y` argument. This uses recipes to first convert the tuples to OHLC objects, and subsequently create a :path series with the appropriate line segments.",
[:(begin
+6 -7
View File
@@ -154,6 +154,7 @@ const _mimeformats = Dict(
"application/postscript" => "ps",
"image/svg+xml" => "svg",
"text/plain" => "txt",
"application/x-tex" => "tex",
)
const _best_html_output_type = KW(
@@ -301,6 +302,10 @@ function setup_atom()
Media.render(pane, Atom.div(".fill", Atom.HTML(stringmime(MIME("text/html"), plt))))
plt[:size] = sz
end
# special handling for PlotlyJS
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyJSBackend})
display(Plots.PlotsDisplay(), plt)
end
else
#
function Media.render(pane::Atom.PlotPane, plt::Plot)
@@ -313,14 +318,8 @@ 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
# special handling for PlotlyJS to pass through to that render method
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyJSBackend})
Plots.prepare_output(plt)
Media.render(pane, plt.o)
end
end
end
+8 -1
View File
@@ -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
+56
View File
@@ -0,0 +1,56 @@
const _attribute_defaults = Dict(:Series => _series_defaults,
:Subplot => _subplot_defaults,
:Plot => _plot_defaults,
:Axis => _axis_defaults)
attrtypes() = join(keys(_attribute_defaults), ", ")
attributes(attrtype::Symbol) = sort(collect(keys(_attribute_defaults[attrtype])))
function lookup_aliases(attrtype, attribute)
attribute = Symbol(attribute)
attribute = in(attribute, keys(_keyAliases)) ? _keyAliases[attribute] : attribute
in(attribute, keys(_attribute_defaults[attrtype])) && return attribute
error("There is no attribute named $attribute in $attrtype")
end
function plotattr()
println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())")
end
function plotattr(attrtype::Symbol)
in(attrtype, keys(_attribute_defaults)) || error("Viable options are $(attrtypes())")
println("Defined $attrtype attributes are:\n$(join(attributes(attrtype), ", "))")
end
function plotattr(attribute::AbstractString)
attribute = Symbol(attribute)
attribute = in(attribute, keys(_keyAliases)) ? _keyAliases[attribute] : attribute
for (k, v) in _attribute_defaults
if in(attribute, keys(v))
return plotattr(k, "$attribute")
end
end
error("There is no attribute named $attribute")
end
function plotattr(attrtype::Symbol, attribute::AbstractString)
in(attrtype, keys(_attribute_defaults)) || ArgumentError("`attrtype` must match one of $(attrtypes())")
attribute = Symbol(lookup_aliases(attrtype, attribute))
desc = get(_arg_desc, attribute, "")
first_period_idx = findfirst(desc, '.')
typedesc = desc[1:first_period_idx-1]
desc = strip(desc[first_period_idx+1:end])
als = keys(filter((_,v)->v==attribute, _keyAliases)) |> collect |> sort
als = join(map(string,als), ", ")
def = _attribute_defaults[attrtype][attribute]
# Looks up the different elements and plots them
println("$attribute ", typedesc == "" ? "" : "{$typedesc}", "\n",
als == "" ? "" : "$als\n",
"\n$desc\n",
"$(attrtype) attribute, ", def == "" ? "" : " default: $def")
end
+392 -87
View File
@@ -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, wautolims = _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.5mean(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,16 +348,21 @@ 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
@@ -374,110 +380,355 @@ end
x := xseg.pts
y := yseg.pts
seriestype := :shape
ylims --> wautolims
()
end
@deps bar shape
# ---------------------------------------------------------------------------
# Histograms
# edges from number of bins
function calc_edges(v, bins::Integer)
vmin, vmax = extrema(v)
linspace(vmin, vmax, bins+1)
_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
# just pass through arrays
calc_edges(v, bins::AVec) = bins
# find the bucket index of this value
function bucket_index(vi, edges)
for (i,e) in enumerate(edges)
if vi <= e
return max(1,i-1)
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 _binbarlike_autolims{T<:Real}(min_value::T, max_value::T, scale::Symbol)
lo = if (scale in _logScales)
_binbarlike_baseline(min_value, scale)
else
min(min_value * T(1.1), zero(T))
end::T
hi = if !isnan(max_value)
if (scale in _logScales)
max_value * T(_logScaleBases[scale]^log10(2))
else
max(max_value * T(1.1), zero(T))
end
end
return length(edges)-1
else
one(T)
end::T
(lo, hi)
end
function my_hist(v, bins; normed = false, weights = nothing)
edges = calc_edges(v, bins)
counts = zeros(length(edges)-1)
# add a weighted count
for (i,vi) in enumerate(v)
idx = bucket_index(vi, edges)
counts[idx] += (weights == nothing ? 1.0 : weights[i])
function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol)
w_adj = _scale_adjusted_values(T, w, wscale)
w_min = minimum(w_adj)
w_max = maximum(w_adj)
baseline = _binbarlike_baseline(w_min, wscale)
autolims = _binbarlike_autolims(w_min, w_max,wscale)
w_adj, baseline, autolims
end
function _preprocess_barlike(d, x, y)
xscale = get(d, :xscale, :identity)
yscale = get(d, :yscale, :identity)
weights, baseline, wautolims = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale)
x, weights, xscale, yscale, baseline, wautolims
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, wautolims = _preprocess_binbarlike_weights(T, y, yscale)
edge, weights, xscale, yscale, baseline, wautolims
end
@recipe function f(::Type{Val{:barbins}}, x, y, z)
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
if (d[:bar_width] == nothing)
bar_width := diff(edge)
end
x := _bin_centers(edge)
y := weights
seriestype := :bar
()
end
@deps barbins bar
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
xerror := diff(edge)/2
x := _bin_centers(edge)
y := weights
seriestype := :scatter
()
end
@deps scatterbins scatter
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
# normalize by bar area?
norm_denom = normed ? sum(diff(edges) .* counts) : 1.0
if norm_denom == 0
norm_denom = 1.0
x = eltype(edge)[]
y = eltype(weights)[]
it_e, it_w = start(edge), start(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)
if (log_scale_x && a 0)
a = b/_logScaleBases[xscale]^3
end
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
edges, counts ./ norm_denom
(x, y)
end
@recipe function f(::Type{Val{:stepbins}}, x, y, z)
axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis]
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale)
if !isvertical(d)
xpts, ypts = ypts, xpts
end
# create a secondary series for the markers
if d[:markershape] != :none
@series begin
seriestype := :scatter
x := _bin_centers(edge)
y := weights
fillrange := nothing
label := ""
primary := false
()
end
markershape := :none
xerror := :none
yerror := :none
end
x := xpts
y := ypts
seriestype := :path
ylims --> wautolims
()
end
Plots.@deps stepbins path
function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto)
_cl(x) = max(ceil(Int, x), 1)
_iqr(v) = quantile(v, 0.75) - quantile(v, 0.25)
_span(v) = maximum(v) - minimum(v)
n_samples = length(linearindices(first(vs)))
# Estimator for number of samples in one row/column of bins along each axis:
n = max(1, n_samples^(1/N))
v = vs[dim]
if mode == :auto
30
elseif mode == :sqrt # Square-root choice
_cl(sqrt(n))
elseif mode == :sturges # Sturges' formula
_cl(log2(n)) + 1
elseif mode == :rice # Rice Rule
_cl(2 * n^(1/3))
elseif mode == :scott # Scott's normal reference rule
_cl(_span(v) / (3.5 * std(v) / n^(1/3)))
elseif mode == :fd # FreedmanDiaconis rule
_cl(_span(v) / (2 * _iqr(v) / n^(1/3)))
else
error("Unknown auto-binning mode $mode")
end::Int
end
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) = StatsBase.histrange(vs[dim], binning, :left)
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) = _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning))
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) = binning
_hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::NTuple{N}) =
map(dim -> _hist_edge(vs, dim, binning[dim]), (1:N...))
_hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, AbstractVector}) =
map(dim -> _hist_edge(vs, dim, binning), (1:N...))
_hist_norm_mode(mode::Symbol) = mode
_hist_norm_mode(mode::Bool) = mode ? :pdf : :none
function _make_hist{N}(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing)
info("binning = $binning")
edges = _hist_edges(vs, binning)
h = float( weights == nothing ?
StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) :
StatsBase.fit(StatsBase.Histogram, vs, weights, edges, closed = :left)
)
normalize!(h, mode = _hist_norm_mode(normed))
end
@recipe function f(::Type{Val{:histogram}}, x, y, z)
edges, counts = my_hist(y, d[:bins],
normed = d[:normalize],
weights = d[:weights])
x := edges
y := counts
seriestype := :bar
seriestype := :barhist
()
end
@deps histogram bar
@deps histogram barhist
@recipe function f(::Type{Val{:barhist}}, x, y, z)
h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights])
x := h.edges[1]
y := h.weights
seriestype := :barbins
()
end
@deps barhist barbins
@recipe function f(::Type{Val{:stephist}}, x, y, z)
h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights])
x := h.edges[1]
y := h.weights
seriestype := :stepbins
()
end
@deps stephist stepbins
@recipe function f(::Type{Val{:scatterhist}}, x, y, z)
h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights])
x := h.edges[1]
y := h.weights
seriestype := :scatterbins
()
end
@deps scatterhist scatterbins
@recipe function f{T, E}(h::StatsBase.Histogram{T, 1, E})
seriestype --> :barbins
st_map = Dict(
:bar => :barbins, :scatter => :scatterbins, :step => :stepbins,
:steppost => :stepbins # :step can be mapped to :steppost in pre-processing
)
seriestype := get(st_map, d[:seriestype], d[:seriestype])
if d[:seriestype] == :scatterbins
# Workaround, error bars currently not set correctly by scatterbins
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, h.edges[1], h.weights)
xerror --> diff(h.edges[1])/2
seriestype := :scatter
(Plots._bin_centers(edge), weights)
else
(h.edges[1], h.weights)
end
end
@recipe function f{H <: StatsBase.Histogram}(hv::AbstractVector{H})
for h in hv
@series begin
h
end
end
end
# ---------------------------------------------------------------------------
# Histogram 2D
# if tuple, map out bins, otherwise use the same for both
calc_edges_2d(x, y, bins) = calc_edges(x, bins), calc_edges(y, bins)
calc_edges_2d{X,Y}(x, y, bins::Tuple{X,Y}) = calc_edges(x, bins[1]), calc_edges(y, bins[2])
@recipe function f(::Type{Val{:bins2d}}, x, y, z)
edge_x, edge_y, weights = x, y, z.surf
# the 2D version
function my_hist_2d(x, y, bins; normed = false, weights = nothing)
xedges, yedges = calc_edges_2d(x, y, bins)
counts = zeros(length(yedges)-1, length(xedges)-1)
# add a weighted count
for i=1:length(x)
r = bucket_index(y[i], yedges)
c = bucket_index(x[i], xedges)
counts[r,c] += (weights == nothing ? 1.0 : weights[i])
float_weights = float(weights)
if is(float_weights, weights)
float_weights = deepcopy(float_weights)
end
# normalize to cubic area of the imaginary surface towers
norm_denom = normed ? sum((diff(yedges) * diff(xedges)') .* counts) : 1.0
if norm_denom == 0
norm_denom = 1.0
end
xedges, yedges, counts ./ norm_denom
end
centers(v::AVec) = 0.5 * (v[1:end-1] + v[2:end])
@recipe function f(::Type{Val{:histogram2d}}, x, y, z)
xedges, yedges, counts = my_hist_2d(x, y, d[:bins],
normed = d[:normalize],
weights = d[:weights])
for (i,c) in enumerate(counts)
for (i, c) in enumerate(float_weights)
if c == 0
counts[i] = NaN
float_weights[i] = NaN
end
end
x := centers(xedges)
y := centers(yedges)
z := Surface(counts)
linewidth := 0
x := Plots._bin_centers(edge_x)
y := Plots._bin_centers(edge_y)
z := Surface(float_weights)
match_dimensions := true
seriestype := :heatmap
()
end
@deps histogram2d heatmap
Plots.@deps bins2d heatmap
@recipe function f(::Type{Val{:histogram2d}}, x, y, z)
h = _make_hist((x, y), d[:bins], normed = d[:normalize], weights = d[:weights])
x := h.edges[1]
y := h.edges[2]
z := Surface(h.weights)
seriestype := :bins2d
()
end
@deps histogram2d bins2d
@recipe function f{T, E}(h::StatsBase.Histogram{T, 2, E})
seriestype --> :bins2d
(h.edges[1], h.edges[2], Surface(h.weights))
end
# ---------------------------------------------------------------------------
@@ -789,16 +1040,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
+39 -12
View File
@@ -6,7 +6,7 @@
# This should cut down on boilerplate code and allow more focused dispatch on type
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
typealias FuncOrFuncs Union{Function, AVec{Function}}
typealias FuncOrFuncs{F} Union{F, Vector{F}, Matrix{F}}
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
@@ -96,8 +96,8 @@ nobigs(v) = v
end
# not allowed
compute_xyz(x::Void, y::FuncOrFuncs, z) = error("If you want to plot the function `$y`, you need to define the x values!")
compute_xyz(x::Void, y::Void, z::FuncOrFuncs) = error("If you want to plot the function `$z`, you need to define x and y values!")
compute_xyz{F<:Function}(x::Void, y::FuncOrFuncs{F}, z) = error("If you want to plot the function `$y`, you need to define the x values!")
compute_xyz{F<:Function}(x::Void, y::Void, z::FuncOrFuncs{F}) = error("If you want to plot the function `$z`, you need to define x and y values!")
compute_xyz(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
# --------------------------------------------------------------------
@@ -257,12 +257,23 @@ end
# # 1 argument
# # --------------------------------------------------------------------
# helper function to ensure relevant attributes are wrapped by Surface
function wrap_surfaces(d::KW)
if haskey(d, :fill_z)
v = d[:fill_z]
if !isa(v, Surface)
d[:fill_z] = Surface(v)
end
end
end
@recipe f(n::Integer) = is3d(get(d,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing)
# return a surface if this is a 3d plot, otherwise let it be sliced up
@recipe function f{T<:Union{Integer,AbstractFloat}}(mat::AMat{T})
if all3D(d)
n,m = size(mat)
wrap_surfaces(d)
SliceIt, 1:m, 1:n, Surface(mat)
else
SliceIt, nothing, mat, nothing
@@ -274,6 +285,7 @@ end
if all3D(d)
mat = fmt.data
n,m = size(mat)
wrap_surfaces(d)
SliceIt, 1:m, 1:n, Formatted(Surface(mat), fmt.formatter)
else
SliceIt, nothing, fmt, nothing
@@ -341,9 +353,13 @@ end
# function without range... use the current range of the x-axis
@recipe function f(f::FuncOrFuncs)
@recipe function f{F<:Function}(f::FuncOrFuncs{F})
plt = d[:plot_object]
xmin,xmax = axis_limits(plt[1][:xaxis])
xmin, xmax = try
axis_limits(plt[1][:xaxis])
catch
-5, 5
end
f, xmin, xmax
end
@@ -356,8 +372,9 @@ end
# # if functions come first, just swap the order (not to be confused with parametric functions...
# # as there would be more than one function passed in)
@recipe function f(f::FuncOrFuncs, x)
@assert !(typeof(x) <: FuncOrFuncs) # otherwise we'd hit infinite recursion here
@recipe function f{F<:Function}(f::FuncOrFuncs{F}, x)
F2 = typeof(x)
@assert !(F2 <: Function || (F2 <: AbstractArray && F2.parameters[1] <: Function)) # otherwise we'd hit infinite recursion here
x, f
end
@@ -386,6 +403,7 @@ end
# seriestype := :path3d
# end
# end
wrap_surfaces(d)
SliceIt, x, y, z
end
@@ -395,6 +413,7 @@ end
@recipe function f(x::AVec, y::AVec, zf::Function)
# x = X <: Number ? sort(x) : x
# y = Y <: Number ? sort(y) : y
wrap_surfaces(d)
SliceIt, x, y, Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported
end
@@ -405,6 +424,7 @@ end
if !like_surface(get(d, :seriestype, :none))
d[:seriestype] = :contour
end
wrap_surfaces(d)
SliceIt, x, y, Surface(z)
end
@@ -416,16 +436,23 @@ end
#
# # special handling... xmin/xmax with parametric function(s)
@recipe f(f::FuncOrFuncs, xmin::Number, xmax::Number) = linspace(xmin, xmax, 100), f
@recipe f(fx::FuncOrFuncs, fy::FuncOrFuncs, u::AVec) = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)
@recipe f(fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Number, umax::Number, n = 200) = fx, fy, linspace(umin, umax, n)
@recipe function f(f::Function, xmin::Number, xmax::Number)
xs = adapted_grid(f, (xmin, xmax))
xs, f
end
@recipe function f{F<:Function}(fs::AbstractArray{F}, xmin::Number, xmax::Number)
xs = Any[adapted_grid(f, (xmin, xmax)) for f in fs]
xs, fs
end
@recipe f{F<:Function,G<:Function}(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, u::AVec) = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)
@recipe f{F<:Function,G<:Function}(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, umin::Number, umax::Number, n = 200) = fx, fy, linspace(umin, umax, n)
#
# # special handling... 3D parametric function(s)
@recipe function f(fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, u::AVec)
@recipe function f{F<:Function,G<:Function,H<:Function}(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, u::AVec)
mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)
end
@recipe function f(fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, umin::Number, umax::Number, numPoints = 200)
@recipe function f{F<:Function,G<:Function,H<:Function}(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, umin::Number, umax::Number, numPoints = 200)
fx, fy, fz, linspace(umin, umax, numPoints)
end
+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,
+1 -1
View File
@@ -265,7 +265,7 @@ maketuple(x::Real) = (x,x)
maketuple{T,S}(x::Tuple{T,S}) = x
mapFuncOrFuncs(f::Function, u::AVec) = map(f, u)
mapFuncOrFuncs(fs::AVec{Function}, u::AVec) = [map(f, u) for f in fs]
mapFuncOrFuncs{F<:Function}(fs::AVec{F}, u::AVec) = [map(f, u) for f in fs]
unzip{X,Y}(xy::AVec{Tuple{X,Y}}) = [t[1] for t in xy], [t[2] for t in xy]
unzip{X,Y,Z}(xyz::AVec{Tuple{X,Y,Z}}) = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
+1 -1
View File
@@ -23,7 +23,7 @@ facts("PyPlot") do
@fact pyplot() --> Plots.PyPlotBackend()
@fact backend() --> Plots.PyPlotBackend()
image_comparison_facts(:pyplot, skip=[25,30], eps=img_eps)
image_comparison_facts(:pyplot, skip=[6,25,30], eps=img_eps)
end
facts("GR") do