Compare commits

..

1392 Commits

Author SHA1 Message Date
Josef Heinen b9c9fc615b Update gr.jl 2018-08-01 13:06:55 +02:00
Daniel Schwabeneder 50c62ec48e Merge pull request #1593 from fredrikekre/fe/0.72
small additional fixes for 0.7
2018-07-05 08:14:48 +02:00
Fredrik Ekre b16ced0367 small fixes 2018-07-05 00:19:21 +02:00
Daniel Schwabeneder 0717805773 more deprecation fixes 2018-07-04 22:33:51 +02:00
Daniel Schwabeneder a7f2484d45 fix some deprecation warnings 2018-07-04 20:56:13 +02:00
Daniel Schwabeneder 96d97699a0 Merge pull request #1588 from daschw/julia0.7
fix Pkg.installed
2018-07-03 20:02:22 +02:00
Daniel Schwabeneder e92e832258 fix Pkg.installed 2018-07-03 19:59:03 +02:00
femtocleaner[bot] d68829820b Fix deprecations 2018-06-30 23:15:27 +00:00
Daniel Schwabeneder 9cf3036ab5 Merge pull request #1587 from daschw/julia0.7
remove StatPlots from tests
2018-07-02 00:28:22 +02:00
Daniel Schwabeneder 2467eb71c1 remove StatPlots from tests 2018-07-02 00:26:23 +02:00
Daniel Schwabeneder 345bb5d1aa Merge pull request #1586 from daschw/julia0.7
use Pkg in travis commands
2018-07-02 00:19:54 +02:00
Daniel Schwabeneder 8d50828998 Merge branch 'julia0.7' into julia0.7 2018-07-02 00:03:27 +02:00
Daniel Schwabeneder 201de82baf fix some things in tests 2018-07-02 00:00:40 +02:00
Daniel Schwabeneder 99519ac3da use Pkg in travis commands 2018-07-01 23:48:56 +02:00
Daniel Schwabeneder a575ab7c74 Merge branch 'master' into julia0.7 2018-07-01 23:30:40 +02:00
Daniel Schwabeneder c4f79814df Merge pull request #1584 from daschw/julia0.7
julia 0.7 fixes
2018-07-01 23:24:38 +02:00
Daniel Schwabeneder 6135f6271c julia 0.7 fixes 2018-07-01 21:40:48 +02:00
Daniel Schwabeneder 0eab0dc680 Merge pull request #1583 from daschw/release
prepare release
2018-07-01 10:11:07 +02:00
Daniel Schwabeneder 2b48f50de4 prepare release 2018-07-01 10:06:49 +02:00
Daniel Schwabeneder fa60eacfc5 Merge pull request #1572 from daschw/widen
Widen axes for most series types and log scales
2018-07-01 09:52:29 +02:00
Daniel Schwabeneder d2a4136d4f Merge pull request #1582 from daschw/test
don't checkout PlotUtils in tests
2018-07-01 09:33:19 +02:00
Daniel Schwabeneder 7d88a746ea don't checkout PlotUtils in tests 2018-07-01 09:27:11 +02:00
Daniel Schwabeneder 7f4537bdc6 Merge pull request #1577 from JuliaPlots/pv/webio
WebIO integration for PlotlyJS backend
2018-07-01 08:44:40 +02:00
Andrew Palugniok 8ef70f07f0 Merge pull request #1576 from apalugniok/hover-zcolor
Fix hover and zcolor interaction in Plotly (Fixes #1567)
2018-06-28 08:28:42 +01:00
Andrew Palugniok 17b7e37885 Merge pull request #1575 from apalugniok/flip-plotly
Fix axis flip on Plotly (Fixes #1556)
2018-06-28 08:28:01 +01:00
Pietro Vertechi 35c17044e1 prepare output 2018-06-27 15:39:54 +01:00
Pietro Vertechi 7085d98f41 webio integration 2018-06-27 15:24:50 +01:00
Andrew Palugniok ee73e32b0e Fix hover and zcolor interaction in Plotly. 2018-06-26 18:26:13 +01:00
Andrew Palugniok 371430c172 Fix axis flip on Plotly. 2018-06-26 12:18:22 +01:00
Daniel Schwabeneder 495753b517 Merge pull request #1573 from yha/plotly-log-noticks
Plotly: fix log scale with no ticks
2018-06-25 15:59:12 +02:00
yharel 211be0a863 Setting axis scale regardless of ticks 2018-06-25 00:42:36 +03:00
Daniel Schwabeneder 12c9a8e6c3 plots_heatmap 2018-06-24 19:01:06 +02:00
Daniel Schwabeneder fb5d9e0c01 Merge pull request #1571 from daschw/pgf_dpi
New attributes for PGFPlots
2018-06-24 18:05:14 +02:00
Daniel Schwabeneder 61a2d962c0 widen most seriestypes including logscales 2018-06-24 11:03:56 +02:00
Daniel Schwabeneder 440622830a disregard dpi for pgfplots 2018-06-24 00:34:11 +02:00
Daniel Schwabeneder 2652990432 annotations 2018-06-23 23:44:43 +02:00
Daniel Schwabeneder 652e2f27b6 implement font rotation 2018-06-23 23:38:38 +02:00
Daniel Schwabeneder 77a82eaa6a implent font size and colors 2018-06-23 23:24:09 +02:00
Daniel Schwabeneder 624a181b23 implement axis and grid arguments and corresponding thickness_scaling 2018-06-23 21:47:01 +02:00
Daniel Schwabeneder 865ac52442 pgf_thickness_scaling for series linewidths and markers 2018-06-23 19:39:25 +02:00
Daniel Schwabeneder 4f064d7c02 Merge pull request #1561 from daschw/size
Fix size and dpi for GR and PyPlot
2018-06-23 09:14:52 +02:00
Daniel Schwabeneder facb67e94e Merge pull request #1570 from daschw/flip
fix flip for heatmap and image on GR (fix #1491)
2018-06-23 07:34:24 +02:00
Daniel Schwabeneder 124c838e06 fix flip for heatmap and image on GR 2018-06-22 22:07:00 +02:00
Daniel Schwabeneder 026e894e1d Merge pull request #1565 from daschw/fillrange
Fix fillrange with line segments on PyPlot and Plotly (fix #1563)
2018-06-18 21:58:36 +02:00
Daniel Schwabeneder 2ed0f1661a fix plotly fillrange 2018-06-18 19:55:09 +02:00
Daniel Schwabeneder 00f285cba3 fix pyplot fillrange 2018-06-18 19:45:43 +02:00
Daniel Schwabeneder ddf5bf472f Merge pull request #1562 from daschw/py_marker
fix markercolor as vector on pyplot (fix #1494)
2018-06-18 09:22:13 +02:00
Daniel Schwabeneder 534c7799e5 fix markercolor as vector on pyplot 2018-06-17 22:20:20 +02:00
Daniel Schwabeneder b254aaa081 Merge pull request #1559 from yha/log-heatmap
Log-scale heatmap edge computation
2018-06-16 21:24:23 +02:00
Daniel Schwabeneder 76f2860c74 fix gr 2018-06-16 20:38:46 +02:00
Daniel Schwabeneder 5ebcb77d0d rename _gr_dpi_scale to _gr_thickness_scaling 2018-06-16 19:29:28 +02:00
Daniel Schwabeneder 4847752ef4 make dpi change plot size 2018-06-16 19:24:58 +02:00
Daniel Schwabeneder 84ec8d61ae fix thickness_scaling in pyplot 2018-06-16 17:14:19 +02:00
Daniel Schwabeneder 0f13551b6d fix margins on gr 2018-06-16 16:57:07 +02:00
Daniel Schwabeneder 3e66c6cce4 change DPI value back 2018-06-16 11:51:49 +02:00
yha 09de3a5e7a GR heatmap: warning for non-equal spacing 2018-06-16 04:14:27 +03:00
yha 00483d4c0d GR heatmap: warning for non-equal spacing 2018-06-16 04:07:21 +03:00
yha 1e3d10ad31 GR heatmap: warning for non-equal spacing 2018-06-16 03:13:13 +03:00
yha dc31cd7103 A better heuristic for outer heatmap edges 2018-06-16 03:10:48 +03:00
yharel cffb670f72 Merge branch 'master' of https://github.com/JuliaPlots/Plots.jl 2018-06-14 04:06:08 +03:00
yharel 781fea7431 Heatmap log scale fix 2018-06-14 02:59:04 +03:00
Daniel Schwabeneder 78b0b7e01d Merge pull request #1557 from daschw/release
prepare release
2018-06-12 21:09:12 +02:00
Daniel Schwabeneder e96367cd4b prepare release 2018-06-12 21:07:45 +02:00
Daniel Schwabeneder 30af3c7f8a Merge pull request #1547 from wfrgra/round_axis_limits
allow automatic widening of the axis limits to the next power of 10 …
2018-06-06 21:48:52 +02:00
Daniel Schwabeneder 264405827e Merge pull request #1549 from daschw/plotly-lims
fix single subplot in plotly (fix #1485)
2018-06-06 21:48:31 +02:00
Daniel Schwabeneder 083721bbc1 fix single subplot in plotly 2018-06-06 18:25:22 +02:00
Will Grant 91ed04ff83 update documentation in arg_desc with round limits option 2018-06-06 18:44:07 +10:00
Will Grant cbbd4fd029 allow automatic widening of the axis limits to the next power of 10 with xlim/ylim = :round 2018-06-06 11:20:05 +10:00
Daniel Schwabeneder f6bc7721a8 Merge pull request #1536 from fredrikekre/fe/_show
restructure some show methods
2018-06-05 13:15:26 +02:00
Fredrik Ekre 32ec9e82bf make UnicodePlots print to the given io
and add support for text/plain in Plots own display_dict
fix #1514
2018-06-04 12:36:50 +02:00
Fredrik Ekre 69a7a8a04e define show for more mime-types 2018-06-04 12:36:50 +02:00
Fredrik Ekre ccb5194bb5 make fallback method a method of _show instead of show
fix #1529
2018-06-04 12:36:45 +02:00
Fredrik Ekre 2d280edf0c forward showable call to _show instead of show since all backends return true otherwise 2018-06-04 10:15:13 +02:00
Daniel Schwabeneder afe4817150 Merge pull request #1537 from fredrikekre/fe/fileio
only try the pdf -> png convert sometimes
2018-06-03 17:03:15 +02:00
Daniel Schwabeneder 6754b3746e Merge pull request #1543 from daschw/ticks
set fallback tick specification for axes with discrete values
2018-06-03 16:21:54 +02:00
Daniel Schwabeneder 287f83f4d0 Merge pull request #1544 from daschw/pyplot-legend
PyPlot: fix bg_legend = invisible()
2018-06-03 16:21:32 +02:00
Daniel Schwabeneder bf518a961e clean up 2018-05-30 16:28:56 +02:00
Daniel Schwabeneder 4a55467eef add plot_color 2018-05-30 16:20:19 +02:00
Daniel Schwabeneder 56cf5249f9 remove extra line 2018-05-30 16:18:56 +02:00
Daniel Schwabeneder 17e8bc6949 set legend alpha in pyplot 2018-05-30 16:13:39 +02:00
Daniel Schwabeneder 02ede8020f fix tick conditions 2018-05-30 14:26:35 +02:00
Daniel Schwabeneder 54158a0340 check for dvals at the end 2018-05-30 13:59:16 +02:00
Daniel Schwabeneder 7ce96a4e3d set fallback tick specification for axes with discrete values 2018-05-30 13:25:00 +02:00
Daniel Schwabeneder 2067b70445 Merge pull request #1535 from fredrikekre/fe/text/plain
add text/plain default, fix #1515
2018-05-22 14:29:16 +02:00
Fredrik Ekre d02658e0ba add text/plain default, fix #1515 2018-05-21 15:09:50 +02:00
Fredrik Ekre 27e68ed6a9 only try the pdf -> png convert if the backend support application/pdf mime 2018-05-21 14:49:18 +02:00
Daniel Schwabeneder b3e0ac017f Merge pull request #1534 from daschw/release
prepare release
2018-05-21 09:55:56 +02:00
Daniel Schwabeneder 8bc437a84e prepare release 2018-05-21 09:53:58 +02:00
Daniel Schwabeneder 11e5a94fc4 Merge pull request #1528 from jdeldre/je/fixcontour
Contour plots with x,y in grid (i.e. multi-dimensional array) form
2018-05-18 16:06:08 +02:00
Daniel Schwabeneder c11941cbc1 Merge pull request #1523 from daschw/seriesrecipe
update series attributes after processing series recipes fix (#1520)
2018-05-18 16:00:35 +02:00
Jeff Eldredge f792aea98e Changed treatment of contour types, to allow for x,y in grid form, allowed by PyPlot backend 2018-05-16 11:19:10 -07:00
Daniel Schwabeneder 12e5937a91 Merge pull request #1525 from daschw/plotly-ribbon
Fix Plotly(JS) ribbon (fix #1518)
2018-05-13 23:37:43 +02:00
Daniel Schwabeneder 60b9cd8789 remove space 2018-05-13 19:52:26 +02:00
Daniel Schwabeneder 41e4c80494 fix ribbon for plotly 2018-05-13 19:49:02 +02:00
Daniel Schwabeneder bd2756c0bf fix ribbon for plotly 2018-05-13 19:48:49 +02:00
Daniel Schwabeneder 1f3c4948c6 update series attributes after processing series recipes 2018-05-11 18:38:04 +02:00
Daniel Schwabeneder 062f9a195c Merge pull request #1522 from daschw/recipe-colors
make get_*color functions return plot_color (markercolor in series recipes in GR)
2018-05-11 14:25:02 +02:00
Daniel Schwabeneder a3e8af40b2 make get_***color return plot_color 2018-05-10 22:21:50 +02:00
Daniel Schwabeneder 49f4773e81 Merge pull request #1510 from chfin/segments-legendgroup-fix
Make series of shapes and segments toggle together in plotly[js] (fixes #1488)
2018-05-06 21:46:10 +02:00
Daniel Schwabeneder ee78385b4c Merge branch 'master' into segments-legendgroup-fix 2018-05-06 09:37:08 +02:00
Daniel Schwabeneder e99ccd0051 Merge pull request #1501 from daschw/integers
replace Int64 by Int
2018-05-06 09:31:52 +02:00
Daniel Schwabeneder cbc022524b Merge pull request #1511 from daschw/markercolors
fix marker arguments (fix #1503 fix #1505)
2018-05-06 09:30:25 +02:00
Daniel Schwabeneder 34d9d042aa update iter_segments for scatters 2018-05-05 21:42:08 +02:00
Daniel Schwabeneder 22f69a99e2 remove cfuncind in gr_draw_markers 2018-05-05 20:42:47 +02:00
Daniel Schwabeneder 4ee5539e3d plotly fixes 2018-05-05 19:22:34 +02:00
Daniel Schwabeneder 048636e894 fix plotly marker_z colorbar 2018-05-05 18:50:57 +02:00
Daniel Schwabeneder 5797ad2d5b fix plotly 2018-05-05 18:37:16 +02:00
Daniel Schwabeneder ba9a8d52cc pgfplots markercolors 2018-05-05 17:44:13 +02:00
Daniel Schwabeneder ee18a9dd6c plotly markercolors 2018-05-05 16:47:32 +02:00
Daniel Schwabeneder 517c2f456c markercolors for pyplot 2018-05-05 16:22:41 +02:00
Christoph Finkensiep e8734daa4d add legendgroups to shapes/segments and remove gaps in legend 2018-05-05 12:27:16 +02:00
Daniel Schwabeneder 1fd7c6e2f1 fix args.jl 2018-05-05 01:10:07 +02:00
Daniel Schwabeneder bc638ea06e first gr tests 2018-05-05 00:57:29 +02:00
Michael K. Borregaard 5b0ba79a35 Update Travis commands for 0.7 2018-05-04 10:53:21 +02:00
Michael Krabbe Borregaard 173c7b2aec Update julia version to 0.7
Isn't working yet.
2018-05-03 20:46:32 +02:00
Daniel Schwabeneder fd37a9c660 replace Int64 by Int 2018-04-27 17:44:20 +02:00
Daniel Schwabeneder fc460554e7 Merge pull request #1497 from daschw/markerstroke
fix markerstrokecolor = :auto (fix #1496)
2018-04-25 17:56:20 +02:00
Daniel Schwabeneder 73490903a3 fix markerstrokecolor = :auto 2018-04-25 14:14:20 +02:00
Daniel Schwabeneder 964c0ac420 Merge pull request #1489 from daschw/pgf-contour
fix contours in PGFPlots (fix #1321)
2018-04-18 17:28:26 +02:00
Daniel Schwabeneder f59ad1620a contour improvements: colorbar, contour_labels and levels 2018-04-18 16:13:28 +02:00
Daniel Schwabeneder 4797f18819 fix view for contours 2018-04-18 15:44:37 +02:00
Andrew Palugniok b0d73a3314 Merge pull request #1442 from apalugniok/native-ticks
Fixes for :native axes. (Fixes #1435 and partly #1425)
2018-04-17 12:38:23 +01:00
Michael Krabbe Borregaard 562e60f964 Merge pull request #1480 from ma-laforge/hdf5
Add support for Surface plots.
2018-04-15 12:50:36 +02:00
Daniel Schwabeneder fde0fa673b Merge pull request #1482 from daschw/release
prepare release
2018-04-13 17:09:12 +02:00
Daniel Schwabeneder c93d5e7830 Merge pull request #1481 from daschw/gr-mindep
add minimal version for GR dependency
2018-04-13 16:43:01 +02:00
Daniel Schwabeneder e305b973b2 Merge pull request #1477 from daschw/heatmap-recipe
RFC: WIP: Heatmap recipe
2018-04-13 16:42:31 +02:00
Daniel Schwabeneder 506d3611fd prepare release 2018-04-13 16:33:38 +02:00
Daniel Schwabeneder 14b644777d add minimal version for GR dependency 2018-04-13 16:21:18 +02:00
Daniel Schwabeneder b9c23c75f4 Merge pull request #1380 from davidanthoff/always-install-gr
Add GR to REQUIRE
2018-04-13 16:18:37 +02:00
Daniel Schwabeneder af60d03060 make alternative plots_heatmap seriestype 2018-04-13 16:14:03 +02:00
Andrew Palugniok adb66cae9d Merge pull request #1479 from apalugniok/pgfplots-scientific
Replace `×` with `\times` for PGFPlots. (Fixes #1464)
2018-04-10 09:20:29 +01:00
Andrew Palugniok aeaa0c5f8d Fix axis limits for ticks = :native 2018-04-09 21:28:45 +01:00
Andrew Palugniok b009da4b47 Fix :native DateTime and categorical ticks for Plotly. 2018-04-09 21:20:41 +01:00
Andrew Palugniok 8abd70bed8 Replace × with \times for PGFPlots. 2018-04-09 09:46:01 +01:00
Daniel Schwabeneder 91cd6c1954 Merge pull request #1443 from fedxa/fedxa-autosciaxis
Partial attempt to fix labeling to atomatically scientific notation
2018-04-09 10:40:26 +02:00
Daniel Schwabeneder 7a702489d0 fixes for plotly 2018-04-07 15:54:06 +02:00
Daniel Schwabeneder d33331f650 Merge pull request #1476 from daschw/default-theme
allow to set the theme in PLOTS_DEFAULTS
2018-04-07 15:34:05 +02:00
Daniel Schwabeneder 8e3bd07c91 set line_z 2018-04-07 14:37:15 +02:00
Daniel Schwabeneder ad55551819 allow to set the theme in PLOTS_DEFAULTS 2018-04-07 08:55:52 +02:00
Daniel Schwabeneder 1d38e50281 Merge pull request #1475 from daschw/pgf-legendmarker
Filled legend marker for filled areas in PGFPlots
2018-04-06 20:20:09 +02:00
Daniel Schwabeneder cef0882e80 Merge pull request #1471 from hycakir/master
Remove SVG support for plotly, which is not there
2018-04-06 18:50:36 +02:00
Daniel Schwabeneder 5a07c4917e fix multiple series 2018-04-06 18:37:57 +02:00
Daniel Schwabeneder e498d091cd filled legend marker for filled area in PGFPlots 2018-04-06 17:14:19 +02:00
Michael Krabbe Borregaard 8ba30c5453 Merge pull request #1474 from mkborregaard/master
Improve histogram2d bin estimation
2018-04-06 11:45:23 +02:00
Daniel Schwabeneder 685e2eaff7 implement heatmapr recipe 2018-04-06 10:32:45 +02:00
Michael K. Borregaard 6ca8471c64 Improve histogram2d bin estimation
The existing one would error when the correlation was high
2018-04-06 09:09:03 +02:00
Hamza Yusuf Çakır e30f4652af Remove SVG support, which is not there
plotly backend does not support SVG output. What it shows is the HTML output of Plotly backend.
This commit makes the request for SVG output to return an error as in PNG.
2018-04-05 02:53:50 +03:00
Daniel Schwabeneder 9acb89ba8a Merge pull request #1467 from daschw/segments
Segments: vector arguments, line_z and fill_z for GR, PyPlot, Plotly(JS) and PGFPlots
2018-04-04 23:27:48 +02:00
Daniel Schwabeneder 9b9a775a41 fix test errors 2018-04-03 18:43:18 +02:00
Daniel Schwabeneder a6f11cdb31 fix pyplot (leave commented lines for possible future work) 2018-04-02 23:21:57 +02:00
Daniel Schwabeneder 777642ef55 pyplot use linecollection only WITHOUT fillrange 2018-04-02 22:44:29 +02:00
Daniel Schwabeneder d1d7fd258f add fill_z and line_z to supported pgfplots attr 2018-04-02 22:14:50 +02:00
Daniel Schwabeneder 7e4635de26 fix transparency on GR 2018-04-02 22:11:22 +02:00
Daniel Schwabeneder d7b2173066 fix linestyle in pyplot 2018-04-02 22:08:00 +02:00
Daniel Schwabeneder 55e9c8c9eb implement fillrange, vector arguments, line_z and fill_z for pgfplots 2018-04-02 21:39:45 +02:00
Daniel Schwabeneder c34e1d3c19 implement vector arguments, line_z and fill_z for plotly 2018-04-02 18:35:26 +02:00
Daniel Schwabeneder f89b1ba303 implement vector arguments for GR and PyPlot 2018-04-02 00:41:13 +02:00
Daniel Schwabeneder fc7b6dd0c6 some bug fixes 2018-03-31 18:41:43 +02:00
Daniel Schwabeneder 1b5240a513 introduce iter_segments(series::Series) considering certain vector series attributes 2018-03-31 18:18:58 +02:00
Christopher Rackauckas 4bcf43c84b Update imgcomp.jl 2018-03-31 09:11:02 -07:00
Daniel Schwabeneder b57abfd563 remove sp arg from get_linecolor and get_fillcolor 2018-03-31 14:45:12 +02:00
Daniel Schwabeneder bfc26fa407 Merge pull request #1445 from daschw/infinite-objects
Infinite objects (fix #1422)
2018-03-28 21:49:32 +02:00
Daniel Schwabeneder e7b435b47f Merge pull request #1454 from CarloLucibello/master
import filter from Base
2018-03-28 21:48:51 +02:00
CarloLucibello dd6842522f avoid import 2018-03-28 09:50:46 -07:00
Daniel Schwabeneder f56d944870 hspan and vspan recipes 2018-03-28 11:32:23 +02:00
Daniel Schwabeneder 772b79306d Merge pull request #1460 from daschw/pyplot-marker_z
PyPlot: fix markercolor in legend for marker_z with st = :path
2018-03-28 10:53:23 +02:00
Daniel Schwabeneder 4ef2c6286b Merge pull request #1459 from daschw/mplot3d
import mplot3d in pyplot (fix #1457)
2018-03-27 15:45:02 +02:00
Daniel Schwabeneder a5f7c1b867 fix markercolor in legend for marker_z with st = :path 2018-03-27 14:24:26 +02:00
Daniel Schwabeneder 4d8ef2a008 import mplot3d in pyplot 2018-03-27 13:41:18 +02:00
CarloLucibello 8bc28d472f import filter 2018-03-24 19:12:18 -04:00
piever 3753ab1b55 increase version number for tests 2018-03-22 20:37:27 +00:00
Pietro Vertechi babc600915 Merge pull request #1450 from JuliaPlots/pv/release
update news
2018-03-22 14:22:03 -06:00
piever b2f92e246e update news 2018-03-22 19:39:18 +00:00
Fedor Bezrukov 92f9ccce5c Added :plain formatter 2018-03-21 23:58:26 +00:00
Daniel Schwabeneder 0ace28b784 extend straightline data beyond axes limits 2018-03-21 11:42:01 +01:00
Fedor Bezrukov bd06f0c713 Fixed broken behaviour for function :formatter, and pgfplots 2018-03-21 10:07:09 +00:00
Fedor Bezrukov 4e5c88eb74 Fixed unicode display for plotly() 2018-03-21 00:12:57 +00:00
Daniel Schwabeneder 004ad15875 Merge pull request #1437 from daschw/plotly-bar
RFC: use bar recipe in plotly
2018-03-20 17:11:37 +01:00
Daniel Schwabeneder 1c0a731ff6 fix typo in glvisualize 2018-03-19 21:51:02 +01:00
Daniel Schwabeneder 9a5f42c251 infinite shapes 2018-03-19 21:34:55 +01:00
Daniel Schwabeneder c8cdade884 :straightline for all backends 2018-03-19 16:24:23 +01:00
Daniel Schwabeneder bbff66a041 glvisualize() :straightline 2018-03-19 14:55:38 +01:00
Fedor Bezrukov 6b6394ba97 Fixed bug introduced into GR Polar plot 2018-03-19 03:15:14 +00:00
Daniel Schwabeneder d11c6a20bf Merge pull request #1438 from daschw/categorical-ticks
allow ticks = :all and ticks = n::Int for categorical axes
2018-03-18 23:21:44 +01:00
Daniel Schwabeneder 6c396e1d88 Merge pull request #1436 from daschw/fill-magic
fix fill magic argument
2018-03-18 23:21:16 +01:00
Daniel Schwabeneder bffd9bcb53 :straightline seriestype and gr implementation 2018-03-18 23:15:45 +01:00
Andrew Palugniok 7cee448d68 Merge pull request #1378 from apalugniok/dynamic-link-axes
Implement synchronized interactive linked axes for PyPlot and Plotly.
2018-03-18 19:48:09 +00:00
Fedor Bezrukov c273bf6a7b Partial attempt to fix label scaling to atomatically scientific notation.
Note, that the logic of replacing scientific notation in GR backend is a bit dodgy.
2018-03-18 17:57:27 +00:00
Daniel Schwabeneder 047a13a8dc Merge pull request #1430 from yakir12/patch-2
add option to supress saved message
2018-03-16 11:28:28 +01:00
Daniel Schwabeneder 717aed5a06 allow ticks = :all and ticks = n::Int for categorical axes 2018-03-16 11:26:56 +01:00
Daniel Schwabeneder 7d58090e59 use bar recipe in plotly 2018-03-16 09:36:24 +01:00
Daniel Schwabeneder 501df8cfb9 allow passing Real or 2Tuple of Reals as fillrange for Plotly 2018-03-15 21:46:19 +01:00
Daniel Schwabeneder 7f6fe09a00 fix magic fill argument 2018-03-15 21:22:29 +01:00
Andrew Palugniok d183d579cf Link axes before adding series. 2018-03-15 19:13:38 +01:00
Yakir Luc Gagnon bfa2fd2edc add option to supress saved message
Added option `show_msg::Bool` to `buildanimation` to show/suppress the "Saved animation to..." message.
2018-03-14 12:01:01 +01:00
Pietro Vertechi 7c257a09f6 Partially address #1409: group with named tuples (#1429)
* group with named tuples

* comma
2018-03-13 09:18:32 -06:00
Andrew Palugniok da4111579d Implement interactive linked axes for Plotly. 2018-03-07 15:09:25 +00:00
Andrew Palugniok 6b117234bc Implement interactive linked axes for PyPlot. 2018-03-07 15:09:25 +00:00
Daniel Schwabeneder c4bac660cf Merge pull request #1420 from daschw/contour-fix
Contour improvements
2018-03-01 19:59:09 +01:00
Michael Krabbe Borregaard ee2e7d509c Merge pull request #1419 from sglyon/sl/plotly_mime
ENH: provide "application/vnd.plotly.v1+json" for Plotly and PlotlyJS backends
2018-03-01 07:41:12 +01:00
Spencer Lyon 461e93fc56 ENH: provide "application/vnd.plotly.v1+json" for Plotly and PlotlyJS backends
For use in jupyterlab and nteract

closes #1418

closes #1386
2018-02-28 17:26:53 -05:00
Daniel Schwabeneder c74adc6521 check if a vector of the color black is passed to gr contour 2018-02-28 23:00:46 +01:00
Daniel Schwabeneder 7cc60d0b0c fix single-color case for plotly 2018-02-28 22:53:36 +01:00
Daniel Schwabeneder d8f0612f5a implement contour_labels and partially vector of colors for Plotly(JS) 2018-02-28 22:51:06 +01:00
Daniel Schwabeneder cd4b41a537 allow to pass a vector of colors for contour lines in PyPlot 2018-02-28 22:25:06 +01:00
Daniel Schwabeneder fdb2ee2847 implement contour_labels for PyPlot and fix #1091 2018-02-28 22:10:45 +01:00
Daniel Schwabeneder 9c4cc5acda GR colorbar fixees 2018-02-28 21:27:34 +01:00
Daniel Schwabeneder f901254519 add contour_labels attribute and minor GR contour fixes 2018-02-28 21:19:18 +01:00
Daniel Schwabeneder 18032bb9af Merge pull request #1414 from daschw/bar
default bar width for plots with only one bar (fix #1413)
2018-02-26 10:32:06 +01:00
Daniel Schwabeneder a7a5fe36f9 default to a bar width of _bar_width for bar plots with only one data point 2018-02-26 10:03:02 +01:00
Daniel Schwabeneder 32e1536955 Merge pull request #1411 from daschw/pyplot-marker
replace hline and vline marker shapes with _ and | on pyplot (fix #1188)
2018-02-26 09:15:55 +01:00
Daniel Schwabeneder 77c2ee6782 replace hline and vline marker shapes with _ and | on pyplot 2018-02-25 09:52:26 +01:00
Andrew Palugniok dbe5b78307 Merge pull request #1395 from apalugniok/native-ticks
Add :native option to ticks attribute (Fixes #1382)
2018-02-24 13:41:56 +00:00
Michael Krabbe Borregaard 9578fe03b9 Merge pull request #1408 from piever/plotlyjs
make plotlyjs use html in ijulia
2018-02-24 12:09:04 +01:00
piever ef48b66ac4 fix plotly 2018-02-24 01:55:59 +00:00
piever b9d586c009 make plotlyjs use html in ijulia 2018-02-24 01:35:30 +00:00
Andrew Palugniok 1d51982cb0 Fix non-native lims for ticks = :native on PyPlot. 2018-02-23 10:56:57 +00:00
Daniel Schwabeneder 046985277d Merge pull request #1399 from massemanet/fix-ijulia-integration
fix IJulia integration (fix #1365)
2018-02-23 11:44:16 +01:00
Daniel Schwabeneder d679337700 Merge pull request #1405 from daschw/contour
Make contourf work with uniform data
2018-02-23 11:01:56 +01:00
Daniel Schwabeneder 2d5f896069 Merge pull request #1403 from daschw/pyplot-colorbar
reduce pyplot colorbar size for z values with very small or big abs vals
2018-02-23 11:01:24 +01:00
Daniel Schwabeneder de51beebe8 ensure non-unique clims 2018-02-21 17:47:11 +01:00
Andrew Palugniok 80b25657bc Merge pull request #1401 from apalugniok/pgfplots-extra-brackets
Prevent addition of curly braces around style string. (Fixes #1396)
2018-02-21 16:09:46 +00:00
Daniel Schwabeneder 0db60348aa reduce pyplot colorbar size for z values with very small or big absolute values 2018-02-21 17:03:23 +01:00
Andrew Palugniok 5017024557 Fix handling of discrete values with ticks = :native for Plotly. 2018-02-21 14:50:32 +00:00
Andrew Palugniok 94863d69b1 Consider all ticks = false aliases in backends. 2018-02-21 10:17:13 +00:00
Andrew Palugniok 06466b060f Implement :native ticks option. 2018-02-21 10:09:57 +00:00
Daniel Schwabeneder 3ac9f3d9cc Merge pull request #1376 from grahamas/master
Allow animation frame saving frequency to be a variable.
2018-02-20 09:29:13 +01:00
Daniel Schwabeneder d335a0221d Merge pull request #1398 from daschw/time
add Dates.Time recipe (fix #1391)
2018-02-20 09:27:02 +01:00
Daniel Schwabeneder a118d73871 Merge pull request #1400 from daschw/step-ribbon
consider fillrange in step recipes (fix #1393)
2018-02-20 09:26:07 +01:00
Daniel Schwabeneder 6c13d87a00 remove old make_steps function 2018-02-18 22:59:37 +01:00
Daniel Schwabeneder 9e2264c841 consider fillrange in step recipes 2018-02-18 22:49:27 +01:00
Daniel Schwabeneder c0248069a1 add Dates.Time recipe 2018-02-17 23:33:55 +01:00
Andrew Palugniok 5ba4c10a18 Prevent addition of curly braces around style string. 2018-02-17 17:32:53 +00:00
mats cronqvist 82ceb71bd0 fix IJulia integration 2018-02-16 14:46:45 +01:00
Andrew Palugniok a4636fd88d Merge pull request #1390 from apalugniok/plotly-annotations
Fix misplaced Plotly annotations. (Fixes #1356)
2018-02-11 19:08:18 +00:00
Andrew Palugniok e19e25473c Fix misplaced Plotly annotations. 2018-02-11 10:36:12 +00:00
MA Laforge bde415edd7 Add support for Surface plots. 2018-02-06 06:26:07 -05:00
David Anthoff 2004090ce5 Remove GR clone in travis tests 2018-02-05 12:34:39 -08:00
David Anthoff 18ea542cc4 Add GR to REQUIRE 2018-02-05 09:21:06 -08:00
Graham A Smith 11a856fbb3 Allow animation frame saving frequency to be a variable. 2018-01-31 13:12:32 -06:00
Andrew Palugniok 1ed7899296 Merge pull request #1362 from apalugniok/cropped-image
Fix image axis limits and add image movement and resizing.
2018-01-19 15:41:41 +00:00
Andrew Palugniok a79a40b1e8 Allow manual flipping of yaxis for images. 2018-01-18 18:21:26 +00:00
Andrew Palugniok d4075a1ef5 Allow movement and resizing of images. 2018-01-18 16:23:39 +00:00
Andrew Palugniok 99f3b7ae99 Fix axis limits for images. 2018-01-18 16:23:39 +00:00
Daniel Schwabeneder fcb5b355b1 Merge pull request #1361 from daschw/group
fix grouping of series_annotations
2018-01-18 11:13:43 +01:00
Daniel Schwabeneder 43d26af34d Merge pull request #1360 from daschw/pyplot
Update pyplot backend
2018-01-18 11:06:27 +01:00
Daniel Schwabeneder 5e1c67c042 fix grouping of series_annotations 2018-01-18 10:44:35 +01:00
Daniel Schwabeneder 11ef2be506 update pyart3D 2018-01-17 15:18:36 +01:00
Andrew Palugniok 0f9bb7793c Merge pull request #1331 from apalugniok/subplot-labeling
RFC: Subplot labeling. Fixes #998
2018-01-15 23:02:40 +00:00
Daniel Schwabeneder decd7c2f60 Merge pull request #1354 from apalugniok/cropped-image
Fix axis limits not cropping image. Fixes #1296
2018-01-15 14:35:48 +01:00
Daniel Schwabeneder edf88ffdf6 Merge pull request #1353 from wkearn/wsk-bugfix-1329
Check if any of the iterator args are zero
2018-01-15 14:34:49 +01:00
Daniel Schwabeneder 435a7c809b Merge pull request #1352 from wkearn/wsk-bugfix-1823
Uncomment convertToAnyVector for Date/DateTime
2018-01-15 14:34:32 +01:00
Andrew Palugniok d79c66e5b6 Add position aliases. 2018-01-14 11:46:41 +00:00
Andrew Palugniok 10a8520805 Add subplot labeling via annotations. 2018-01-14 11:46:41 +00:00
Will Kearney cf6c16102b Use isempty rather than iszero 2018-01-13 13:57:03 -05:00
Will Kearney 32baaea5cb Check if any of the iterator args are zero
Fixes #1329
2018-01-13 11:20:33 -05:00
Andrew Palugniok 27e2795576 Fix deprecation. 2018-01-13 16:18:08 +00:00
Andrew Palugniok c21f3810b9 Fix axis limits not cropping image. 2018-01-13 15:44:52 +00:00
Will Kearney 877e7ab940 Uncomment convertToAnyVector for Date/DateTime
Fixes #1283
2018-01-13 10:07:27 -05:00
Daniel Schwabeneder 7a9a871be3 Merge pull request #1351 from daschw/gr-loglabels
gr: fix labels with logscales
2018-01-11 22:23:15 +01:00
Daniel Schwabeneder de31ce1c73 Merge pull request #1350 from daschw/tests
update version for tests
2018-01-11 22:16:59 +01:00
Daniel Schwabeneder 8b6dba8301 fix labels with logscales 2018-01-11 21:26:33 +01:00
Daniel Schwabeneder af859b4c13 update version in NEWS.md 2018-01-11 20:30:47 +01:00
Daniel Schwabeneder 9b5295ff00 update version for tests 2018-01-11 20:11:59 +01:00
Josef Heinen c1a94d704e Merge pull request #1349 from jheinen/master
fixed problems with labels in scientific notation
2018-01-11 03:45:24 +01:00
Josef Heinen c2b56878fc fixed problems with labels in scientific notation 2018-01-10 20:30:10 +01:00
Josef Heinen 4757bd89c0 Merge pull request #1249 from apalugniok/pgfplots-scaled-ticks
WIP: Fix scientific formatter for PGFPlots and GR. Fixes #1241
2018-01-10 19:05:13 +01:00
Michael Krabbe Borregaard 1e56bf939d Merge pull request #1347 from mkborregaard/master
update news for 0.14.3
2018-01-10 11:38:38 +01:00
Michael K. Borregaard dbd5ae46dd update news 2018-01-10 11:38:11 +01:00
Daniel Schwabeneder 7c6095b6e8 Merge pull request #1344 from daschw/heatmap-alpha
allow transparency in heatmaps (fix #1342)
2018-01-09 10:19:04 +02:00
Daniel Schwabeneder 04888646e7 fix gr 2018-01-08 13:50:16 +01:00
Daniel Schwabeneder f6ed3fbb76 allow transparency in heatmaps 2018-01-08 12:50:46 +01:00
Daniel Schwabeneder 7bf2918438 Merge pull request #1324 from wkearn/plotlyjs_rgba
Map rgba_string over :color vector and cycle through result
2018-01-08 12:44:47 +02:00
Daniel Schwabeneder 92fefc7089 Merge pull request #1340 from wkearn/framestyle_ticks
Add a check for ticks==nothing or false
2018-01-08 11:51:10 +02:00
Will Kearney e6df4d977d Add a check for ticks==nothing or false
Fixes #1336
2018-01-06 14:54:57 -05:00
Andrew Palugniok 62ca787e6e Fix scientific formatter for GR and PGFPlots. 2017-12-23 00:35:44 +00:00
Andrew Palugniok 32d59fff61 Turn off scaled ticks for PGFPlots. 2017-12-22 23:29:50 +00:00
Andrew Palugniok 1949b6fe0f Merge pull request #1330 from apalugniok/pyplot-alphaImages
Fix PyPlot ignoring alpha values of images. Fixes #1131
2017-12-19 14:19:32 +00:00
Andrew Palugniok 95a5b5025a Fix PyPlot ignoring alpha values of images 2017-12-19 12:05:11 +00:00
Daniel Schwabeneder aa22fd2ff2 Merge pull request #1328 from daschw/gr-grid3d
fix gr 3d grid appearance
2017-12-18 22:57:47 +01:00
Daniel Schwabeneder 50df9a70c9 fix gr 3d grid appearance 2017-12-18 22:15:57 +01:00
Michael Krabbe Borregaard 6d88e150d0 Merge pull request #1327 from mkborregaard/master
Don't return false from abline!
2017-12-18 09:20:36 +01:00
Michael K. Borregaard b1817e513b Don't return false 2017-12-18 09:19:31 +01:00
Michael Krabbe Borregaard ce737a9491 Merge pull request #1326 from mkborregaard/master
Don't add `abline!` if outside plot window
2017-12-18 09:17:36 +01:00
Michael K. Borregaard 6ff4dce62a Don't add abline! if outside plot window 2017-12-18 09:16:51 +01:00
Will Kearney 89b5582d0d Map rgba_string over :color vector and cycle through result 2017-12-17 16:13:35 -05:00
Daniel Schwabeneder 09c5e8a375 Merge pull request #1323 from daschw/plottheme
Reduce number of ticks in heatmap in showtheme recipe
2017-12-17 17:21:18 +01:00
Daniel Schwabeneder a1a7dcd6b8 reduce tick number in heatmap plot 2017-12-17 17:04:05 +01:00
Daniel Schwabeneder d223d872fb Merge pull request #1322 from daschw/line_z
Fix line_z
2017-12-17 17:01:28 +01:00
Andrew Palugniok 91eaa32ad7 Merge pull request #1320 from apalugniok/pyplot-legend
Fix mismatched legend color when linecolor is given. Fixes #1319
2017-12-17 16:00:08 +00:00
Daniel Schwabeneder 6cdccf4353 add missing 'series' 2017-12-17 16:44:20 +01:00
Josef Heinen ac9aee97fd Merge pull request #1318 from jheinen/master
gr: improve PNG output (resolution)
2017-12-17 13:07:16 +01:00
Josef Heinen 5be95be9ae gr: improve PNG output (resolution) 2017-12-17 12:52:20 +01:00
Andrew Palugniok e402f5dfce Fix mismatched legend color when linecolor is given. 2017-12-16 20:11:11 +00:00
Michael Krabbe Borregaard 61be113714 Merge pull request #1317 from apalugniok/3d-marker_z
3D marker_z handling. Fixes #1205
2017-12-16 10:08:13 +01:00
Andrew Palugniok a637f43edd Only base clims on z values when series is colored by z. 2017-12-15 22:49:46 +00:00
Daniel Schwabeneder 4bb43887a4 Merge pull request #1314 from daschw/showtheme
update showtheme recipe
2017-12-15 14:04:19 +01:00
Daniel Schwabeneder 802b20be6f update showtheme recipe 2017-12-15 10:30:56 +01:00
Michael K. Borregaard 216a9c3666 reactivate precompilation 2017-12-15 09:24:00 +01:00
Michael K. Borregaard d52b2a9adc update news 2017-12-15 09:22:20 +01:00
Michael K. Borregaard 81782c3927 turn off precompilation 2017-12-15 09:18:37 +01:00
Michael Krabbe Borregaard 2c2ebbba0e Merge pull request #1313 from joshday/jd/fix-histogram
Fix plotly histogram
2017-12-15 09:15:06 +01:00
Josh Day 3d323a734d fix plotly histogram 2017-12-15 00:22:05 -05:00
Michael Krabbe Borregaard 93263a61b1 Merge pull request #1301 from JuliaPlots/sd/fixlines
fix JuliaGL/GLVisualize.jl#238
2017-12-15 05:04:38 +01:00
Michael Krabbe Borregaard 8b551e5285 Merge pull request #1311 from apalugniok/ribbons
Fix ribbons slicing for several series. Fixes #1302
2017-12-14 22:13:44 +01:00
Michael Krabbe Borregaard e11c91ddd9 Merge pull request #1308 from rdeits/line-z-example
add line_z and marker_z example
2017-12-14 22:05:30 +01:00
Andrew Palugniok 938c83533b Fix slicing of ribbons. 2017-12-14 19:25:59 +00:00
Daniel Schwabeneder 46136d616f Merge pull request #1310 from daschw/release
precompile on
2017-12-14 11:33:19 +01:00
Daniel Schwabeneder 8fe902e96c precompile on 2017-12-14 11:29:55 +01:00
Daniel Schwabeneder 2fb7dddffb Merge pull request #1309 from daschw/release
prepare release
2017-12-14 11:25:30 +01:00
Daniel Schwabeneder 5d1876ab6d precompile off 2017-12-14 11:03:52 +01:00
Daniel Schwabeneder 1aa4e7eee6 update news.md 2017-12-14 11:02:59 +01:00
Daniel Schwabeneder 995e12bd57 Merge pull request #1279 from daschw/plottheme
New PlotTheme type
2017-12-14 09:38:49 +01:00
Robin Deits 349b6e8254 fix typo 2017-12-13 18:59:15 -05:00
Robin Deits ee6dbb9ac7 add line_z and marker_z example 2017-12-13 18:55:48 -05:00
Daniel Schwabeneder 5b85cd83f2 Merge pull request #1307 from wkearn/pyplot_legend_style
Add linestyle argument to the legend
2017-12-13 22:27:59 +01:00
Will Kearney 1645c3f66b Add linestyle argument to the legend
This fixes #1305
2017-12-13 15:07:54 -05:00
Michael Krabbe Borregaard 084d45141d Merge pull request #1304 from joshday/jd/histogram
plotly: bar_width and stroke_width support for bar plots
2017-12-12 21:50:45 +01:00
Josh Day 50bec7a461 cleanup 2017-12-12 15:18:17 -05:00
Josh Day f80afddd8f add strokewidth and bar_width for plotly's bar 2017-12-12 15:15:12 -05:00
Andrew Palugniok 5d2c630b05 Merge pull request #1299 from apalugniok/gr-logticks
Fix default log scale ticks in GR backend. Fixes #1203
2017-12-12 17:37:07 +00:00
Andrew Palugniok f655b2313c Fix default log scale ticks in GR backend. 2017-12-12 16:45:26 +00:00
SimonDanisch 2a819c2849 fix JuliaGL/GLVisualize.jl#238 2017-12-11 12:34:21 +01:00
Michael Krabbe Borregaard 0ef13dcf7a Merge pull request #1300 from mkborregaard/master
RFC: abline! does not change axis limits; fix: #1297
2017-12-11 12:12:52 +01:00
Michael K. Borregaard 5e5f3c1e95 abline! does not change axis limits 2017-12-11 10:26:33 +01:00
Daniel Schwabeneder c76ca2dd6e add showtheme recipe 2017-12-11 09:27:02 +01:00
Daniel Schwabeneder ab490b8f95 Merge pull request #1295 from wkearn/font_bugfix
Use the :fontsize keys so the scalefontsizes command works
2017-12-08 09:52:17 +01:00
Will Kearney bd42d9e7cc Use the :fontsize labels so the scalefontsizes command works
Fixes #1294
2017-12-07 20:56:54 -05:00
Michael Krabbe Borregaard e3d8f4a223 Merge pull request #1291 from mkborregaard/postrelease
reactivate precompilation
2017-12-07 13:13:57 +01:00
Michael K. Borregaard 34567e1282 reactivate precompilation 2017-12-07 13:12:02 +01:00
Michael Krabbe Borregaard acfb14a1f5 Merge pull request #1289 from mkborregaard/master
update news
2017-12-07 13:11:03 +01:00
Michael K. Borregaard 6a3495819a update news 2017-12-07 13:10:26 +01:00
Michael Krabbe Borregaard bf6e8d3c1f Merge pull request #1288 from mkborregaard/add-scatterpath
added scatterpath series recipe
2017-12-07 12:04:08 +01:00
Michael Krabbe Borregaard 66f08cc1a3 fix typo on docstring 2017-12-07 08:52:09 +01:00
Michael Krabbe Borregaard 470012501b Merge pull request #1286 from mforets/patch-1
say how to get the list of attributes in `?plot`
2017-12-07 08:51:19 +01:00
Marcelo Forets 986bd02e5e Update plot.jl 2017-12-06 22:33:47 -03:00
Michael K. Borregaard 9b8510ab3e added scatterpath series recipe 2017-12-06 23:19:35 +01:00
Marcelo Forets 0db9710e0f say how to get the list of attributes in ?plot 2017-12-06 17:46:35 -03:00
Michael Krabbe Borregaard 7f231057fd Merge pull request #1284 from JuliaPlots/tbreloff-patch-1
change author section
2017-12-06 07:01:26 +01:00
Tom Breloff bb687e47cc change author section 2017-12-05 21:14:08 -05:00
Daniel Schwabeneder 0f3928ec9a fix kw support 2017-12-05 22:29:56 +01:00
Daniel Schwabeneder a8380334df fix kw support 2017-12-05 22:28:22 +01:00
Daniel Schwabeneder 70bead1eb1 support old PlotTheme type 2017-12-05 22:09:18 +01:00
Michael Krabbe Borregaard df63530b89 Merge pull request #1282 from wkearn/wsk/scale-fix
Update iterator properly in _subplot_setup
2017-12-05 20:44:08 +01:00
Daniel Schwabeneder 34dedd36e6 Merge pull request #1281 from hayatoikoma/fix_grayimg
Fix the display of an grayscale image for image-nonsupported backends
2017-12-05 19:43:38 +01:00
Will Kearney eb6c15caba Update iterator properly
This seems to fix #1266
2017-12-05 13:12:10 -05:00
Hayato Ikoma 39a7815f80 Fix the display of an grayscale image for image-nonsupported backends 2017-12-05 08:54:54 -08:00
Daniel Schwabeneder 4bbe367aab Merge pull request #1278 from JackDevine/master
Examples are limited to 90 columns.
2017-12-05 16:53:41 +01:00
Daniel Schwabeneder 7d50c7e4fe Merge pull request #1280 from daschw/default-magic
Default magic
2017-12-05 16:51:49 +01:00
JackDevine 5d0adb1783 Add comma 2017-12-05 08:36:04 +13:00
Daniel Schwabeneder 81ef4bdee8 remove _magic_arguments 2017-12-04 19:45:21 +01:00
Daniel Schwabeneder 2cf365d36d Allow magic arguments in default() 2017-12-04 19:34:02 +01:00
Daniel Schwabeneder 22d8ecffe5 fix typo 2017-12-04 15:53:45 +01:00
Daniel Schwabeneder b987331b4f update new heme() function 2017-12-04 14:54:35 +01:00
Jack Devine eff8159d46 Merge branch 'master' into master 2017-12-04 22:44:31 +13:00
Jack Devine f0e4f4dc9d Merge branch 'master' into master 2017-12-04 22:42:26 +13:00
JackDevine e02a70249e Examples are limited to 90 columns.
Thanks @daschw for pointing out the correct place to make these
changes. I have also changed the explanation texts, which may be a
little overkill, but I do think that the style guides apply to Markdown
string too (could be wrong though).
2017-12-04 22:34:45 +13:00
Daniel Schwabeneder 899afd625a add new heme() function 2017-12-04 09:16:00 +01:00
Daniel Schwabeneder 863ec08681 Merge pull request #1274 from daschw/pyplot-framestyle_grid
PyPlot: set tick marks color to match grid color for framestyle = :grid
2017-12-02 10:16:08 +01:00
Daniel Schwabeneder 28c958fb20 set tick marks color to grid color for framestyle = :grid 2017-12-01 16:14:59 +01:00
Daniel Schwabeneder 4c9f4a55d5 Merge pull request #1271 from daschw/gr-legend
allow to change the foreground_color_legend in gr
2017-11-30 16:50:18 +01:00
Daniel Schwabeneder a7fcf77251 allow to change the foreground_color_legend in gr 2017-11-30 16:26:48 +01:00
Daniel Schwabeneder a57745ed64 Merge pull request #1270 from daschw/grid
Extend grid lines to axes limits for GR (and GLVisualize)
2017-11-30 13:00:48 +01:00
Daniel Schwabeneder dd16c7d560 extend grid lines to axes limits 2017-11-30 11:47:20 +01:00
Daniel Schwabeneder 7f3780a20d Merge pull request #1269 from daschw/tests
use new StatPlots df syntax in testexamples
2017-11-30 11:16:10 +01:00
Daniel Schwabeneder 99c8713e7f Merge pull request #1268 from daschw/contour-fill
fix axes limits for fill=true in 3d plots (fix #1267)
2017-11-30 11:15:53 +01:00
Daniel Schwabeneder 49eb2c426d update testexample 30 2017-11-30 11:05:05 +01:00
Daniel Schwabeneder 4c55ff5df8 use new StatPlots df syntax in testexamples 2017-11-30 11:01:12 +01:00
Daniel Schwabeneder 714f8dea1d fix axes limits for fill=true in 3d plots 2017-11-30 09:45:09 +01:00
Josef Heinen 1419a919aa Merge pull request #1260 from jheinen/master
gr: added support for non-string legend labels
2017-11-22 21:46:38 +01:00
Josef Heinen 6d4717fc96 gr: added support for non-string legend labels 2017-11-22 21:26:53 +01:00
Josef Heinen 6a8f4caee3 Merge pull request #1258 from jheinen/master
gr: fix 'hidden window' problem after savefig
2017-11-21 14:58:12 +01:00
Josef Heinen dbf96a69d7 gr: fix 'hidden window' problem after savefig 2017-11-21 14:45:00 +01:00
Daniel Schwabeneder 0519f18bd7 Merge pull request #1257 from daschw/pyplot-fonts
fix guidefontamily typo in pyplot
2017-11-20 16:56:38 +01:00
Daniel Schwabeneder f7765c80b8 fix guidefontamily typo in pyplot 2017-11-20 16:54:05 +01:00
Daniel Schwabeneder f2e2ffa170 Merge pull request #1255 from daschw/fonts
Allow setting fonts in recipes (fix #555)
2017-11-20 15:17:33 +01:00
Daniel Schwabeneder b2a816452d Merge pull request #1242 from biggsbiggsby/patch-1
Generate a palette for each gif frame; Fixes #1239
2017-11-20 11:01:28 +01:00
Daniel Schwabeneder 299e9a85f2 Merge pull request #1253 from romainFr/pull-request/c01d8199
Plotly : always define range explicitely. Solves axis linking #1124
2017-11-20 08:40:12 +01:00
Daniel Schwabeneder ad34863bd6 Merge pull request #1254 from daschw/axes-limits
expand axes extrema for heatmap edges
2017-11-20 08:40:01 +01:00
Daniel Schwabeneder 129a91b36f update arg description 2017-11-19 21:18:04 +01:00
Daniel Schwabeneder 78f10de8cd update inspectdr 2017-11-19 20:44:22 +01:00
Daniel Schwabeneder 189b2e5cd6 update glvisualize 2017-11-19 20:36:26 +01:00
Daniel Schwabeneder d4f67ec3b5 update glvisualize 2017-11-19 20:31:28 +01:00
Daniel Schwabeneder 7ec54b9c2e update plotly(js) 2017-11-19 19:54:52 +01:00
Daniel Schwabeneder 60d20ea998 update pyplot 2017-11-19 18:15:22 +01:00
Daniel Schwabeneder e80a73cc1c fix magic font argument and cascading font defaults 2017-11-19 16:59:54 +01:00
Daniel Schwabeneder 6e51a08694 fix errors 2017-11-19 15:36:11 +01:00
Daniel Schwabeneder 0da6f6b4a4 update gr 2017-11-19 15:32:30 +01:00
Daniel Schwabeneder ba3e75e710 fix errors 2017-11-19 15:16:49 +01:00
Daniel Schwabeneder 8fee5e0de7 implement titlefont legendfont tickfont and guidefont functions to construct font objects from subplots and axes 2017-11-19 14:58:30 +01:00
Daniel Schwabeneder 68a060b7eb implement titlefont, legendfont, tickfont and guidefont magic keyword arguments 2017-11-19 14:31:30 +01:00
Daniel Schwabeneder 9f5be974b6 add fontfamily, fontsize, fonthalign, fontvalign, fontrotation, fontcolor keywords 2017-11-19 14:02:49 +01:00
Daniel Schwabeneder ea976d5f08 expand axes extrema for heatmap edges 2017-11-19 12:53:11 +01:00
Daniel Schwabeneder 892d68e792 Merge pull request #1251 from daschw/pyplot-legend
PyPlot: change legend symbols for shapes and filled plots
2017-11-18 08:43:23 +01:00
Romain Franconville 5a0744e2f1 Remove commented code 2017-11-17 16:06:14 -05:00
Romain Franconville c01d8199f9 Also include scaling 2017-11-17 15:29:55 -05:00
Romain Franconville df023d6bdb Always define axis range explicitely 2017-11-17 15:02:16 -05:00
Daniel Schwabeneder 4bfb562477 remove extra space 2017-11-17 13:01:13 +01:00
Daniel Schwabeneder 4bc01b92bd avoid too big linewidths in legend 2017-11-17 12:59:20 +01:00
biggsbiggsby ee0f4e11ea Update animation.jl
Changed palette for each frame to an option, made the default palette a lossless bmp file for best quality/filesize, but still compatible with FFMPEG 3.4 on Win7 x64
2017-11-17 12:35:36 +01:00
Daniel Schwabeneder 1aa780f0a2 change legend symbols for shapes and filled plots on pyplot 2017-11-17 11:33:10 +01:00
biggsbiggsby cf58f3cbf2 Update animation.jl
Generates a color palette for each frame (instead of each animation) to improve quality, and avoid palette file format issues in FFMPEG 3.4
2017-11-17 10:30:23 +01:00
Michael Krabbe Borregaard 18619e9010 Merge pull request #1246 from huckl3b3rry87/pull-request/ae37dce0
allow legend to be outside for pgfplots()
2017-11-14 20:33:20 +00:00
Huckleberry Febbo ae37dce0f3 allow legend to be outside for pgfplots() 2017-11-14 13:43:17 -05:00
Michael Krabbe Borregaard e48831d092 Merge pull request #1243 from apalugniok/polar-output
Correct polar tick alignment for PGFPlots.
2017-11-14 15:05:15 +01:00
Andrew Palugniok 99f25ef744 Fix typo. 2017-11-14 13:49:53 +00:00
biggsbiggsby acf6e86c0f gif animation.jl
Change palette from png to gif to avoid png encoding bug in ffmpeg
2017-11-14 09:39:59 +01:00
Michael Krabbe Borregaard 19192b622b Merge pull request #1224 from hessammehr/master
Fix for #1138
2017-11-13 17:06:03 +01:00
Michael Krabbe Borregaard 183f399341 Merge pull request #1208 from apalugniok/polar-output
Polar plots consistency
2017-11-13 05:17:46 +01:00
Andrew Palugniok 240c1efab9 Improve default radial axis padding. 2017-11-12 18:09:08 +00:00
Andrew Palugniok 8bbdb0f1b8 Adds radial data filtering for points within axis limits. 2017-11-12 18:08:40 +00:00
Daniel Schwabeneder ecee135a63 Merge pull request #1230 from daschw/pgfplots-legend-symbols
change pgfplots legend symbol for shapes and filled plots (fix #1215)
2017-11-09 09:57:43 +01:00
Daniel Schwabeneder 51d4630405 change pgfplots legend symbol for shapes and filled plots 2017-11-08 22:02:40 +01:00
Michael Krabbe Borregaard 60e7695546 Merge pull request #1228 from PallHaraldsson/patch-1
Typo?
2017-11-07 12:29:10 +01:00
Páll Haraldsson 6d14a858a3 Typo?
Guessing here, 0.2.0 must be really old?
2017-11-07 11:11:46 +00:00
Andrew Palugniok 08a6f3af36 Allow custom radial ticks for GR. Fix polar ylims for non-zero ymin values in GR. 2017-11-05 10:37:51 +00:00
Andrew Palugniok cc43202e8f Fix radial axis tick alignment for GR. 2017-11-04 23:04:49 +00:00
Hessam Mehr 8fb3f3b1c9 Fixed for #1138 2017-11-04 15:20:41 -07:00
Andrew Palugniok 2fe2ff474c Implement grid attributes for polar plots. 2017-11-04 21:27:02 +00:00
Andrew Palugniok f0ad851aa7 Make radial axis vertical. 2017-11-03 19:45:17 +00:00
Daniel Schwabeneder ab29a712c0 Merge pull request #1221 from daschw/gr-contour-lw
allow setting the linewidth for contour plots in GR
2017-11-03 11:50:30 +01:00
Daniel Schwabeneder 8dd264c4da remove unnecessary line 2017-11-03 10:15:55 +01:00
Daniel Schwabeneder 40282ae23a allow setting the linestyle for contours on GR 2017-11-03 10:02:16 +01:00
Josef Heinen ed75369c6d Merge pull request #1220 from jheinen/master
gr: use correct aspect ratio (fixes #1219)
2017-11-02 22:15:30 +01:00
Josef Heinen b34f4141a2 Update gr.jl 2017-11-02 21:53:11 +01:00
Daniel Schwabeneder 5d5d8f073a allow setting the linewidth for contour plots in GR 2017-11-02 20:38:06 +01:00
Josef Heinen f690961af2 gr: use correct aspect ratio (fixes #1219) 2017-11-02 20:12:11 +01:00
Andrew Palugniok 12aa43ff5f Fix deprecations. 2017-11-02 16:33:05 +00:00
Andrew Palugniok 4f171e3eb5 Add handling of polar axes. 2017-11-02 16:32:57 +00:00
Daniel Schwabeneder 671f5c3a68 Merge pull request #1213 from daschw/fillrange
Make `fill = true` fill to zero
2017-10-31 09:21:47 +01:00
Daniel Schwabeneder 1f12185441 Merge pull request #1214 from apalugniok/plotly-colorbar
Fix colorbar always displaying in Plotly. (Fixes #1211)
2017-10-31 09:21:31 +01:00
Andrew Palugniok a3e599e38d Fix colorbar always displaying in Plotly. 2017-10-30 19:50:02 +00:00
Daniel Schwabeneder 5a3779e431 fill = true fills to 0 2017-10-30 10:49:22 +01:00
Michael Krabbe Borregaard 5ddcdef1b4 Merge pull request #1210 from mkborregaard/master
add hline marker to pgfplots
2017-10-27 19:22:11 +02:00
Michael K. Borregaard 7b6b44b284 add hline to pgfplots 2017-10-27 15:52:32 +02:00
Michael Krabbe Borregaard a691d5c7e8 Merge pull request #1187 from anowacki/movie-compatibility
Animations: improve movie compatibility when using ffmpeg
2017-10-25 11:44:03 +02:00
Josef Heinen 7cf40b16df Merge pull request #1206 from jheinen/master
gr: implement title location
2017-10-24 20:06:00 +02:00
Josef Heinen ad6b707abf gr: implement title location 2017-10-24 19:50:18 +02:00
Andy Nowacki 133052b58c Animations: improve movie compatibility when using ffmpeg
Add the -pix_fmt yuv420p option when using ffmpeg to save
animations with the mov or mp4 commands. This improves
compatibility of the movie files since many players do not
support the ffmpeg defaults.

To do this, add a third positional argument to `buildanimation`
to specify if we want an animated GIF file.  The default
is `true`.

See the following for more information:
- https://trac.ffmpeg.org/wiki/Encode/H.264 ('Compatibility')
- https://apple.stackexchange.com/questions/166553/why-wont-video-from-ffmpeg-show-in-quicktime-imovie-or-quick-preview
2017-10-23 14:16:12 +01:00
Michael Krabbe Borregaard 226bf7e705 Merge pull request #1199 from mkborregaard/make-revise-possible
Make revise possible
2017-10-21 07:40:53 +02:00
Michael K. Borregaard cdcbdc308c include backend files 2017-10-20 22:45:04 +02:00
Daniel Schwabeneder 5bfa6151ac Merge pull request #1195 from apalugniok/pgfplots-logticks
Fix log scale ticks LaTeX error for PGFPlots. (fixes #1192)
2017-10-19 17:38:44 +02:00
Daniel Schwabeneder 020760f0c8 Merge pull request #1190 from daschw/tests
Minor test_example changes (close #1162)
2017-10-19 17:38:25 +02:00
Andrew Palugniok 0c4750547a Fix LaTeX error for log scale ticks. 2017-10-19 15:30:45 +01:00
Michael Krabbe Borregaard 9c46509f84 Merge pull request #1185 from H-M-H/animation_fix
Use ffmpeg & palette to create gifs, closes #1050
2017-10-18 22:28:56 +02:00
Daniel Schwabeneder 928a2d646b Merge pull request #1189 from daschw/spy
use fg_color for matrices with unique non-zeros in spy recipe
2017-10-18 21:31:54 +02:00
Daniel Schwabeneder 7ffd1fc9c2 some further improvements for framestyle and group testexamples 2017-10-18 21:24:28 +02:00
Daniel Schwabeneder 6d4f456826 fix framestyle testexample 2017-10-18 21:06:37 +02:00
Daniel Schwabeneder e78bf87377 update some test_examples 2017-10-18 20:51:43 +02:00
Daniel Schwabeneder c76fc5b909 use fg_color for matrices with unique non-zeros in spy recipe 2017-10-18 20:47:06 +02:00
Michael Krabbe Borregaard eecd14f53a Merge pull request #1036 from JuliaPlots/fbot/deps
Fix deprecations
2017-10-17 21:45:13 +02:00
femtocleaner[bot] ef29b4a5b0 Fix deprecations 2017-10-17 09:59:09 +00:00
Daniel Schwabeneder d6748792e9 Merge pull request #1184 from daschw/gr-box-flip
fix combination of box framestyle and flip on gr
2017-10-17 09:23:47 +02:00
Daniel Schwabeneder ae9c26504d Merge pull request #1183 from daschw/spy
spy recipe: change default color for matrices with unique values
2017-10-17 09:23:25 +02:00
HMH 7f7b543e18 Use ffmpeg & palette to create gifs, closes #1050
First let ffmpeg generate a colorpalette so it uses the limited amount
of colors available properly and only then create the actual gif using
the generated palette. This replaces convert completely as it yields far
worse results for long gifs and is considerably slower.
2017-10-16 23:53:00 +02:00
Daniel Schwabeneder 2464d7bd9a fix combination of box framestyle and flip on gr 2017-10-16 21:46:23 +02:00
Daniel Schwabeneder 3ce71999e2 spy recipe: change default color for matrices with unique values 2017-10-16 21:24:13 +02:00
Daniel Schwabeneder 7f9d83c088 Merge pull request #1168 from darwindarak/dd/reset-defaults
RFC: Add (back?) ability to reset defaults
2017-10-16 20:17:02 +02:00
Daniel Schwabeneder e8f6e7b56c Merge pull request #1181 from daschw/colorbar
Fix GR annotations with colorbar (fix #1179)
2017-10-16 19:19:03 +02:00
Daniel Schwabeneder 94c0957e11 draw colorbar in the end 2017-10-16 18:04:46 +02:00
Michael Krabbe Borregaard b0ffe03c99 Merge pull request #1178 from JuliaPlots/patch-appveyor-readme
Fix appveyor badge
2017-10-15 13:01:03 +02:00
Michael Krabbe Borregaard 8ea878a2a2 Fix appveyor badge 2017-10-15 12:43:15 +02:00
Michael Krabbe Borregaard bbbab914d8 Merge pull request #1177 from JuliaPlots/revert-1176-no_copy
Revert "Don't copy input arguments - fix #1175"
2017-10-14 22:56:12 +02:00
Michael Krabbe Borregaard 735a45b4e9 Revert "Don't copy input arguments - fix #1175" 2017-10-14 22:55:23 +02:00
Michael Krabbe Borregaard a4558302f2 Merge pull request #1176 from mkborregaard/no_copy
Don't copy input arguments - fix #1175
2017-10-14 22:39:00 +02:00
Michael K. Borregaard d8ba26f790 Don't copy input arguments into d 2017-10-14 08:52:51 +02:00
Michael Krabbe Borregaard dcc3055dec Merge pull request #1174 from mkborregaard/fix_hist_weights
fix `weights` in `histogram`; closes #1173
2017-10-13 17:09:06 +02:00
Michael K. Borregaard 6db7116db9 add weights argument to histogram example 2017-10-13 17:08:26 +02:00
Michael K. Borregaard 422988b3f6 fix weights in histogram 2017-10-13 12:38:56 +02:00
Michael Krabbe Borregaard 2f04c5fec8 Merge pull request #1141 from apalugniok/apalugniok-test2
Adds camera attribute for 3D plots.
2017-10-13 00:26:39 +02:00
Pietro Vertechi e811aa44b0 Merge pull request #1164 from piever/svg
fix #750 : save svg plotlyjs
2017-10-12 14:09:41 +01:00
Darwin Darakananda 4c7ab232d5 Add (back?) ability to reset defaults 2017-10-11 10:25:54 -07:00
Daniel Schwabeneder fc42641469 Merge pull request #1163 from daschw/gr-flip
fix flip for GR
2017-10-11 14:53:40 +02:00
Michael Krabbe Borregaard b71cfce105 Merge pull request #1155 from mkborregaard/newspy
RFC: New spy implementation
2017-10-11 09:01:58 +02:00
Pietro Vertechi be55c1ad6f save svg plotlyjs 2017-10-10 23:29:18 +01:00
Daniel Schwabeneder 979a846298 fix flip for GR 2017-10-10 23:26:39 +02:00
Daniel Schwabeneder a4c59ce964 Merge pull request #1153 from daschw/gr-marker_z
Fix marker_z for 3D plots on GR (test example 24) (fix #1152)
2017-10-10 21:06:01 +02:00
Daniel Schwabeneder 208c70f933 Merge pull request #1161 from daschw/tests
update version for tests
2017-10-10 19:51:47 +02:00
Daniel Schwabeneder 9dcbc06b3d update version for tests 2017-10-10 19:50:45 +02:00
Josef Heinen e3f6da382d Merge pull request #1158 from jheinen/master
gr: fixed colorbar problem for flipped axes
2017-10-10 12:20:49 +02:00
Josef Heinen cc201ce4e7 gr: fixed colorbar problem for flipped axes 2017-10-10 10:54:29 +02:00
Michael K. Borregaard 08bdd11410 New spy implementation 2017-10-09 21:19:32 +02:00
Daniel Schwabeneder bac192d825 remove unnecessary lines 2017-10-09 17:20:36 +02:00
Daniel Schwabeneder 55c968f138 fix marker_z for 3D plots - draw colorbar once per series 2017-10-09 17:13:44 +02:00
Andrew Palugniok 6df2bc2790 Clarify gr.jl setspace() rounding syntax. 2017-10-09 11:40:04 +01:00
Andrew Palugniok f8576c7135 Remove :view alias for :camera attribute. 2017-10-09 11:33:24 +01:00
Daniel Schwabeneder 7d220f571d Merge pull request #1142 from daschw/line_z
Fix linestyle on GR (fix #1139)(fix #1123)
2017-10-08 13:50:43 +02:00
Christopher Rackauckas eda1ebe36b Fix docs link
Ugh, flubbed that one. There's the `http://`
2017-10-07 13:24:03 -07:00
Christopher Rackauckas ae4288719f Merge pull request #1145 from JuliaPlots/ChrisRackauckas-patch-3
New docs page link
2017-10-07 13:22:53 -07:00
Christopher Rackauckas a016b655f4 New docs page link 2017-10-07 13:06:08 -07:00
Andrew Palugniok f4bc2e0649 Convert :camera attribute input for GR. 2017-10-07 20:05:53 +01:00
Andrew Palugniok cf6f7035b6 Added extra :camera aliases. 2017-10-07 20:05:05 +01:00
Daniel Schwabeneder cb7498a30d fix linestyle on gr 2017-10-07 21:02:14 +02:00
Andrew Palugniok ccb3cadd2a Implemented camera attribute for Plotly/PlotlyJS. 2017-10-06 20:47:04 +01:00
Andrew Palugniok 0fb1a0ed6b Implemented camera attribute for PGFPlots. 2017-10-06 20:47:04 +01:00
Andrew Palugniok 94e79f1e4c Implemented camera attribute for PyPlot. 2017-10-06 20:46:25 +01:00
Andrew Palugniok 65a28e76e5 Implemented camera attribute for GR. 2017-10-06 20:46:25 +01:00
Andrew Palugniok 0c5a9172ab Added camera attribute processing. 2017-10-06 20:46:25 +01:00
Daniel Schwabeneder 1c21a0d609 Merge pull request #1132 from darwindarak/dd/pyplot-linez
RFC: Fix `line_z` for PyPlot backend (fix #1021)
2017-10-06 09:24:57 +02:00
Darwin Darakananda 16d18552f8 Allow line_z to specify color across multiple lines 2017-10-05 20:49:17 -07:00
Daniel Schwabeneder 001cb80cfe Merge pull request #1120 from daschw/axis-false
showaxis attribute
2017-10-05 23:17:55 +02:00
Daniel Schwabeneder bd14d9c07b Merge pull request #1108 from AnkurD/colorbar
Colorbar takes font style from Y Axis
2017-10-05 13:58:41 +02:00
Michael Krabbe Borregaard 08bbde327f Merge pull request #1135 from mkborregaard/drop-travis-pyplot
Drop tests for pyplot (temporarily)
2017-10-05 13:42:45 +02:00
Michael K. Borregaard 12488bf2b0 Drop tests for pyplot (temporarily)
revisit 12 oct
2017-10-05 13:24:21 +02:00
Michael Krabbe Borregaard 4bf0d69f79 Merge pull request #1133 from JackDevine/legend-markers
PyPlot legends now show marker types.
2017-10-05 12:58:02 +02:00
Michael K. Borregaard 78e3b69cc5 prec 2017-10-05 12:30:29 +02:00
Michael K. Borregaard 531a38bc39 no prec 2017-10-05 12:28:52 +02:00
Michael K. Borregaard 77fa5454e2 remember backticks 2017-10-05 12:27:51 +02:00
Michael Krabbe Borregaard 0cd382a1ce Merge pull request #1129 from mkborregaard/fix-function-vector
Apply automatic limits for vectors of functions
2017-10-05 12:26:04 +02:00
Michael K. Borregaard 9fc0c98722 precompile 2017-10-05 12:25:04 +02:00
Michael Krabbe Borregaard af23074820 Merge pull request #1134 from mkborregaard/patch-release
ready for release
2017-10-05 12:22:52 +02:00
Michael K. Borregaard fdf2d5b20b ready for release 2017-10-05 12:22:12 +02:00
Michael K. Borregaard b37f2141a1 Also import px and pct into PlotMeasures
Necessary for example 29 to work
2017-10-05 12:12:54 +02:00
JackDevine 520dc80eeb Added marker strokes 2017-10-05 22:58:18 +13:00
JackDevine 878fa48afa PyPlot legends now show marker types. 2017-10-05 21:35:38 +13:00
Darwin Darakananda 514cd1bd37 normalize colors even when plotting without colorbars 2017-10-04 15:10:36 -07:00
Darwin Darakananda f5ee5ea814 Fix line_z for PyPlot backend
`LineCollection` expects an array with pairs of coordinates,
corresponding to the starting and ending points of each segment.
2017-10-04 14:26:35 -07:00
Daniel Schwabeneder e3b0f7cd94 pgfplots: remove axis arrows and implement origin and zerolines framestyles 2017-10-04 13:40:56 +02:00
Michael K. Borregaard 5567038cec simplify 2017-10-04 11:47:20 +02:00
Michael K. Borregaard 0327c9101e slight refactor for clarity 2017-10-04 11:44:20 +02:00
Michael K. Borregaard 3d86d5f530 Apply automatic limits for vectors of functions 2017-10-04 11:38:32 +02:00
Michael K. Borregaard 073724a84c reactivate 2017-10-03 15:14:10 +02:00
Michael Krabbe Borregaard 6a129bfe92 Merge pull request #1128 from mkborregaard/hotfix-measures
Make Measures available in Plots in general too
2017-10-03 15:12:27 +02:00
Michael K. Borregaard 53a4c36aab Make Measures available in Plots in general too 2017-10-03 15:12:01 +02:00
Michael Krabbe Borregaard eb36f4eca0 Merge pull request #1127 from mkborregaard/release-13
Reactivate precompilation
2017-10-03 10:31:29 +02:00
Michael K. Borregaard 54838d386d Reactivate precompilation 2017-10-03 10:31:05 +02:00
Michael Krabbe Borregaard 0235821f24 Merge pull request #1126 from mkborregaard/release-13
release-0.13
2017-10-03 10:29:39 +02:00
Michael K. Borregaard efd116ec52 deactivate precompilation 2017-10-03 10:29:06 +02:00
Michael K. Borregaard ff0f1c5c50 update news.md 2017-10-03 10:28:54 +02:00
Michael Krabbe Borregaard 6bbb26d2ea Merge pull request #855 from mkborregaard/submodule-measure
Add submodule PlotMeasures (fix #821)
2017-10-02 15:20:41 +02:00
Michael K. Borregaard 2a1140c0b3 include PlotMeasures in example 29 2017-10-02 15:07:16 +02:00
Michael Krabbe Borregaard a80c7ada27 Merge pull request #1116 from jw3126/replaceD
replace d by plotattributes inside recipes
2017-10-02 14:46:11 +02:00
Michael Krabbe Borregaard 9bc6d0c7d1 Merge pull request #1122 from mkborregaard/bar_width_fix
Fix barwidth to minimum(diff) not mean(diff)
2017-10-02 11:16:25 +02:00
Michael K. Borregaard f3566a4933 sort before taking diff 2017-10-02 10:02:39 +02:00
Michael K. Borregaard cd958a6c68 Fix barwidth to minimum(diff) not mean(diff) 2017-10-02 08:53:41 +02:00
Michael K. Borregaard 4f6a920f72 Import Measures into Plots 2017-10-02 08:28:25 +02:00
Michael K. Borregaard b717cf1dc0 Rename submodule to PlotMeasures 2017-10-02 08:24:59 +02:00
Michael K. Borregaard 33e5a51a28 add submodule Measure 2017-10-02 07:59:04 +02:00
Daniel Schwabeneder ff751ca423 implement showaxis and basic framestyles for pgfplots 2017-10-01 20:29:46 +02:00
Daniel Schwabeneder 93df7f4367 implement showaxis for glvisualize 2017-10-01 19:09:24 +02:00
Josef Heinen dca5a7ce4d Merge pull request #1119 from apalugniok/master
Change GR default 3D view angles
2017-10-01 12:50:51 +02:00
apalugniok bf4dd78a7d Change GR default 3D view angles to match PyPlot 2017-10-01 10:29:44 +01:00
Jan Weidner 489e484117 bump required RecipesBase to 0.2.3 2017-09-29 23:24:58 +02:00
Jan Weidner 6e1cc8449b replace d by plotattributes inside recipes 2017-09-29 23:09:34 +02:00
Daniel Schwabeneder 148ad8032f implement showaxis for pyplot 2017-09-29 20:16:27 +02:00
Daniel Schwabeneder 6d53594850 implement showaxis for plotly 2017-09-29 15:09:28 +02:00
Daniel Schwabeneder ee7a3b3686 general axis fixes and improvemennts 2017-09-29 13:41:54 +02:00
Daniel Schwabeneder 18188516ec implement showaxis attribute for gr 2017-09-29 11:48:17 +02:00
Michael Krabbe Borregaard bcc2f089be Merge pull request #1115 from mkborregaard/default-function-limits
Function default x limits: fix #1109
2017-09-29 09:44:54 +02:00
Michael K. Borregaard 07843c00d3 Add negative ranges 2017-09-29 09:18:20 +02:00
Daniel Schwabeneder de12915eba Merge pull request #1112 from daschw/tick-orientation
Implement new tick_direction attribute for GR, Plotly(JS), PyPlot, GLVisualize and PGFPlots
2017-09-29 09:08:52 +02:00
Michael K. Borregaard 4395718e0c Try to find default x axis limits where function is defined 2017-09-29 08:58:54 +02:00
Michael Krabbe Borregaard 913fdf5247 Merge pull request #1114 from mkborregaard/fix-1113
Don't delete attr when `plot(::Plot)` - fix #1113
2017-09-29 08:34:44 +02:00
Michael K. Borregaard 650c1730c9 Don't delete attr when plot(::Plot) - fix #1113 2017-09-28 23:32:25 +02:00
Daniel Schwabeneder fba1c66499 Merge pull request #1110 from daschw/line_z
RFC: Implement line_z and fill_z for GR
2017-09-28 00:12:12 +02:00
Daniel Schwabeneder 1c04823877 reset tick size for gr and glvisualize 2017-09-28 00:07:58 +02:00
Daniel Schwabeneder 6c84624d71 fix pgfplots 2017-09-27 23:22:55 +02:00
Daniel Schwabeneder 69fa9e7b10 implement tick_direction for PGFPlots 2017-09-27 17:07:09 +02:00
Daniel Schwabeneder 350237a774 add tick_direction to supported arguments 2017-09-27 13:56:12 +02:00
Daniel Schwabeneder b73ea55bbd implement tick_direction for GR, PyPlot, Plotly and GLVisualize 2017-09-27 13:53:06 +02:00
Daniel Schwabeneder 9eac6a1db0 fix fillalpha 2017-09-26 17:40:54 +02:00
Daniel Schwabeneder ea6ab46a13 fix fill_z for shapes (draw colorbar once) 2017-09-26 17:18:35 +02:00
Daniel Schwabeneder 5f84865365 implement fill_z and line_z for GR 2017-09-26 16:58:46 +02:00
AnkurD 5b3c41bd77 Colorbar takes font style from Y Axis 2017-09-26 17:22:17 +09:00
AnkurD c6b7ff6c75 Colorbar takes font style from Y Axis 2017-09-26 17:16:03 +09:00
Daniel Schwabeneder 337a107168 different colors for different line segments in GR 2017-09-25 17:22:13 +02:00
Daniel Schwabeneder a7485cc7f5 Merge pull request #1105 from daschw/plot-empty-any
Allow plotting empty Vector{Any} (fix #1078)
2017-09-25 09:57:23 +02:00
Daniel Schwabeneder 8b4edae358 implement line_z for GR 2017-09-24 20:52:02 +02:00
Daniel Schwabeneder b6dca5e9b1 Allow plotting empty Vector{Any} 2017-09-22 20:27:16 +02:00
Daniel Schwabeneder 371f0a6a73 Merge pull request #1092 from daschw/plotly-marker_z
fix marker_z for plotly
2017-09-21 22:04:16 +02:00
Michael Krabbe Borregaard b777a2d3c8 Merge pull request #1096 from fedxa/fix_logscale
Fix for wrong setting of logscale for values below 1e-16
2017-09-20 07:46:16 +02:00
Fedor Bezrukov bdfc4636f0 Fix for wrong setting of logscale for values below 1e-16 2017-09-19 23:22:36 +01:00
Daniel Schwabeneder 7ba128db71 fix marker_z for plotly 2017-09-17 19:14:44 +02:00
Daniel Schwabeneder 0f1d8478ce Merge pull request #1089 from daschw/pyplot-colorbar
activate clims for inactive colorbar in pyplot
2017-09-15 20:04:57 +02:00
Daniel Schwabeneder 9eae2ad76b remove unnecessary setting of needs_colorbar 2017-09-15 18:42:38 +02:00
Daniel Schwabeneder f43f2956f5 activate clims for inactive colorbar 2017-09-15 18:39:56 +02:00
Daniel Schwabeneder 2dc03cc537 Merge pull request #1084 from daschw/pyplot-marker_z
Only one colorbar per subplot on pyplot
2017-09-13 09:17:36 +02:00
Michael Krabbe Borregaard 233b0d0de2 Merge pull request #1086 from anriseth/writemimefix
Use show instead of writemime for eps
2017-09-13 00:09:14 +02:00
Asbjørn Nilsen Riseth dc9a044141 Use show instead of writemime for eps 2017-09-12 16:08:32 +01:00
Daniel Schwabeneder 518fba759f only one colorbar per subplot in pyplot 2017-09-09 11:21:39 +02:00
Daniel Schwabeneder 7dfa1ec984 make GR use hascolorbar 2017-09-09 10:05:58 +02:00
Daniel Schwabeneder da5a538f89 Merge pull request #1083 from daschw/gr-marker_z
Fix GR marker_z and clims (fix #1063)
2017-09-09 09:36:06 +02:00
Daniel Schwabeneder a518796736 reset runtests accuracy 2017-09-08 23:38:43 +02:00
Daniel Schwabeneder 13111b3779 fix marker_z for GR 2017-09-08 22:50:25 +02:00
Michael Krabbe Borregaard 8412d77067 Merge pull request #1082 from timholy/teh/nbins
histogram: ensure the number of bins is finite
2017-09-08 10:25:23 +02:00
Tim Holy fe0ea168f3 histogram: ensure the number of bins is finite 2017-09-08 03:18:46 -05:00
Daniel Schwabeneder af9d97d561 Merge pull request #1077 from daschw/seriestype-error
improve recipe error
2017-09-07 13:29:09 +02:00
Daniel Schwabeneder 478f5b6e20 Merge pull request #1079 from daschw/framestyle
implement framestyles for plotly(js) (fix #1075)
2017-09-07 13:28:43 +02:00
Daniel Schwabeneder c89b125b9a implement framestyles for plotly(js) 2017-09-06 19:09:52 +02:00
Daniel Schwabeneder a981dc71f9 Merge pull request #1057 from daschw/framestyle
RFC: Add :origin framestyle
2017-09-06 16:34:31 +02:00
Daniel Schwabeneder 331dd49326 improve recipe error 2017-09-06 16:03:39 +02:00
Michael Krabbe Borregaard b69c37f1bb Merge pull request #1073 from mkborregaard/fix-2dhistogram-bins
fix 2dhistogram bins
2017-09-06 10:15:03 +02:00
Michael K. Borregaard 20ef846c38 move bracket in Sturges 2017-09-05 22:42:05 +02:00
Michael K. Borregaard cd9f00300c Add correction for correlations 2017-09-05 16:02:52 +02:00
Michael K. Borregaard d6e5b57a08 fix-2dhistogram-bins 2017-09-05 14:01:59 +02:00
Pietro Vertechi d5e5d81ee2 Merge pull request #1062 from piever/groupedbar
WIP: allow to group user recipes
2017-09-05 08:53:26 +01:00
Pietro Vertechi dee24e6f08 add kw support 2017-09-04 12:29:10 +01:00
Michael K. Borregaard 9a2a54b885 reactivate precompilation on master 2017-09-04 13:09:37 +02:00
Michael K. Borregaard 4c2b01ccb0 change version number for testing 2017-09-04 12:18:10 +02:00
Michael Krabbe Borregaard ddf4136022 Merge pull request #1070 from JuliaPlots/release-0.12.4
Release 0.12.4
2017-09-04 12:05:07 +02:00
Michael K. Borregaard 4f8fc61689 Turn off precompile for release 2017-09-04 12:02:34 +02:00
Michael K. Borregaard c8a7a050de Update News.md with 12.4 improvements 2017-09-04 12:02:19 +02:00
Michael Krabbe Borregaard fb04b3d78b Merge pull request #1069 from daschw/seriestype-error
Seriestype error (fix #1068)
2017-09-04 11:50:17 +02:00
Pietro Vertechi 0f28b59c5f added support for 1 or 3 arguments to group as matrix 2017-09-04 10:24:43 +01:00
Pietro Vertechi e2795341d9 moved group_as_matrix to Plots 2017-09-04 09:48:49 +01:00
Michael Krabbe Borregaard 04c20b84ad Merge pull request #1053 from mkborregaard/wand_edges
Make wand edges possible in statplots
2017-09-03 17:30:17 +02:00
Michael Krabbe Borregaard 04f5d7e411 Merge pull request #1064 from mkborregaard/fix-barwidth
Change default bar width to 0.8
2017-09-03 17:28:47 +02:00
Michael Krabbe Borregaard 82877dc53e Merge pull request #1009 from JackDevine/add-stride
Add stride to wireframe/surface
2017-09-03 07:35:35 +02:00
Jack Devine c7eb22021f Merge branch 'master' into add-stride 2017-09-03 13:04:32 +12:00
JackDevine 654fa0426b Remove documentation 2017-09-03 12:53:49 +12:00
Daniel Schwabeneder ae6c1c0c66 make it even more descriptive 2017-09-02 23:19:29 +02:00
Daniel Schwabeneder b3f5939689 make seriestype error more descriptive 2017-09-02 22:58:26 +02:00
Josef Heinen 184404beac Merge pull request #1065 from jheinen/master
gr: suppress default output in Juno
2017-09-02 08:03:01 -04:00
Daniel Schwabeneder 456b8258c3 add zerolines framestyle 2017-09-02 02:35:26 +02:00
Michael K. Borregaard a1896d189c Revert ordering 2017-09-01 16:31:13 +02:00
Michael K. Borregaard e47dde9f41 simplify
but creates type instability
2017-09-01 16:26:49 +02:00
Michael K. Borregaard 4be19ba6d8 Make wand edges possible in statplots 2017-09-01 15:53:26 +02:00
Michael Krabbe Borregaard 73a2839e34 Merge pull request #1037 from mkborregaard/hist-description
changes default histogram bins
2017-09-01 13:20:12 +02:00
Michael Krabbe Borregaard 224472c90a Merge pull request #1048 from mkborregaard/fix-margin-example
Reduce margin to 10 px
2017-09-01 10:40:37 +02:00
Michael K. Borregaard d77be82a99 fix classic typo 2017-09-01 10:36:44 +02:00
Josef Heinen 4320c7b9fb gr: suppress default output in Juno 2017-09-01 07:40:39 +02:00
Michael K. Borregaard 2dcf7fb3dd Change default bar width to 0.8 2017-08-31 23:58:07 +02:00
Michael K. Borregaard cd1913c008 Update bins description 2017-08-31 23:20:55 +02:00
Michael K. Borregaard 62694e4a93 Make Freedman-Diaconis the default 2017-08-31 23:19:00 +02:00
Michael K. Borregaard e92fbadc3a Update histogram normalization desc 2017-08-31 23:12:33 +02:00
Michael K. Borregaard 17c10bbe68 Reduce margin to 10 px 2017-08-31 23:01:46 +02:00
Pietro Vertechi 6c548f025e wip groupedbar 2017-08-31 19:34:38 +01:00
Michael Krabbe Borregaard cc15882faf Merge pull request #1058 from mkborregaard/histogram-like
Make it possible for downstream users (e.g. StatPlots) to define that a seriestype is "histogram-like", "line-like" or "surface-like"
2017-08-31 08:39:16 +02:00
Daniel Schwabeneder 3fd745a5df remove 0 tick label 2017-08-30 23:42:57 +02:00
Daniel Schwabeneder 5e968e0aa8 ticks to axes 2017-08-30 22:19:13 +02:00
Michael Krabbe Borregaard 1e3783b4dc Merge pull request #1052 from mkborregaard/fix-appveyor
add nightly and 32-bit to allow-failures in Appveyor
2017-08-30 14:56:46 +02:00
Michael K. Borregaard c355e02a20 add nightly and 32-bit to allow-failures 2017-08-30 14:56:02 +02:00
Josef Heinen e178dca167 Merge pull request #1060 from jheinen/master
gr: suppress default output in CI or Jupyter mode
2017-08-30 04:36:52 -04:00
Josef Heinen 8beee23e21 gr: suppress default output in CI or Jupyter mode
_update_min_padding() is called before the backend is "started".
In GR, this triggers an automatic initialization and starts the
default output driver (X11, Quartz or GDI). This doesn't make
sense in headless testing environments (CI) or when using Plots
in Jupyter notebooks.

These patches correct this behavour - but it's unclear (to me),
why the call of _update_min_padding() can't be postponed.
2017-08-30 09:59:23 +02:00
Michael K. Borregaard a894d377dc add vectors to hold histogram-like seriestypes and friends 2017-08-29 23:34:07 +02:00
Daniel Schwabeneder f41426c85a fix pyplot 2017-08-29 22:04:33 +02:00
Daniel Schwabeneder 41877e362a add origin framestyle 2017-08-29 20:36:59 +02:00
Daniel Schwabeneder de32b02c75 Merge pull request #1056 from jgoldfar/fix-incorrect-escape-v0.7
Fix incorrect escape sequence error on Julia nightly
2017-08-29 19:33:02 +02:00
Jonathan Goldfarb e3cba22ab7 Correct fix to warning for unknown grid argument. 2017-08-29 13:29:30 -04:00
Jonathan Goldfarb 25bcc3cbc1 Fix incorrect escape sequence error on v0.7. 2017-08-29 12:19:01 -04:00
piever ca5310025f Merge pull request #1033 from piever/group
Group now groups kw arguments as well
2017-08-29 17:16:40 +01:00
piever 5b9561c13e Merge pull request #1049 from piever/ticks
To be merged together with PlotUtils #26: accept axis with 4 ticks
2017-08-29 11:56:46 +01:00
Pietro Vertechi d594ac2f00 Accept axis with 4 ticks 2017-08-28 18:16:10 +01:00
Pietro Vertechi 5157089d87 group on a tuple of vectors 2017-08-27 18:56:10 +01:00
Michael Krabbe Borregaard d5b455b1f9 Merge pull request #1046 from mkborregaard/fix-tests-on-mac
Remove hidden files when checking version numbers
2017-08-27 11:12:59 +02:00
Michael K. Borregaard 6cb1ed6c92 Remove hidden files when checking version numbers 2017-08-27 11:10:06 +02:00
piever 3d0d52f82a Merge pull request #1043 from piever/grfixes
readd fill for cross and xcross on GR
2017-08-26 16:35:50 +01:00
Daniel Schwabeneder be04828d35 Merge pull request #1042 from daschw/ds-blackborder
make linecolor default to :auto
2017-08-26 15:58:11 +02:00
Josef Heinen 5f9aa2edc0 Merge pull request #1044 from jheinen/master
gr: defer the calculation of padding constraints
2017-08-26 13:05:30 +02:00
Josef Heinen a5751895f0 gr: update padding constraints before first plot 2017-08-26 06:49:00 -04:00
Josef Heinen 78b0918216 gr: defer the calculation of padding constraints 2017-08-25 13:54:56 -04:00
Pietro Vertechi 5a7ed24078 allow tuples 2017-08-25 17:01:29 +01:00
Pietro Vertechi 509f8f6a95 readd fill for cross and xcross on GR 2017-08-25 16:46:07 +01:00
Daniel Schwabeneder 6f3301e82f make linecolor default to auto 2017-08-25 14:16:53 +02:00
Josef Heinen 80f11ce30b Merge remote-tracking branch 'upstream/master' 2017-08-25 04:14:59 -04:00
Michael Krabbe Borregaard 95a6d24111 Merge pull request #990 from jverzani/patch-1
Update appveyor.yml
2017-08-25 08:51:30 +02:00
Michael Krabbe Borregaard 1fc2c511af Merge pull request #1030 from mkborregaard/pyplot-in-ijulia
Turn off gui for pyplot in ijulia
2017-08-25 08:47:24 +02:00
Josef Heinen 3bcaac7051 t push
Merge remote-tracking branch 'upstream/master'
2017-08-24 23:05:22 -04:00
Josef Heinen 25afd5c0e7 Merge pull request #1039 from jheinen/master
gr: always use NDCs when inquiring text extents
2017-08-25 05:05:13 +02:00
Josef Heinen dbbbeddad0 gr: always use NDCs when inquiring text extents 2017-08-24 22:32:05 -04:00
Josef Heinen c0f274d54b gr: always use NDCs when inquiring text extents 2017-08-24 22:27:04 -04:00
Michael Krabbe Borregaard 7816e078b5 Merge pull request #808 from darwindarak/dd/world-age
Hack around world age issue PyPlot (fix #734)
2017-08-24 22:53:04 +02:00
Daniel Schwabeneder 56bda82529 Merge pull request #1029 from daschw/ds-axes-border
Allow turning on/off the axes border (fix #1025)
2017-08-24 22:38:01 +02:00
Daniel Schwabeneder 54adc34348 fix glvisualize framestyle :none ticks 2017-08-24 22:21:13 +02:00
Darwin Darakananda a4ed700338 Use invokelatest to get around world age issue 2017-08-24 13:12:32 -07:00
Daniel Schwabeneder e2d107a70b add framestyle test example 2017-08-24 21:39:33 +02:00
Josef Heinen 31f080e4f4 Merge pull request #1038 from piever/grmargin
Adjust margin (ticks + margin given by user) with GR ( fix #1028 )
2017-08-24 20:58:41 +02:00
Daniel Schwabeneder 6e4b9af6b1 Merge pull request #780 from daschw/ds-ticks
WIP: Allow specifying the number of ticks by passing an Integer to the ticks attribute
2017-08-24 17:21:37 +02:00
Daniel Schwabeneder d301d2a06b fix ticks = nothing on pyplot, ... 2017-08-24 16:58:43 +02:00
Daniel Schwabeneder 2bbd4cbb17 clean up 2017-08-24 16:26:54 +02:00
Daniel Schwabeneder 5a2d39320f framestyle attribute for gr, pyplot and glvisualize 2017-08-24 16:13:01 +02:00
Pietro Vertechi 91158b1c20 add proper pad for ticks 2017-08-23 18:19:36 +01:00
Pietro Vertechi 06115f25ba factorize tickfont 2017-08-23 17:45:23 +01:00
Pietro Vertechi b3b533db94 fix margin in case there is no label (gr) 2017-08-23 14:10:35 +01:00
Pietro Vertechi e16125cb50 some GR margin fixes 2017-08-23 13:49:33 +01:00
Michael Krabbe Borregaard eb0dbac0c1 Merge pull request #1035 from piever/errorbar
don't draw fill for 1D markers in gr
2017-08-23 10:35:42 +02:00
Michael Krabbe Borregaard eb1d1876d3 Merge pull request #1034 from JuliaPlots/ChrisRackauckas-patch-1
Remove the -pre
2017-08-23 10:34:54 +02:00
Pietro Vertechi f751b1b7ff don't draw fill for 1D markers in gr 2017-08-23 08:40:19 +01:00
Christopher Rackauckas 34f9cfaa02 Remove the -pre
Plots.jl is no longer tested on the prereleases so it shouldn't say that they are supported.
2017-08-23 00:27:33 -07:00
Pietro Vertechi 6dba32bf99 only check kw is at least as long as group 2017-08-21 15:54:47 +01:00
Pietro Vertechi 9529246bfb keywords arguments of same length as series get grouped 2017-08-21 15:33:30 +01:00
Michael K. Borregaard 25774ee4c3 Turn off gui for pyplot in ijulia 2017-08-21 10:19:47 +02:00
Daniel Schwabeneder 1137513236 add aliases :box and :frame 2017-08-21 00:07:44 +02:00
Daniel Schwabeneder c76855698e Merge pull request #1027 from daschw/ds-datetime-ticks
Allow Date and DateTime as ticks (fix: #1026)
2017-08-20 22:51:26 +02:00
Daniel Schwabeneder be8c66adc9 fix polar plots on pyplot 2017-08-20 22:45:30 +02:00
Daniel Schwabeneder be4a374122 allow turning on/off the axes border 2017-08-20 21:55:21 +02:00
Daniel Schwabeneder d76a6d1c38 Allow and as ticks 2017-08-20 15:43:52 +02:00
Michael Krabbe Borregaard 5945196a4f Merge pull request #1023 from piever/pull-request/eea30fa2
RFC: added ribbon to plotly
2017-08-20 15:13:14 +02:00
Pietro Vertechi e164ea4b46 added default transparency to ribbon 2017-08-20 14:06:15 +01:00
Pietro Vertechi db3dca1d73 changed ribbon legend to line 2017-08-20 11:46:21 +01:00
Pietro Vertechi eea30fa253 added ribbon to plotly 2017-08-19 11:34:13 +01:00
Michael Krabbe Borregaard b585a0ef61 Merge pull request #1012 from mkborregaard/more_docstrings
Specified some docstrings
2017-08-18 10:30:02 +02:00
Michael K. Borregaard db82f22320 add the last docstrings 2017-08-18 09:48:36 +02:00
Michael K. Borregaard 66ce38d948 Specified some docstrings 2017-08-18 09:48:36 +02:00
Daniel Schwabeneder e61d435b00 Merge pull request #1020 from daschw/ds-precompile
reactivate precompilation
2017-08-18 00:58:55 +02:00
Daniel Schwabeneder d0a8985800 Merge pull request #1019 from daschw/ds-release
prepare release
2017-08-18 00:55:29 +02:00
Daniel Schwabeneder 4c1c092234 reactivate precompilation 2017-08-18 00:46:02 +02:00
Daniel Schwabeneder f02079dafe Merge pull request #1014 from daschw/ds-tests
import plot! placeholder from RecipesBase
2017-08-18 00:37:14 +02:00
Daniel Schwabeneder 4be0093a8a prepare release 2017-08-18 00:34:15 +02:00
Daniel Schwabeneder 130eb778d3 Merge pull request #1006 from daschw/ds-grid-axis
grid should be axis attribute (fix #675)
2017-08-17 23:57:59 +02:00
Daniel Schwabeneder be177e0f80 Merge pull request #1015 from daschw/ds-marker-z
only flip colorbar for marker_z on gr
2017-08-17 23:45:35 +02:00
Daniel Schwabeneder 42f54b8df9 remove Bools from _allGridArgs 2017-08-17 14:10:04 +02:00
Daniel Schwabeneder 4b60b05f75 update grid defaults and modify grid example 2017-08-17 13:42:54 +02:00
Michael Krabbe Borregaard 6afd0f9f82 Merge pull request #1011 from martinbiel/enforce-plotorder
Enforce plot order in user recipes
2017-08-17 09:10:01 +02:00
Daniel Schwabeneder 8288e85c25 only flip colorbar for marker_z 2017-08-16 22:32:00 +02:00
Daniel Schwabeneder bb2f4ff16b import inplace plot placeholder from RecipesBase 2017-08-16 21:05:05 +02:00
Daniel Schwabeneder 682ba1f764 allow non-boolean args for xgrid function 2017-08-16 19:41:13 +02:00
Daniel Schwabeneder e0c679f5ee magic grid argument 2017-08-16 17:45:32 +02:00
Martin Biel a1d0d028b6 Updated error text in _process_userrecipes, now uses correct variable 2017-08-16 10:16:37 +02:00
JackDevine 7741872578 Comma in the wrong place 2017-08-16 11:20:04 +12:00
JackDevine d1dcd536f5 I forgot a comma 2017-08-16 10:41:19 +12:00
JackDevine 177d380092 Added suggestions
Changed the interface to stride, which is a tuple. Also added aliases and a docstring in arg_desc.
2017-08-16 10:18:26 +12:00
Martin Biel 33a15f1e93 Process user recipes depth-first rather than breadth-first to enforce the plot order given in the recipe 2017-08-15 18:03:57 +02:00
JackDevine ad2eaf7aef Add stride to wireframe/surface
I only have this for PyPlot at the moment, I would be more than happy
to add other backends if people find it useful. Also, if people have
any ideas for aliases, then I would be happy to do that too.
2017-08-15 20:10:02 +12:00
Daniel Schwabeneder 23ae99b97e undo support for foreground_color_grid and foreground_color_axis attributes in plotly(js) 2017-08-11 12:57:11 +02:00
Daniel Schwabeneder 3c37de152d fix testimage 16 error - only add grid segments when ticks are defined 2017-08-10 22:54:45 +02:00
Daniel Schwabeneder 2dd99d053a make it work on all backends 2017-08-10 20:49:03 +02:00
Daniel Schwabeneder c60d66d94a make it work for gr, pyplot and plotly(js) 2017-08-10 17:46:11 +02:00
Daniel Schwabeneder 6b814b8dca initial commit mostly a copy of #695 2017-08-10 16:32:24 +02:00
Josef Heinen 11c71d7a5d Merge pull request #1005 from jheinen/master
gr: use correct gradient labels for scatter plot
2017-08-10 09:47:57 +02:00
Josef Heinen d90b2e6142 gr: use correct gradient labels for scatter plot 2017-08-10 09:31:54 +02:00
Josef Heinen 2ab7f3c767 Merge pull request #1003 from jheinen/master
gr: no longer handle '_' and '^' in text
2017-08-09 11:03:55 +02:00
Josef Heinen a937fa0ef8 gr: no longer handle '_' and '^' in text 2017-08-09 10:46:23 +02:00
Michael Krabbe Borregaard bc36749f6d Merge pull request #1002 from mkborregaard/mkb-precompile
allow precompilation
2017-08-09 08:12:45 +02:00
Michael K. Borregaard 88d1735380 allow precompilation 2017-08-09 08:12:22 +02:00
Michael K. Borregaard 92672ffddf Update news.md 2017-08-09 08:10:04 +02:00
Michael Krabbe Borregaard 2ccfa9b4fa Merge pull request #1001 from mkborregaard/mkb-release
disable precompilation for release
2017-08-09 08:05:45 +02:00
Michael K. Borregaard 1f07be6ae0 disable precompilation for release 2017-08-09 08:05:21 +02:00
Michael Krabbe Borregaard 9a8c7b290f Merge pull request #1000 from mkborregaard/fix-993
Move when output is included
2017-08-09 08:03:41 +02:00
Michael K. Borregaard 2e3bc15d2b Move when output is included 2017-08-08 20:24:17 +02:00
john verzani 9f0117d914 Update README.md
add appveyor badge. (But how does appveyor get run, as it doesn't seem to be current)
2017-08-01 15:48:12 -04:00
Michael Krabbe Borregaard 5e5412887c Merge pull request #989 from mkborregaard/fix-markershape-recipes
RFC: fix markershape in recipes
2017-07-29 08:51:51 +02:00
Josef Heinen b2efd5150b Merge pull request #992 from jheinen/master
gr: improved calculation of bottom margin
2017-07-28 05:37:09 -05:00
Josef Heinen 50ec31a7a3 gr: improved calculation of bottom margin 2017-07-28 12:17:47 +02:00
Daniel Schwabeneder 20bd9d6160 Merge pull request #988 from stevengj/nopywrap
don't use pywrap
2017-07-28 10:11:30 +02:00
john verzani 8c3c07acb7 Update appveyor.yml
remove v0.5 testing from appveyor
2017-07-27 16:56:17 -04:00
john verzani 26a56c3105 Update appveyor.yml
add testing on v0.6 with 32 and 64 bit.
2017-07-27 15:48:52 -04:00
Steven G. Johnson d0070c72fd whoops, forgot to commit these pywrap fixes 2017-07-27 14:15:48 -04:00
Michael K. Borregaard 780f3c49e9 Add test for markershape 2017-07-27 16:37:55 +02:00
Steven G. Johnson 2c191dbdbf don't use pywrap (closes #983) 2017-07-26 16:34:03 -04:00
Daniel Schwabeneder 4b617f96a3 Merge pull request #987 from daschw/ds-precompile
reactivate precompilation
2017-07-26 15:43:47 +02:00
Daniel Schwabeneder dabc3f998b reactivate precompilation 2017-07-26 15:14:07 +02:00
Daniel Schwabeneder 23a22102c5 Merge pull request #986 from daschw/ds-release
prepare v0.12.1 release
2017-07-26 15:09:33 +02:00
Daniel Schwabeneder 8d9ff7af11 prepare v0.12.1 release 2017-07-26 14:50:57 +02:00
Josef Heinen fdcb6086d1 Merge pull request #985 from jheinen/master
gr: fixed padding for guides
2017-07-26 03:02:03 -05:00
Josef Heinen 00e05efd7c gr: fixed padding for guides 2017-07-26 09:44:34 +02:00
Daniel Schwabeneder 0dd5eef3f2 Merge pull request #982 from daschw/ds-old-matplotlib
Allow Matplotlib 1.5 usage (fix #978)
2017-07-25 18:46:39 +02:00
Daniel Schwabeneder 6ecd30d42b warning --> warn 2017-07-24 14:55:28 +02:00
Daniel Schwabeneder 317091639f Merge pull request #977 from daschw/ds-plotly-surf
allow setting surface alpha in plotly(js) (fix #957)
2017-07-24 10:05:24 +02:00
Daniel Schwabeneder 9c8e879465 Merge pull request #976 from daschw/ds-gr-legend
Line legend marker for ribbons in GR (fix #896)
2017-07-24 10:03:57 +02:00
Daniel Schwabeneder dc5a04346a Merge pull request #975 from daschw/ds-tests
drop FactCheck in tests (fix #915)
2017-07-24 10:03:25 +02:00
Daniel Schwabeneder 44b533f501 allow matplotlib 1.5 usage 2017-07-24 10:02:44 +02:00
Daniel Schwabeneder 0fa459d590 fix alpha in legend markers 2017-07-21 10:52:36 +02:00
Daniel Schwabeneder 96d34bb5ee changed marker for path with fillrange 2017-07-21 10:05:27 +02:00
Daniel Schwabeneder 9f712b44f3 add ribbon area to marker 2017-07-21 09:12:27 +02:00
Daniel Schwabeneder 1ff8663e44 allow setting surface alpha in plotly 2017-07-21 01:12:39 +02:00
Daniel Schwabeneder 52f042263b fix case 2017-07-20 23:38:16 +02:00
Daniel Schwabeneder da7e57989c drop FactCheck and Glob in test/REQUIRE 2017-07-20 22:55:05 +02:00
Daniel Schwabeneder 65c3d90642 Merge pull request #971 from timholy/pull-request/a7a447a8
Update to newer Images
2017-07-20 22:23:52 +02:00
Daniel Schwabeneder 3c044d729d Merge pull request #970 from JuliaPlots/sd/glvisualize
fix glvisualize backend for 0.6
2017-07-20 22:20:34 +02:00
Daniel Schwabeneder 82ecf894c0 fix issues - replace at-fact with at-test 2017-07-20 21:50:06 +02:00
Daniel Schwabeneder 7b15f7d74b fix round() deprecation in gr.jl 2017-07-20 16:08:45 +02:00
Daniel Schwabeneder 371406845c drop Glob (enable testing on Windows) 2017-07-20 13:43:58 +02:00
Daniel Schwabeneder ccd26a6d42 drop FactCheck in tests 2017-07-20 13:25:09 +02:00
SimonDanisch e992930ff6 add contour as a dependency 2017-07-20 10:38:06 +02:00
SimonDanisch f66d8bed8f fix glvisualize backend for 0.6 2017-07-20 10:37:48 +02:00
Daniel Schwabeneder 155634ef34 change gr legend marker for ribbon 2017-07-19 21:26:25 +02:00
Josef Heinen dbc7bc4253 Merge pull request #940 from daschw/ds-heatmap-logscale
Avoid non-positive heatmap edges for log axis on GR and PyPlot
2017-07-18 01:22:26 -05:00
Daniel Schwabeneder fc427e618a Merge pull request #916 from pfitzseb/sp/juno
WIP: Better Juno integration
2017-07-17 20:40:48 +02:00
Sebastian Pfitzner 6d66190644 no eval shenanigans 2017-07-17 15:16:20 +02:00
Daniel Schwabeneder 9b2da0d645 Merge branch 'master' into ds-heatmap-logscale 2017-07-16 12:51:33 +02:00
Sebastian Pfitzner 95c60b9554 unrecursify this definition 2017-07-15 12:01:00 +02:00
Sebastian Pfitzner bc7f6a6fac circumvent warnings 2017-07-15 11:40:11 +02:00
Daniel Schwabeneder 0b1118540a Merge pull request #969 from pearlzli/plotly-fill
Add fillrange for Plotly backend
2017-07-14 22:55:33 +02:00
Tim Holy 96bd0bb46c Fix some errors/depwarns 2017-07-14 10:09:30 -05:00
Tim Holy 33e97ee49b Update to newer Images 2017-07-14 10:07:58 -05:00
Daniel Schwabeneder 8414facde2 Merge pull request #967 from JackDevine/fix-pyplot-deprecation
Fixed a deprecation warning on the pyplot backend
2017-07-13 09:33:25 +02:00
Pearl Li 2a0d5a0a03 Hide legend entry for series being filled to 2017-07-12 17:04:19 -04:00
Pearl Li aec30301a1 Add fillrange for Plotly 2017-07-12 16:20:53 -04:00
Sebastian Pfitzner 9cf246a03e fix juno plot sizing fallback 2017-07-12 10:40:26 +02:00
Sebastian Pfitzner c385035ac5 handle ijulia with requires
and properly check if juno/ijulia are actually used and not just loaded
2017-07-12 10:38:15 +02:00
JackDevine 409cf2c630 Fixed a deprecation warning on the pyplot backend
The follwing code created a deprecation warining:
using Plots; pyplot()
plot([1,2,3,4], [2,3,4,5], yscale=:log10)
2017-07-12 17:37:37 +12:00
SimonDanisch 02ddbc8381 fix glvisualize backend for 0.6 2017-07-11 09:04:35 +02:00
Daniel Schwabeneder 1c2a588864 Merge pull request #965 from rdeits/staticarrays
Switch from FixedSizeArrays to StaticArrays.FixedSizeArrays
2017-07-10 13:47:49 +02:00
Robin Deits de043eeaa2 switch from FixedSizeArrays to StaticArrays.FixedSizeArrays 2017-07-05 17:12:39 -04:00
Sebastian Pfitzner 5e5f23b5e5 fix world age error 2017-07-02 20:56:04 +02:00
Sebastian Pfitzner d671ccd6ba better juno integration 2017-07-02 20:56:04 +02:00
Daniel Schwabeneder f4f2f09d17 Merge pull request #955 from albi3ro/master
fixing deprecation warning
2017-06-28 21:04:04 +02:00
Christina Lee 2f1c70e49f fixing deprecation warning 2017-06-28 11:42:16 -07:00
Josef Heinen d9890498d1 Merge pull request #951 from jheinen/master
gr: implemented "old" heatmap behaviour
2017-06-23 00:52:04 +02:00
Josef Heinen 46ae505bab gr: implemented "old" heatmap behaviour 2017-06-22 15:31:13 -07:00
Josef Heinen b0e84a68d0 Merge pull request #949 from jheinen/master
gr: fixed heatmap bug
2017-06-22 21:58:37 +02:00
Josef Heinen 356a5b6136 gr: fixed heatmap bug 2017-06-22 12:56:41 -07:00
Daniel Schwabeneder e86193cebe Merge pull request #947 from daschw/ds-datetime
Replace deprecated DateTime convert methods
2017-06-22 20:51:50 +02:00
Daniel Schwabeneder e35b2ec3ff replace deprecated DateTime convert methods 2017-06-22 18:51:03 +02:00
Josef Heinen 69d421d785 Merge pull request #944 from jheinen/master
gr: heatmaps now respect xlim/ylim specifications
2017-06-20 03:34:04 +02:00
Josef Heinen 47c51b28c1 gr: heatmaps now respect xlim/ylim specifications
Fixes https://github.com/JuliaPlots/Plots.jl/issues/942
2017-06-19 18:15:33 -07:00
Daniel Schwabeneder dd2653968e Merge pull request #941 from daschw/ds-plotlyjs-colorbar
Allow turning off the colorbar for heatmap, contour and surface on Plotly and PlotlyJS (fix #932)
2017-06-19 20:04:22 +02:00
Daniel Schwabeneder b091d95eb2 turn off colorbar for wireframe 2017-06-18 17:56:47 +02:00
Daniel Schwabeneder 33327d3992 allow turning off the colorbar for heatmap, contour and surface 2017-06-18 17:45:20 +02:00
Daniel Schwabeneder 027ce58655 avoid negative heatmap edges for log axis on gr and pyplot 2017-06-18 16:14:44 +02:00
Daniel Schwabeneder cd611ef4bf Merge pull request #939 from daschw/ds-tests
changed wkhtmltox link for tests
2017-06-18 16:10:25 +02:00
Daniel Schwabeneder bc7f5118ea changed package name for dpkg 2017-06-18 15:51:24 +02:00
Daniel Schwabeneder 53ae915044 changed wkhtmltox link 2017-06-18 11:59:27 +02:00
Michael Krabbe Borregaard a47f14ec13 Merge pull request #936 from ma-laforge/inspectdr
Conform to changes in InspectDR.PlotLayout.
2017-06-18 08:00:09 +02:00
MA Laforge 86149ba3a7 Conform to changes in InspectDR.PlotLayout. 2017-06-16 17:17:01 -04:00
Michael Krabbe Borregaard cc3822b222 Merge pull request #933 from sbromberger/patch-1
Update output.jl
2017-06-16 17:21:26 +02:00
Seth Bromberger 57b9602b13 Update output.jl
Change `readall` to `readstring` for 0.6- compatibility.
2017-06-15 20:12:26 -07:00
Daniel Schwabeneder c9839dbefa Merge pull request #926 from daschw/ds-pyplot-colorbar
Reduced colorbar size on PyPlot for big z values (fix #925)
2017-06-13 18:48:48 +02:00
Daniel Schwabeneder 5b6423ec6c only change top corners of colorbar axes 2017-06-12 22:15:57 +02:00
Daniel Schwabeneder b3efcf9b68 reduced colorbar size for z axis limits >= 1e7 2017-06-12 20:39:49 +02:00
Michael Krabbe Borregaard cadb0f96e2 Merge pull request #837 from floswald/reset
resetfontsizes: fixes #836
2017-06-12 13:31:55 +02:00
florian oswald d3b825b49f fix docstrings. provide 2 methods scalefontsizes now, with and without an argument. no argument version resets to initial values, with argument you rescale the current sizes. 2017-06-12 12:29:19 +02:00
Michael K. Borregaard c808cbb4fa restore precompilation 2017-06-11 22:28:07 +02:00
Michael Krabbe Borregaard 228d3af1fa Merge pull request #922 from mkborregaard/make-tkelman-happy
remove all 0.5-compliant uses of the transpose operator
2017-06-11 22:26:53 +02:00
Michael K. Borregaard a1df325051 Remove all 0.5-compliant uses of the transpose operator (')
A horrible change, but one required by the metadata maintainers.
2017-06-11 22:25:15 +02:00
Daniel Schwabeneder 8e6fdfac3c Merge pull request #921 from daschw/ds-precompile
reactivate precompilation on master
2017-06-10 23:36:57 +02:00
Daniel Schwabeneder 9a1afb2376 reactivate precompilation 2017-06-10 23:13:03 +02:00
Michael K. Borregaard e9ab8c4dac require RecipesBase 0.2.0 2017-06-09 22:57:23 +02:00
Michael Krabbe Borregaard 1d98acc407 deactivate precompilation for release 2017-06-09 22:04:48 +02:00
Michael Krabbe Borregaard 034613b50c Merge pull request #804 from ChrisRackauckas/_cycle
Change cycle => _cycle
2017-06-09 20:09:26 +02:00
Michael Krabbe Borregaard 282e611ef7 Merge pull request #803 from ChrisRackauckas/recipes_change
RecipesBase change: all recipes usable from RecipesBase
2017-06-09 20:09:15 +02:00
ChrisRackauckas 49fc903334 fix last cycle 2017-06-09 08:43:01 -07:00
ChrisRackauckas 44b6157f17 cycle => _cycle 2017-06-09 08:43:01 -07:00
ChrisRackauckas 0a8d3f9251 animate from RecipesBase 2017-06-09 08:42:00 -07:00
ChrisRackauckas ac505ede44 move abstract types and make PlotRecipe on abstract type 2017-06-09 08:42:00 -07:00
ChrisRackauckas 4770f8b580 Merge remote-tracking branch 'ChrisRackauckas/master' into patch-1 2017-06-09 08:41:26 -07:00
Christopher Rackauckas 67e5598d28 Move the @userplot recipes
https://github.com/JuliaPlots/RecipesBase.jl/pull/16
2017-06-09 08:41:26 -07:00
ChrisRackauckas 554d7ab887 remove @shorthands 2017-06-09 08:41:26 -07:00
Michael K. Borregaard 40734bf90e Revert "turn off precompilation for release"
This reverts commit 66d9c79bef.
2017-06-09 16:00:39 +02:00
Michael Krabbe Borregaard 3e720f8bae Merge pull request #919 from mkborregaard/ready-for-release
turn off precompilation for release
2017-06-09 15:58:38 +02:00
Michael K. Borregaard 66d9c79bef turn off precompilation for release 2017-06-09 15:58:09 +02:00
Michael Krabbe Borregaard 89a5e5d57a Merge pull request #914 from mkborregaard/change-ignorenan-case
ignoreNaN => ignorenan
2017-06-08 12:54:47 +02:00
Michael K. Borregaard 8f6b0c50d6 ignoreNaN => ignorenan 2017-06-08 12:54:25 +02:00
Michael Krabbe Borregaard d85dfaf38a Merge pull request #913 from mkborregaard/fix-broadcast
update Base..* to 0.6 syntax
2017-06-08 11:13:08 +02:00
Michael K. Borregaard 8511152982 update Base..* to 0.6 syntax 2017-06-08 10:56:12 +02:00
Michael Krabbe Borregaard 40f9a51d4f Merge pull request #909 from mkborregaard/reactivate-precompilation
reactivate precompilation
2017-06-08 10:47:56 +02:00
Daniel Schwabeneder 30ad6d93bc Merge pull request #908 from daschw/ds-tests-2
Make tests pass on 0.6 2
2017-06-08 10:27:04 +02:00
Josef Heinen 770d907fb8 Merge pull request #910 from jheinen/master
gr: removed println statement
2017-06-07 18:18:11 -07:00
Josef Heinen 46cdbacf0b gr: removed println statement 2017-06-07 18:15:43 -07:00
Michael K. Borregaard c0a8adc167 reactivate precompilation 2017-06-08 00:55:23 +02:00
Daniel Schwabeneder 4dd176a7f2 add @eval in image_comparision_tests and replaced transpose in testexample 13 2017-06-08 00:19:36 +02:00
Michael Krabbe Borregaard eac9023b9a Merge pull request #904 from mkborregaard/Change-test-versions-to-release
Use ImageMagick release
2017-06-08 00:09:41 +02:00
Michael Krabbe Borregaard a4c403286d Merge pull request #906 from mkborregaard/change-to-0.6
Up requirement to julia 0.6
2017-06-07 23:59:21 +02:00
Michael K. Borregaard 3a2ee0fc72 Fix some deprecations 2017-06-07 23:55:30 +02:00
Michael K. Borregaard f097fb57b5 Fix some deprecation warnings 2017-06-07 23:55:30 +02:00
Michael K. Borregaard 7415a362c4 reactivate precompilation 2017-06-07 23:55:30 +02:00
Michael K. Borregaard 8a7b7f5c9b Up requirement to 0.6 2017-06-07 23:55:30 +02:00
Michael Krabbe Borregaard 4ce35ef352 Merge pull request #894 from mkborregaard/legendtitle_example
Adds legendtitle to example 12
2017-06-07 23:54:39 +02:00
Michael K. Borregaard a12f601b9c add legendtitle to example 2017-06-07 23:54:05 +02:00
Michael K. Borregaard 4106161aa8 add colon 2017-06-07 23:54:05 +02:00
Michael K. Borregaard 58c2f35bcf reinclude Plots 2017-06-07 23:54:05 +02:00
Michael K. Borregaard c41839a816 Add legendtitle to example 13 2017-06-07 23:54:05 +02:00
Michael K. Borregaard df729cd0f6 hotfix-FixedPointNumbers in require 2017-06-07 17:08:06 +02:00
Michael Krabbe Borregaard 230ab34fe9 Merge pull request #905 from mkborregaard/fix-version-number-fixedsizearrays
Up FixedSizeArrays requirement to 0.3
2017-06-07 17:00:03 +02:00
Michael K. Borregaard 51fabab7b7 Up FixedSizeArrays requirement to 0.3 2017-06-07 16:59:20 +02:00
Michael K. Borregaard c7a13a4641 Use ImageMagick release 2017-06-07 16:54:24 +02:00
Michael Krabbe Borregaard f855386bf1 Merge pull request #903 from mkborregaard/ready-for-0.11.3
get ready for 0.11.3 release
2017-06-07 16:07:21 +02:00
Michael K. Borregaard b8d1d9d7f1 Turn off precompilation for release 2017-06-07 16:06:04 +02:00
Michael K. Borregaard a22412d39d Update News.md with 0.11.3 2017-06-07 16:05:51 +02:00
Michael K. Borregaard f8bc9ba476 update version number in tests 2017-06-07 16:05:35 +02:00
Michael Krabbe Borregaard fe83937368 Merge pull request #870 from wfrgra/legend
add ability to specify legend placement to gr backend
2017-06-07 15:44:00 +02:00
Daniel Schwabeneder 3def6265c4 Merge pull request #886 from daschw/ds-spy
Changed spy recipe and added spy example to tests (fix #883)
2017-06-07 11:16:06 +02:00
Michael Krabbe Borregaard d9f7c19344 Merge pull request #900 from mkborregaard/amend-histogram-docs
amend bins description, fixes #898
2017-06-07 11:02:31 +02:00
Michael K. Borregaard db1dd618ea Add example with linspace 2017-06-07 11:01:47 +02:00
Michael K. Borregaard 132306fef1 amend bins description 2017-06-07 08:02:18 +02:00
Daniel Schwabeneder 18d29a0c7c changed markershape to :dtriangle in spy example 2017-06-06 22:51:34 +02:00
Michael Krabbe Borregaard 4125fa75dd Merge pull request #893 from mkborregaard/fix-example12-transpose
fix-example12-transpose
2017-06-06 14:48:59 +02:00
Michael K. Borregaard bad7772b15 fix-example12-transpose 2017-06-06 14:45:30 +02:00
Michael Krabbe Borregaard 6a23202e89 Merge pull request #825 from ma-laforge/hdf5plots
Re-integrate HDF5 plots.
2017-06-06 12:36:46 +02:00
Josef Heinen 21c384fcdd Merge pull request #888 from jheinen/master
gr: added support for legend title
2017-06-04 10:04:15 +02:00
Josef Heinen b140fddebd gr: added support for legend title 2017-06-04 10:02:20 +02:00
Daniel Schwabeneder 24ea1c4847 Merge pull request #887 from daschw/ds-pyplot-legendtitle
Added legend_title attribute for Pylot backend
2017-06-04 09:29:50 +02:00
Daniel Schwabeneder 9d115fc02e added space in arg_desc 2017-06-03 13:49:06 +02:00
Daniel Schwabeneder 5e7756810d changed default attribute to legendtitle 2017-06-03 13:47:24 +02:00
Daniel Schwabeneder c65abd19ae Merge pull request #885 from daschw/gr-legend-markers
Changed GR legend markers for plots with fillrange
2017-06-03 13:39:05 +02:00
Daniel Schwabeneder 1a07c39fad changed spy plot example 2017-06-03 13:27:38 +02:00
Daniel Schwabeneder ee23cb2185 grid --> false in spy recipe, removed info, added example 2017-06-03 01:14:25 +02:00
Daniel Schwabeneder ee5617c6b8 added attribute for pyplot backend 2017-06-02 18:55:47 +02:00
Daniel Schwabeneder dc757cbf6c changed gr legend markers for fillrange 2017-06-02 17:39:25 +02:00
Daniel Schwabeneder 3d3ec2a194 add info about default markersize in spy recipe 2017-06-02 17:18:01 +02:00
Daniel Schwabeneder d2e79f33a3 Merge pull request #884 from daschw/ds-maketestspass
Make tests pass for GR and PyPlot 2 (fix #670 and #838)
2017-06-02 16:23:23 +02:00
Daniel Schwabeneder 6156228c89 install xfonts-75dpi for whtmltox 2017-06-02 15:07:17 +02:00
Daniel Schwabeneder 90f7e370f3 make tests pass for gr and pyplot cf. #877 2017-06-02 14:58:49 +02:00
Michael Krabbe Borregaard 92688f03a8 Merge pull request #881 from mkborregaard/change-NaNMath-implementation
change NaNMath implementation
2017-06-01 22:28:02 +02:00
Michael K. Borregaard 80d0d6ecc8 Change NaNMath implementation
We needed some functions to forward to Base methods, e.g. when non-`AbstractArray{<:AbstractFloat}` was passed
2017-06-01 22:19:38 +02:00
Michael Krabbe Borregaard d29df4289e RFC: Ignore NaNs on 0.6 (like on 0.5): fixes #796 (#876)
Replaces min, max, minimum, mean, maximum and extrema with NaNMath versions in places where NaNs can occur.

To avoid returning NaN when there are NaNs in the Vector

* Also add maximum and minimum

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

* variable arg numbers for Base methods

* Different implementation of the override

* remove underscore from 2-arg versions of maximum

* some forgotten extrema -> _extrema

* Fix bug in _extrema definition

* edit comment

* replace min and max with _min and _max

* Base NaN-compliant functions on NaNMath


replace _min and _max with NaNMath versions

* Use NaNMath explicitly everywhere

* remove unneccesary NaNMath calls

* Ensure ceil does not error on NaN

* Added one more maximum in gr
2017-06-01 19:17:28 +02:00
Michael Krabbe Borregaard 84406f0823 Fixed writing error. 2017-06-01 17:10:03 +02:00
Michael Krabbe Borregaard 380907af8d Merge pull request #879 from mkborregaard/change-glvisualize-string
Change installation message
2017-06-01 11:56:20 +02:00
Michael K. Borregaard 0e308d9f50 Change installation message 2017-06-01 11:55:43 +02:00
Michael Krabbe Borregaard 7805f3f85b Merge pull request #862 from JuliaPlots/sd/fix_signals
fix glvisualize backend
2017-06-01 11:51:09 +02:00
Daniel Schwabeneder e04d13323d Merge pull request #878 from oschulz/debug-info-cleanup
Remove remnant debug output about binning
2017-05-31 23:27:21 +02:00
Oliver Schulz 6e8bfe1ea6 Remove remnant debug output about binning 2017-05-31 23:07:10 +02:00
Josef Heinen 3baceb9dc4 Merge pull request #874 from jheinen/master
gr: fixed several bugs
2017-05-30 10:31:17 +02:00
Josef Heinen abf8ca2dc7 gr: fixed several bugs
- use correct image orientation
- added missing marker keywords
- improved alignment of axes labels
- corrected scaling of polar coordinates
- slightly shrink pie chart viewport
2017-05-30 10:29:31 +02:00
Michael Krabbe Borregaard 2a0a5f2d08 Merge pull request #868 from staticfloat/updated_ci_url
Update CI URLs to point to new caching infrastructure
2017-05-29 09:05:40 +02:00
Josef Heinen d45b228461 Merge pull request #871 from jheinen/master
gr: fix problems with axes display
2017-05-28 16:25:52 +02:00
Josef Heinen 231e11715f gr: fix problems with axes display 2017-05-28 16:23:21 +02:00
wgrant d6f1120dfc add ability to specify legend placement to gr backend 2017-05-27 16:46:38 +10:00
Josef Heinen 7471bc791c Merge pull request #869 from jheinen/master
gr: corrected size of shape markers
2017-05-26 15:02:05 +02:00
Josef Heinen effcffff8a gr: corrected size of shape markers 2017-05-26 14:59:30 +02:00
Josef Heinen 76186cab97 Merge pull request #863 from jheinen/master
gr: improve viewport size for 3D plots
2017-05-24 11:21:27 +02:00
Josef Heinen 4756e04e25 gr: improve viewport size for 3D plots 2017-05-24 11:19:43 +02:00
SimonDanisch 5b73f1e56c remove clean up code, switch to renderloop 2017-05-23 16:41:18 +02:00
Michael Krabbe Borregaard af7d332453 Merge pull request #859 from innerlee/patch-1
Update backends.jl
2017-05-23 15:43:33 +02:00
lizz 5439c3a3ce Update backends.jl 2017-05-23 21:41:31 +08:00
Michael Krabbe Borregaard 6c4b6bbfbe Merge pull request #858 from mkborregaard/hotfix-glvisualizetext
Fix missing brackets
2017-05-23 10:51:26 +02:00
Michael K. Borregaard 53719e5a8e Fix missing brackets 2017-05-23 10:51:00 +02:00
Michael Krabbe Borregaard aed34c3b9b Merge pull request #857 from mkborregaard/glvisualize_tert
Replace `text` with `glvisualize_text`
2017-05-23 10:23:53 +02:00
Michael K. Borregaard a5482453ce Replace text with glvisualize_text
glvisualize defined a `text` function that shadowed a method of Plots exported `text` function
2017-05-23 10:23:20 +02:00
Michael Krabbe Borregaard 712d2011c3 Merge pull request #843 from mkborregaard/change_default_backend
Change default backends
2017-05-22 12:04:46 +02:00
Daniel Schwabeneder 0e6942a182 Merge pull request #853 from daschw/ds-ticks-tuple
fix passing ticks tuple on 0.6
2017-05-22 08:05:04 +02:00
Daniel Schwabeneder ce169edd08 fix passing ticks tuple on 0.6 2017-05-21 23:58:20 +02:00
Daniel Schwabeneder dd526e00ab undo: fix passing ticks tuple on 0.6 2017-05-21 23:47:26 +02:00
Daniel Schwabeneder bad2ef63c6 fix passing ticks tuple on 0.6 2017-05-21 23:44:12 +02:00
Michael K. Borregaard e283c6557b Change default backends 2017-05-21 12:44:18 +02:00
Michael Krabbe Borregaard e8da23c3e7 Merge pull request #852 from mkborregaard/remove-conda-messag
Remove conda update message
2017-05-21 11:30:51 +02:00
Michael K. Borregaard 08d7bee224 Remove conda update message
These instructions led to installing a deprecated matplotlib version
2017-05-21 11:30:11 +02:00
Michael Krabbe Borregaard 16c95c6deb Merge pull request #848 from darwindarak/dd/pyplot-worldage
RFC: fix world-age problem in PyPlot initialization
2017-05-21 10:55:19 +02:00
Michael Krabbe Borregaard 1d03e97721 Merge pull request #849 from dlfivefifty/pull-request/9abcba37
Fix plot(::Matrix{RGB{Float64}}) in plotly backend
2017-05-21 09:38:55 +02:00
Sheehan Olver 9abcba3753 Fix plot(::Matrix{RGB{Float64}}) in plotly backend 2017-05-21 16:53:28 +10:00
Darwin Darakananda b501c9bf4b fix world-age problem in PyPlot initialization 2017-05-20 15:39:26 -07:00
Michael Krabbe Borregaard 72c506b62b Merge pull request #845 from ChrisRackauckas/patch-2
Add JSON to REQUIRE
2017-05-19 17:52:38 +02:00
Christopher Rackauckas f09dfb7035 Update REQUIRE 2017-05-19 07:56:36 -07:00
florian oswald 6cca763284 removed test for k 2017-05-17 21:07:54 +02:00
Florian Oswald 915c41c9d9 addressed changes requested 2017-05-17 17:48:03 +02:00
Florian Oswald 9c2c548874 create dict _initial_fontsizes and copy from that. creates new method scalefontsizes() [no keyword] 2017-05-17 17:10:21 +02:00
Florian Oswald fdf699bf35 added const copies of _all_defaults and _axis_defaults to be able to reset fonts to initial values with new resetfontsizes method 2017-05-17 16:34:03 +02:00
Florian Oswald e3ce1ab1d1 just calling default(k) does not give back the default value for k 2017-05-17 15:40:47 +02:00
Florian Oswald af56d6f265 added resetfontsizes() 2017-05-17 15:31:26 +02:00
Daniel Schwabeneder 05eb687ca4 Merge pull request #834 from daschw/ds-testing
Move new PlotExample to the end for VRT testing
2017-05-17 08:32:12 +02:00
Elliot Saba 99e4408da4 Update CI URLs to point to new caching infrastructure 2017-05-16 17:25:27 -07:00
MA Laforge 64dd69f550 Improve robustness
More generic Array support.
Add support for ColorGradient.
Don't crash if plot specifies GridLayout.
(Does not properly restore info on layout).
2017-05-16 19:21:35 -04:00
MA Laforge 8b8de6bcd3 Move where backends.jl is included.
Must ensure all types required by HDF5 plots are defined.
2017-05-16 19:20:55 -04:00
MA Laforge b920ee8550 Re-integrate HDF5 plots.
Made code compatible with Julia v0.6.
Parametric types no longer <: DataType (now <: Type).
Add workaround to initialize Dict with "Type" keys.
2017-05-16 19:19:35 -04:00
Daniel Schwabeneder 89cd67792b update numbers of skipped examples in VRT 2017-05-16 21:46:11 +02:00
Daniel Schwabeneder 1f7ecb969c move new PlotExample to the end for VRT 2017-05-16 21:43:22 +02:00
Daniel Schwabeneder d4ef1761e4 change skipped images because of new example 2017-05-16 21:32:57 +02:00
Michael Krabbe Borregaard dc01cc5c8e Merge pull request #832 from mkborregaard/master
Revert "changed xor in gr.jl"
2017-05-16 20:39:50 +02:00
Michael K. Borregaard db341f1814 Revert "changed xor in gr.jl"
This reverts commit 5c54722626.
2017-05-16 20:38:37 +02:00
Daniel Schwabeneder 06e469f059 Merge pull request #831 from daschw/ds-pyplot-fill
fix filling stepstyle on pyplot
2017-05-16 19:45:16 +02:00
Michael Krabbe Borregaard 9ec1e674d0 Merge pull request #830 from mkborregaard/fix-xor-0.6
changed xor in gr.jl for 0.6
2017-05-16 11:29:17 +02:00
Michael K. Borregaard 5c54722626 changed xor in gr.jl 2017-05-16 11:28:38 +02:00
Daniel Schwabeneder 0a92b13263 Merge pull request #827 from oschulz/no-hist-autolims
Remove ylims default setting for bar and histogram plots
2017-05-16 07:58:58 +02:00
Daniel Schwabeneder 2fbc3c954a fix filling stepstyle on pyplot 2017-05-16 07:32:14 +02:00
Oliver Schulz 746f96cdcd Remove ylims default setting for bar and histogram plots
Setting `ylims -> ...` doesn't play well with multiple series and cannot
be properly overridden by user.
2017-05-15 23:26:30 +02:00
Michael Krabbe Borregaard ee9d78b190 Merge pull request #824 from daschw/ds-0.5-compat
Fix precompilation on 0.5: Fixes #823
2017-05-14 22:23:08 +02:00
Daniel Schwabeneder 0e6a02b810 make precompilation work on o.5 2017-05-13 23:46:29 +02:00
Michael Krabbe Borregaard 864dddb1ff Merge pull request #806 from dpsanders/0.6_deprecations
0.6 deprecations
2017-05-13 08:55:17 +02:00
Michael Krabbe Borregaard 321495f253 Merge pull request #820 from mkborregaard/Switch-precompilation-on
Switch back on
2017-05-12 11:47:33 +02:00
Michael K. Borregaard eced31e3d7 Update version number in tests 2017-05-12 11:46:51 +02:00
Michael K. Borregaard 4b8dc06ddb Switch precompilation back on 2017-05-12 11:45:46 +02:00
Michael Krabbe Borregaard ff3ba18b15 Merge pull request #819 from mkborregaard/switch_off_precompile
Switch off precompilation for release
2017-05-12 11:42:51 +02:00
Michael K. Borregaard d24f327342 Switch off precompilation for release 2017-05-12 11:42:26 +02:00
Daniel Schwabeneder d801a2789e Merge pull request #818 from daschw/ds-testing
update version number for testing
2017-05-12 09:08:27 +02:00
Daniel Schwabeneder b8c8c49176 update version number for testing 2017-05-11 22:45:04 +02:00
Michael Krabbe Borregaard 601f24a006 Merge pull request #816 from mkborregaard/master
Up minor version number
2017-05-11 14:00:47 +02:00
Michael K. Borregaard 160b2bf03a Up minor version number 2017-05-11 14:00:29 +02:00
Michael Krabbe Borregaard 944163e889 Merge pull request #815 from mkborregaard/master
Updates for release 0.11
2017-05-11 13:41:13 +02:00
Michael K. Borregaard 8656fe002a Add minimum version numbers to PlotUtils and PlotThemes 2017-05-11 13:40:39 +02:00
Michael K. Borregaard d5e50983d8 Move rgba_string to PlotUtils
requested by Tony Kelman
2017-05-11 13:40:10 +02:00
Michael Krabbe Borregaard f3d31a62db Merge pull request #814 from ChrisRackauckas/patch-2
Fix plotpane notice
2017-05-11 09:48:15 +02:00
Christopher Rackauckas ee15b2c166 Fix plotpane notice
PlotlyJS actually plots to the plot pane, so the text was misleading.
2017-05-11 00:31:30 -07:00
Michael Krabbe Borregaard 4d84ab155a Merge pull request #812 from JonathanAnderson/JonathanAnderson-patch-1
Update gr.jl inline display to match GR.jl
2017-05-10 13:28:29 +02:00
Michael Krabbe Borregaard accc063db8 Merge pull request #811 from fuzzybear3965/master
increase plotly bottom margin to 20px; fixes #810
2017-05-10 13:24:08 +02:00
fuzzybear3965 b88d26ce77 increase bottom margin to 20px; fixes #810 2017-05-09 12:29:35 -04:00
Michael Krabbe Borregaard 886386508c Merge pull request #809 from mkborregaard/master
Amend news.md
2017-05-09 09:32:26 +02:00
Michael K. Borregaard d893034f47 Amend news.md 2017-05-09 09:31:40 +02:00
Josef Heinen f4b798765d Merge pull request #807 from jheinen/master
gr: use correct colorbar scaling
2017-05-08 23:39:09 +02:00
Josef Heinen 5e6a9da3ed gr: use correct colorbar scaling 2017-05-08 14:36:25 -07:00
David Sanders 10f214fbb4 Change typealias to const 2017-05-08 15:20:21 -05:00
David Sanders 698d583d1d Fix world-age problem with IJulia 2017-05-08 15:16:21 -05:00
Michael Krabbe Borregaard 598211c349 Merge pull request #802 from oschulz/bins-default-auto
Change default for bins to :auto (meaning 30 bins)
2017-05-08 11:39:58 +02:00
Oliver Schulz 7843821109 Change default for bins to :auto (meaning 30 bins) 2017-05-08 11:37:02 +02:00
Michael Krabbe Borregaard 96f3baca41 Merge pull request #800 from oschulz/barplot-fix
Barplot fix
2017-05-08 10:49:14 +02:00
Oliver Schulz 67b4157e25 Improve data preprocessing for bar and histogram plots
Fixes broken bar-plots with non-numeric a-axes
2017-05-06 15:00:31 +02:00
Oliver Schulz a523903c15 Remove remnant debugging output 2017-05-06 14:58:48 +02:00
Josef Heinen 92e9fa2084 Merge pull request #798 from jheinen/master
gr: fixed linewidth bug (lw=0)
2017-05-04 16:31:43 +02:00
Josef Heinen c75e1df190 gr: fixed linewidth bug (lw=0) 2017-05-04 16:28:49 +02:00
Michael Krabbe Borregaard 79bf45b823 Merge pull request #795 from sebastianpech/master
Add pgfplots support for zcolor and colorbar
2017-05-04 16:18:26 +02:00
Daniel Schwabeneder 58989465f4 Merge pull request #793 from daschw/ds-ticks-reduction
Avoid reducing the number of ticks set by the user
2017-05-04 16:17:57 +02:00
Daniel Schwabeneder 1e6b442c6c Merge pull request #794 from daschw/ds-pyplot-colorbar
Avoid PyPlot colorbar label cropping
2017-05-04 16:17:17 +02:00
Michael Krabbe Borregaard 33addf4449 Merge pull request #758 from mcawte/master
Added an animation with subplots example
2017-05-04 13:43:27 +02:00
Michael Krabbe Borregaard c5fed9524a Merge pull request #790 from huckl3b3rry87/pull-request/2e732993
changed warning in imagemagick
2017-05-04 13:42:30 +02:00
Michael Krabbe Borregaard cbfadde43c Merge pull request #769 from blegat/surfaceclims
Use clims with :surface for PyPlot
2017-05-04 13:19:10 +02:00
Michael Krabbe Borregaard cebe1eedeb Merge pull request #797 from mkborregaard/updatenews
Update News.md
2017-05-04 13:17:06 +02:00
Michael K. Borregaard c22a9e51a1 Update News.md 2017-05-04 13:15:05 +02:00
Michael Krabbe Borregaard e41022c7be Merge pull request #787 from oschulz/new-hist-impl
Rewrite of histogram recipes, using StatsBase.histogram
2017-05-04 12:33:42 +02:00
Oliver Schulz 56a9389023 Fix log-scale for 1D bar/bin/histogram series types 2017-05-04 10:02:07 +02:00
Oliver Schulz 1188230641 Change histogram implementation, use StatsPlots, add new histogram styles
New series recipes for binned data:

* barbins
* scatterbins
* stepbins

New series recipes for histogram:

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

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

Also adds support for some common auto-binning modes:

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

Maybe these could be contributed to StatsBase at some point.

Error bars currently don't work correctly for scatterbins and scatterhist,
due to problem with manipulating error bars in a series recipe, but do work
for "plot(h::StatsBase.Histogram, seriestype = :scatter)" (works around
the problem by calling scatter directly, it seems that error bars can be
manipulated correctly in a type recipe).
2017-05-04 10:02:07 +02:00
Michael Krabbe Borregaard e760b42560 Merge pull request #789 from huckl3b3rry87/pull-request/5e5e1850
deleted old warning for conda
2017-05-04 09:55:31 +02:00
Huckleberry Febbo 627c03193a Merge branch 'master' into pull-request/5e5e1850 2017-05-03 16:00:06 -04:00
Sebastian Pech 0f837f3438 Add pgfplots support for zcolor and colorbar 2017-05-03 10:46:25 +02:00
Daniel Schwabeneder af072da0b0 avoid auto-reduction of user-defined ticks 2017-05-02 21:10:43 +02:00
Daniel Schwabeneder c4f3b93da5 increase rightpad for colorbars 2017-05-02 20:36:33 +02:00
Michael Krabbe Borregaard 906f11ed76 Merge pull request #782 from oschulz/fix-pylot-conda-handling
Prevent inadvertent Conda ROOTENV initialization
2017-05-02 16:10:46 +02:00
Huckleberry Febbo 2e7329931c changed warning in imagemagick 2017-05-01 11:14:38 -04:00
Huckleberry Febbo 5e5e1850ac deleted old warning for conda 2017-05-01 11:04:39 -04:00
Daniel Schwabeneder 93d16a27c1 undo unnecessary changes 2017-04-30 19:27:01 +02:00
Daniel Schwabeneder a602309a02 wip let axis limits expand 2017-04-30 19:02:42 +02: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
Daniel Schwabeneder 11e9eb3aa3 allow Int as input type for the ticks attribute to set the desired number of ticks 2017-04-23 20:30:48 +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
Tom Breloff c092d3cab4 Merge branch 'master' into dev 2016-12-13 14:54:46 -05:00
Pablo Zubieta 46ad076751 Proper id synchronization of plotlyjs plots 2016-12-10 23:49:17 -06:00
Thomas Breloff 07731614a9 fix ComplexPlot; closes #598 2016-12-02 20:37:35 -05:00
Tom Breloff d8ffd729f4 Merge pull request #597 from tbreloff/dev
Output/Animation improvements
2016-12-01 15:26:21 -05:00
Tom Breloff b23d94eeb8 inline display 2016-12-01 15:22:51 -05:00
Tom Breloff 4ed7144ca4 animation fixes: show for videos, imagemagick init 2016-12-01 10:23:41 -05:00
Tom Breloff ad924e8cc9 Merge pull request #595 from tbreloff/dev
buildanimation: mov and mp4
2016-11-30 09:54:26 -05:00
Tom Breloff aa929ec24f buildanimation: mov and mp4 2016-11-30 09:50:28 -05:00
Tom Breloff 07f7fd3c7a Merge remote-tracking branch 'origin/master' into dev 2016-11-28 12:58:08 -05:00
Tom Breloff 83beca098b Merge pull request #591 from pabloferz/pz/plotlyjs
Fix embeding of PlotlyJS plots in Jupyter
2016-11-28 12:57:35 -05:00
Pablo Zubieta 2c3d35d249 Fix embeding of PlotlyJS plots in Jupyter 2016-11-28 11:53:14 -06:00
Tom Breloff 90e655d979 use_remote for plotly html output 2016-11-28 11:02:32 -05:00
Tom Breloff 8204b51213 Merge remote-tracking branch 'origin/master' into dev 2016-11-28 10:13:40 -05:00
Tom Breloff c3f40d0555 allow end in Plot/Subplot getindex; closes #587 2016-11-28 10:13:00 -05:00
Tom Breloff cbd134987b Merge pull request #590 from piever/pull-request/167fd687
Added savefig html
2016-11-27 23:26:37 -05:00
Pietro Vertechi 167fd68774 Added savefig html 2016-11-28 04:15:09 +00:00
Tom Breloff 2b8cc7cfde Merge pull request #589 from piever/pull-request/62280fb2
Allow errorbars in plots with categorical x axis (see #549 )
2016-11-26 21:56:44 -05:00
Pietro Vertechi 62280fb24b Modified error_coords to allow errorbars in plots with categorical x-axis 2016-11-26 01:49:48 +00:00
Tom Breloff 2a7604ef5f gr: fix 3d grid 2016-11-22 13:45:11 -05:00
Tom Breloff 0b47aafd14 Merge pull request #585 from tbreloff/sd/dev
use more unique name
2016-11-22 12:36:09 -05:00
Simon Danisch 24eefbed2b use more unique name 2016-11-22 18:35:12 +01:00
Tom Breloff ab7a73c879 Merge pull request #584 from tbreloff/sd/dev
fix closing window
2016-11-22 11:25:13 -05:00
Simon Danisch 81e0868725 fix closing window 2016-11-22 17:16:01 +01:00
Tom Breloff eba1e366bb _canvas_type in unicodeplots 2016-11-21 14:49:39 -05:00
Tom Breloff e9ccdef447 Merge pull request #579 from piever/pull-request/bdce27dd
Implemented legend position in plotly
2016-11-21 11:21:39 -05:00
Pietro Vertechi bdce27dd7b Implemented legend position in plotly 2016-11-20 15:35:58 +00:00
Tom Breloff 436ab89d2d Merge pull request #570 from tbreloff/sd/dev
refactors + rename for new GLWindow version
2016-11-18 09:17:11 -05:00
SimonDanisch 74c2db4909 rebase 2016-11-18 00:49:33 +01:00
SimonDanisch e12c3f332e add missing to_vec 2016-11-18 00:44:54 +01:00
SimonDanisch 34a64db91d changes for markers etc 2016-11-18 00:44:53 +01:00
SimonDanisch e2a4a1e2ea clean up signals propperly 2016-11-18 00:44:53 +01:00
SimonDanisch 22f12316ef refactors + rename from GLWindow 2016-11-18 00:44:53 +01:00
Tom Breloff e24acece49 shape_coords fixes; makekw 2016-11-17 13:45:49 -05:00
Tom Breloff dd7462bd3f travis 2016-11-17 13:07:58 -05:00
Tom Breloff da7e0cba3e deprecate curve_points and shape_coords and extend coords; move directed_curve/shorten_segment/random_control_point to PlotRecipes 2016-11-17 13:00:56 -05:00
Tom Breloff 50219aa872 Merge pull request #573 from swt30/subplot-methods
Enable shorthand methods on subplots too
2016-11-17 12:47:16 -05:00
Tom Breloff 000660b43a return font from EachAnn; several annotation fixes; tests fixes 2016-11-17 11:28:33 -05:00
Tom Breloff fbeaa59f18 curve offset 2016-11-16 13:55:07 -05:00
Scott Thomas 578e601368 Enable shorthand methods on subplots too
Shorthand methods like `title!` and `annotate!` currently only
work on fully-fledged plots; this change broadens the method
definitions so that they work on subplots too.
2016-11-16 17:28:39 +00:00
Tom Breloff 247fe27f03 limit subplot attr when setting subplot kw 2016-11-16 09:23:39 -05:00
Tom Breloff ee2e807cc2 isnothing 2016-11-15 17:05:26 -05:00
Tom Breloff c4a880c870 plotlyjs surf fix 2016-11-14 16:45:01 -05:00
Tom Breloff 4eb6fac881 series_annotations scalefactor 2016-11-14 13:29:32 -05:00
Tom Breloff 0ab37f49fa plotlyjs reuse window; plotlyjs closeall; closes #567 2016-11-14 09:43:04 -05:00
Tom Breloff 376ee02041 fix series_annotations size 2016-11-11 17:43:46 -05:00
Tom Breloff c779dc6577 fix maker-->marker 2016-11-11 13:17:50 -05:00
Tom Breloff ad71e81338 rtri/ltri shapes; go between in directed_curve 2016-11-11 11:10:06 -05:00
Thomas Breloff 9f2ba09fc4 fix colors example 2016-11-09 17:08:28 -05:00
Simon 1e6cee2c5d Merge pull request #564 from tbreloff/sd/dev
Sd/dev
2016-11-09 17:35:38 +01:00
Thomas Breloff 4dc742489d fix cycle in fillrange 2016-11-08 11:32:17 -05:00
SimonDanisch d751b985ac incorperate new text scaling 2016-11-08 16:55:25 +01:00
SimonDanisch 8a58190cce fix mesh particle size issue 2016-11-07 23:50:09 +01:00
SimonDanisch 612ca15fc0 variable change from GLVisualize 2016-11-07 23:50:09 +01:00
Thomas Breloff 2200b76054 directed_curve 2016-11-07 00:20:14 -05:00
Thomas Breloff 08771395b8 rewrite directed_curve 2016-11-06 11:46:22 -05:00
Thomas Breloff e3c06cad57 cleanup and comments 2016-11-04 15:54:26 -04:00
Thomas Breloff 4dfadeaf15 series_annotations refactor and gr/pyplot fixes 2016-11-04 15:39:53 -04:00
Thomas Breloff af1896dc36 don't export Axis/Plot/etc; closes #552; fix series_annotations; support SeriesAnnotations in gr; fix scale/translate 2016-11-03 22:02:23 -04:00
Thomas Breloff 350ffdee25 Base.cycle to cycle; text_size; animate; MixedMeasures; SeriesAnnotations 2016-11-03 13:29:20 -04:00
Thomas Breloff 281b92c262 gr arrow tail 2016-11-02 14:09:31 -04:00
Thomas Breloff 75f1cf8cbb complexplot; Arrow side; gr arrows 2016-11-02 14:00:03 -04:00
Thomas Breloff bf0f44773f basic support for arrow in GR 2016-11-02 13:22:50 -04:00
Thomas Breloff dfb89ef7f5 scalefontsize/scalefontsizes; closes #560 2016-11-02 10:20:33 -04:00
Thomas Breloff 5ef7126a3a meta_checkout; closes #544 2016-11-02 10:00:38 -04:00
Tom Breloff c9835a53e3 Merge pull request #559 from tbreloff/sd/dev
fix mesh particle size bug and better window creation
2016-11-01 12:08:21 -04:00
Tom Breloff 5ea48e6fcd Merge pull request #557 from mkborregaard/fix-markerstrokecolor-doc
fix docs for msc
2016-11-01 12:07:54 -04:00
Tom Breloff 1d1a703e3c Merge pull request #554 from ChrisRackauckas/patch-2
Remove precompilation
2016-11-01 12:07:33 -04:00
SimonDanisch 8110fec4ef fix mesh particle + better window creation 2016-11-01 12:28:37 +01:00
Michael K. Borregaard 67ecf4e350 fix docs for msc
specifies msc defaults to foreground_color_subplots
2016-10-31 14:21:49 +01:00
Christopher Rackauckas e8ed0a3034 Remove precompilation
Precompilation has never played nice with Plots, but now it has gotten even worse. Getting rid of precompilation fixes #543 and in normal use cases, the vast majority of time to plot comes from importing the other plotting libraries, so I did not notice a significant performance loss.
2016-10-28 22:21:40 -07:00
SimonDanisch add962c8ea Merge branch 'dev' into sd/dev 2016-10-28 11:39:52 +02:00
SimonDanisch 9bed393210 changes for new GLVisualize 2016-10-28 11:39:10 +02:00
Thomas Breloff 3aac2b2895 check for empty labs 2016-10-25 22:33:53 -04:00
Thomas Breloff aa6814a6d3 rename update! to attr! 2016-10-18 20:45:56 -04:00
Thomas Breloff d291582ad9 fix gr flipped heatmap 2016-10-14 13:49:47 -04:00
Thomas Breloff ebc591747a fix empty axes; closes #536 2016-10-14 10:42:09 -04:00
SimonDanisch 456602b79f various fixes 2016-10-14 00:39:54 +02:00
Thomas Breloff b1835a91af gr extrema fix; themes gradient_name fix 2016-10-13 13:24:25 -04:00
Thomas Breloff 0a8d88a4fe NEWS; bump version 2016-10-13 09:56:27 -04:00
Thomas Breloff e2adcbb486 fix gradient in theme 2016-10-13 09:53:25 -04:00
Thomas Breloff aee13d295c fix plotlyjs lims: apply scalefunc 2016-10-12 15:11:51 -04:00
Thomas Breloff 6677e0e0a0 fix link_axes for nested singleton subplot 2016-10-12 14:52:30 -04:00
Thomas Breloff 9d64914e62 reset theme with :none/:default 2016-10-12 13:34:07 -04:00
Thomas Breloff d136977fc4 fix date/datetime 2016-10-12 13:25:19 -04:00
Thomas Breloff 7fb995094e added closeall for gr/pyplot 2016-10-12 11:28:43 -04:00
Thomas Breloff f002f66890 add PlotThemes to REQUIRE; add warning for DataFrames 2016-10-12 09:30:49 -04:00
Thomas Breloff 9de3ed8cf0 remove Compat from REQUIRE 2016-10-11 19:20:07 -04:00
Thomas Breloff 7ff843ec1a msw alias 2016-10-11 16:50:58 -04:00
Thomas Breloff b181788dc2 add PlotThemes dep, change set_theme to theme 2016-10-11 15:36:56 -04:00
Thomas Breloff 81302c1e9d NEWS; bump version 2016-10-11 12:43:38 -04:00
Thomas Breloff 77fbf3eb51 use drawimage for heatmap 2016-10-11 10:32:51 -04:00
Tom Breloff 837c0c06ed Merge pull request #530 from jheinen/dev
gr: changed heatmap code
2016-10-11 09:32:53 -04:00
Josef Heinen 93e7bc2a2e gr: changed heatmap code 2016-10-11 15:03:31 +02:00
Thomas Breloff 702ab3c504 remove plotly png output... point to plotlyjs 2016-10-10 07:34:51 -04:00
Thomas Breloff b9dea42be6 fix Date recipe; closes #529 2016-10-10 07:02:10 -04:00
Thomas Breloff ae608d4d78 staged date fix, still not working 2016-10-10 01:08:29 -04:00
Thomas Breloff 5e8c88d657 spy recipes 2016-10-09 00:52:53 -04:00
Thomas Breloff 9bbe0f9414 gr: image transpose fix 2016-10-08 23:19:26 -04:00
Thomas Breloff f290748c72 gr: don't set GKS_WSTYPE for windows/use_default 2016-10-08 23:03:07 -04:00
Thomas Breloff 96821f6303 remove spy; support spy seriestype in unicodeplots; recipes cleanup 2016-10-08 22:39:49 -04:00
Thomas Breloff d290c6702a handle series_attr merge and add_defaults when combining subplots; closes #526 2016-10-08 22:00:22 -04:00
Thomas Breloff 2877cb7160 gr: replaced withenv calls with _gr_wstype and gr_set_output 2016-10-07 14:54:26 -04:00
Thomas Breloff 14fd3c94b5 fix plotly horizontal bars 2016-10-07 13:49:00 -04:00
Thomas Breloff f615a5d05e experimenting with gr heatmap 2016-10-07 12:53:18 -04:00
Thomas Breloff 04a4357684 fix plotly aspect_ratio and reword arg desc; closes #523 2016-10-07 12:14:06 -04:00
Thomas Breloff a4c25321d8 histogram2d puts NaN for 0 count; fix pyplot NaNs in heatmap; change default markersize to 4 2016-10-07 11:33:02 -04:00
Thomas Breloff 068282af55 aliases for subplot colors; default(d,k); fg_color/fg_color_sp; fix tick_padding for nothing/false 2016-10-06 12:45:21 -04:00
Tom Breloff 24078661c9 Merge pull request #522 from dennybiasiolli/dennybiasiolli-patch-1
Fix typo in args.jl
2016-10-06 09:01:28 -04:00
Tom Breloff 54670d4259 Merge pull request #517 from fedxa/dpi-fix
Fix for dpi in pyplot backend
2016-10-06 09:01:05 -04:00
Denny Biasiolli bc276acb96 Fix typo in args.jl
Fix #521
2016-10-06 14:29:24 +02:00
Fedor Bezrukov 9e8869acf1 Fix for dpi in pyplot backend 2016-10-03 00:37:50 +03:00
Thomas Breloff c39f5e1483 plotly: always set tickangle 2016-09-30 13:48:27 -04:00
Thomas Breloff f41a09b68e plotly: support aspect_ratio 2016-09-30 13:44:37 -04:00
Thomas Breloff 4416fc919e improve tick_padding and fix rotation for plotly/gr 2016-09-30 12:46:38 -04:00
Thomas Breloff 5ed913ba5e plotly: plotly_surface_data and wireframes; closes #479 2016-09-30 11:25:29 -04:00
Thomas Breloff f4329a9483 support color for plotly bar; closes #513 2016-09-30 10:40:26 -04:00
Thomas Breloff 24a4c31f0d widen bar plots; improve ggplot2 theme 2016-09-29 16:14:46 -04:00
Thomas Breloff 2b1c4685d2 glvisualize MetaPkg 2016-09-27 15:55:28 -04:00
Thomas Breloff 980a92c625 remove show; fix plotlyjs _series_updated, closes #505 2016-09-27 13:05:28 -04:00
Thomas Breloff 54923c082c reset_extrema; setxyz for z matrix 2016-09-27 12:51:20 -04:00
Thomas Breloff 7ce783705a Atom match PlotPane size and support plotlyjs 2016-09-26 11:52:24 -04:00
Thomas Breloff e23cf3377e gr wstype default; gr tighten tick pos 2016-09-24 23:16:35 -04:00
Thomas Breloff bed9beafdc fix axis widen when lims is set 2016-09-24 21:59:58 -04:00
Thomas Breloff fe1b759787 faster plotIndex count; withenv logic and cairox11/cairopng in gr 2016-09-23 12:24:56 -04:00
SimonDanisch 8c6c81e8d0 Merge branch 'sd/labels' into sd/dev 2016-09-23 12:47:26 +02:00
SimonDanisch 874e94218c add labels 2016-09-23 12:42:38 +02:00
Thomas Breloff 755a70bf77 added series_list to Subplot object to improve performance 2016-09-22 19:36:25 -04:00
Thomas Breloff c58de34e63 layout error msg 2016-09-22 17:36:08 -04:00
Thomas Breloff c798fe6822 NEWS; bump version 2016-09-22 13:49:51 -04:00
Thomas Breloff 5f4dfdd5d2 add_backend/add_backend_string redesign 2016-09-22 13:47:33 -04:00
Thomas Breloff 1f7043e02a allow curly after grid in layout macro 2016-09-21 15:51:10 -04:00
Thomas Breloff c651be7a12 support pdf and eps in plotlyjs 2016-09-21 14:17:38 -04:00
Thomas Breloff 0cc15102fb NEWS and bump version 2016-09-21 11:18:26 -04:00
Thomas Breloff 22aaefd1a0 _apply_type_recipe fix 2016-09-20 16:40:49 -04:00
Thomas Breloff 8638626ff5 Formatted and elementwise type recipes 2016-09-20 16:23:59 -04:00
Thomas Breloff 24fa5c8cbe glvisualize 2016-09-20 12:53:32 -04:00
Thomas Breloff 90d054c2ec glvisualize fixes; limit ticks to amin/amax closes #495 2016-09-20 12:05:16 -04:00
Thomas Breloff 555145a650 added pixel marker for pyplot 2016-09-19 22:23:35 -04:00
Thomas Breloff ec17d557a7 add imperfect shape support to unicodeplots; closes #490 2016-09-16 16:22:11 -04:00
Tom Breloff 792df32e69 Merge pull request #491 from KristofferC/patch-1
stop double adding style options to the axis in pgfplots
2016-09-16 11:12:55 -04:00
Kristoffer Carlsson adc96917fc stop double adding style options to the axis in pgfplots 2016-09-16 08:48:46 +02:00
Tom Breloff 9b0e35b4b1 Merge pull request #478 from tbreloff/sd/dev
text rotation, move commands into module, is_marker_supported
2016-09-15 11:13:39 -04:00
Simon 9d652c8fe2 remove module and still don't overwrite scatter 2016-09-15 16:05:21 +02:00
Thomas Breloff 1be5794e05 Merge remote-tracking branch 'origin/master' into dev 2016-09-15 09:12:17 -04:00
Tom Breloff 0e561e1cd6 Merge pull request #488 from KristofferC/kc/fix_ticks
fix ticks for pgfplots
2016-09-15 09:11:24 -04:00
Kristoffer Carlsson 4475c38140 fix ticks for pgfplots 2016-09-15 14:58:28 +02:00
Tom Breloff cf02408620 Merge pull request #483 from sivark/pull-request/9c317b8c
gif() now accepts an argument specifying number of times to loop
2016-09-15 08:52:58 -04:00
Thomas Breloff 87ab1d9ca4 added colorbar_title attr and pyplot impl 2016-09-13 12:50:28 -04:00
Sivaramakrishnan Swaminathan 9c317b8c3f gif() now accepts an argument specifying number of times to loop
Note that GIF playback might have some variability depending on the
player used: https://github.com/ImageMagick/ImageMagick/issues/263
2016-09-13 10:12:44 -04:00
Thomas Breloff ea18b11475 pyplot font family 2016-09-12 19:34:34 -04:00
Thomas Breloff 17afa11723 plotly_data for Surface; improve add_backend(:plotlyjs) 2016-09-09 22:37:55 -04:00
Simon fc660e3486 correctly implement is_marker_supported 2016-09-09 12:34:24 +02:00
Simon dbc12bb9ba add rotations and move plotting commands to module 2016-09-09 12:34:24 +02:00
Simon 2c1f58e773 adhere to new scale primitive api 2016-09-09 12:34:24 +02:00
Thomas Breloff 2bde412fa3 xlims/ylims/zlims convenience methods 2016-09-07 12:22:06 -04:00
Thomas Breloff 03a9fc3419 is_supported refactor; removed deprecated backends 2016-09-06 14:01:39 -04:00
Tom Breloff 2ca7324a45 Merge pull request #474 from KristofferC/patch-1
forget plot if no label is provided
2016-09-06 10:00:04 -04:00
Kristoffer Carlsson cf381880a5 forget plot if no label is provided 2016-09-06 15:48:27 +02:00
Thomas Breloff 12230f1fc9 Merge remote-tracking branch 'origin/master' into dev 2016-09-05 21:35:23 -04:00
Tom Breloff 6145214734 Merge pull request #471 from fredrikekre/fe/kw
Puts some values in the correct spot for PGFPlot
2016-09-05 08:28:04 -04:00
Tom Breloff 412801821f Merge pull request #472 from jheinen/dev
gr: added support for aspect_ratio
2016-09-05 08:26:27 -04:00
Josef Heinen c65c7ae252 gr: added support for aspect_ratio 2016-09-05 13:23:43 +02:00
Fredrik Ekre c3511005c7 put values in correct spot 2016-09-05 11:29:46 +02:00
Thomas Breloff 31ea149820 glvisualize: checkout packages in add_backend 2016-09-01 21:36:51 -04:00
Thomas Breloff a0aa702725 glvisualize: checkout packages in add_backend 2016-09-01 21:26:28 -04:00
Thomas Breloff ac1e82075c revert change to axes.jl 2016-09-01 21:10:23 -04:00
Tom Breloff 65649ade14 Merge pull request #469 from jheinen/dev
Added support for clims kwarg
2016-09-01 21:00:11 -04:00
Tom Breloff 34135f8e6b Merge pull request #374 from SimonDanisch/dev
glvisualize backend
2016-09-01 20:59:13 -04:00
Simon 31c8a04856 fix api change 2016-09-01 12:11:35 +02:00
Josef Heinen 234f9b202e Added support for clims kwarg 2016-09-01 11:59:28 +02:00
Thomas Breloff 4035c0bbe0 allow integers for colors, maps to palette index 2016-08-31 22:34:41 -04:00
Thomas Breloff 03a228fbe7 centering in bbox 2016-08-31 11:56:20 -04:00
Thomas Breloff 6e3de26477 backend_object; pgfplots _update_plot_object fix 2016-08-29 09:18:08 -04:00
Thomas Breloff d892c57596 Atom fixes 2016-08-26 18:05:37 -04:00
Thomas Breloff 576ed7b7b3 Atom: add back PLOTS_USE_ATOM_PLOTPANE; initialize backend when backend is set and removed the println 2016-08-26 17:46:12 -04:00
Thomas Breloff 966dede6e8 Atom PlotPane finally working 2016-08-26 16:14:05 -04:00
Simon af32590314 fix hover cam and title pos 2016-08-26 16:48:55 +02:00
Simon 475eb8f263 add GLVisualize backend 2016-08-26 15:11:47 +02:00
Thomas Breloff 8a40ac8991 added Volume with recipe, conversion, expand_extrema, and :volume type 2016-08-25 14:30:08 -04:00
Thomas Breloff 3335bf21fa bump version and NEWS 2016-08-25 13:04:58 -04:00
Thomas Breloff 011f51fbd9 recipe postprocessing for aliases and magic args 2016-08-19 19:04:10 -04:00
Tom Breloff 333714911c Merge pull request #452 from TotalVerb/master
Remove unnecessary `_print` extension
2016-08-19 15:49:09 -04:00
Tom Breloff f165423527 Merge pull request #453 from maximsch2/master
add DateTime recepie
2016-08-19 15:48:56 -04:00
Maxim Grechkin 428fbb9cb9 add DateTime recepie 2016-08-19 12:43:30 -07:00
Thomas Breloff 342f9c60b2 improved twinx 2016-08-19 09:59:50 -04:00
Thomas Breloff e13070cd6d working on twinx 2016-08-19 02:22:12 -04:00
Thomas Breloff 76bb6bab96 gr support for mirror; switch Axis.sp for sps; fixes to inset sp setup and linking 2016-08-19 01:55:55 -04:00
Fengyang Wang ff7b147888 Remove unnecessary _print extension 2016-08-19 01:40:20 -04:00
Thomas Breloff 55a598b796 fix mirror default 2016-08-18 21:23:50 -04:00
Thomas Breloff f63eac9a73 added mirror and implemented in pyplot 2016-08-18 21:11:03 -04:00
Thomas Breloff 8d7c4cd108 type recipe for Dates; closes #451 2016-08-18 17:33:26 -04:00
Thomas Breloff 99f608defb bar fix: reset orientation; layout fixes 2016-08-18 17:33:26 -04:00
Thomas Breloff 34596ada49 orientation extrema fix 2016-08-18 17:33:26 -04:00
Thomas Breloff 60c8f6f578 atom fix; add_backend for pyplot/plotly/plotlyjs; closes #449 2016-08-18 17:33:26 -04:00
Tom Breloff 959da6c5ae Merge pull request #450 from anriseth/anriseth/saveeps
Add eps to savefig
2016-08-18 17:32:53 -04:00
Asbjørn Nilsen Riseth 5c127f945f Add eps to savefig 2016-08-18 15:51:51 +01:00
Thomas Breloff 74ec733444 check for empty inputs; closes #448 2016-08-16 09:47:14 -04:00
Thomas Breloff f560884436 _plotly_js_path fix 2016-08-12 11:02:14 -04:00
Thomas Breloff f68f82e3f4 gr: fix image and alpha; switch transpose_z to use permutedims 2016-08-12 10:30:53 -04:00
Tom Breloff 56bd8006bc Merge pull request #446 from tkelman/patch-1
another Pkg.dir -> dirname(@__FILE__) replacement
2016-08-12 10:23:24 -04:00
Tony Kelman ca062c3ce2 another Pkg.dir -> dirname(@__FILE__) replacement
ref #425
2016-08-12 02:46:33 -07:00
Thomas Breloff 90aba32ca5 fix for spurious scale warnings; closes #444 2016-08-11 13:11:22 -04:00
Thomas Breloff e164a8274a fix pyplot heatmap; closes #388 2016-08-10 14:32:54 -04:00
Thomas Breloff 23b25d4954 fixed rotate 2016-08-10 09:42:21 -04:00
Patrick Kofod Mogensen bc7c8993c0 Support *ticks in PGFplots. 2016-08-10 09:41:43 -04:00
Thomas Breloff 9db7de8373 added skinny markers + and x; closes #436 2016-08-09 17:09:53 -04:00
Thomas Breloff f8fddb49e2 fix for sticks default fillrange for log scale; closes #435 2016-08-09 16:38:32 -04:00
Thomas Breloff 991b2e7ca5 fix clims for line_z in pyplot; closes #395 2016-08-09 16:28:40 -04:00
Thomas Breloff 54cd96e5e0 handle axis=nothing; closes #428 2016-08-09 15:42:09 -04:00
Thomas Breloff 599f91860a allow failures: nightly 2016-08-09 15:03:29 -04:00
Thomas Breloff d59564999c Atom inline display 2016-08-09 13:15:04 -04:00
Tom Breloff 5a87adaa7f Merge pull request #425 from tkelman/nopkgdir
Use dirname(@__FILE__) instead of Pkg.dir
2016-08-05 16:57:56 -04:00
Tony Kelman 4e6150fe1e use S3 links on appveyor
and add fast-fail snippet
2016-08-02 20:39:49 -07:00
Tony Kelman 553125713d 0.4 no longer supported on master 2016-08-02 20:37:39 -07:00
Tony Kelman 5583d9f315 Use dirname(@__FILE__) instead of Pkg.dir
This allows installing the package elsewhere.

Add testing against 0.5 to Travis - this runs the most
recent RC now, release once final tags are done
2016-08-02 22:52:33 -04:00
Thomas Breloff 20df4967a4 NEWS 2016-08-02 21:24:17 -04:00
Thomas Breloff 6a30435071 gr: added GKS_DOUBLE_BUF to display and removed forgotten debugging statement 2016-08-02 21:04:36 -04:00
Thomas Breloff 5776ff1fdf clear insets after use; closes #416 2016-07-26 15:48:41 -04:00
Thomas Breloff bbb00816f1 axis formatter 2016-07-26 12:34:06 -04:00
Thomas Breloff 3b1c409fd7 reset GR viewport for annotations; fixes #398 2016-07-25 16:06:24 -04:00
Thomas Breloff ee68798de3 add back single function recipe; closes #401 2016-07-25 15:40:28 -04:00
Thomas Breloff 3ae8dc9bd7 fix cycle; fix GR fill 2016-07-25 15:25:50 -04:00
Thomas Breloff e9dca92c11 remove mkdir call in tests; closes #397 2016-07-22 11:18:28 -04:00
Thomas Breloff 98cce223e9 unicodeplots size fix 2016-07-22 09:43:43 -04:00
Thomas Breloff 1d7a470f78 plotly ticks fix 2016-07-21 10:52:06 -04:00
Thomas Breloff 461d5efc4b removed release from travis; push for series; update for subplot 2016-07-20 20:44:28 -04:00
Thomas Breloff 705dbf60fa removed compat; added series update methods 2016-07-20 15:15:40 -04:00
Thomas Breloff bb180ad59a UTF8String to String 2016-07-20 09:40:10 -04:00
Thomas Breloff 463e1bcb90 require julia 0.5-; writemime to show 2016-07-19 16:51:05 -04:00
Thomas Breloff 22ac2df595 bump version; NEWS 2016-07-19 12:13:40 -04:00
52 changed files with 9485 additions and 3276 deletions
+3 -4
View File
@@ -2,10 +2,9 @@
language: julia
os:
- linux
- osx
# - osx
julia:
- release
- nightly
- 0.7
matrix:
allow_failures:
- julia: nightly
@@ -45,7 +44,7 @@ notifications:
# uncomment the following lines to override the default test script
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone(pwd()); Pkg.build("Plots")'
- julia -e 'using Pkg; Pkg.add(pwd()); Pkg.build("Plots")'
- julia test/travis_commands.jl
# - julia -e 'Pkg.clone("ImageMagick"); Pkg.build("ImageMagick")'
# - julia -e 'Pkg.clone("GR"); Pkg.build("GR")'
+374 -3
View File
@@ -3,11 +3,382 @@
#### notes on release changes, ongoing development, and future planned work
- All new development should target 0.7!
- Minor version 0.17 is the last one to support Julia 0.6!!
- Minor version 0.11 is the last one to support Julia 0.5!!
- Critical bugfixes only
- `backports` branch is for Julia 0.5
---
## (current master)
- All new development should target Julia 0.7!
## 0.17.3
- Log-scale heatmap edge computation
- Fix size and dpi for GR and PyPlot
- Fix fillrange with line segments on PyPlot and Plotly
- fix flip for heatmap and image on GR
- New attributes for PGFPlots
- Widen axes for most series types and log scales
- Plotly: fix log scale with no ticks
- Fix axis flip on Plotly
- Fix hover and zcolor interaction in Plotly
- WebIO integration for PlotlyJS backend
## 0.17.2
- fix single subplot in plotly
- implement `(xyz)lims = :round`
- PyPlot: fix bg_legend = invisible()
- set fallback tick specification for axes with discrete values
- restructure of show methods
## 0.17.1
- Fix contour for PGFPlots
- 32Bit fix: Int64 -> Int
- Make series of shapes and segments toggle together in Plotly(JS)
- Fix marker arguments
- Fix processing order of series recipes
- Fix Plotly(JS) ribbon
- Contour plots with x,y in grid form on PyPlot
## 0.17.0
- Add GR dependency to make it the default backend
- Improve histogram2d bin estimation
- Allow vector arguments for certain series attributes and support line_z and fill_z on GR, PyPlot, Plotly(JS) and PGFPlots
- Automatic scientific notation for tick labels
- Allow to set the theme in PLOTS_DEFAULTS
- Implement plots_heatmap seriestype providing a Plots recipe for heatmaps
## 0.16.0
- fix 3D plotting in PyPlot
- Infinite objects
## 0.15.1
- fix scientific notation for labels in GR
- fix labels with logscale
- fix image cropping with GR
- fix grouping of annotations
- fix annotations in Plotly
- allow saving notebook with plots as pdf from IJulia
- fix fillrange and ribbon for step recipes
- implement native ticks that respond to zoom
- fix bar plot with one bar
- contour labels and colorbar fixes
- interactive linked axis for PyPlot
- add `NamedTuple` syntax to group with named legend
- use bar recipe in Plotly
- implement categorical ticks
## 0.15.0
- improve resolution of png output of GR with savefig()
- add check for ticks=nothing
- allow transparency in heatmaps
- fix line_z for GR
- fix legendcolor for pyplot
- fix pyplot ignoring alpha values of images
- don't let `abline!` change subplot limits
- update showtheme recipe
## 0.14.2
- fix plotly bar lines bug
- allow passing multiple series to `ribbon`
- add a new example for `line_z`
## 0.14.1
- Add linestyle argument to the legend
- Plotly: bar_width and stroke_width support for bar plots
- abline! does not change axis limits
- Fix default log scale ticks in GR backend
- Use the :fontsize keys so the scalefontsizes command works
- Prepare support for new PlotTheme type in PlotThemes
## 0.14.0
- remove use of imagemagick; saving gifs now requires ffmpeg
- improvements to ffmpeg gif quality and speed
- overhaul of fonts, allows setting fonts in recipes and with magic arguments
- added `camera` attribute to control camera position for 3d plots
- added `showaxis` attribute to control which axes to display
- improvements of polar plots axes, and better backend consistency
- changed the 'spy' recipe back to using heatmap
- added `scatterpath` seriestype
- allow plotlyjs to save svg
- add `reset_defaults()` function to reset plot defaults
- update syntax to 0.6
- make `fill = true` fill to 0 rather than to 1
- use new `@df` syntax in StatPlots examples
- allow changing the color of legend box
- implement `title_location` for gr
- add `hline` marker to pgfplots - fixes errorbars
- pyplot legends now show marker types
- pyplot colorbars take font style from y axis
- pyplot tickmarks color the same as axis color
- allow setting linewidth for contour in gr
- allow legend to be outside plot area for pgfplots
- expand axis extrema for heatmap
- extendg grid lines to axis limits
- fix `line_z` for pyplot and gr
- fixed colorbar problem for flipped axes with gr
- fix marker_z for 3d plots in gr
- fix `weights` functionality for histograms
- fix gr annotations with colorbar
- fix aspect ratio in gr
- fix "hidden window" problem after savefig in gr
- fix pgfplots logscale ticks error
- fix pgfplots legends symbols
- fix axis linking for plotlyjs
- fix plotting of grayscale images
## 0.13.1
- fix a bug when passing a vector of functions with no bounds (e.g. `plot([sin, cos])`)
- export `pct` and `px` from Plots.PlotMeasures
## 0.13.0
- support `plotattributes` rather than `d` in recipes
- no longer export `w`, `h` and names from Measures.jl; use `using Plots.PlotMeasures` to get these names back
- `bar_width` now depends on the minimum distance between bars, not the mean
- better automatic x axis limits for plotting Functions
- `tick_direction` attribute now allows ticks to be on the inside of the plot border
- removed a bug where `p1 = plot(randn(10)); plot(p1, p2)` made `display(p1)` impossible
- allow `plot([])` to generate an empty plot
- add `origin` framestyle
- ensure finite bin number on histograms with only one unique value
- better automatic histogram bins for 2d histograms
- more informative error message on passing unsupported seriestype in a recipe
- allow grouping in user recipes
- GR now has `line_z` and `fill_z` attributes for determining the color of shapes and lines
- change GR default view angle for 3D plots to match that of PyPlot
- fix `clims` on GR
- fix `marker_z` for plotly backend
- implement `framestyle` for plotly
- fix logscale bug error for values < 1e-16 on pyplot
- fix an issue on pyplot where >1 colorbar would be shown if there was >1 series
- fix `writemime` for eps
## 0.12.4
- added a new `framestyle` argument with choices: :box, :semi, :axes, :grid and :none
- changed the default bar width to 0.8
- added working ribbon to plotly backend
- ensure that automatic ticks always generate 4 to 8 ticks
- group now groups keyword arguments of the same length as the input
- allow passing DateTime objects as ticks
- allow specifying the number of ticks as an integre
- fix bug on errorbars in gr
- fixed some but not all world age issues
- better margin with room for text
- added a `match` option for linecolor
- better error message un unsupported series types
- add a 'stride' keyword for the pyplot backend
## 0.12.3
- new grid line style defaults
- `grid` is now an axis attribute and a magic argument: it is now possible to modify the grid line style, alpha and line width
- Enforce plot order in user recipes
- import `plot!` from RecipesBase
- GR no longer automatically handles _ and ^ in texts
- fix GR colorbar for scatter plots
#### 0.12.2
- fix an issue with Juno/PlotlyJS compatibility on new installations
- fix markers not showing up in seriesrecipes using :scatter
- don't use pywrap in the pyplot backend
- improve the bottom margin for the gr backend
#### 0.12.1
- fix deprecation warnings
- switch from FixedSizeArrays to StaticArrays.FixedSizeArrays
- drop FactCheck in tests
- remove julia 0.5 compliant uses of transpose operator
- fix GR heatmap bugs
- fix GR guide padding
- improve legend markers in GR
- add surface alpha for Plotly(JS)
- add fillrange to Plotly(JS)
- allow usage of Matplotlib 1.5 with PyPlot
- fix GLVisualize for julia 0.6
- conform to changes in InspectDR
#### 0.12.0
- 0.6 only
#### 0.11.3
- add HDF5 backend
- GR replaces PyPlot as first-choice backend
- support for legend position in GR
- smaller markers in GR
- better viewport size in GR
- fix glvisualize support
- remove bug with three-argument method of `text`
- `legendtitle` attribute added
- add test for `spy`
#### 0.11.0
- julia 0.6 compatibility
- matplotlib 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
- added dependency on PlotThemes
- set_theme --> theme
- remove Compat from REQUIRE
- warning for DataFrames without StatPlots
- closeall exported and implemented for gr/pyplot
- fix DateTime recipe
- reset theme with theme(:none)
- fix link_axes! for nested subplots
- fix plotly lims for log scale
#### 0.9.4
- optimizations surrounding Subplot.series_list
- better Atom support, support plotlyjs
- gr:
- gks_wstype defaults and gr_set_output
- heatmap uses GR.drawimage
- histogram2d puts NaN for zeros
- improved support of NaN in heatmaps
- rebuilt spy recipes to output scatters with marker_z set
- deprecate png support in plotly... point to plotlyjs
- fixes:
- axis widen with lims set
- reset_extrema, setxyz
- bar plot widen
- better tick padding
- consistent tick rotation
- consistent aspect_ratio
- pyplot dpi
- plotly horizontal bars
- handle series attributes when combining subplots
- gr images transposed
- converted Date/DateTime to new type recipe approach for arrays
- issues closed include: #505 #513 #479 #523 #526 #529
#### 0.9.3
- support pdf and eps in plotlyjs backend
- allow curly after grid: `@layout [a b; grid(4,4){0.8h}]`
- add_backend redesign
#### 0.9.2
- glvisualize backend (@SimonDanisch)
- too much to list! ready for alpha testing
- Volume and volume seriestype
- Atom: support for PlotPane and proper gui display
- gr:
- clims
- aspect ratio
- pgfplots:
- fixes for ticks, axes, and more
- pyplot:
- font families
- colorbar guide
- pixel marker
- unicodeplots
- basic support for shapes
- improved add_backend
- refactor of is_supported methods
- element-wise type recipes (see https://github.com/tbreloff/Plots.jl/issues/460#issuecomment-248428908)
- several other fixes/improvements
#### 0.9.1
- Pkg.dir --> dirname (@tkelman)
- `axis = nothing` magic
- fixes:
- clim for line_z
- sticks default range for log scale
- rotate method
- pyplot heatmap
- spurious scale warnings
- gr image/alpha
- plotly.js path
- orientation extrema
- bar, reset orientation
- switch transpose_z to use permutedims
- skinny x/+ markers
- ticks in pgfplots
- eps in savefig (@anriseth)
- add_backend convenience
- type recipes for Date/DateTime (@maximsch2)
- mirror attribute and twinx convenience
- Axis.sp --> Axis.sps
- recipe postprocessing for allowing aliases and magic args in recipe bodies
#### 0.9.0
- fixes to cycle
- add back single function recipe: `plot!(cos)`
- new axis formatter attribute... accepts functions to convert numbers to strings
- fix for inset plots
- GR:
- fillrange fix
- annotations fix
- force double buffering in display
---
## 0.8 (current master/dev)
## 0.8
#### 0.8.2 (backported bug fixes for julia 0.4)
- plotly ticks fix
- unicodeplots size fix
- remove mkdir call in tests
#### 0.8.1
- manual drawing of axes/ticks/labels
- get_ticks uses optimize_ticks and Showoff
- changed PLOTS_DEFAULTS to be a global variable, not ENV key
- parameterized Segments for pushing tuples
- fix to axis extrema for Bool/nothing
- GR:
- manually draw 2D axes... fixes several issues and missing features
- fontsize fix
- PGFPlots: pass axis syle
#### 0.8.0
@@ -204,7 +575,7 @@
- z-axis keywords
- 3D indexing overhaul: `push!`, `append!` support
- matplotlib colormap constants (`:inferno` is the new default colormap for Plots)
- `typealias KW Dict{Symbol,Any}` used in place of splatting in many places
- `const KW = Dict{Symbol,Any}` used in place of splatting in many places
- png generation for plotly backend using wkhtmltoimage
- `normalize` and `weights` keywords
- background/foreground subcategories for fine-tuning of looks
+6 -3
View File
@@ -1,13 +1,16 @@
# 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)
[![Build status](https://ci.appveyor.com/api/projects/status/github/juliaplots/plots.jl?branch=master&svg=true)](https://ci.appveyor.com/project/mkborregaard/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) -->
<!-- [![Coverage Status](https://coveralls.io/repos/tbreloff/Plots.jl/badge.svg?branch=master)](https://coveralls.io/r/tbreloff/Plots.jl?branch=master) -->
<!-- [![codecov.io](http://codecov.io/github/tbreloff/Plots.jl/coverage.svg?branch=master)](http://codecov.io/github/tbreloff/Plots.jl?branch=master) -->
#### Author: Thomas Breloff (@tbreloff)
#### Created by Tom Breloff (@tbreloff)
#### Maintained by the [JuliaPlot members](https://github.com/orgs/JuliaPlots/people)
Plots is a plotting API and toolset. My goals with the package are:
@@ -19,4 +22,4 @@ Plots is a plotting API and toolset. My goals with the package are:
- **Lightweight**. Very few dependencies.
- **Smart**. Attempts to figure out what you **want** it to do... not just what you **tell** it.
View the [full documentation](http://juliaplots.github.io).
View the [full documentation](http://docs.juliaplots.org/latest).
+12 -5
View File
@@ -1,9 +1,16 @@
julia 0.4
julia 0.7-alpha
RecipesBase
PlotUtils
RecipesBase 0.2.3
PlotUtils 0.4.1
PlotThemes 0.1.3
Reexport
Compat
FixedSizeArrays
StaticArrays 0.5
FixedPointNumbers 0.3
Measures
Showoff
StatsBase 0.14.0
JSON
NaNMath
Requires
Contour
GR 0.31.0
+18 -8
View File
@@ -1,11 +1,15 @@
environment:
matrix:
# Releases
- JULIAVERSION: "stable/win32"
- JULIAVERSION: "stable/win64"
# Nightlies
- JULIAVERSION: "download/win32"
- JULIAVERSION: "download/win64"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
matrix:
allow_failures:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe" #check and address
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
notifications:
- provider: Email
@@ -14,8 +18,14 @@ notifications:
on_build_status_changed: false
install:
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
# If there's a newer build queued for the same PR, cancel this one
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
throw "There are newer queued builds for this pull request, failing early." }
# Download most recent Julia Windows binary
- ps: (new-object net.webclient).DownloadFile($("http://status.julialang.org/"+$env:JULIAVERSION), "C:\projects\julia-binary.exe")
- ps: (new-object net.webclient).DownloadFile($env:JULIA_URL, "C:\projects\julia-binary.exe")
# Run installer silently, output to C:\projects\julia
- C:\projects\julia-binary.exe /S /D=C:\projects\julia
@@ -26,4 +36,4 @@ build_script:
test_script:
# - C:\projects\julia\bin\julia -e "Pkg.test(\"Plots\")"
- C:\projects\julia\bin\julia -e "include(Pkg.dir(\"Plots\", \"test\", \"travis_commands.jl\"))"
- C:\projects\julia\bin\julia -e "include(Pkg.dir(\"Plots\", \"test\", \"travis_commands.jl\"))"
+1 -1
View File
@@ -3,6 +3,6 @@
local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js")
if !isfile(local_fn)
info("Cannot find deps/plotly-latest.min.js... downloading latest version.")
@info("Cannot find deps/plotly-latest.min.js... downloading latest version.")
download("https://cdn.plot.ly/plotly-latest.min.js", local_fn)
end
+149 -93
View File
@@ -1,46 +1,42 @@
__precompile__()
__precompile__(true)
module Plots
using Compat
using Reexport
# @reexport using Colors
# using Requires
using FixedSizeArrays
import StaticArrays
using StaticArrays.FixedSizeArrays
using Dates, Printf, Statistics, Base64, LinearAlgebra
@reexport using RecipesBase
import RecipesBase: plot, plot!, animate
using Base.Meta
@reexport using PlotUtils
@reexport using PlotThemes
import Showoff
import StatsBase
import JSON
using Requires
export
AbstractPlot,
Plot,
Subplot,
AbstractLayout,
GridLayout,
grid,
EmptyLayout,
bbox,
plotarea,
@layout,
AVec,
AMat,
KW,
wrap,
set_theme,
add_theme,
theme,
plot,
plot!,
attr!,
current,
default,
with,
@userplot,
@shorthands,
twinx,
pie,
pie!,
@@ -60,44 +56,46 @@ export
yflip!,
xaxis!,
yaxis!,
xgrid!,
ygrid!,
xlims,
ylims,
zlims,
savefig,
png,
gui,
inline,
closeall,
backend,
backends,
backend_name,
backend_object,
add_backend,
aliases,
dataframes,
Shape,
text,
font,
Axis,
stroke,
brush,
Surface,
OHLC,
arrow,
Segments,
debugplots,
supported_args,
supported_types,
supported_styles,
supported_markers,
is_subplot_supported,
Formatted,
Animation,
frame,
gif,
mov,
mp4,
animate,
@animate,
@gif,
spy,
test_examples,
iter_segments,
coords,
@@ -110,23 +108,55 @@ export
P2,
P3,
BezierCurve,
curve_points,
directed_curve
plotattr
# ---------------------------------------------------------
import NaNMath # define functions that ignores NaNs. To overcome the destructive effects of https://github.com/JuliaLang/julia/pull/12563
ignorenan_minimum(x::AbstractArray{F}) where {F<:AbstractFloat} = NaNMath.minimum(x)
ignorenan_minimum(x) = Base.minimum(x)
ignorenan_maximum(x::AbstractArray{F}) where {F<:AbstractFloat} = NaNMath.maximum(x)
ignorenan_maximum(x) = Base.maximum(x)
ignorenan_mean(x::AbstractArray{F}) where {F<:AbstractFloat} = NaNMath.mean(x)
ignorenan_mean(x) = Base.mean(x)
ignorenan_extrema(x::AbstractArray{F}) where {F<:AbstractFloat} = NaNMath.extrema(x)
ignorenan_extrema(x) = Base.extrema(x)
# ---------------------------------------------------------
# to cater for block matrices, Base.transpose is recursive.
# This makes it impossible to create row vectors of String and Symbol with the transpose operator.
# This solves this issue, internally in Plots at least.
# commented out on the insistence of the METADATA maintainers
#Base.transpose(x::Symbol) = x
#Base.transpose(x::String) = x
# ---------------------------------------------------------
import Measures
module PlotMeasures
import Measures
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h
typealias BBox Measures.Absolute2DBox
export BBox, BoundingBox, mm, cm, inch, pt, px, pct, w, h
const BBox = Measures.Absolute2DBox
# allow pixels and percentages
const px = AbsoluteLength(0.254)
const pct = Length{:pct, Float64}(1.0)
export BBox, BoundingBox, mm, cm, inch, px, pct, pt, w, h
end
using .PlotMeasures
import .PlotMeasures: Length, AbsoluteLength, Measure, width, height
# ---------------------------------------------------------
include("types.jl")
include("utils.jl")
include("components.jl")
include("axes.jl")
include("backends.jl")
include("args.jl")
include("themes.jl")
include("plot.jl")
@@ -136,34 +166,31 @@ include("layouts.jl")
include("subplots.jl")
include("recipes.jl")
include("animation.jl")
include("output.jl")
include("examples.jl")
include("arg_desc.jl")
include("plotattr.jl")
include("backends.jl")
include("output.jl")
# ---------------------------------------------------------
# define and export shorthand plotting method definitions
macro shorthands(funcname::Symbol)
funcname2 = Symbol(funcname, "!")
esc(quote
export $funcname, $funcname2
$funcname(args...; kw...) = plot(args...; kw..., seriestype = $(quot(funcname)))
$funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(quot(funcname)))
end)
end
@shorthands scatter
@shorthands bar
@shorthands barh
@shorthands histogram
@shorthands barhist
@shorthands stephist
@shorthands scatterhist
@shorthands histogram2d
@shorthands density
@shorthands heatmap
@shorthands plots_heatmap
@shorthands hexbin
@shorthands sticks
@shorthands hline
@shorthands vline
@shorthands hspan
@shorthands vspan
@shorthands ohlc
@shorthands contour
@shorthands contourf
@@ -177,80 +204,109 @@ end
@shorthands quiver
@shorthands curves
"Plot a pie diagram"
pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
"Plot with seriestype :path3d"
plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d)
plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d)
"Add title to an existing plot"
title!(s::AbstractString; kw...) = plot!(; title = s, kw...)
"Add xlabel to an existing plot"
xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...)
"Add ylabel to an existing plot"
ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...)
xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; xlims = lims, kw...)
ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; ylims = lims, kw...)
zlims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; zlims = lims, kw...)
"Set xlims for an existing plot"
xlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; xlims = lims, kw...)
"Set ylims for an existing plot"
ylims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; ylims = lims, kw...)
"Set zlims for an existing plot"
zlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; zlims = lims, kw...)
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...)
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...)
zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...)
xticks!{T<:Real}(v::AVec{T}; kw...) = plot!(; xticks = v, kw...)
yticks!{T<:Real}(v::AVec{T}; kw...) = plot!(; yticks = v, kw...)
xticks!{T<:Real,S<:AbstractString}(
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; xticks = (ticks,labels), kw...)
yticks!{T<:Real,S<:AbstractString}(
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; yticks = (ticks,labels), kw...)
"Set xticks for an existing plot"
xticks!(v::AVec{T}; kw...) where {T<:Real} = plot!(; xticks = v, kw...)
"Set yticks for an existing plot"
yticks!(v::AVec{T}; kw...) where {T<:Real} = plot!(; yticks = v, kw...)
xticks!(
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...)
yticks!(
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...)
"Add annotations to an existing plot"
annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)
annotate!{T<:Tuple}(anns::AVec{T}; kw...) = plot!(; annotation = anns, kw...)
annotate!(anns::AVec{T}; kw...) where {T<:Tuple} = plot!(; annotation = anns, kw...)
"Flip the current plots' x axis"
xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...)
"Flip the current plots' y axis"
yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...)
"Specify x axis attributes for an existing plot"
xaxis!(args...; kw...) = plot!(; xaxis = args, kw...)
"Specify x axis attributes for an existing plot"
yaxis!(args...; kw...) = plot!(; yaxis = args, kw...)
xgrid!(args...; kw...) = plot!(; xgrid = args, kw...)
ygrid!(args...; kw...) = plot!(; ygrid = args, kw...)
title!(plt::Plot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
xlabel!(plt::Plot, s::AbstractString; kw...) = plot!(plt; xlabel = s, kw...)
ylabel!(plt::Plot, s::AbstractString; kw...) = plot!(plt; ylabel = s, kw...)
xlims!{T<:Real,S<:Real}(plt::Plot, lims::Tuple{T,S}; kw...) = plot!(plt; xlims = lims, kw...)
ylims!{T<:Real,S<:Real}(plt::Plot, lims::Tuple{T,S}; kw...) = plot!(plt; ylims = lims, kw...)
zlims!{T<:Real,S<:Real}(plt::Plot, lims::Tuple{T,S}; kw...) = plot!(plt; zlims = lims, kw...)
xlims!(plt::Plot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin,xmax), kw...)
ylims!(plt::Plot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin,ymax), kw...)
zlims!(plt::Plot, zmin::Real, zmax::Real; kw...) = plot!(plt; zlims = (zmin,zmax), kw...)
xticks!{T<:Real}(plt::Plot, ticks::AVec{T}; kw...) = plot!(plt; xticks = ticks, kw...)
yticks!{T<:Real}(plt::Plot, ticks::AVec{T}; kw...) = plot!(plt; yticks = ticks, kw...)
xticks!{T<:Real,S<:AbstractString}(plt::Plot,
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; xticks = (ticks,labels), kw...)
yticks!{T<:Real,S<:AbstractString}(plt::Plot,
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; yticks = (ticks,labels), kw...)
annotate!(plt::Plot, anns...; kw...) = plot!(plt; annotation = anns, kw...)
annotate!{T<:Tuple}(plt::Plot, anns::AVec{T}; kw...) = plot!(plt; annotation = anns, kw...)
xflip!(plt::Plot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...)
yflip!(plt::Plot, flip::Bool = true; kw...) = plot!(plt; yflip = flip, kw...)
xaxis!(plt::Plot, args...; kw...) = plot!(plt; xaxis = args, kw...)
yaxis!(plt::Plot, args...; kw...) = plot!(plt; yaxis = args, kw...)
let PlotOrSubplot = Union{Plot, Subplot}
global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
global xlabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; xlabel = s, kw...)
global ylabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; ylabel = s, kw...)
global xlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; xlims = lims, kw...)
global ylims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; ylims = lims, kw...)
global zlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; zlims = lims, kw...)
global xlims!(plt::PlotOrSubplot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin,xmax), kw...)
global ylims!(plt::PlotOrSubplot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin,ymax), kw...)
global zlims!(plt::PlotOrSubplot, zmin::Real, zmax::Real; kw...) = plot!(plt; zlims = (zmin,zmax), kw...)
global xticks!(plt::PlotOrSubplot, ticks::AVec{T}; kw...) where {T<:Real} = plot!(plt; xticks = ticks, kw...)
global yticks!(plt::PlotOrSubplot, ticks::AVec{T}; kw...) where {T<:Real} = plot!(plt; yticks = ticks, kw...)
global xticks!(plt::PlotOrSubplot,
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; xticks = (ticks,labels), kw...)
global yticks!(plt::PlotOrSubplot,
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; yticks = (ticks,labels), kw...)
global xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...)
global ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...)
global annotate!(plt::PlotOrSubplot, anns...; kw...) = plot!(plt; annotation = anns, kw...)
global annotate!(plt::PlotOrSubplot, anns::AVec{T}; kw...) where {T<:Tuple} = plot!(plt; annotation = anns, kw...)
global xflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...)
global yflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; yflip = flip, kw...)
global xaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xaxis = args, kw...)
global yaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; yaxis = args, kw...)
end
# ---------------------------------------------------------
const CURRENT_BACKEND = CurrentBackend(:none)
function __init__()
setup_ijulia()
setup_atom()
# for compatibility with Requires.jl:
@init begin
if isdefined(Main, :PLOTS_DEFAULTS)
if haskey(Main.PLOTS_DEFAULTS, :theme)
theme(Main.PLOTS_DEFAULTS[:theme])
end
for (k,v) in Main.PLOTS_DEFAULTS
default(k, v)
k == :theme || default(k, v)
end
end
end
# ---------------------------------------------------------
# if VERSION >= v"0.4.0-dev+5512"
# include("precompile.jl")
# _precompile_()
# end
# ---------------------------------------------------------
end # module
+92 -44
View File
@@ -1,62 +1,108 @@
immutable Animation
dir::Compat.ASCIIString
frames::Vector{Compat.ASCIIString}
"Represents an animation object"
struct Animation
dir::String
frames::Vector{String}
end
function Animation()
tmpdir = convert(Compat.ASCIIString, mktempdir())
Animation(tmpdir, Compat.ASCIIString[])
tmpdir = convert(String, mktempdir())
Animation(tmpdir, String[])
end
function frame{P<:AbstractPlot}(anim::Animation, plt::P=current())
i = length(anim.frames) + 1
filename = @sprintf("%06d.png", i)
png(plt, joinpath(anim.dir, filename))
push!(anim.frames, filename)
"""
frame(animation[, plot])
Add a plot (the current plot if not specified) to an existing animation
"""
function frame(anim::Animation, plt::P=current()) where P<:AbstractPlot
i = length(anim.frames) + 1
filename = @sprintf("%06d.png", i)
png(plt, joinpath(anim.dir, filename))
push!(anim.frames, filename)
end
giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif")
movfn() = (isijulia() ? "tmp.mov" : tempname()*".mov")
mp4fn() = (isijulia() ? "tmp.mp4" : tempname()*".mp4")
mutable struct FrameIterator
itr
every::Int
kw
end
FrameIterator(itr; every=1, kw...) = FrameIterator(itr, every, kw)
"""
Animate from an iterator which returns the plot args each iteration.
"""
function animate(fitr::FrameIterator, fn = giffn(); kw...)
anim = Animation()
for (i, plotargs) in enumerate(fitr.itr)
if mod1(i, fitr.every) == 1
plot(wraptuple(plotargs)...; fitr.kw...)
frame(anim)
end
end
gif(anim, fn; kw...)
end
# most things will implement this
function animate(obj, fn = giffn(); every=1, fps=20, loop=0, kw...)
animate(FrameIterator(obj, every, kw), fn; fps=fps, loop=loop)
end
# -----------------------------------------------
"Wraps the location of an animated gif so that it can be displayed"
immutable AnimatedGif
filename::Compat.ASCIIString
struct AnimatedGif
filename::String
end
function gif(anim::Animation, fn = (isijulia() ? "tmp.gif" : tempname()*".gif"); fps::Integer = 20)
fn = abspath(fn)
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
try
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...)
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
# high quality
speed = round(Int, 100 / fps)
file = joinpath(Pkg.dir("ImageMagick"), "deps","deps.jl")
if isfile(file) && !haskey(ENV, "MAGICK_CONFIGURE_PATH")
include(file)
function buildanimation(animdir::AbstractString, fn::AbstractString,
is_animated_gif::Bool=true;
fps::Integer = 20, loop::Integer = 0,
variable_palette::Bool=false,
show_msg::Bool=true)
fn = abspath(fn)
if is_animated_gif
if variable_palette
# generate a colorpalette for each frame for highest quality, but larger filesize
palette="palettegen=stats_mode=single[pal],[0:v][pal]paletteuse=new=1"
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`)
else
# generate a colorpalette first so ffmpeg does not have to guess it
run(`ffmpeg -v 0 -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`)
# then apply the palette to get better results
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -y $fn`)
end
else
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`)
end
# prefix = get(ENV, "MAGICK_CONFIGURE_PATH", "")
run(`convert -delay $speed -loop 0 $(joinpath(anim.dir, "*.png")) -alpha off $fn`)
catch err
warn("""Tried to create gif using convert (ImageMagick), but got error: $err
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`
Will try ffmpeg, but it's lower quality...)""")
# low quality
run(`ffmpeg -v 0 -framerate $fps -i $(anim.dir)/%06d.png -y $fn`)
# run(`ffmpeg -v warning -i "fps=$fps,scale=320:-1:flags=lanczos"`)
end
info("Saved animation to ", fn)
AnimatedGif(fn)
show_msg && info("Saved animation to ", fn)
AnimatedGif(fn)
end
# write out html to view the gif... note the rand call which is a hack so the image doesn't get cached
function Base.writemime(io::IO, ::MIME"text/html", agif::AnimatedGif)
write(io, "<img src=\"$(relpath(agif.filename))?$(rand())>\" />")
function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
ext = file_extension(agif.filename)
write(io, if ext == "gif"
"<img src=\"$(relpath(agif.filename))?$(rand())>\" />"
elseif ext in ("mov", "mp4")
"<video controls><source src=\"$(relpath(agif.filename))?$(rand())>\" type=\"video/$ext\"></video>"
else
error("Cannot show animation with extension $ext: $agif")
end)
end
@@ -70,6 +116,7 @@ function _animate(forloop::Expr, args...; callgif = false)
# add the call to frame to the end of each iteration
animsym = gensym("anim")
countersym = gensym("counter")
freqassert = :()
block = forloop.args[2]
# create filter
@@ -82,7 +129,7 @@ function _animate(forloop::Expr, args...; callgif = false)
# filter every `freq` frames (starting with the first frame)
@assert n == 2
freq = args[2]
@assert isa(freq, Integer) && freq > 0
freqassert = :(@assert isa($freq, Integer) && $freq > 0)
:(mod1($countersym, $freq) == 1)
elseif args[1] == :when
@@ -102,6 +149,7 @@ function _animate(forloop::Expr, args...; callgif = false)
# full expression:
esc(quote
$freqassert # if filtering, check frequency is an Integer > 0
$animsym = Animation() # init animation object
$countersym = 1 # init iteration counter
$forloop # for loop, saving a frame after each iteration
@@ -122,7 +170,7 @@ Example:
```
"""
macro gif(forloop::Expr, args...)
_animate(forloop, args...; callgif = true)
_animate(forloop, args...; callgif = true)
end
"""
@@ -131,13 +179,13 @@ Collect one frame per for-block iteration and return an `Animation` object.
Example:
```
p = plot(1)
anim = @animate for x=0:0.1:5
p = plot(1)
anim = @animate for x=0:0.1:5
push!(p, 1, sin(x))
end
gif(anim)
end
gif(anim)
```
"""
macro animate(forloop::Expr, args...)
_animate(forloop, args...)
_animate(forloop, args...)
end
+46 -11
View File
@@ -19,9 +19,9 @@ const _arg_desc = KW(
:markersize => "Number or AbstractVector. Size (radius pixels) of the markers.",
:markerstrokestyle => "Symbol. Style of the marker stroke (border). Choose from $(_allStyles)",
: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 `:seriescolor`.",
: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 (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `linspace(extrema(x)..., 25)`",
:smooth => "Bool. Add a regression line?",
:group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.",
:x => "Various. Input data. First Dimension",
@@ -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,9 +40,10 @@ 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 discrete Probability Density Function, where the total area of the bins is 1), :probability (bin heights sum to 1) and :density (the area of each bin, rather than the height, is equal to the counts - useful for uneven 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.",
:contour_labels => "Bool. Show labels at the contour lines?",
: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`.",
:subplot => "Integer (subplot index) or Subplot object. The subplot that this series belongs to.",
:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.",
@@ -63,48 +65,81 @@ const _arg_desc = KW(
:html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.",
:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots",
:dpi => "Number. Dots Per Inch of output figures",
:thickness_scaling => "Number. Scale for the thickness of all line elements like lines, borders, axes, grid lines, ... defaults to 1.",
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
:extra_kwargs => "KW (Dict{Symbol,Any}). Pass a map of extra keyword args which may be specific to a backend.",
:fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides",
# subplot args
:title => "String. Subplot title.",
:title_location => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`",
:titlefont => "Font. Font of subplot title.",
:titlefontfamily => "String or Symbol. Font family of subplot title.",
:titlefontsize => "Integer. Font pointsize of subplot title.",
:titlefonthalign => "Symbol. Font horizontal alignment of subplot title: :hcenter, :left, :right or :center",
:titlefontvalign => "Symbol. Font vertical alignment of subplot title: :vcenter, :top, :bottom or :center",
:titlefontrotation => "Real. Font rotation of subplot title",
:titlefontcolor => "Color Type. Font color of subplot title",
:background_color_subplot => "Color Type or `:match` (matches `:background_color`). Base background color of the subplot.",
:background_color_legend => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.",
:background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).",
:foreground_color_subplot => "Color Type or `:match` (matches `:foreground_color`). Base foreground color of the subplot.",
:foreground_color_legend => "Color Type or `:match` (matches `:foreground_color_subplot`). Foreground color of the legend.",
:foreground_color_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of grid lines.",
:foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.",
:color_palette => "Vector of colors (cycle through) or color gradient (generate list from gradient) or `:auto` (generate a color list using `Colors.distiguishable_colors` and custom seed colors chosen to contrast with the background). The color palette is a color list from which series colors are automatically chosen.",
:legend => "Bool (show the legend?) or Symbol (legend position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:inside`, `:legend`, `:topright`, `:topleft`, `:bottomleft`, `:bottomright` (note: only some may be supported in each backend)",
:legendfontfamily => "String or Symbol. Font family of legend entries.",
:legendfontsize => "Integer. Font pointsize of legend entries.",
:legendfonthalign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center",
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
:legendfontrotation => "Real. Font rotation of legend entries",
:legendfontcolor => "Color Type. Font color of legend entries",
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
:legendfont => "Font. Font of legend items.",
:grid => "Bool. Show the grid lines?",
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.",
:projection => "Symbol or String. '3d' or 'polar'",
:aspect_ratio => "Symbol (:equal) or Number (width to height ratio of plot area).",
:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `apect_ratio` x-units.",
:margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.",
:left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.",
:top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.",
:right_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the right of the subplot.",
:bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.",
:subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.",
:colorbar_title => "String. Title of colorbar.",
:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)",
:camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots",
# axis args
:guide => "String. Axis guide (label).",
:lims => "NTuple{2,Number}. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example).",
:lims => "NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example). `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]",
:ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`",
:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`",
:rotation => "Number. Degrees rotation of tick labels.",
:flip => "Bool. Should we flip (reverse) the axis?",
:tickfont => "Font. Font of axis tick labels.",
:guidefont => "Font. Font of axis guide (label).",
:formatter => "Function, :scientific, or :auto. A method which converts a number to a string for tick labeling.",
:tickfontfamily => "String or Symbol. Font family of tick labels.",
:tickfontsize => "Integer. Font pointsize of tick labels.",
:tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center",
:tickfontvalign => "Symbol. Font vertical alignment of tick labels: :vcenter, :top, :bottom or :center",
:tickfontrotation => "Real. Font rotation of tick labels",
:tickfontcolor => "Color Type. Font color of tick labels",
:guidefontfamily => "String or Symbol. Font family of axes guides.",
:guidefontsize => "Integer. Font pointsize of axes guides.",
:guidefonthalign => "Symbol. Font horizontal alignment of axes guides: :hcenter, :left, :right or :center",
:guidefontvalign => "Symbol. Font vertical alignment of axes guides: :vcenter, :top, :bottom or :center",
:guidefontrotation => "Real. Font rotation of axes guides",
:guidefontcolor => "Color Type. Font color of axes guides",
:foreground_color_axis => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis ticks.",
:foreground_color_border => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of plot area border (spines).",
:foreground_color_text => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of tick labels.",
:foreground_color_guide => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis guides (axis labels).",
:mirror => "Bool. Switch the side of the tick labels (right or top).",
:grid => "Bool, Symbol, String or `nothing`. Show the grid lines? `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:none`, `:off`",
:foreground_color_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of grid lines.",
:gridalpha => "Number in [0,1]. The alpha/opacity override for the grid lines.",
:gridstyle => "Symbol. Style of the grid lines. Choose from $(_allStyles)",
:gridlinewidth => "Number. Width of the grid lines (in pixels)",
:tick_direction => "Symbol. Direction of the ticks. `:in` or `:out`",
:showaxis => "Bool, Symbol or String. Show the axis. `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:off`",
:widen => "Bool. Widen the axis limits by a small factor to avoid cut-off markers and lines at the borders. Defaults to `true`.",
)
+507 -115
View File
File diff suppressed because it is too large Load Diff
+296 -109
View File
@@ -23,13 +23,13 @@ function Axis(sp::Subplot, letter::Symbol, args...; kw...)
lk = Symbol(letter, k)
lv = _axis_defaults_byletter[lk]
d[k] = (lv == :match ? v : lv)
end
end
# merge!(d, _axis_defaults)
d[:discrete_values] = []
# update the defaults
update!(Axis(sp, d), args...; kw...)
attr!(Axis([sp], d), args...; kw...)
end
function get_axis(sp::Subplot, letter::Symbol)
@@ -70,17 +70,23 @@ function process_axis_arg!(d::KW, arg, letter = "")
elseif arg == nothing
d[Symbol(letter,:ticks)] = []
elseif T <: Bool || arg in _allShowaxisArgs
d[Symbol(letter,:showaxis)] = showaxis(arg, letter)
elseif typeof(arg) <: Number
d[Symbol(letter,:rotation)] = arg
else
elseif typeof(arg) <: Function
d[Symbol(letter,:formatter)] = arg
elseif !handleColors!(d, arg, Symbol(letter, :foreground_color_axis))
warn("Skipped $(letter)axis arg $arg")
end
end
# update an Axis object with magic args and keywords
function update!(axis::Axis, args...; kw...)
function attr!(axis::Axis, args...; kw...)
# first process args
d = axis.d
for arg in args
@@ -115,7 +121,7 @@ Base.show(io::IO, axis::Axis) = dumpdict(axis.d, "Axis", true)
# Base.getindex(axis::Axis, k::Symbol) = getindex(axis.d, k)
Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.d, v, ks...)
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.d, k)
Base.extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
ignorenan_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
const _scale_funcs = Dict{Symbol,Function}(
@@ -129,6 +135,12 @@ const _inv_scale_funcs = Dict{Symbol,Function}(
:ln => exp,
)
# const _label_func = Dict{Symbol,Function}(
# :log10 => x -> "10^$x",
# :log2 => x -> "2^$x",
# :ln => x -> "e^$x",
# )
const _label_func = Dict{Symbol,Function}(
:log10 => x -> "10^$x",
:log2 => x -> "2^$x",
@@ -141,59 +153,125 @@ invscalefunc(scale::Symbol) = x -> get(_inv_scale_funcs, scale, identity)(Float6
labelfunc(scale::Symbol, backend::AbstractBackend) = get(_label_func, scale, string)
function optimal_ticks_and_labels(axis::Axis, ticks = nothing)
lims = axis_limits(axis)
amin,amax = axis_limits(axis)
# scale the limits
scale = axis[:scale]
scaled_lims = map(scalefunc(scale), lims)
# @show lims scaled_lims
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
cv = if ticks == nothing
optimize_ticks(scaled_lims...,
k_min = 5, # minimum number of ticks
if ticks == nothing
scaled_ticks = optimize_ticks(
sf(amin),
sf(amax);
k_min = 4, # minimum number of ticks
k_max = 8, # maximum number of ticks
# span_buffer = 0.0 # padding buffer in case nice ticks are closeby
)[1]
elseif typeof(ticks) <: Int
scaled_ticks, viewmin, viewmax = optimize_ticks(
sf(amin),
sf(amax);
k_min = ticks, # minimum number of ticks
k_max = ticks, # maximum number of ticks
k_ideal = ticks,
# `strict_span = false` rewards cases where the span of the
# chosen ticks is not too much bigger than amin - amax:
strict_span = false,
)
axis[:lims] = map(invscalefunc(scale), (viewmin, viewmax))
else
ticks
scaled_ticks = map(sf, (filter(t -> amin <= t <= amax, ticks)))
end
unscaled_ticks = map(invscalefunc(scale), scaled_ticks)
labels = if any(isfinite, unscaled_ticks)
formatter = axis[:formatter]
if formatter == :auto
# the default behavior is to make strings of the scaled values and then apply the labelfunc
map(labelfunc(scale, backend()), Showoff.showoff(scaled_ticks, :auto))
elseif formatter == :plain
# Leave the numbers in plain format
map(labelfunc(scale, backend()), Showoff.showoff(scaled_ticks, :plain))
elseif formatter == :scientific
Showoff.showoff(unscaled_ticks, :scientific)
else
# there was an override for the formatter... use that on the unscaled ticks
map(formatter, unscaled_ticks)
# if the formatter left us with numbers, still apply the default formatter
# However it leave us with the problem of unicode number decoding by the backend
# if eltype(unscaled_ticks) <: Number
# Showoff.showoff(unscaled_ticks, :auto)
# end
end
else
# no finite ticks to show...
String[]
end
# # expand to ensure we see all the ticks
# expand_extrema!(axis, cv)
# rescale and return values and labels
# @show cv
ticklabels = if any(isfinite, cv)
map(labelfunc(scale, backend()), Showoff.showoff(cv, :plain))
else
UTF8String[]
end
tickvals = map(invscalefunc(scale), cv)
# @show tickvals ticklabels
# ticklabels = Showoff.showoff(tickvals, scale == :log10 ? :scientific : :auto)
tickvals, ticklabels
# basestr = scale == :log10 ? "10^" : scale == :log2 ? "2^" : scale == :ln ? "e^" : ""
# tickvals, ["$basestr$cvi" for cvi in cv]
# @show unscaled_ticks labels
# labels = Showoff.showoff(unscaled_ticks, scale == :log10 ? :scientific : :auto)
unscaled_ticks, labels
end
# return (continuous_values, discrete_values) for the ticks on this axis
function get_ticks(axis::Axis)
ticks = axis[:ticks]
ticks = _transform_ticks(axis[:ticks])
ticks in (nothing, false) && return nothing
# treat :native ticks as :auto
ticks = ticks == :native ? :auto : ticks
dvals = axis[:discrete_values]
cv, dv = if !isempty(dvals) && ticks == :auto
# discrete ticks...
axis[:continuous_values], dvals
elseif ticks == :auto
# compute optimal ticks and labels
optimal_ticks_and_labels(axis)
elseif typeof(ticks) <: AVec
# override ticks, but get the labels
optimal_ticks_and_labels(axis, ticks)
elseif typeof(ticks) <: NTuple{2}
cv, dv = if typeof(ticks) <: Symbol
if !isempty(dvals)
# discrete ticks...
n = length(dvals)
rng = if ticks == :auto
Int[round(Int,i) for i in range(1, stop=n, length=15)]
else # if ticks == :all
1:n
end
axis[:continuous_values][rng], dvals[rng]
elseif ispolar(axis.sps[1]) && axis[:letter] == :x
#force theta axis to be full circle
(collect(0:pi/4:7pi/4), string.(0:45:315))
else
# compute optimal ticks and labels
optimal_ticks_and_labels(axis)
end
elseif typeof(ticks) <: Union{AVec, Int}
if !isempty(dvals) && typeof(ticks) <: Int
rng = Int[round(Int,i) for i in range(1, stop=length(dvals), length=ticks)]
axis[:continuous_values][rng], dvals[rng]
else
# override ticks, but get the labels
optimal_ticks_and_labels(axis, ticks)
end
elseif typeof(ticks) <: NTuple{2, Any}
# assuming we're passed (ticks, labels)
ticks
else
@@ -201,20 +279,29 @@ function get_ticks(axis::Axis)
end
# @show ticks dvals cv dv
# TODO: better/smarter cutoff values for sampling ticks
if length(cv) > 30
rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)]
cv[rng], dv[rng]
else
cv, dv
end
return cv, dv
end
_transform_ticks(ticks) = ticks
_transform_ticks(ticks::AbstractArray{T}) where T <: Dates.TimeType = Dates.value.(ticks)
_transform_ticks(ticks::NTuple{2, Any}) = (_transform_ticks(ticks[1]), ticks[2])
# -------------------------------------------------------------------------
function reset_extrema!(sp::Subplot)
for asym in (:x,:y,:z)
sp[Symbol(asym,:axis)][:extrema] = Extrema()
end
for series in sp.series_list
expand_extrema!(sp, series.d)
end
end
function expand_extrema!(ex::Extrema, v::Number)
ex.emin = min(v, ex.emin)
ex.emax = max(v, ex.emax)
ex.emin = isfinite(v) ? min(v, ex.emin) : ex.emin
ex.emax = isfinite(v) ? max(v, ex.emax) : ex.emax
ex
end
@@ -223,17 +310,17 @@ function expand_extrema!(axis::Axis, v::Number)
end
# these shouldn't impact the extrema
expand_extrema!(axis::Axis, ::Void) = axis[:extrema]
expand_extrema!(axis::Axis, ::Nothing) = axis[:extrema]
expand_extrema!(axis::Axis, ::Bool) = axis[:extrema]
function expand_extrema!{MIN<:Number,MAX<:Number}(axis::Axis, v::Tuple{MIN,MAX})
function expand_extrema!(axis::Axis, v::Tuple{MIN,MAX}) where {MIN<:Number,MAX<:Number}
ex = axis[:extrema]
ex.emin = min(v[1], ex.emin)
ex.emax = max(v[2], ex.emax)
ex.emin = isfinite(v[1]) ? min(v[1], ex.emin) : ex.emin
ex.emax = isfinite(v[2]) ? max(v[2], ex.emax) : ex.emax
ex
end
function expand_extrema!{N<:Number}(axis::Axis, v::AVec{N})
function expand_extrema!(axis::Axis, v::AVec{N}) where N<:Number
ex = axis[:extrema]
for vi in v
expand_extrema!(ex, vi)
@@ -243,11 +330,25 @@ end
function expand_extrema!(sp::Subplot, d::KW)
vert = isvertical(d)
# first expand for the data
for letter in (:x, :y, :z)
data = d[letter]
axis = sp.attr[Symbol(letter, "axis")]
if eltype(data) <: Number || (isa(data, Surface) && all(di -> isa(di, Number), data.surf))
data = d[if vert
letter
else
letter == :x ? :y : letter == :y ? :x : :z
end]
if letter != :z && d[:seriestype] == :straightline && any(series[:seriestype] != :straightline for series in series_list(sp)) && data[1] != data[2]
data = [NaN]
end
axis = sp[Symbol(letter, "axis")]
if isa(data, Volume)
expand_extrema!(sp[:xaxis], data.x_extents)
expand_extrema!(sp[:yaxis], data.y_extents)
expand_extrema!(sp[:zaxis], data.z_extents)
elseif eltype(data) <: Number || (isa(data, Surface) && all(di -> isa(di, Number), data.surf))
if !(eltype(data) <: Number)
# huh... must have been a mis-typed surface? lets swap it out
data = d[letter] = Surface(Matrix{Float64}(data.surf))
@@ -269,12 +370,11 @@ function expand_extrema!(sp::Subplot, d::KW)
# end
# expand for fillrange
vert = isvertical(d)
fr = d[:fillrange]
if fr == nothing && d[:seriestype] == :bar
fr = 0.0
end
if fr != nothing
if fr != nothing && !all3D(d)
axis = sp.attr[vert ? :yaxis : :xaxis]
if typeof(fr) <: Tuple
for fri in fr
@@ -292,15 +392,22 @@ function expand_extrema!(sp::Subplot, d::KW)
bw = d[:bar_width]
if bw == nothing
bw = d[:bar_width] = mean(diff(data))
bw = d[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data))))
end
# @show data bw
axis = sp.attr[Symbol(dsym, :axis)]
expand_extrema!(axis, maximum(data) + 0.5maximum(bw))
expand_extrema!(axis, minimum(data) - 0.5minimum(bw))
expand_extrema!(axis, ignorenan_maximum(data) + 0.5maximum(bw))
expand_extrema!(axis, ignorenan_minimum(data) - 0.5minimum(bw))
end
# expand for heatmaps
if d[:seriestype] == :heatmap
for letter in (:x, :y)
data = d[letter]
axis = sp[Symbol(letter, "axis")]
scale = get(d, Symbol(letter, "scale"), :identity)
expand_extrema!(axis, heatmap_edges(data, scale))
end
end
end
function expand_extrema!(sp::Subplot, xmin, xmax, ymin, ymax)
@@ -311,27 +418,38 @@ end
# -------------------------------------------------------------------------
# push the limits out slightly
function widen(lmin, lmax)
span = lmax - lmin
# eps = max(1e-16, min(1e-2span, 1e-10))
eps = max(1e-16, 0.03span)
lmin-eps, lmax+eps
function widen(lmin, lmax, scale = :identity)
f, invf = scalefunc(scale), invscalefunc(scale)
span = f(lmax) - f(lmin)
# eps = NaNMath.max(1e-16, min(1e-2span, 1e-10))
eps = NaNMath.max(1e-16, 0.03span)
invf(f(lmin)-eps), invf(f(lmax)+eps)
end
# figure out if widening is a good idea. if there's a scale set it's too tricky,
# so lazy out and don't widen
# figure out if widening is a good idea.
const _widen_seriestypes = (:line, :path, :steppre, :steppost, :sticks, :scatter, :barbins, :barhist, :histogram, :scatterbins, :scatterhist, :stepbins, :stephist, :bins2d, :histogram2d, :bar, :shape, :path3d, :scatter3d)
function default_should_widen(axis::Axis)
should_widen = false
if axis[:scale] == :identity
for series in series_list(axis.sp)
if series.d[:seriestype] in (:scatter,) || series.d[:markershape] != :none
should_widen = true
if !is_2tuple(axis[:lims])
for sp in axis.sps
for series in series_list(sp)
if series.d[:seriestype] in _widen_seriestypes
should_widen = true
end
end
end
end
should_widen
end
function round_limits(amin,amax)
scale = 10^(1-round(log10(amax - amin)))
amin = floor(amin*scale)/scale
amax = ceil(amax*scale)/scale
amin, amax
end
# using the axis extrema and limit overrides, return the min/max value for this axis
function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis))
ex = axis[:extrema]
@@ -348,8 +466,22 @@ function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis)
if amax <= amin && isfinite(amin)
amax = amin + 1.0
end
if should_widen
widen(amin, amax)
if !isfinite(amin) && !isfinite(amax)
amin, amax = 0.0, 1.0
end
if ispolar(axis.sps[1])
if axis[:letter] == :x
amin, amax = 0, 2pi
elseif lims == :auto
#widen max radius so ticks dont overlap with theta axis
amin, amax + 0.1 * abs(amax - amin)
else
amin, amax
end
elseif should_widen && axis[:widen]
widen(amin, amax, axis[:scale])
elseif lims == :round
round_limits(amin,amax)
else
amin, amax
end
@@ -365,7 +497,7 @@ function discrete_value!(axis::Axis, dv)
# @show axis[:discrete_map], axis[:discrete_values], dv
if cv_idx == -1
ex = axis[:extrema]
cv = max(0.5, ex.emax + 1.0)
cv = NaNMath.max(0.5, ex.emax + 1.0)
expand_extrema!(axis, cv)
push!(axis[:discrete_values], dv)
push!(axis[:continuous_values], cv)
@@ -430,39 +562,94 @@ function axis_drawing_info(sp::Subplot)
ymin, ymax = axis_limits(yaxis)
xticks = get_ticks(xaxis)
yticks = get_ticks(yaxis)
spine_segs = Segments(2)
grid_segs = Segments(2)
xaxis_segs = Segments(2)
yaxis_segs = Segments(2)
xtick_segs = Segments(2)
ytick_segs = Segments(2)
xgrid_segs = Segments(2)
ygrid_segs = Segments(2)
xborder_segs = Segments(2)
yborder_segs = Segments(2)
if !(xaxis[:ticks] in (nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
t1 = invf(f(ymin) + 0.015*(f(ymax)-f(ymin)))
t2 = invf(f(ymax) - 0.015*(f(ymax)-f(ymin)))
if sp[:framestyle] != :none
# xaxis
if xaxis[:showaxis]
if sp[:framestyle] != :grid
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
push!(xaxis_segs, (xmin, y1), (xmax, y1))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(xticks in (nothing,false)) && length(xticks) > 1
showticks = xticks[1] .!= 0
xticks = (xticks[1][showticks], xticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin, y2), (xmax, y2)) # top spine
end
if !(xaxis[:ticks] in (nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(ymin) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
t2 = invf(f(ymax) - 0.015 * (f(ymax) - f(ymin)) * ticks_in)
t3 = invf(f(0) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
push!(spine_segs, (xmin,ymin), (xmax,ymin)) # bottom spine
push!(spine_segs, (xmin,ymax), (xmax,ymax)) # top spine
for xtick in xticks[1]
push!(spine_segs, (xtick, ymin), (xtick, t1)) # bottom tick
push!(grid_segs, (xtick, t1), (xtick, t2)) # vertical grid
push!(spine_segs, (xtick, ymax), (xtick, t2)) # top tick
for xtick in xticks[1]
if xaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1)
end
push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
end
# sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
end
end
# yaxis
if yaxis[:showaxis]
if sp[:framestyle] != :grid
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
end
push!(yaxis_segs, (x1, ymin), (x1, ymax))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(yticks in (nothing,false)) && length(yticks) > 1
showticks = yticks[1] .!= 0
yticks = (yticks[1][showticks], yticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (x2, ymin), (x2, ymax)) # right spine
end
if !(yaxis[:ticks] in (nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(xmin) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
t2 = invf(f(xmax) - 0.015 * (f(xmax) - f(xmin)) * ticks_in)
t3 = invf(f(0) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
for ytick in yticks[1]
if yaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, t2) : (xmin, t1)
end
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
end
# sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
end
end
if !(yaxis[:ticks] in (nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
t1 = invf(f(xmin) + 0.015*(f(xmax)-f(xmin)))
t2 = invf(f(xmax) - 0.015*(f(xmax)-f(xmin)))
push!(spine_segs, (xmin,ymin), (xmin,ymax)) # left spine
push!(spine_segs, (xmax,ymin), (xmax,ymax)) # right spine
for ytick in yticks[1]
push!(spine_segs, (xmin, ytick), (t1, ytick)) # left tick
push!(grid_segs, (t1, ytick), (t2, ytick)) # horizontal grid
push!(spine_segs, (xmax, ytick), (t2, ytick)) # right tick
end
end
xticks, yticks, spine_segs, grid_segs
xticks, yticks, xaxis_segs, yaxis_segs, xtick_segs, ytick_segs, xgrid_segs, ygrid_segs, xborder_segs, yborder_segs
end
+117 -49
View File
@@ -1,12 +1,16 @@
using Pkg
immutable NoBackend <: AbstractBackend end
struct NoBackend <: AbstractBackend end
const _backendType = Dict{Symbol, DataType}(:none => NoBackend)
const _backendSymbol = Dict{DataType, Symbol}(NoBackend => :none)
const _backends = Symbol[]
const _initialized_backends = Set{Symbol}()
"Returns a list of supported backends"
backends() = _backends
"Returns the name of the current backend"
backend_name() = CURRENT_BACKEND.sym
_backend_instance(sym::Symbol) = haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym")
@@ -15,7 +19,7 @@ macro init_backend(s)
sym = Symbol(str)
T = Symbol(string(s) * "Backend")
esc(quote
immutable $T <: AbstractBackend end
struct $T <: AbstractBackend end
export $sym
$sym(; kw...) = (default(; kw...); backend(Symbol($str)))
backend_name(::$T) = Symbol($str)
@@ -26,24 +30,18 @@ macro init_backend(s)
end)
end
@init_backend Immerse
@init_backend Gadfly
@init_backend PyPlot
@init_backend Qwt
@init_backend UnicodePlots
@init_backend Winston
@init_backend Bokeh
@init_backend Plotly
@init_backend PlotlyJS
@init_backend GR
@init_backend GLVisualize
@init_backend PGFPlots
include("backends/web.jl")
# include("backends/supported.jl")
# ---------------------------------------------------------
function add_backend(pkg::Symbol)
info("To do a standard install of $pkg, copy and run this:\n\n")
println(add_backend_string(_backend_instance(pkg)))
println()
end
add_backend_string(b::AbstractBackend) = warn("No custom install defined for $(backend_name(b))")
# don't do anything as a default
_create_backend_figure(plt::Plot) = nothing
_prepare_plot_object(plt::Plot) = nothing
@@ -54,18 +52,49 @@ _series_updated(plt::Plot, series::Series) = nothing
_before_layout_calcs(plt::Plot) = nothing
title_padding(sp::Subplot) = sp[:title] == "" ? 0mm : sp[:titlefont].pointsize * pt
guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefont].pointsize * pt
title_padding(sp::Subplot) = sp[:title] == "" ? 0mm : sp[:titlefontsize] * pt
guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefontsize] * pt
# TODO: this should account for both tick font and the size/length/rotation of tick labels
"Returns the (width,height) of a text label."
function text_size(lablen::Int, sz::Number, rot::Number = 0)
# we need to compute the size of the ticks generically
# this means computing the bounding box and then getting the width/height
# note:
ptsz = sz * pt
width = 0.8lablen * ptsz
# now compute the generalized "height" after rotation as the "opposite+adjacent" of 2 triangles
height = abs(sind(rot)) * width + abs(cosd(rot)) * ptsz
width = abs(sind(rot+90)) * width + abs(cosd(rot+90)) * ptsz
width, height
end
text_size(lab::AbstractString, sz::Number, rot::Number = 0) = text_size(length(lab), sz, rot)
# account for the size/length/rotation of tick labels
function tick_padding(axis::Axis)
ptsz = axis[:tickfont].pointsize * pt
if axis[:ticks] in (nothing,false)
ticks = get_ticks(axis)
if ticks == nothing
0mm
elseif axis[:letter] == :x
2mm + ptsz
else
8mm
vals, labs = ticks
isempty(labs) && return 0mm
# ptsz = axis[:tickfont].pointsize * pt
longest_label = maximum(length(lab) for lab in labs)
# generalize by "rotating" y labels
rot = axis[:rotation] + (axis[:letter] == :y ? 90 : 0)
# # we need to compute the size of the ticks generically
# # this means computing the bounding box and then getting the width/height
# labelwidth = 0.8longest_label * ptsz
#
#
# # now compute the generalized "height" after rotation as the "opposite+adjacent" of 2 triangles
# hgt = abs(sind(rot)) * labelwidth + abs(cosd(rot)) * ptsz + 1mm
# hgt
# get the height of the rotated label
text_size(longest_label, axis[:tickfontsize], rot)[2]
end
end
@@ -77,6 +106,15 @@ function _update_min_padding!(sp::Subplot)
toppad = sp[:top_margin] + title_padding(sp)
rightpad = sp[:right_margin]
bottompad = tick_padding(sp[:xaxis]) + sp[:bottom_margin] + guide_padding(sp[:xaxis])
# switch them?
if sp[:xaxis][:mirror]
bottompad, toppad = toppad, bottompad
end
if sp[:yaxis][:mirror]
leftpad, rightpad = rightpad, leftpad
end
# @show (leftpad, toppad, rightpad, bottompad)
sp.minpad = (leftpad, toppad, rightpad, bottompad)
end
@@ -86,7 +124,7 @@ _update_plot_object(plt::Plot) = nothing
# ---------------------------------------------------------
type CurrentBackend
mutable struct CurrentBackend
sym::Symbol
pkg::AbstractBackend
end
@@ -97,8 +135,7 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, _backend_instance(sym))
function pickDefaultBackend()
env_default = get(ENV, "PLOTS_DEFAULT_BACKEND", "")
if env_default != ""
try
Pkg.installed(env_default) # this will error if not installed
if env_default in keys(Pkg.installed())
sym = Symbol(lowercase(env_default))
if haskey(_backendType, sym)
return backend(sym)
@@ -106,7 +143,7 @@ function pickDefaultBackend()
warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t",
join(sort(_backends), "\n\t"))
end
catch
else
warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not installed.")
end
end
@@ -114,8 +151,8 @@ function pickDefaultBackend()
# the ordering/inclusion of this package list is my semi-arbitrary guess at
# which one someone will want to use if they have the package installed...accounting for
# features, speed, and robustness
for pkgstr in ("PyPlot", "GR", "PlotlyJS", "Immerse", "Gadfly", "UnicodePlots")
if Pkg.installed(pkgstr) != nothing
for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR", "GLVisualize")
if pkgstr in keys(Pkg.installed())
return backend(Symbol(lowercase(pkgstr)))
end
end
@@ -140,14 +177,15 @@ function backend()
sym = CURRENT_BACKEND.sym
if !(sym in _initialized_backends)
# initialize
println("[Plots.jl] Initializing backend: ", sym)
# # initialize
# println("[Plots.jl] Initializing backend: ", sym)
inst = _backend_instance(sym)
try
_initialize_backend(inst)
catch err
warn("Couldn't initialize $sym. (might need to install it?)")
add_backend(sym)
rethrow(err)
end
@@ -164,12 +202,14 @@ function backend(pkg::AbstractBackend)
CURRENT_BACKEND.sym = backend_name(pkg)
warn_on_deprecated_backend(CURRENT_BACKEND.sym)
CURRENT_BACKEND.pkg = pkg
backend()
end
function backend(modname::Symbol)
warn_on_deprecated_backend(modname)
CURRENT_BACKEND.sym = modname
CURRENT_BACKEND.pkg = _backend_instance(modname)
backend()
end
const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse]
@@ -180,23 +220,7 @@ function warn_on_deprecated_backend(bsym::Symbol)
end
end
# ---------------------------------------------------------
supported_types(::AbstractBackend) = []
supported_styles(::AbstractBackend) = [:solid]
supported_markers(::AbstractBackend) = [:none]
supported_scales(::AbstractBackend) = [:identity]
is_subplot_supported(::AbstractBackend) = false
is_string_supported(::AbstractBackend) = false
nativeImagesSupported(b::AbstractBackend) = :image in supported_types(b)
supported_types() = supported_types(backend())
supported_styles() = supported_styles(backend())
supported_markers() = supported_markers(backend())
supported_scales() = supported_scales(backend())
is_subplot_supported() = is_subplot_supported(backend())
is_string_supported() = is_string_supported(backend())
nativeImagesSupported() = nativeImagesSupported(backend())
# ---------------------------------------------------------
@@ -226,7 +250,7 @@ const _base_supported_args = [
:subplot_index,
:discrete_values,
:projection,
]
function merge_with_base_supported(v::AVec)
@@ -238,5 +262,49 @@ function merge_with_base_supported(v::AVec)
end
end
end
v
Set(v)
end
# @init_backend Immerse
# @init_backend Gadfly
@init_backend PyPlot
# @init_backend Qwt
@init_backend UnicodePlots
# @init_backend Winston
# @init_backend Bokeh
@init_backend Plotly
@init_backend PlotlyJS
@init_backend GR
@init_backend GLVisualize
@init_backend PGFPlots
@init_backend InspectDR
@init_backend HDF5
# ---------------------------------------------------------
# create the various `is_xxx_supported` and `supported_xxxs` methods
# by default they pass through to checking membership in `_gr_xxx`
for s in (:attr, :seriestype, :marker, :style, :scale)
f = Symbol("is_", s, "_supported")
f2 = Symbol("supported_", s, "s")
@eval begin
$f(::AbstractBackend, $s) = false
$f(bend::AbstractBackend, $s::AbstractVector) = all(v -> $f(bend, v), $s)
$f($s) = $f(backend(), $s)
$f2() = $f2(backend())
end
for bend in backends()
bend_type = typeof(_backend_instance(bend))
v = Symbol("_", bend, "_", s)
@eval begin
$f(::$bend_type, $s::Symbol) = $s in $v
$f2(::$bend_type) = $v
end
end
end
# is_subplot_supported(::AbstractBackend) = false
# is_subplot_supported() = is_subplot_supported(backend())
+1488 -268
View File
File diff suppressed because it is too large Load Diff
+672 -252
View File
File diff suppressed because it is too large Load Diff
+665
View File
@@ -0,0 +1,665 @@
#HDF5 Plots: Save/replay plots to/from HDF5
#-------------------------------------------------------------------------------
#==Usage
===============================================================================
Write to .hdf5 file using:
p = plot(...)
Plots.hdf5plot_write(p, "plotsave.hdf5")
Read from .hdf5 file using:
pyplot() #Must first select backend
pread = Plots.hdf5plot_read("plotsave.hdf5")
display(pread)
==#
#==TODO
===============================================================================
1. Support more features
- SeriesAnnotations & GridLayout known to be missing.
3. Improve error handling.
- Will likely crash if file format is off.
2. Save data in a folder parallel to "plot".
- Will make it easier for users to locate data.
- Use HDF5 reference to link data?
3. Develop an actual versioned file format.
- Should have some form of backward compatibility.
- Should be reliable for archival purposes.
==#
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "hdf5.jl"))
end
import FixedPointNumbers: N0f8 #In core Julia
#Dispatch types:
struct HDF5PlotNative; end #Indentifies a data element that can natively be handled by HDF5
struct HDF5CTuple; end #Identifies a "complex" tuple structure
mutable struct HDF5Plot_PlotRef
ref::Union{Plot, Nothing}
end
#==Useful constants
===============================================================================#
const _hdf5_plotroot = "plot"
const _hdf5_dataroot = "data" #TODO: Eventually move data to different root (easier to locate)?
const _hdf5plot_datatypeid = "TYPE" #Attribute identifying type
const _hdf5plot_countid = "COUNT" #Attribute for storing count
#Dict has problems using "Types" as keys. Initialize in "_initialize_backend":
const HDF5PLOT_MAP_STR2TELEM = Dict{String, Type}()
const HDF5PLOT_MAP_TELEM2STR = Dict{Type, String}()
#Don't really like this global variable... Very hacky
const HDF5PLOT_PLOTREF = HDF5Plot_PlotRef(nothing)
#Simple sub-structures that can just be written out using _hdf5plot_gwritefields:
const HDF5PLOT_SIMPLESUBSTRUCT = Union{Font, BoundingBox,
GridLayout, RootLayout, ColorGradient, SeriesAnnotations, PlotText
}
#==
===============================================================================#
const _hdf5_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
:label,
:linecolor, :linestyle, :linewidth, :linealpha,
:markershape, :markercolor, :markersize, :markeralpha,
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
:fillrange, :fillcolor, :fillalpha,
:bins, :bar_width, :bar_edges, :bar_position,
:title, :title_location, :titlefont,
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
:orientation,
:overwrite_figure,
:polar,
:normalize, :weights,
:contours, :aspect_ratio,
:match_dimensions,
:clims,
:inset_subplots,
:dpi,
:colorbar_title,
])
const _hdf5_seriestype = [
:path, :steppre, :steppost, :shape, :straightline,
:scatter, :hexbin, #:histogram2d, :histogram,
# :bar,
:heatmap, :pie, :image,
:contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe
]
const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot]
const _hdf5_marker = vcat(_allMarkers, :pixel)
const _hdf5_scale = [:identity, :ln, :log2, :log10]
is_marker_supported(::HDF5Backend, shape::Shape) = true
function add_backend_string(::HDF5Backend)
"""
if !Plots.is_installed("HDF5")
Pkg.add("HDF5")
end
"""
end
#==Helper functions
===============================================================================#
_hdf5_plotelempath(subpath::String) = "$_hdf5_plotroot/$subpath"
_hdf5_datapath(subpath::String) = "$_hdf5_dataroot/$subpath"
_hdf5_map_str2telem(k::String) = HDF5PLOT_MAP_STR2TELEM[k]
_hdf5_map_str2telem(v::Vector) = HDF5PLOT_MAP_STR2TELEM[v[1]]
function _hdf5_merge!(dest::Dict, src::Dict)
for (k, v) in src
if isa(v, Axis)
_hdf5_merge!(dest[k].d, v.d)
else
dest[k] = v
end
end
return
end
#==
===============================================================================#
function _initialize_backend(::HDF5Backend)
@eval begin
import HDF5
export HDF5
if length(HDF5PLOT_MAP_TELEM2STR) < 1
#Possible element types of high-level data types:
telem2str = Dict{String, Type}(
"NATIVE" => HDF5PlotNative,
"VOID" => Nothing,
"BOOL" => Bool,
"SYMBOL" => Symbol,
"TUPLE" => Tuple,
"CTUPLE" => HDF5CTuple, #Tuple of complex structures
"RGBA" => ARGB{N0f8},
"EXTREMA" => Extrema,
"LENGTH" => Length,
"ARRAY" => Array, #Dict won't allow Array to be key in HDF5PLOT_MAP_TELEM2STR
#Sub-structure types:
"FONT" => Font,
"BOUNDINGBOX" => BoundingBox,
"GRIDLAYOUT" => GridLayout,
"ROOTLAYOUT" => RootLayout,
"SERIESANNOTATIONS" => SeriesAnnotations,
# "PLOTTEXT" => PlotText,
"COLORGRADIENT" => ColorGradient,
"AXIS" => Axis,
"SURFACE" => Surface,
"SUBPLOT" => Subplot,
"NULLABLE" => Nullable,
)
merge!(HDF5PLOT_MAP_STR2TELEM, telem2str)
merge!(HDF5PLOT_MAP_TELEM2STR, Dict{Type, String}(v=>k for (k,v) in HDF5PLOT_MAP_STR2TELEM))
end
end
end
# ---------------------------------------------------------------------------
# Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{HDF5Backend})
#Do nothing
end
# ---------------------------------------------------------------------------
# # this is called early in the pipeline, use it to make the plot current or something
# function _prepare_plot_object(plt::Plot{HDF5Backend})
# end
# ---------------------------------------------------------------------------
# Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{HDF5Backend}, sp::Subplot{HDF5Backend})
#Do nothing
end
# ---------------------------------------------------------------------------
# Add one series to the underlying backend object.
# Called once per series
# NOTE: Seems to be called when user calls plot()... even if backend
# plot, sp.o has not yet been constructed...
function _series_added(plt::Plot{HDF5Backend}, series::Series)
#Do nothing
end
# ---------------------------------------------------------------------------
# When series data is added/changed, this callback can do dynamic updates to the backend object.
# note: if the backend rebuilds the plot from scratch on display, then you might not do anything here.
function _series_updated(plt::Plot{HDF5Backend}, series::Series)
#Do nothing
end
# ---------------------------------------------------------------------------
# called just before updating layout bounding boxes... in case you need to prep
# for the calcs
function _before_layout_calcs(plt::Plot{HDF5Backend})
#Do nothing
end
# ----------------------------------------------------------------
# Set the (left, top, right, bottom) minimum padding around the plot area
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{HDF5Backend})
#Do nothing
end
# ----------------------------------------------------------------
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations])
function _update_plot_object(plt::Plot{HDF5Backend})
#Do nothing
end
# ----------------------------------------------------------------
# Display/show the plot (open a GUI window, or browser page, for example).
function _display(plt::Plot{HDF5Backend})
msg = "HDF5 interface does not support `display()` function."
msg *= "\nUse `Plots.hdf5plot_write(::String)` method to write to .HDF5 \"plot\" file instead."
warn(msg)
return
end
#==HDF5 write functions
===============================================================================#
function _hdf5plot_writetype(grp, k::String, tstr::Array{String})
d = HDF5.d_open(grp, k)
HDF5.a_write(d, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writetype(grp, k::String, T::Type)
tstr = HDF5PLOT_MAP_TELEM2STR[T]
d = HDF5.d_open(grp, k)
HDF5.a_write(d, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_overwritetype(grp, k::String, T::Type)
tstr = HDF5PLOT_MAP_TELEM2STR[T]
d = HDF5.d_open(grp, k)
HDF5.a_delete(d, _hdf5plot_datatypeid)
HDF5.a_write(d, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writetype(grp, T::Type) #Write directly to group
tstr = HDF5PLOT_MAP_TELEM2STR[T]
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_overwritetype(grp, T::Type) #Write directly to group
tstr = HDF5PLOT_MAP_TELEM2STR[T]
HDF5.a_delete(grp, _hdf5plot_datatypeid)
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writetype(grp, ::Type{Array{T}}) where T<:Any
tstr = HDF5PLOT_MAP_TELEM2STR[Array] #ANY
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writetype(grp, ::Type{T}) where T<:BoundingBox
tstr = HDF5PLOT_MAP_TELEM2STR[BoundingBox]
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
end
function _hdf5plot_writecount(grp, n::Int) #Write directly to group
HDF5.a_write(grp, _hdf5plot_countid, n)
end
function _hdf5plot_gwritefields(grp, k::String, v)
grp = HDF5.g_create(grp, k)
for _k in fieldnames(v)
_v = getfield(v, _k)
kstr = string(_k)
_hdf5plot_gwrite(grp, kstr, _v)
end
_hdf5plot_writetype(grp, typeof(v))
return
end
# Write data
# ----------------------------------------------------------------
function _hdf5plot_gwrite(grp, k::String, v) #Default
grp[k] = v
_hdf5plot_writetype(grp, k, HDF5PlotNative)
end
function _hdf5plot_gwrite(grp, k::String, v::Array{T}) where T<:Number #Default for arrays
grp[k] = v
_hdf5plot_writetype(grp, k, HDF5PlotNative)
end
#=
function _hdf5plot_gwrite(grp, k::String, v::Array{Any})
# @show grp, k
warn("Cannot write Array: $k=$v")
end
=#
function _hdf5plot_gwrite(grp, k::String, v::Nothing)
grp[k] = 0
_hdf5plot_writetype(grp, k, Nothing)
end
function _hdf5plot_gwrite(grp, k::String, v::Bool)
grp[k] = Int(v)
_hdf5plot_writetype(grp, k, Bool)
end
function _hdf5plot_gwrite(grp, k::String, v::Symbol)
grp[k] = string(v)
_hdf5plot_writetype(grp, k, Symbol)
end
function _hdf5plot_gwrite(grp, k::String, v::Tuple)
varr = [v...]
elt = eltype(varr)
# if isleaftype(elt)
_hdf5plot_gwrite(grp, k, varr)
if elt <: Number
#We just wrote a simple dataset
_hdf5plot_overwritetype(grp, k, Tuple)
else #Used a more complex scheme (using subgroups):
_hdf5plot_overwritetype(grp[k], HDF5CTuple)
end
#NOTE: _hdf5plot_overwritetype overwrites "Array" type with "Tuple".
end
function _hdf5plot_gwrite(grp, k::String, d::Dict)
# warn("Cannot write dict: $k=$d")
end
function _hdf5plot_gwrite(grp, k::String, v::AbstractRange)
_hdf5plot_gwrite(grp, k, collect(v)) #For now
end
function _hdf5plot_gwrite(grp, k::String, v::ARGB{N0f8})
grp[k] = [v.r.i, v.g.i, v.b.i, v.alpha.i]
_hdf5plot_writetype(grp, k, ARGB{N0f8})
end
function _hdf5plot_gwrite(grp, k::String, v::Colorant)
_hdf5plot_gwrite(grp, k, ARGB{N0f8}(v))
end
#Custom vector (when not using simple numeric type):
function _hdf5plot_gwritearray(grp, k::String, v::Array{T}) where T
if "annotations" == k;
return #Hack. Does not yet support annotations.
end
vgrp = HDF5.g_create(grp, k)
_hdf5plot_writetype(vgrp, Array) #ANY
sz = size(v)
for iter in eachindex(v)
coord = LinearIndices(sz, iter)
elem = v[iter]
idxstr = join(coord, "_")
_hdf5plot_gwrite(vgrp, "v$idxstr", v[iter])
end
_hdf5plot_gwrite(vgrp, "dim", [sz...])
return
end
_hdf5plot_gwrite(grp, k::String, v::Array) =
_hdf5plot_gwritearray(grp, k, v)
function _hdf5plot_gwrite(grp, k::String, v::Extrema)
grp[k] = [v.emin, v.emax]
_hdf5plot_writetype(grp, k, Extrema)
end
function _hdf5plot_gwrite(grp, k::String, v::Length{T}) where T
grp[k] = v.value
_hdf5plot_writetype(grp, k, [HDF5PLOT_MAP_TELEM2STR[Length], string(T)])
end
# Write more complex structures:
# ----------------------------------------------------------------
function _hdf5plot_gwrite(grp, k::String, v::Plot)
#Don't write plot references
end
function _hdf5plot_gwrite(grp, k::String, v::HDF5PLOT_SIMPLESUBSTRUCT)
_hdf5plot_gwritefields(grp, k, v)
return
end
function _hdf5plot_gwrite(grp, k::String, v::Axis)
grp = HDF5.g_create(grp, k)
for (_k, _v) in v.d
kstr = string(_k)
_hdf5plot_gwrite(grp, kstr, _v)
end
_hdf5plot_writetype(grp, Axis)
return
end
function _hdf5plot_gwrite(grp, k::String, v::Surface)
grp = HDF5.g_create(grp, k)
_hdf5plot_gwrite(grp, "data2d", v.surf)
_hdf5plot_writetype(grp, Surface)
end
# #TODO: "Properly" support Nullable using _hdf5plot_writetype?
# function _hdf5plot_gwrite(grp, k::String, v::Nullable)
# if isnull(v)
# _hdf5plot_gwrite(grp, k, nothing)
# else
# _hdf5plot_gwrite(grp, k, v.value)
# end
# return
# end
function _hdf5plot_gwrite(grp, k::String, v::SeriesAnnotations)
#Currently no support for SeriesAnnotations
return
end
function _hdf5plot_gwrite(grp, k::String, v::Subplot)
grp = HDF5.g_create(grp, k)
_hdf5plot_gwrite(grp, "index", v[:subplot_index])
_hdf5plot_writetype(grp, Subplot)
return
end
function _hdf5plot_write(grp, d::Dict)
for (k, v) in d
kstr = string(k)
_hdf5plot_gwrite(grp, kstr, v)
end
return
end
# Write main plot structures:
# ----------------------------------------------------------------
function _hdf5plot_write(sp::Subplot{HDF5Backend}, subpath::String, f)
f = f::HDF5.HDF5File #Assert
grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/attr"))
_hdf5plot_write(grp, sp.attr)
grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list"))
_hdf5plot_writecount(grp, length(sp.series_list))
for (i, series) in enumerate(sp.series_list)
grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list/series$i"))
_hdf5plot_write(grp, series.d)
end
return
end
function _hdf5plot_write(plt::Plot{HDF5Backend}, f)
f = f::HDF5.HDF5File #Assert
grp = HDF5.g_create(f, _hdf5_plotelempath("attr"))
_hdf5plot_write(grp, plt.attr)
grp = HDF5.g_create(f, _hdf5_plotelempath("subplots"))
_hdf5plot_writecount(grp, length(plt.subplots))
for (i, sp) in enumerate(plt.subplots)
_hdf5plot_write(sp, "subplots/subplot$i", f)
end
return
end
function hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString)
HDF5.h5open(path, "w") do file
_hdf5plot_write(plt, file)
end
end
hdf5plot_write(path::AbstractString) = hdf5plot_write(current(), path)
#==HDF5 playback (read) functions
===============================================================================#
function _hdf5plot_readcount(grp) #Read directly from group
return HDF5.a_read(grp, _hdf5plot_countid)
end
_hdf5plot_convert(T::Type{HDF5PlotNative}, v) = v
_hdf5plot_convert(T::Type{Nothing}, v) = nothing
_hdf5plot_convert(T::Type{Bool}, v) = (v!=0)
_hdf5plot_convert(T::Type{Symbol}, v) = Symbol(v)
_hdf5plot_convert(T::Type{Tuple}, v) = tuple(v...) #With Vector{T<:Number}
function _hdf5plot_convert(T::Type{ARGB{N0f8}}, v)
r, g, b, a = reinterpret(N0f8, v)
return Colors.ARGB{N0f8}(r, g, b, a)
end
_hdf5plot_convert(T::Type{Extrema}, v) = Extrema(v[1], v[2])
# Read data structures:
# ----------------------------------------------------------------
function _hdf5plot_read(grp, k::String, T::Type, dtid)
v = HDF5.d_read(grp, k)
return _hdf5plot_convert(T, v)
end
function _hdf5plot_read(grp, k::String, T::Type{Length}, dtid::Vector)
v = HDF5.d_read(grp, k)
TU = Symbol(dtid[2])
T = typeof(v)
return Length{TU,T}(v)
end
# Read more complex data structures:
# ----------------------------------------------------------------
function _hdf5plot_read(grp, k::String, T::Type{Font}, dtid)
grp = HDF5.g_open(grp, k)
family = _hdf5plot_read(grp, "family")
pointsize = _hdf5plot_read(grp, "pointsize")
halign = _hdf5plot_read(grp, "halign")
valign = _hdf5plot_read(grp, "valign")
rotation = _hdf5plot_read(grp, "rotation")
color = _hdf5plot_read(grp, "color")
return Font(family, pointsize, halign, valign, rotation, color)
end
function _hdf5plot_read(grp, k::String, T::Type{Array}, dtid) #ANY
grp = HDF5.g_open(grp, k)
sz = _hdf5plot_read(grp, "dim")
if [0] == sz; return []; end
sz = tuple(sz...)
result = Array{Any}(sz)
for iter in eachindex(result)
coord = LinearIndices(sz, iter)
idxstr = join(coord, "_")
result[iter] = _hdf5plot_read(grp, "v$idxstr")
end
#Hack: Implicitly make Julia detect element type.
# (Should probably write it explicitly to file)
result = [result[iter] for iter in eachindex(result)] #Potentially make more specific
return reshape(result, sz)
end
function _hdf5plot_read(grp, k::String, T::Type{HDF5CTuple}, dtid)
v = _hdf5plot_read(grp, k, Array, dtid)
return tuple(v...)
end
function _hdf5plot_read(grp, k::String, T::Type{ColorGradient}, dtid)
grp = HDF5.g_open(grp, k)
colors = _hdf5plot_read(grp, "colors")
values = _hdf5plot_read(grp, "values")
return ColorGradient(colors, values)
end
function _hdf5plot_read(grp, k::String, T::Type{BoundingBox}, dtid)
grp = HDF5.g_open(grp, k)
x0 = _hdf5plot_read(grp, "x0")
a = _hdf5plot_read(grp, "a")
return BoundingBox(x0, a)
end
_hdf5plot_read(grp, k::String, T::Type{RootLayout}, dtid) = RootLayout()
function _hdf5plot_read(grp, k::String, T::Type{GridLayout}, dtid)
grp = HDF5.g_open(grp, k)
# parent = _hdf5plot_read(grp, "parent")
parent = RootLayout()
minpad = _hdf5plot_read(grp, "minpad")
bbox = _hdf5plot_read(grp, "bbox")
grid = _hdf5plot_read(grp, "grid")
widths = _hdf5plot_read(grp, "widths")
heights = _hdf5plot_read(grp, "heights")
attr = KW() #TODO support attr: _hdf5plot_read(grp, "attr")
return GridLayout(parent, minpad, bbox, grid, widths, heights, attr)
end
function _hdf5plot_read(grp, k::String, T::Type{Axis}, dtid)
grp = HDF5.g_open(grp, k)
kwlist = KW()
_hdf5plot_read(grp, kwlist)
return Axis([], kwlist)
end
function _hdf5plot_read(grp, k::String, T::Type{Surface}, dtid)
grp = HDF5.g_open(grp, k)
data2d = _hdf5plot_read(grp, "data2d")
return Surface(data2d)
end
function _hdf5plot_read(grp, k::String, T::Type{Subplot}, dtid)
grp = HDF5.g_open(grp, k)
idx = _hdf5plot_read(grp, "index")
return HDF5PLOT_PLOTREF.ref.subplots[idx]
end
function _hdf5plot_read(grp, k::String)
dtid = HDF5.a_read(grp[k], _hdf5plot_datatypeid)
T = _hdf5_map_str2telem(dtid) #expect exception
return _hdf5plot_read(grp, k, T, dtid)
end
#Read in values in group to populate d:
function _hdf5plot_read(grp, d::Dict)
gnames = names(grp)
for k in gnames
try
v = _hdf5plot_read(grp, k)
d[Symbol(k)] = v
catch e
@show e
@show grp
warn("Could not read field $k")
end
end
return
end
# Read main plot structures:
# ----------------------------------------------------------------
function _hdf5plot_read(sp::Subplot, subpath::String, f)
f = f::HDF5.HDF5File #Assert
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr"))
kwlist = KW()
_hdf5plot_read(grp, kwlist)
_hdf5_merge!(sp.attr, kwlist)
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list"))
nseries = _hdf5plot_readcount(grp)
for i in 1:nseries
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list/series$i"))
kwlist = KW()
_hdf5plot_read(grp, kwlist)
plot!(sp, kwlist[:x], kwlist[:y]) #Add data & create data structures
_hdf5_merge!(sp.series_list[end].d, kwlist)
end
return
end
function _hdf5plot_read(plt::Plot, f)
f = f::HDF5.HDF5File #Assert
#Assumpltion: subplots are already allocated (plt.subplots)
HDF5PLOT_PLOTREF.ref = plt #Used when reading "layout"
grp = HDF5.g_open(f, _hdf5_plotelempath("attr"))
_hdf5plot_read(grp, plt.attr)
for (i, sp) in enumerate(plt.subplots)
_hdf5plot_read(sp, "subplots/subplot$i", f)
end
return
end
function hdf5plot_read(path::AbstractString)
plt = nothing
HDF5.h5open(path, "r") do file
grp = HDF5.g_open(file, _hdf5_plotelempath("subplots"))
n = _hdf5plot_readcount(grp)
plt = plot(layout=n) #Get reference to a new plot
_hdf5plot_read(plt, file)
end
return plt
end
#Last line
+543
View File
@@ -0,0 +1,543 @@
# 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,
=#
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "inspectdr.jl"))
end
# ---------------------------------------------------------------------------
#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,
:window_title,
:guide, :lims, :scale, #:ticks, :flip, :rotation,
:titlefontfamily, :titlefontsize, :titlefontcolor,
:legendfontfamily, :legendfontsize, :legendfontcolor,
:tickfontfamily, :tickfontsize, :tickfontcolor,
:guidefontfamily, :guidefontsize, :guidefontcolor,
: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, :straightline, #, :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:
INSPECTDR_GLYPH_SHAPE = InspectDR.GlyphPolyline(
2*InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y
)
mutable struct InspecDRPlotRef
mplot::Union{Nothing, InspectDR.Multiplot}
gui::Union{Nothing, 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, y = if st == :straightline
straightline_data(series)
else
_vectorize(series[:x]), _vectorize(series[:y])
end
#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,)
x, y = shape_data(series)
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, :straightline) #, :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})
plot = sp.o
strip = plot.strips[1] #Only 1 strip supported with Plots.jl
xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
xgrid_show = xaxis[:grid]
ygrid_show = yaxis[:grid]
strip.grid = InspectDR.GridRect(
vmajor=xgrid_show, # vminor=xgrid_show,
hmajor=ygrid_show, # hminor=ygrid_show,
)
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 = NaNMath.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_canvas].fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot])
l[:frame_data].fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
l[:frame_data].line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
l[:font_title] = InspectDR.Font(sp[:titlefontfamily],
_inspectdr_mapptsize(sp[:titlefontsize]),
color = _inspectdr_mapcolor(sp[:titlefontcolor])
)
#Cannot independently control fonts of axes with InspectDR:
l[:font_axislabel] = InspectDR.Font(xaxis[:guidefontfamily],
_inspectdr_mapptsize(xaxis[:guidefontsize]),
color = _inspectdr_mapcolor(xaxis[:guidefontcolor])
)
l[:font_ticklabel] = InspectDR.Font(xaxis[:tickfontfamily],
_inspectdr_mapptsize(xaxis[:tickfontsize]),
color = _inspectdr_mapcolor(xaxis[:tickfontcolor])
)
l[:enable_legend] = (sp[:legend] != :none)
#l[:halloc_legend] = 150 #TODO: compute???
l[:font_legend] = InspectDR.Font(sp[:legendfontfamily],
_inspectdr_mapptsize(sp[:legendfontsize]),
color = _inspectdr_mapcolor(sp[:legendfontcolor])
)
l[:frame_legend].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})
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.layout[: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.layout[:ncolumns] = 1
elseif nsubplots <= 4
mplot.layout[:ncolumns] = 2
elseif nsubplots <= 6
mplot.layout[:ncolumns] = 3
elseif nsubplots <= 12
mplot.layout[:ncolumns] = 4
else
mplot.layout[: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.values, 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.values, 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, ::Nothing, 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
# ----------------------------------------------------------------
# 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
+388 -79
View File
@@ -2,13 +2,18 @@
# significant contributions by: @pkofod
supported_args(::PGFPlotsBackend) = merge_with_base_supported([
# :annotations,
# :background_color_legend,
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "pgfplots.jl"))
end
const _pgfplots_attr = merge_with_base_supported([
:annotations,
:background_color_legend,
:background_color_inside,
# :background_color_outside,
# :foreground_color_legend, :foreground_color_grid, :foreground_color_axis,
# :foreground_color_text, :foreground_color_border,
# :foreground_color_legend,
:foreground_color_grid, :foreground_color_axis,
:foreground_color_text, :foreground_color_border,
:label,
:seriescolor, :seriesalpha,
:linecolor, :linestyle, :linewidth, :linealpha,
@@ -22,25 +27,34 @@ supported_args(::PGFPlotsBackend) = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend,
# :colorbar,
# :marker_z, :levels,
:colorbar,
:fill_z, :line_z, :marker_z, :levels,
# :ribbon, :quiver, :arrow,
# :orientation,
# :overwrite_figure,
# :polar,
:polar,
# :normalize, :weights, :contours,
:aspect_ratio,
# :match_dimensions,
:tick_direction,
:framestyle,
:camera,
:contour_labels,
])
supported_types(::PGFPlotsBackend) = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour]
supported_styles(::PGFPlotsBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supported_markers(::PGFPlotsBackend) = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon] #vcat(_allMarkers, Shape)
supported_scales(::PGFPlotsBackend) = [:identity, :ln, :log2, :log10]
is_subplot_supported(::PGFPlotsBackend) = false
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,]
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape)
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
# --------------------------------------------------------------------------------------
function add_backend_string(::PGFPlotsBackend)
"""
Pkg.add("PGFPlots")
Pkg.build("PGFPlots")
"""
end
function _initialize_backend(::PGFPlotsBackend; kw...)
@eval begin
@@ -64,6 +78,8 @@ const _pgfplots_markers = KW(
:none => "none",
:cross => "+",
:xcross => "x",
:+ => "+",
:x => "x",
:utriangle => "triangle*",
:dtriangle => "triangle*",
:circle => "*",
@@ -72,6 +88,7 @@ const _pgfplots_markers = KW(
:star6 => "asterisk",
:diamond => "diamond*",
:pentagon => "pentagon*",
:hline => "-"
)
const _pgfplots_legend_pos = KW(
@@ -79,6 +96,7 @@ const _pgfplots_legend_pos = KW(
:bottomright => "south east",
:topright => "north east",
:topleft => "north west",
:outertopright => "outer north east",
)
@@ -91,69 +109,131 @@ 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"
)
const _pgf_framestyles = [:box, :axes, :origin, :zerolines, :grid, :none]
const _pgf_framestyle_defaults = Dict(:semi => :box)
function pgf_framestyle(style::Symbol)
if style in _pgf_framestyles
return style
else
default_style = get(_pgf_framestyle_defaults, style, :axes)
warn("Framestyle :$style is not (yet) supported by the PGFPlots backend. :$default_style was cosen instead.")
default_style
end
end
# --------------------------------------------------------------------------------------
# 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_fillstyle(d::KW)
cstr,a = pgf_color(d[:fillcolor])
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
pgf_thickness_scaling(plt::Plot) = plt[:thickness_scaling]
pgf_thickness_scaling(sp::Subplot) = pgf_thickness_scaling(sp.plt)
pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot])
function pgf_fillstyle(d, i = 1)
cstr,a = pgf_color(get_fillcolor(d, i))
fa = get_fillalpha(d, i)
if fa != nothing
a = fa
end
"fill = $cstr, fill opacity=$a"
end
function pgf_linestyle(d::KW)
cstr,a = pgf_color(d[:linecolor])
function pgf_linestyle(linewidth::Real, color, α = 1, linestyle = "solid")
cstr, a = pgf_color(plot_color(color, α))
"""
color = $cstr,
draw opacity=$a,
line width=$(d[:linewidth]),
$(get(_pgfplots_linestyles, d[:linestyle], "solid"))"""
draw opacity = $a,
line width = $linewidth,
$(get(_pgfplots_linestyles, linestyle, "solid"))"""
end
function pgf_marker(d::KW)
shape = d[:markershape]
cstr, a = pgf_color(d[:markercolor])
cstr_stroke, a_stroke = pgf_color(d[:markerstrokecolor])
function pgf_linestyle(d, i = 1)
lw = pgf_thickness_scaling(d) * get_linewidth(d, i)
lc = get_linecolor(d, i)
la = get_linealpha(d, i)
ls = get_linestyle(d, i)
return pgf_linestyle(lw, lc, la, ls)
end
function pgf_font(fontsize, thickness_scaling = 1, font = "\\selectfont")
fs = fontsize * thickness_scaling
return string("{\\fontsize{", fs, " pt}{", 1.3fs, " pt}", font, "}")
end
function pgf_marker(d, i = 1)
shape = _cycle(d[:markershape], i)
cstr, a = pgf_color(plot_color(get_markercolor(d, i), get_markeralpha(d, i)))
cstr_stroke, a_stroke = pgf_color(plot_color(get_markerstrokecolor(d, i), get_markerstrokealpha(d, i)))
"""
mark = $(get(_pgfplots_markers, shape, "*")),
mark size = $(0.5 * d[:markersize]),
mark size = $(pgf_thickness_scaling(d) * 0.5 * _cycle(d[:markersize], i)),
mark options = {
color = $cstr_stroke, draw opacity = $a_stroke,
fill = $cstr, fill opacity = $a,
line width = $(d[:markerstrokewidth]),
line width = $(pgf_thickness_scaling(d) * _cycle(d[:markerstrokewidth], i)),
rotate = $(shape == :dtriangle ? 180 : 0),
$(get(_pgfplots_linestyles, d[:markerstrokestyle], "solid"))
$(get(_pgfplots_linestyles, _cycle(d[:markerstrokestyle], i), "solid"))
}"""
end
function pgf_add_annotation!(o, x, y, val, thickness_scaling = 1)
# 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),
font=$(pgf_font(val.font.pointsize, thickness_scaling))
"""))
end
# --------------------------------------------------------------------------------------
function pgf_series(sp::Subplot, series::Series)
d = series.d
st = d[:seriestype]
style = []
kw = KW()
push!(style, pgf_linestyle(d))
push!(style, pgf_marker(d))
if d[:fillrange] != nothing
push!(style, pgf_fillstyle(d))
end
# add to legend?
if sp[:legend] != :none && should_add_to_legend(series)
kw[:legendentry] = d[:label]
end
series_collection = PGFPlots.Plot[]
# function args
args = if st == :contour
args = if st == :contour
d[:z].surf, d[:x], d[:y]
elseif is3d(st)
d[:x], d[:y], d[:z]
elseif st == :straightline
straightline_data(series)
elseif st == :shape
shape_data(series)
elseif ispolar(sp)
theta, r = filter_radial_data(d[:x], d[:y], axis_limits(sp[:yaxis]))
rad2deg.(theta), r
else
d[:x], d[:y]
end
@@ -164,34 +244,131 @@ function pgf_series(sp::Subplot, series::Series)
else
a
end, args)
# for (i,a) in enumerate(args)
# if typeof(a) <: AbstractVector && typeof(a) != Vector
# args[i] = collect(a)
# end
# end
# include additional style, then add to the kw
if st in (:contour, :histogram2d)
style = []
kw = KW()
push!(style, pgf_linestyle(d))
push!(style, pgf_marker(d))
push!(style, "forget plot")
kw[:style] = join(style, ',')
func = if st == :histogram2d
PGFPlots.Histogram2
else
kw[:labels] = series[:contour_labels]
kw[:levels] = series[:levels]
PGFPlots.Contour
end
push!(series_collection, func(args...; kw...))
else
# series segments
segments = iter_segments(series)
for (i, rng) in enumerate(segments)
style = []
kw = KW()
push!(style, pgf_linestyle(d, i))
push!(style, pgf_marker(d, i))
if st == :shape
push!(style, pgf_fillstyle(d, i))
end
# add to legend?
if i == 1 && sp[:legend] != :none && should_add_to_legend(series)
if d[:fillrange] != nothing
push!(style, "forget plot")
push!(series_collection, pgf_fill_legend_hack(d, args))
else
kw[:legendentry] = d[:label]
if st == :shape # || d[:fillrange] != nothing
push!(style, "area legend")
end
end
else
push!(style, "forget plot")
end
seg_args = (arg[rng] for arg in args)
# include additional style, then add to the kw
if haskey(_pgf_series_extrastyle, st)
push!(style, _pgf_series_extrastyle[st])
end
kw[:style] = join(style, ',')
# add fillrange
if series[:fillrange] != nothing && st != :shape
push!(series_collection, pgf_fillrange_series(series, i, _cycle(series[:fillrange], rng), seg_args...))
end
# build/return the series object
func = if st == :path3d
PGFPlots.Linear3
elseif st == :scatter
PGFPlots.Scatter
else
PGFPlots.Linear
end
push!(series_collection, func(seg_args...; kw...))
end
end
series_collection
end
function pgf_fillrange_series(series, i, fillrange, args...)
st = series[:seriestype]
style = []
kw = KW()
push!(style, "line width = 0")
push!(style, "draw opacity = 0")
push!(style, pgf_fillstyle(series, i))
push!(style, pgf_marker(series, i))
push!(style, "forget plot")
if haskey(_pgf_series_extrastyle, st)
push!(style, _pgf_series_extrastyle[st])
end
kw[:style] = join(style, ',')
func = is3d(series) ? PGFPlots.Linear3 : PGFPlots.Linear
return func(pgf_fillrange_args(fillrange, args...)...; kw...)
end
# build/return the series object
function pgf_fillrange_args(fillrange, x, y)
n = length(x)
x_fill = [x; x[n:-1:1]; x[1]]
y_fill = [y; _cycle(fillrange, n:-1:1); y[1]]
return x_fill, y_fill
end
function pgf_fillrange_args(fillrange, x, y, z)
n = length(x)
x_fill = [x; x[n:-1:1]; x[1]]
y_fill = [y; y[n:-1:1]; x[1]]
z_fill = [z; _cycle(fillrange, n:-1:1); z[1]]
return x_fill, y_fill, z_fill
end
function pgf_fill_legend_hack(d, args)
style = []
kw = KW()
push!(style, pgf_linestyle(d, 1))
push!(style, pgf_marker(d, 1))
push!(style, pgf_fillstyle(d, 1))
push!(style, "area legend")
kw[:legendentry] = d[:label]
kw[:style] = join(style, ',')
st = d[:seriestype]
func = if st == :path3d
PGFPlots.Linear3
elseif st == :scatter
PGFPlots.Scatter
elseif st == :histogram2d
PGFPlots.Histogram2
elseif st == :contour
PGFPlots.Contour
else
PGFPlots.Linear
end
func(args...; kw...)
return func(([arg[1]] for arg in args)...; kw...)
end
# ----------------------------------------------------------------
function pgf_axis(sp::Subplot, letter)
@@ -199,9 +376,19 @@ function pgf_axis(sp::Subplot, letter)
style = []
kw = KW()
# turn off scaled ticks
push!(style, "scaled $(letter) ticks = false")
# set to supported framestyle
framestyle = pgf_framestyle(sp[:framestyle])
# axis guide
kw[Symbol(letter,:label)] = axis[:guide]
# Add label font
cstr, α = pgf_color(plot_color(axis[:guidefontcolor]))
push!(style, string(letter, "label style = {font = ", pgf_font(axis[:guidefontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", axis[:guidefontrotation], "}"))
# flip/reverse?
axis[:flip] && push!(style, "$letter dir=reverse")
@@ -213,18 +400,77 @@ function pgf_axis(sp::Subplot, letter)
end
# ticks on or off
if axis[:ticks] in (nothing, false)
if axis[:ticks] in (nothing, false, :none) || framestyle == :none
push!(style, "$(letter)majorticks=false")
end
# grid on or off
if axis[:grid] && framestyle != :none
push!(style, "$(letter)majorgrids = true")
else
push!(style, "$(letter)majorgrids = false")
end
# limits
# TODO: support zlims
if letter != :z
lims = axis_limits(axis)
lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(axis)) : axis_limits(axis)
kw[Symbol(letter,:min)] = lims[1]
kw[Symbol(letter,:max)] = lims[2]
end
if !(axis[:ticks] in (nothing, false, :none, :native)) && framestyle != :none
ticks = get_ticks(axis)
#pgf plot ignores ticks with angle below 90 when xmin = 90 so shift values
tick_values = ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] : ticks[1]
push!(style, string(letter, "tick = {", join(tick_values,","), "}"))
if axis[:showaxis] && axis[:scale] in (:ln, :log2, :log10) && axis[:ticks] == :auto
# wrap the power part of label with }
tick_labels = Vector{String}(length(ticks[2]))
for (i, label) in enumerate(ticks[2])
base, power = split(label, "^")
power = string("{", power, "}")
tick_labels[i] = string(base, "^", power)
end
push!(style, string(letter, "ticklabels = {\$", join(tick_labels,"\$,\$"), "\$}"))
elseif axis[:showaxis]
tick_labels = ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] : ticks[2]
if axis[:formatter] in (:scientific, :auto)
tick_labels = string.("\$", convert_sci_unicode.(tick_labels), "\$")
tick_labels = replace.(tick_labels, "×", "\\times")
end
push!(style, string(letter, "ticklabels = {", join(tick_labels,","), "}"))
else
push!(style, string(letter, "ticklabels = {}"))
end
push!(style, string(letter, "tick align = ", (axis[:tick_direction] == :out ? "outside" : "inside")))
cstr, α = pgf_color(plot_color(axis[:tickfontcolor]))
push!(style, string(letter, "ticklabel style = {font = ", pgf_font(axis[:tickfontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", axis[:tickfontrotation], "}"))
push!(style, string(letter, " grid style = {", pgf_linestyle(pgf_thickness_scaling(sp) * axis[:gridlinewidth], axis[:foreground_color_grid], axis[:gridalpha], axis[:gridstyle]), "}"))
end
# framestyle
if framestyle in (:axes, :origin)
axispos = framestyle == :axes ? "left" : "middle"
# the * after lines disables the arrows at the axes
push!(style, string("axis lines* = ", axispos))
end
if framestyle == :zerolines
push!(style, string("extra ", letter, " ticks = 0"))
push!(style, string("extra ", letter, " tick labels = "))
push!(style, string("extra ", letter, " tick style = {grid = major, major grid style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_axis], 1.0), "}}"))
end
if !axis[:showaxis]
push!(style, "separate axis lines")
end
if !axis[:showaxis] || framestyle in (:zerolines, :grid, :none)
push!(style, string(letter, " axis line style = {draw opacity = 0}"))
else
push!(style, string(letter, " axis line style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_axis], 1.0), "}"))
end
# return the style list and KW args
style, kw
end
@@ -232,10 +478,14 @@ end
# ----------------------------------------------------------------
function _make_pgf_plot!(plt::Plot)
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()
@@ -243,29 +493,30 @@ function _make_pgf_plot!(plt::Plot)
for letter in (:x, :y, :z)
if letter != :z || is3d(sp)
axisstyle, axiskw = pgf_axis(sp, letter)
append!(style, axisstyle)
merge!(kw, axiskw)
for sty in axisstyle
push!(style, sty)
end
end
end
# 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,
width = $(width(bb).value)mm,
height = $(height(bb).value)mm,
yshift = $(round((total_height - (bottom(bb))).value, digits=2))mm,
axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])}
""")
kw[:width] = "$(width(bb).value)mm"
kw[:height] = "$(height(bb).value)mm"
if sp[:title] != ""
push!(style, "title = $(sp[:title])")
kw[:title] = "$(sp[:title])"
cstr, α = pgf_color(plot_color(sp[:titlefontcolor]))
push!(style, string("title style = {font = ", pgf_font(sp[:titlefontsize], pgf_thickness_scaling(sp)), ", color = ", cstr, ", draw opacity = ", α, ", rotate = ", sp[:titlefontrotation], "}"))
end
sp[:grid] && push!(style, "grid = major")
if sp[:aspect_ratio] in (1, :equal)
kw[:axisEqual] = "true"
end
@@ -274,28 +525,81 @@ function _make_pgf_plot!(plt::Plot)
if haskey(_pgfplots_legend_pos, legpos)
kw[:legendPos] = _pgfplots_legend_pos[legpos]
end
cstr, a = pgf_color(plot_color(sp[:background_color_legend]))
push!(style, string("legend style = {", pgf_linestyle(pgf_thickness_scaling(sp), sp[:foreground_color_legend], 1.0, "solid"), ",", "fill = $cstr,", "font = ", pgf_font(sp[:legendfontsize], pgf_thickness_scaling(sp)), "}"))
o = PGFPlots.Axis(; style = style, kw...)
if any(s[:seriestype] == :contour for s in series_list(sp))
kw[:view] = "{0}{90}"
kw[:colorbar] = !(sp[:colorbar] in (:none, :off, :hide, false))
elseif is3d(sp)
azim, elev = sp[:camera]
kw[:view] = "{$(azim)}{$(elev)}"
end
axisf = PGFPlots.Axis
if sp[:projection] == :polar
axisf = PGFPlots.PolarAxis
#make radial axis vertical
kw[:xmin] = 90
kw[:xmax] = 450
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, :linecolor)
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 = join(style, ","), kw...)
# add the series object to the PGFPlots.Axis
for series in series_list(sp)
push!(o, pgf_series(sp, series))
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), pgf_thickness_scaling(series))
end
end
# add the annotations
for ann in sp[:annotations]
pgf_add_annotation!(o, locate_annotation(sp, ann...)..., pgf_thickness_scaling(sp))
end
# add the PGFPlots.Axis to the list
push!(plt.o, o)
end
end
function _writemime(io::IO, mime::MIME"image/svg+xml", plt::Plot{PGFPlotsBackend})
_make_pgf_plot!(plt)
writemime(io, mime, plt.o)
function _show(io::IO, mime::MIME"image/svg+xml", plt::Plot{PGFPlotsBackend})
show(io, mime, plt.o)
end
function _writemime(io::IO, mime::MIME"application/pdf", plt::Plot{PGFPlotsBackend})
_make_pgf_plot!(plt)
function _show(io::IO, mime::MIME"application/pdf", plt::Plot{PGFPlotsBackend})
# prepare the object
pgfplt = PGFPlots.plot(plt.o)
@@ -304,15 +608,20 @@ function _writemime(io::IO, mime::MIME"application/pdf", plt::Plot{PGFPlotsBacke
PGFPlots.save(PGFPlots.PDF(fn), pgfplt)
# read it into io
write(io, readall(open(fn)))
write(io, read(open(fn), String))
# 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, read(open(fn), String))
end
function _display(plt::Plot{PGFPlotsBackend})
# prepare the object
_make_pgf_plot!(plt)
pgfplt = PGFPlots.plot(plt.o)
# save an svg
+523 -166
View File
@@ -1,11 +1,15 @@
# https://plot.ly/javascript/getting-started
supported_args(::PlotlyBackend) = merge_with_base_supported([
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "plotly.jl"))
end
const _plotly_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
:foreground_color_legend, :foreground_color_guide,
# :foreground_color_grid, :foreground_color_axis,
:foreground_color_grid, :foreground_color_axis,
:foreground_color_text, :foreground_color_border,
:foreground_color_title,
:label,
@@ -15,45 +19,76 @@ supported_args(::PlotlyBackend) = merge_with_base_supported([
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle,
:fillrange, :fillcolor, :fillalpha,
:bins,
:title, :title_location, :titlefont,
:title, :title_location,
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
:titlefontcolor,
:legendfontfamily, :legendfontsize, :legendfontcolor,
:tickfontfamily, :tickfontsize, :tickfontcolor,
:guidefontfamily, :guidefontsize, :guidefontcolor,
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :levels,
:grid, :gridalpha, :gridlinewidth,
:legend, :colorbar, :colorbar_title,
:marker_z, :fill_z, :line_z, :levels,
:ribbon, :quiver,
:orientation,
# :overwrite_figure,
:polar,
:normalize, :weights,
# :contours, :aspect_ratio,
# :contours,
:aspect_ratio,
:hover,
:inset_subplots,
:bar_width,
:clims,
:framestyle,
:tick_direction,
:camera,
:contour_labels,
])
supported_types(::PlotlyBackend) = [
:path, :scatter, :bar, :pie, :heatmap,
:contour, :surface, :path3d, :scatter3d, :shape, :scattergl,
const _plotly_seriestype = [
:path, :scatter, :pie, :heatmap,
:contour, :surface, :wireframe, :path3d, :scatter3d, :shape, :scattergl,
:straightline
]
supported_styles(::PlotlyBackend) = [:auto, :solid, :dash, :dot, :dashdot]
supported_markers(::PlotlyBackend) = [
const _plotly_style = [:auto, :solid, :dash, :dot, :dashdot]
const _plotly_marker = [
:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle,
:cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline
]
supported_scales(::PlotlyBackend) = [:identity, :log10]
const _plotly_scale = [:identity, :log10]
is_subplot_supported(::PlotlyBackend) = true
is_string_supported(::PlotlyBackend) = true
# is_string_supported(::PlotlyBackend) = true
const _plotly_framestyles = [:box, :axes, :zerolines, :grid, :none]
const _plotly_framestyle_defaults = Dict(:semi => :box, :origin => :zerolines)
function _plotly_framestyle(style::Symbol)
if style in _plotly_framestyles
return style
else
default_style = get(_plotly_framestyle_defaults, style, :axes)
warn("Framestyle :$style is not supported by Plotly and PlotlyJS. :$default_style was cosen instead.")
default_style
end
end
# --------------------------------------------------------------------------------------
function add_backend_string(::PlotlyBackend)
"""
Pkg.build("Plots")
"""
end
const _plotly_js_path = joinpath(dirname(@__FILE__), "..", "..", "deps", "plotly-latest.min.js")
const _plotly_js_path_remote = "https://cdn.plot.ly/plotly-latest.min.js"
function _initialize_backend(::PlotlyBackend; kw...)
@eval begin
import JSON
JSON._print(io::IO, state::JSON.State, dt::Union{Date,DateTime}) = print(io, '"', dt, '"')
_js_path = Pkg.dir("Plots", "deps", "plotly-latest.min.js")
_js_code = open(@compat(readstring), _js_path, "r")
_js_code = open(readstring, _plotly_js_path, "r")
# borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2
_js_script = """
@@ -84,6 +119,20 @@ end
# ----------------------------------------------------------------
const _plotly_legend_pos = KW(
:right => [1., 0.5],
:left => [0., 0.5],
:top => [0.5, 1.],
:bottom => [0.5, 0.],
:bottomleft => [0., 0.],
:bottomright => [1., 0.],
:topright => [1., 1.],
:topleft => [0., 1.]
)
plotly_legend_pos(pos::Symbol) = get(_plotly_legend_pos, pos, [1.,1.])
plotly_legend_pos(v::Tuple{S,T}) where {S<:Real, T<:Real} = v
function plotly_font(font::Font, color = font.color)
KW(
:family => font.family,
@@ -92,12 +141,13 @@ function plotly_font(font::Font, color = font.color)
)
end
function plotly_annotation_dict(x, y, val; xref="paper", yref="paper")
KW(
:text => val,
:xref => xref,
:x => x,
:yref => xref,
:yref => yref,
:y => y,
:showarrow => false,
)
@@ -108,7 +158,7 @@ function plotly_annotation_dict(x, y, ptxt::PlotText; xref="paper", yref="paper"
:font => plotly_font(ptxt.font),
:xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign,
:yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign,
:rotation => ptxt.font.rotation,
:rotation => -ptxt.font.rotation,
))
end
@@ -143,55 +193,97 @@ function plotly_scale(scale::Symbol)
end
end
function shrink_by(lo, sz, ratio)
amt = 0.5 * (1.0 - ratio) * sz
lo + amt, sz - 2amt
end
function plotly_apply_aspect_ratio(sp::Subplot, plotarea, pcts)
aspect_ratio = sp[:aspect_ratio]
if aspect_ratio != :none
if aspect_ratio == :equal
aspect_ratio = 1.0
end
xmin,xmax = axis_limits(sp[:xaxis])
ymin,ymax = axis_limits(sp[:yaxis])
want_ratio = ((xmax-xmin) / (ymax-ymin)) / aspect_ratio
parea_ratio = width(plotarea) / height(plotarea)
if want_ratio > parea_ratio
# need to shrink y
ratio = parea_ratio / want_ratio
pcts[2], pcts[4] = shrink_by(pcts[2], pcts[4], ratio)
elseif want_ratio < parea_ratio
# need to shrink x
ratio = want_ratio / parea_ratio
pcts[1], pcts[3] = shrink_by(pcts[1], pcts[3], ratio)
end
pcts
end
pcts
end
# this method gets the start/end in percentage of the canvas for this axis direction
function plotly_domain(sp::Subplot, letter)
figw, figh = sp.plt[:size]
pcts = bbox_to_pcts(sp.plotarea, figw*px, figh*px)
pcts = plotly_apply_aspect_ratio(sp, sp.plotarea, pcts)
i1,i2 = (letter == :x ? (1,3) : (2,4))
[pcts[i1], pcts[i1]+pcts[i2]]
end
function plotly_axis(axis::Axis, sp::Subplot)
function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
letter = axis[:letter]
framestyle = sp[:framestyle]
ax = KW(
:visible => framestyle != :none,
:title => axis[:guide],
:showgrid => sp[:grid],
:zeroline => false,
:showgrid => axis[:grid],
:gridcolor => rgba_string(plot_color(axis[:foreground_color_grid], axis[:gridalpha])),
:gridwidth => axis[:gridlinewidth],
:zeroline => framestyle == :zerolines,
:zerolinecolor => rgba_string(axis[:foreground_color_axis]),
:showline => framestyle in (:box, :axes) && axis[:showaxis],
:linecolor => rgba_string(plot_color(axis[:foreground_color_axis])),
:ticks => axis[:tick_direction] == :out ? "outside" : "inside",
:mirror => framestyle == :box,
:showticklabels => axis[:showaxis],
)
if letter in (:x,:y)
ax[:domain] = plotly_domain(sp, letter)
ax[:anchor] = "$(letter==:x ? :y : :x)$(plotly_subplot_index(sp))"
end
rot = axis[:rotation]
if rot != 0
ax[:tickangle] = rot
end
if !(axis[:ticks] in (nothing, :none))
ax[:titlefont] = plotly_font(axis[:guidefont], axis[:foreground_color_guide])
ax[:type] = plotly_scale(axis[:scale])
ax[:tickfont] = plotly_font(axis[:tickfont], axis[:foreground_color_text])
ax[:tickcolor] = rgba_string(axis[:foreground_color_border])
ax[:linecolor] = rgba_string(axis[:foreground_color_border])
# lims
lims = axis[:lims]
if lims != :auto && limsType(lims) == :limits
ax[:range] = lims
if is3d(sp)
# don't link 3d axes for synchronized interactivity
x_idx = y_idx = sp[:subplot_index]
else
x_idx, y_idx = plotly_link_indicies(plt, sp)
end
ax[:anchor] = "$(letter==:x ? "y$(y_idx)" : "x$(x_idx)")"
end
ax[:tickangle] = -axis[:rotation]
ax[:type] = plotly_scale(axis[:scale])
lims = axis_limits(axis)
if axis[:ticks] != :native || axis[:lims] != :auto
ax[:range] = map(scalefunc(axis[:scale]), lims)
end
if !(axis[:ticks] in (nothing, :none, false))
ax[:titlefont] = plotly_font(guidefont(axis))
ax[:tickfont] = plotly_font(tickfont(axis))
ax[:tickcolor] = framestyle in (:zerolines, :grid) || !axis[:showaxis] ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis])
ax[:linecolor] = rgba_string(axis[:foreground_color_axis])
# flip
if axis[:flip]
ax[:autorange] = "reversed"
ax[:range] = reverse(ax[:range])
end
# ticks
ticks = get_ticks(axis)
if ticks != :auto && ax[:type] != "-"
if axis[:ticks] != :native
ticks = get_ticks(axis)
ttype = ticksType(ticks)
if ttype == :ticks
ax[:tickmode] = "array"
@@ -206,6 +298,23 @@ function plotly_axis(axis::Axis, sp::Subplot)
ax[:showgrid] = false
end
ax
end
function plotly_polaraxis(axis::Axis)
ax = KW(
:visible => axis[:showaxis],
:showline => axis[:grid],
)
if axis[:letter] == :x
ax[:range] = rad2deg.(axis_limits(axis))
else
ax[:range] = axis_limits(axis)
ax[:orientation] = -90
end
ax
end
@@ -215,13 +324,15 @@ 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[]
for sp in plt.subplots
spidx = plotly_subplot_index(sp)
multiple_subplots = length(plt.subplots) > 1
for sp in plt.subplots
spidx = multiple_subplots ? sp[:subplot_index] : ""
x_idx, y_idx = multiple_subplots ? plotly_link_indicies(plt, sp) : ("", "")
# add an annotation for the title... positioned horizontally relative to plotarea,
# but vertically just below the top of the subplot bounding box
if sp[:title] != ""
@@ -235,38 +346,71 @@ function plotly_layout(plt::Plot)
0.5 * (left(bb) + right(bb))
end
titlex, titley = xy_mm_to_pcts(xmm, top(bbox(sp)), w*px, h*px)
titlefont = font(sp[:titlefont], :top, sp[:foreground_color_title])
push!(d_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], titlefont)))
title_font = font(titlefont(sp), :top)
push!(d_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], title_font)))
end
d_out[:plot_bgcolor] = rgba_string(sp[:background_color_inside])
# TODO: x/y axis tick values/labels
# set to supported framestyle
sp[:framestyle] = _plotly_framestyle(sp[:framestyle])
# if any(is3d, seriesargs)
if is3d(sp)
azim = sp[:camera][1] - 90 #convert azimuthal to match GR behaviour
theta = 90 - sp[:camera][2] #spherical coordinate angle from z axis
d_out[:scene] = KW(
Symbol("xaxis$spidx") => plotly_axis(sp[:xaxis], sp),
Symbol("yaxis$spidx") => plotly_axis(sp[:yaxis], sp),
Symbol("zaxis$spidx") => plotly_axis(sp[:zaxis], sp),
Symbol("xaxis$(spidx)") => plotly_axis(plt, sp[:xaxis], sp),
Symbol("yaxis$(spidx)") => plotly_axis(plt, sp[:yaxis], sp),
Symbol("zaxis$(spidx)") => plotly_axis(plt, sp[:zaxis], sp),
#2.6 multiplier set camera eye such that whole plot can be seen
:camera => KW(
:eye => KW(
:x => cosd(azim)*sind(theta)*2.6,
:y => sind(azim)*sind(theta)*2.6,
:z => cosd(theta)*2.6,
),
),
)
elseif ispolar(sp)
d_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp[:xaxis])
d_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp[:yaxis])
else
d_out[Symbol("xaxis$spidx")] = plotly_axis(sp[:xaxis], sp)
d_out[Symbol("yaxis$spidx")] = plotly_axis(sp[:yaxis], sp)
d_out[Symbol("xaxis$(x_idx)")] = plotly_axis(plt, sp[:xaxis], sp)
# don't allow yaxis to be reupdated/reanchored in a linked subplot
spidx == y_idx ? d_out[Symbol("yaxis$(y_idx)")] = plotly_axis(plt, sp[:yaxis], sp) : nothing
end
# legend
d_out[:showlegend] = sp[:legend] != :none
xpos,ypos = plotly_legend_pos(sp[:legend])
if sp[:legend] != :none
d_out[:legend] = KW(
:bgcolor => rgba_string(sp[:background_color_legend]),
:bordercolor => rgba_string(sp[:foreground_color_legend]),
:font => plotly_font(sp[:legendfont], sp[:foreground_color_legend]),
:font => plotly_font(legendfont(sp)),
:tracegroupgap => 0,
:x => xpos,
:y => ypos
)
end
# annotations
append!(d_out[:annotations], KW[plotly_annotation_dict(ann...; xref = "x$spidx", yref = "y$spidx") for ann in sp[:annotations]])
for ann in sp[:annotations]
append!(d_out[:annotations], KW[plotly_annotation_dict(locate_annotation(sp, ann...)...; xref = "x$(x_idx)", yref = "y$(y_idx)")])
end
# series_annotations
for series in series_list(sp)
anns = series[:series_annotations]
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y])
push!(d_out[:annotations], plotly_annotation_dict(
xi,
yi,
PlotText(str,fnt); xref = "x$(x_idx)", yref = "y$(y_idx)")
)
end
end
# # arrows
# for sargs in seriesargs
@@ -299,14 +443,24 @@ end
function plotly_colorscale(grad::ColorGradient, α)
[[grad.values[i], rgb_string(grad.colors[i])] for i in 1:length(grad.colors)]
[[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in 1:length(grad.colors)]
end
plotly_colorscale(c, α) = plotly_colorscale(cgrad(alpha=α), α)
function plotly_colorscale(c::AbstractVector{<:RGBA}, α)
if length(c) == 1
return [[0.0, rgba_string(plot_color(c[1], α))], [1.0, rgba_string(plot_color(c[1], α))]]
else
vals = range(0.0, stop=1.0, length=length(c))
return [[vals[i], rgba_string(plot_color(c[i], α))] for i in eachindex(c)]
end
end
# plotly_colorscale(c, alpha = nothing) = plotly_colorscale(cgrad(), alpha)
const _plotly_markers = KW(
:rect => "square",
:xcross => "x",
:x => "x",
:utriangle => "triangle-up",
:dtriangle => "triangle-down",
:star5 => "star-triangle-up",
@@ -314,9 +468,15 @@ const _plotly_markers = KW(
:hline => "line-ew",
)
function plotly_subplot_index(sp::Subplot)
spidx = sp[:subplot_index]
spidx == 1 ? "" : spidx
# find indicies of axes to which the supblot links to
function plotly_link_indicies(plt::Plot, sp::Subplot)
if plt[:link] in (:x, :y, :both)
x_idx = sp[:xaxis].sps[1][:subplot_index]
y_idx = sp[:yaxis].sps[1][:subplot_index]
else
x_idx = y_idx = sp[:subplot_index]
end
x_idx, y_idx
end
@@ -326,13 +486,59 @@ function plotly_close_shapes(x, y)
xs, ys = nansplit(x), nansplit(y)
for i=1:length(xs)
shape = Shape(xs[i], ys[i])
xs[i], ys[i] = shape_coords(shape)
xs[i], ys[i] = coords(shape)
end
nanvcat(xs), nanvcat(ys)
end
plotly_data(v) = collect(v)
plotly_data{R<:Rational}(v::AbstractArray{R}) = float(v)
function plotly_data(series::Series, letter::Symbol, data)
axis = series[:subplot][Symbol(letter, :axis)]
data = if axis[:ticks] == :native && data != nothing
plotly_native_data(axis, data)
else
data
end
if series[:seriestype] in (:heatmap, :contour, :surface, :wireframe)
plotly_surface_data(series, data)
else
plotly_data(data)
end
end
plotly_data(v) = v != nothing ? collect(v) : v
plotly_data(surf::Surface) = surf.surf
plotly_data(v::AbstractArray{R}) where {R<:Rational} = float(v)
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)
function plotly_native_data(axis::Axis, data::AbstractArray)
if !isempty(axis[:discrete_values])
construct_categorical_data(data, axis)
elseif axis[:formatter] in (datetimeformatter, dateformatter, timeformatter)
plotly_convert_to_datetime(data, axis[:formatter])
else
data
end
end
plotly_native_data(axis::Axis, a::Surface) = Surface(plotly_native_data(axis, a.surf))
function plotly_convert_to_datetime(x::AbstractArray, formatter::Function)
if formatter == datetimeformatter
map(xi -> replace(formatter(xi), "T", " "), x)
elseif formatter == dateformatter
map(xi -> string(formatter(xi), " 00:00:00"), x)
elseif formatter == timeformatter
map(xi -> string(Dates.Date(Dates.now()), " ", formatter(xi)), x)
else
error("Invalid DateTime formatter. Expected Plots.datetime/date/time formatter but got $formatter")
end
end
#ensures that a gradient is called if a single color is supplied where a gradient is needed (e.g. if a series recipe defines marker_z)
as_gradient(grad::ColorGradient, α) = grad
as_gradient(grad, α) = cgrad(alpha = α)
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
function plotly_series(plt::Plot, series::Series)
@@ -345,56 +551,78 @@ function plotly_series(plt::Plot, series::Series)
d_out = KW()
# these are the axes that the series should be mapped to
spidx = plotly_subplot_index(sp)
d_out[:xaxis] = "x$spidx"
d_out[:yaxis] = "y$spidx"
x_idx, y_idx = plotly_link_indicies(plt, sp)
d_out[:xaxis] = "x$(x_idx)"
d_out[:yaxis] = "y$(y_idx)"
d_out[:showlegend] = should_add_to_legend(series)
x, y = plotly_data(series[:x]), plotly_data(series[:y])
if st == :straightline
x, y = straightline_data(series)
z = series[:z]
else
x, y, z = series[:x], series[:y], series[:z]
end
x, y, z = (plotly_data(series, letter, data)
for (letter, data) in zip((:x, :y, :z), (x, y, z))
)
d_out[:name] = series[:label]
isscatter = st in (:scatter, :scatter3d, :scattergl)
hasmarker = isscatter || series[:markershape] != :none
hasline = st in (:path, :path3d)
hasline = st in (:path, :path3d, :straightline)
hasfillrange = st in (:path, :scatter, :scattergl, :straightline) &&
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
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"
d_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers"
else
hasline ? "lines" : "none"
end
if series[:fillrange] == true || series[:fillrange] == 0
d_out[:fill] = "tozeroy"
d_out[:fillcolor] = rgba_string(series[:fillcolor])
elseif !(series[:fillrange] in (false, nothing))
warn("fillrange ignored... plotly only supports filling to zero. fillrange: $(series[:fillrange])")
end
d_out[:x], d_out[:y] = x, y
elseif st == :bar
d_out[:type] = "bar"
d_out[:x], d_out[:y] = x, y
d_out[:orientation] = isvertical(series) ? "v" : "h"
if st in (:path, :scatter, :scattergl, :straightline, :path3d, :scatter3d)
return plotly_series_segments(series, d_out, x, y, z)
elseif st == :heatmap
x = heatmap_edges(x, sp[:xaxis][:scale])
y = heatmap_edges(y, sp[:yaxis][:scale])
d_out[:type] = "heatmap"
d_out[:x], d_out[:y], d_out[:z] = series[:x], series[:y], transpose_z(series, series[:z].surf, false)
d_out[:x], d_out[:y], d_out[:z] = x, y, z
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
d_out[:showscale] = hascolorbar(sp)
elseif st == :contour
d_out[:type] = "contour"
d_out[:x], d_out[:y], d_out[:z] = series[:x], series[:y], transpose_z(series, series[:z].surf, false)
d_out[:x], d_out[:y], d_out[:z] = x, y, z
# d_out[:showscale] = series[:colorbar] != :none
d_out[:ncontours] = series[:levels]
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines")
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
d_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
d_out[:showscale] = hascolorbar(sp)
elseif st in (:surface, :wireframe)
d_out[:type] = "surface"
d_out[:x], d_out[:y], d_out[:z] = series[:x], series[:y], transpose_z(series, series[:z].surf, false)
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
d_out[:x], d_out[:y], d_out[:z] = x, y, z
if st == :wireframe
d_out[:hidesurface] = true
wirelines = KW(
:show => true,
:color => rgba_string(plot_color(series[:linecolor], series[:linealpha])),
:highlightwidth => series[:linewidth],
)
d_out[:contours] = KW(:x => wirelines, :y => wirelines, :z => wirelines)
d_out[:showscale] = false
else
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
d_out[:opacity] = series[:fillalpha]
if series[:fill_z] != nothing
d_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
d_out[:showscale] = hascolorbar(sp)
end
elseif st == :pie
d_out[:type] = "pie"
@@ -402,16 +630,6 @@ function plotly_series(plt::Plot, series::Series)
d_out[:values] = y
d_out[:hoverinfo] = "label+percent+name"
elseif st in (:path3d, :scatter3d)
d_out[:type] = "scatter3d"
d_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers"
else
hasline ? "lines" : "none"
end
d_out[:x], d_out[:y] = x, y
d_out[:z] = plotly_data(series[:z])
else
warn("Plotly: seriestype $st isn't supported.")
return KW()
@@ -419,98 +637,235 @@ function plotly_series(plt::Plot, series::Series)
# add "marker"
if hasmarker
inds = eachindex(x)
d_out[:marker] = KW(
:symbol => get(_plotly_markers, series[:markershape], string(series[:markershape])),
# :opacity => series[:markeralpha],
:size => 2 * series[:markersize],
# :color => rgba_string(series[:markercolor]),
:size => 2 * _cycle(series[:markersize], inds),
:color => rgba_string.(plot_color.(get_markercolor.(series, inds), get_markeralpha.(series, inds))),
:line => KW(
:color => rgba_string(series[:markerstrokecolor]),
:width => series[:markerstrokewidth],
:color => rgba_string.(plot_color.(get_markerstrokecolor.(series, inds), get_markerstrokealpha.(series, inds))),
:width => _cycle(series[:markerstrokewidth], inds),
),
)
# gotta hack this (for now?) since plotly can't handle rgba values inside the gradient
d_out[:marker][:color] = if series[:marker_z] == nothing
rgba_string(series[:markercolor])
else
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
grad = series[:markercolor]
zmin, zmax = extrema(series[:marker_z])
[rgba_string(grad[(zi - zmin) / (zmax - zmin)]) for zi in series[:marker_z]]
end
end
# add "line"
if hasline
d_out[:line] = KW(
:color => rgba_string(series[:linecolor]),
:width => series[:linewidth],
:shape => if st == :steppre
"vh"
elseif st == :steppost
"hv"
else
"linear"
end,
:dash => string(series[:linestyle]),
# :dash => "solid",
)
end
plotly_polar!(d_out, series)
plotly_hover!(d_out, series[:hover])
[d_out]
return [d_out]
end
function plotly_series_shapes(plt::Plot, series::Series)
d_outs = []
segments = iter_segments(series)
d_outs = Vector{KW}(length(segments))
# TODO: create a d_out for each polygon
# x, y = series[:x], series[:y]
# these are the axes that the series should be mapped to
spidx = plotly_subplot_index(series[:subplot])
base_d = KW()
base_d[:xaxis] = "x$spidx"
base_d[:yaxis] = "y$spidx"
base_d[:name] = series[:label]
# base_d[:legendgroup] = series[:label]
x, y = plotly_data(series[:x]), plotly_data(series[:y])
for (i,rng) in enumerate(iter_segments(x,y))
x_idx, y_idx = plotly_link_indicies(plt, series[:subplot])
d_base = KW(
:xaxis => "x$(x_idx)",
:yaxis => "y$(y_idx)",
:name => series[:label],
:legendgroup => series[:label],
)
x, y = (plotly_data(series, letter, data)
for (letter, data) in zip((:x, :y), shape_data(series))
)
for (i,rng) in enumerate(segments)
length(rng) < 2 && continue
# to draw polygons, we actually draw lines with fill
d_out = merge(base_d, KW(
d_out = merge(d_base, KW(
:type => "scatter",
:mode => "lines",
:x => vcat(x[rng], x[rng[1]]),
:y => vcat(y[rng], y[rng[1]]),
:fill => "tozeroy",
:fillcolor => rgba_string(cycle(series[:fillcolor], i)),
:fillcolor => rgba_string(plot_color(get_fillcolor(series, i), get_fillalpha(series, i))),
))
if series[:markerstrokewidth] > 0
d_out[:line] = KW(
:color => rgba_string(cycle(series[:linecolor], i)),
:width => series[:linewidth],
:dash => string(series[:linestyle]),
:color => rgba_string(plot_color(get_linecolor(series, i), get_linealpha(series, i))),
:width => get_linewidth(series, i),
:dash => string(get_linestyle(series, i)),
)
end
d_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
plotly_polar!(d_out, series)
plotly_hover!(d_out, cycle(series[:hover], i))
push!(d_outs, d_out)
plotly_hover!(d_out, _cycle(series[:hover], i))
d_outs[i] = d_out
end
if series[:fill_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :fill))
elseif series[:line_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :line))
elseif series[:marker_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :marker))
end
d_outs
end
function plotly_series_segments(series::Series, d_base::KW, x, y, z)
st = series[:seriestype]
sp = series[:subplot]
isscatter = st in (:scatter, :scatter3d, :scattergl)
hasmarker = isscatter || series[:markershape] != :none
hasline = st in (:path, :path3d, :straightline)
hasfillrange = st in (:path, :scatter, :scattergl, :straightline) &&
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
segments = iter_segments(series)
d_outs = Vector{KW}((hasfillrange ? 2 : 1 ) * length(segments))
for (i,rng) in enumerate(segments)
!isscatter && length(rng) < 2 && continue
d_out = deepcopy(d_base)
d_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
d_out[:legendgroup] = series[:label]
# set the type
if st in (:path, :scatter, :scattergl, :straightline)
d_out[:type] = st==:scattergl ? "scattergl" : "scatter"
d_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers"
else
hasline ? "lines" : "none"
end
if series[:fillrange] == true || series[:fillrange] == 0 || isa(series[:fillrange], Tuple)
d_out[:fill] = "tozeroy"
d_out[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, i), get_fillalpha(series, i)))
elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real}, Real}
d_out[:fill] = "tonexty"
d_out[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, i), get_fillalpha(series, i)))
elseif !(series[:fillrange] in (false, nothing))
warn("fillrange ignored... plotly only supports filling to zero and to a vector of values. fillrange: $(series[:fillrange])")
end
d_out[:x], d_out[:y] = x[rng], y[rng]
elseif st in (:path3d, :scatter3d)
d_out[:type] = "scatter3d"
d_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers"
else
hasline ? "lines" : "none"
end
d_out[:x], d_out[:y], d_out[:z] = x[rng], y[rng], z[rng]
end
# add "marker"
if hasmarker
d_out[:marker] = KW(
:symbol => get(_plotly_markers, _cycle(series[:markershape], i), string(_cycle(series[:markershape], i))),
# :opacity => series[:markeralpha],
:size => 2 * _cycle(series[:markersize], i),
:color => rgba_string(plot_color(get_markercolor(series, i), get_markeralpha(series, i))),
:line => KW(
:color => rgba_string(plot_color(get_markerstrokecolor(series, i), get_markerstrokealpha(series, i))),
:width => _cycle(series[:markerstrokewidth], i),
),
)
end
# add "line"
if hasline
d_out[:line] = KW(
:color => rgba_string(plot_color(get_linecolor(series, i), get_linealpha(series, i))),
:width => get_linewidth(series, i),
:shape => if st == :steppre
"vh"
elseif st == :steppost
"hv"
else
"linear"
end,
:dash => string(get_linestyle(series, i)),
)
end
plotly_polar!(d_out, series)
plotly_hover!(d_out, _cycle(series[:hover], rng))
if hasfillrange
# if hasfillrange is true, return two dictionaries (one for original
# series, one for series being filled to) instead of one
d_out_fillrange = deepcopy(d_out)
d_out_fillrange[:showlegend] = false
# if fillrange is provided as real or tuple of real, expand to array
if typeof(series[:fillrange]) <: Real
series[:fillrange] = fill(series[:fillrange], length(rng))
elseif typeof(series[:fillrange]) <: Tuple
f1 = typeof(series[:fillrange][1]) <: Real ? fill(series[:fillrange][1], length(rng)) : series[:fillrange][1][rng]
f2 = typeof(series[:fillrange][2]) <: Real ? fill(series[:fillrange][2], length(rng)) : series[:fillrange][2][rng]
series[:fillrange] = (f1, f2)
end
if isa(series[:fillrange], AbstractVector)
d_out_fillrange[:y] = series[:fillrange][rng]
delete!(d_out_fillrange, :fill)
delete!(d_out_fillrange, :fillcolor)
else
# if fillrange is a tuple with upper and lower limit, d_out_fillrange
# is the series that will do the filling
fillrng = Tuple(series[:fillrange][i][rng] for i in 1:2)
d_out_fillrange[:x], d_out_fillrange[:y] = concatenate_fillrange(x[rng], fillrng)
d_out_fillrange[:line][:width] = 0
delete!(d_out, :fill)
delete!(d_out, :fillcolor)
end
d_outs[(2 * i - 1):(2 * i)] = [d_out_fillrange, d_out]
else
d_outs[i] = d_out
end
end
if series[:line_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :line))
elseif series[:fill_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :fill))
elseif series[:marker_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :marker))
end
d_outs
end
function plotly_colorbar_hack(series::Series, d_base::KW, sym::Symbol)
d_out = deepcopy(d_base)
cmin, cmax = get_clims(series[:subplot])
d_out[:showlegend] = false
d_out[:type] = is3d(series) ? :scatter3d : :scatter
d_out[:hoverinfo] = :none
d_out[:mode] = :markers
d_out[:x], d_out[:y] = [series[:x][1]], [series[:y][1]]
if is3d(series)
d_out[:z] = [series[:z][1]]
end
# 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)
d_out[:marker] = KW(
:size => 0,
:opacity => 0,
:color => [0.5],
:cmin => cmin,
:cmax => cmax,
:colorscale => plotly_colorscale(series[Symbol("$(sym)color")], 1),
:showscale => hascolorbar(series[:subplot]),
)
return d_out
end
function plotly_polar!(d_out::KW, series::Series)
# convert polar plots x/y to theta/radius
if ispolar(series[:subplot])
d_out[:t] = rad2deg(pop!(d_out, :x))
d_out[:r] = pop!(d_out, :y)
theta, r = filter_radial_data(pop!(d_out, :x), pop!(d_out, :y), axis_limits(series[:subplot][:yaxis]))
d_out[:t] = rad2deg.(theta)
d_out[:r] = r
end
end
@@ -525,19 +880,25 @@ function plotly_hover!(d_out::KW, hover)
end
# get a list of dictionaries, each representing the series params
function plotly_series_json(plt::Plot)
function plotly_series(plt::Plot)
slist = []
for series in plt.series_list
append!(slist, plotly_series(plt, series))
end
JSON.json(slist)
# JSON.json(map(series -> plotly_series(plt, series), plt.series_list))
slist
end
# get json string for a list of dictionaries, each representing the series params
plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt))
# ----------------------------------------------------------------
const _use_remote = Ref(false)
function html_head(plt::Plot{PlotlyBackend})
"<script src=\"$(Pkg.dir("Plots","deps","plotly-latest.min.js"))\"></script>"
jsfilename = _use_remote[] ? _plotly_js_path_remote : ("file://" * _plotly_js_path)
# "<script src=\"$(joinpath(dirname(@__FILE__),"..","..","deps","plotly-latest.min.js"))\"></script>"
"<script src=\"$jsfilename\"></script>"
end
function html_body(plt::Plot{PlotlyBackend}, style = nothing)
@@ -567,11 +928,7 @@ end
# ----------------------------------------------------------------
function _writemime(io::IO, ::MIME"image/png", plt::Plot{PlotlyBackend})
writemime_png_from_html(io, plt)
end
function _writemime(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyBackend})
function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend})
write(io, html_head(plt) * html_body(plt))
end
+70 -14
View File
@@ -1,16 +1,32 @@
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "plotlyjs.jl"))
end
# https://github.com/spencerlyon2/PlotlyJS.jl
supported_args(::PlotlyJSBackend) = supported_args(PlotlyBackend())
supported_types(::PlotlyJSBackend) = supported_types(PlotlyBackend())
supported_styles(::PlotlyJSBackend) = supported_styles(PlotlyBackend())
supported_markers(::PlotlyJSBackend) = supported_markers(PlotlyBackend())
supported_scales(::PlotlyJSBackend) = supported_scales(PlotlyBackend())
is_subplot_supported(::PlotlyJSBackend) = true
is_string_supported(::PlotlyJSBackend) = true
const _plotlyjs_attr = _plotly_attr
const _plotlyjs_seriestype = _plotly_seriestype
const _plotlyjs_style = _plotly_style
const _plotlyjs_marker = _plotly_marker
const _plotlyjs_scale = _plotly_scale
# --------------------------------------------------------------------------------------
function add_backend_string(::PlotlyJSBackend)
"""
if !Plots.is_installed("PlotlyJS")
Pkg.add("PlotlyJS")
end
if !Plots.is_installed("Rsvg")
Pkg.add("Rsvg")
end
import Blink
Blink.AtomShell.install()
"""
end
function _initialize_backend(::PlotlyJSBackend; kw...)
@eval begin
import PlotlyJS
@@ -27,7 +43,11 @@ end
function _create_backend_figure(plt::Plot{PlotlyJSBackend})
PlotlyJS.plot()
if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot)
PlotlyJS.SyncPlot(PlotlyJS.Plot(), current().o.view)
else
PlotlyJS.plot()
end
end
@@ -43,10 +63,15 @@ end
function _series_updated(plt::Plot{PlotlyJSBackend}, series::Series)
xsym, ysym = (ispolar(series) ? (:t,:r) : (:x,:y))
kw = KW(xsym => (series.d[:x],), ysym => (series.d[:y],))
z = series[:z]
if z != nothing
kw[:z] = (isa(z,Surface) ? transpose_z(series, series[:z].surf, false) : z,)
end
PlotlyJS.restyle!(
plt.o,
findfirst(plt.series_list, series),
KW(xsym => (series.d[:x],), ysym => (series.d[:y],))
kw
)
end
@@ -63,16 +88,47 @@ end
# ----------------------------------------------------------------
function _writemime(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend})
writemime(io, MIME("text/html"), plt.o)
function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend})
if isijulia() && !_use_remote[]
write(io, PlotlyJS.html_body(PlotlyJS.JupyterPlot(plt.o)))
else
show(io, MIME("text/html"), plt.o)
end
end
function _writemime(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend})
tmpfn = tempname() * ".png"
function plotlyjs_save_hack(io::IO, plt::Plot{PlotlyJSBackend}, ext::String)
tmpfn = tempname() * "." * ext
PlotlyJS.savefig(plt.o, tmpfn)
write(io, read(open(tmpfn)))
end
_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "svg")
_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "png")
_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
@require WebIO = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29" begin
function WebIO.render(plt::Plot{PlotlyJSBackend})
prepare_output(plt)
WebIO.render(plt.o)
end
end
function closeall(::PlotlyJSBackend)
if !isplotnull() && isa(current().o, PlotlyJS.SyncPlot)
close(current().o)
end
end
+458 -289
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -67,7 +67,7 @@ end
# "image/png" => "png",
# "application/postscript" => "ps",
# "image/svg+xml" => "svg"
function _writemime(io::IO, ::MIME"image/png", plt::Plot{[PkgName]Backend})
function _show(io::IO, ::MIME"image/png", plt::Plot{[PkgName]Backend})
end
# Display/show the plot (open a GUI window, or browser page, for example).
+88 -27
View File
@@ -1,7 +1,11 @@
# https://github.com/Evizero/UnicodePlots.jl
supported_args(::UnicodePlotsBackend) = merge_with_base_supported([
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "unicodeplots.jl"))
end
const _unicodeplots_attr = merge_with_base_supported([
:label,
:legend,
:seriescolor,
@@ -12,21 +16,30 @@ supported_args(::UnicodePlotsBackend) = merge_with_base_supported([
:title,
:guide, :lims,
])
supported_types(::UnicodePlotsBackend) = [
:path, :scatter,
:histogram2d
const _unicodeplots_seriestype = [
:path, :scatter, :straightline,
# :bar,
:shape,
:histogram2d,
:spy
]
supported_styles(::UnicodePlotsBackend) = [:auto, :solid]
supported_markers(::UnicodePlotsBackend) = [:none, :auto, :circle]
supported_scales(::UnicodePlotsBackend) = [:identity]
is_subplot_supported(::UnicodePlotsBackend) = true
const _unicodeplots_style = [:auto, :solid]
const _unicodeplots_marker = [:none, :auto, :circle]
const _unicodeplots_scale = [:identity]
# don't warn on unsupported... there's just too many warnings!!
warnOnUnsupported_args(pkg::UnicodePlotsBackend, d::KW) = nothing
warnOnUnsupported_args(::UnicodePlotsBackend, d::KW) = nothing
# --------------------------------------------------------------------------------------
function add_backend_string(::UnicodePlotsBackend)
"""
Pkg.add("UnicodePlots")
Pkg.build("UnicodePlots")
"""
end
function _initialize_backend(::UnicodePlotsBackend; kw...)
@eval begin
import UnicodePlots
@@ -36,9 +49,21 @@ end
# -------------------------------
const _canvas_type = Ref(:auto)
function _canvas_map()
KW(
:braille => UnicodePlots.BrailleCanvas,
:ascii => UnicodePlots.AsciiCanvas,
:block => UnicodePlots.BlockCanvas,
:dot => UnicodePlots.DotCanvas,
:density => UnicodePlots.DensityCanvas,
)
end
# do all the magic here... build it all at once, since we need to know about all the series at the very beginning
function rebuildUnicodePlot!(plt::Plot)
function rebuildUnicodePlot!(plt::Plot, width, height)
plt.o = []
for sp in plt.subplots
@@ -57,8 +82,33 @@ function rebuildUnicodePlot!(plt::Plot)
y = Float64[ylim[1]]
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
width, height = plt[:size]
canvas_type = isijulia() ? UnicodePlots.AsciiCanvas : UnicodePlots.BrailleCanvas
ct = _canvas_type[]
canvas_type = if ct == :auto
isijulia() ? UnicodePlots.AsciiCanvas : UnicodePlots.BrailleCanvas
else
_canvas_map()[ct]
end
# special handling for spy
if length(sp.series_list) == 1
series = sp.series_list[1]
if series[:seriestype] == :spy
push!(plt.o, UnicodePlots.spy(
series[:z].surf,
width = width,
height = height,
title = sp[:title],
canvas = canvas_type
))
continue
end
end
# # make it a bar canvas if plotting bar
# if any(series -> series[:seriestype] == :bar, series_list(sp))
# canvas_type = UnicodePlots.BarplotGraphics
# end
o = UnicodePlots.Plot(x, y, canvas_type;
width = width,
height = height,
@@ -92,28 +142,39 @@ function addUnicodeSeries!(o, d::KW, addlegend::Bool, xlim, ylim)
return
end
if st == :path
if st in (:path, :straightline)
func = UnicodePlots.lineplot!
elseif st == :scatter || d[:markershape] != :none
func = UnicodePlots.scatterplot!
# elseif st == :bar
# func = UnicodePlots.barplot!
elseif st == :shape
func = UnicodePlots.lineplot!
else
error("Linestyle $st not supported by UnicodePlots")
end
# get the series data and label
x, y = [collect(float(d[s])) for s in (:x, :y)]
x, y = if st == :straightline
straightline_data(d)
elseif st == :shape
shape_data(series)
else
[collect(float(d[s])) for s in (:x, :y)]
end
label = addlegend ? d[:label] : ""
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
color = d[:linecolor] in UnicodePlots.color_cycle ? d[:linecolor] : :auto
# add the series
x, y = Plots.unzip(collect(Base.Iterators.filter(xy->isfinite(xy[1])&&isfinite(xy[2]), zip(x,y))))
func(o, x, y; color = color, name = label)
end
# -------------------------------
# since this is such a hack, it's only callable using `png`... should error during normal `writemime`
# since this is such a hack, it's only callable using `png`... should error during normal `show`
function png(plt::AbstractPlot{UnicodePlotsBackend}, fn::AbstractString)
fn = addExtension(fn, "png")
@@ -122,7 +183,7 @@ function png(plt::AbstractPlot{UnicodePlotsBackend}, fn::AbstractString)
gui(plt)
# @osx_only begin
@compat @static if is_apple()
@static if Sys.isapple()
# BEGIN HACK
# wait while the plot gets drawn
@@ -143,21 +204,21 @@ end
# we don't do very much for subplots... just stack them vertically
function _update_plot_object(plt::Plot{UnicodePlotsBackend})
w, h = plt[:size]
plt.attr[:size] = div(w, 10), div(h, 20)
plt.attr[:color_palette] = [RGB(0,0,0)]
rebuildUnicodePlot!(plt)
function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend})
w, h = plt[:size]
plt.attr[:color_palette] = [RGB(0,0,0)]
rebuildUnicodePlot!(plt, div(w, 10), div(h, 20))
end
function _writemime(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
map(show, plt.o)
nothing
function _show(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
unicodeplots_rebuild(plt)
foreach(x -> show(io, x), plt.o)
nothing
end
function _display(plt::Plot{UnicodePlotsBackend})
map(show, plt.o)
nothing
unicodeplots_rebuild(plt)
map(show, plt.o)
nothing
end
+10 -7
View File
@@ -2,7 +2,9 @@
# NOTE: backend should implement `html_body` and `html_head`
# CREDIT: parts of this implementation were inspired by @joshday's PlotlyLocal.jl
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "web.jl"))
end
function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr, :window_title, "Plots.jl"))
"""
@@ -10,6 +12,7 @@ function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr
<html>
<head>
<title>$title</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
$(html_head(plt))
</head>
<body>
@@ -20,16 +23,16 @@ function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr
end
function open_browser_window(filename::AbstractString)
@compat @static if is_apple()
@static if Sys.isapple()
return run(`open $(filename)`)
end
@compat @static if is_linux()
@static if Sys.islinux() || Sys.isbsd() # Sys.isbsd() addition is as yet untested, but based on suggestion in https://github.com/JuliaPlots/Plots.jl/issues/681
return run(`xdg-open $(filename)`)
end
@compat @static if is_windows()
return run(`$(ENV["COMSPEC"]) /c start $(filename)`)
@static if Sys.iswindows()
return run(`$(ENV["COMSPEC"]) /c start "" "$(filename)"`)
end
warn("Unknown OS... cannot open browser window.")
@warn("Unknown OS... cannot open browser window.")
end
function write_temp_html(plt::AbstractPlot)
@@ -51,7 +54,7 @@ function html_to_png(html_fn, png_fn, w, h)
run(`wkhtmltoimage -f png -q --width $w --height $h --disable-smart-width $html_fn $png_fn`)
end
function writemime_png_from_html(io::IO, plt::AbstractPlot)
function show_png_from_html(io::IO, plt::AbstractPlot)
# write html to a temporary file
html_fn = write_temp_html(plt)
+335 -90
View File
@@ -1,7 +1,7 @@
typealias P2 FixedSizeArrays.Vec{2,Float64}
typealias P3 FixedSizeArrays.Vec{3,Float64}
const P2 = FixedSizeArrays.Vec{2,Float64}
const P3 = FixedSizeArrays.Vec{3,Float64}
nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b))
nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b))
@@ -11,7 +11,7 @@ compute_angle(v::P2) = (angle = atan2(v[2], v[1]); angle < 0 ? 2π - angle : ang
# -------------------------------------------------------------
immutable Shape
struct Shape
x::Vector{Float64}
y::Vector{Float64}
# function Shape(x::AVec, y::AVec)
@@ -22,22 +22,33 @@ immutable Shape
# end
# end
end
"""
Shape(x, y)
Shape(vertices)
Construct a polygon to be plotted
"""
Shape(verts::AVec) = Shape(unzip(verts)...)
Shape(s::Shape) = deepcopy(s)
get_xs(shape::Shape) = shape.x
get_ys(shape::Shape) = shape.y
vertices(shape::Shape) = collect(zip(shape.x, shape.y))
#deprecated
@deprecate shape_coords coords
function shape_coords(shape::Shape)
"return the vertex points from a Shape or Segments object"
function coords(shape::Shape)
shape.x, shape.y
end
function shape_coords(shapes::AVec{Shape})
function coords(shapes::AVec{Shape})
length(shapes) == 0 && return zeros(0), zeros(0)
xs = map(get_xs, shapes)
ys = map(get_ys, shapes)
x, y = map(copy, shape_coords(shapes[1]))
x, y = map(copy, coords(shapes[1]))
for shape in shapes[2:end]
nanappend!(x, shape.x)
nanappend!(y, shape.y)
@@ -47,7 +58,7 @@ end
"get an array of tuples of points on a circle with radius `r`"
function partialcircle(start_θ, end_θ, n = 20, r=1)
@compat(Tuple{Float64,Float64})[(r*cos(u),r*sin(u)) for u in linspace(start_θ, end_θ, n)]
Tuple{Float64,Float64}[(r*cos(u),r*sin(u)) for u in range(start_θ, stop=end_θ, length=n)]
end
"interleave 2 vectors into each other (like a zipper's teeth)"
@@ -57,7 +68,8 @@ function weave(x,y; ordering = Vector[x,y])
while !done
for o in ordering
try
push!(ret, shift!(o))
push!(ret, popfirst!(o))
catch
end
end
done = isempty(x) && isempty(y)
@@ -72,13 +84,13 @@ function makestar(n; offset = -0.5, radius = 1.0)
z2 = z1 + π / (n)
outercircle = partialcircle(z1, z1 + 2π, n+1, radius)
innercircle = partialcircle(z2, z2 + 2π, n+1, 0.4radius)
Shape(weave(outercircle, innercircle)[1:end-2])
Shape(weave(outercircle, innercircle))
end
"create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle"
function makeshape(n; offset = -0.5, radius = 1.0)
z = offset * π
Shape(partialcircle(z, z + 2π, n+1, radius)[1:end-1])
Shape(partialcircle(z, z + 2π, n+1, radius))
end
@@ -88,7 +100,7 @@ function makecross(; offset = -0.5, radius = 1.0)
outercircle = partialcircle(z1, z1 + 2π, 9, radius)
innercircle = partialcircle(z2, z2 + 2π, 5, 0.5radius)
Shape(weave(outercircle, innercircle,
ordering=Vector[outercircle,innercircle,outercircle])[1:end-2])
ordering=Vector[outercircle,innercircle,outercircle]))
end
@@ -110,6 +122,8 @@ const _shape_keys = Symbol[
:xcross,
:utriangle,
:dtriangle,
:rtriangle,
:ltriangle,
:pentagon,
:heptagon,
:octagon,
@@ -119,14 +133,18 @@ const _shape_keys = Symbol[
:star8,
:vline,
:hline,
:+,
:x,
]
const _shapes = KW(
:circle => makeshape(20),
:rect => makeshape(4, offset=-0.25),
:diamond => makeshape(4),
:utriangle => makeshape(3),
:dtriangle => makeshape(3, offset=0.5),
:utriangle => makeshape(3, offset=0.5),
:dtriangle => makeshape(3, offset=-0.5),
:rtriangle => makeshape(3, offset=0.0),
:ltriangle => makeshape(3, offset=1.0),
:pentagon => makeshape(5),
:hexagon => makeshape(6),
:heptagon => makeshape(7),
@@ -141,12 +159,15 @@ for n in [4,5,6,7,8]
_shapes[Symbol("star$n")] = makestar(n)
end
Shape(k::Symbol) = deepcopy(_shapes[k])
# -----------------------------------------------------------------------
# uses the centroid calculation from https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
"return the centroid of a Shape"
function center(shape::Shape)
x, y = shape_coords(shape)
x, y = coords(shape)
n = length(x)
A, Cx, Cy = 0.0, 0.0, 0.0
for i=1:n
@@ -163,8 +184,8 @@ function center(shape::Shape)
Cx / 6A, Cy / 6A
end
function Base.scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
sx, sy = shape_coords(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)
sx[i] = (sx[i] - cx) * x + cx
@@ -173,13 +194,14 @@ 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!(shape, x, y, c)
scale!(shapecopy, x, y, c)
end
"translate a Shape in space"
function translate!(shape::Shape, x::Real, y::Real = x)
sx, sy = shape_coords(shape)
sx, sy = coords(shape)
for i=1:length(sx)
sx[i] += x
sy[i] += y
@@ -189,7 +211,7 @@ end
function translate(shape::Shape, x::Real, y::Real = x)
shapecopy = deepcopy(shape)
translate!(shape, x, y)
translate!(shapecopy, x, y)
end
function rotate_x(x::Real, y::Real, Θ::Real, centerx::Real, centery::Real)
@@ -206,15 +228,17 @@ function rotate(x::Real, y::Real, θ::Real, c = center(shape))
end
function rotate!(shape::Shape, Θ::Real, c = center(shape))
x, y = shape_coords(shape)
x, y = coords(shape)
cx, cy = c
for i=1:length(x)
x[i] = rotate_x(x[i], y[i], Θ, cx, cy)
y[i] = rotate_y(x[i], y[i], Θ, cx, cy)
xi = rotate_x(x[i], y[i], Θ, cx, cy)
yi = rotate_y(x[i], y[i], Θ, cx, cy)
x[i], y[i] = xi, yi
end
shape
end
"rotate an object in space"
function rotate(shape::Shape, Θ::Real, c = center(shape))
shapecopy = deepcopy(shape)
rotate!(shapecopy, Θ, c)
@@ -223,7 +247,7 @@ end
# -----------------------------------------------------------------------
immutable Font
mutable struct Font
family::AbstractString
pointsize::Int
halign::Symbol
@@ -236,7 +260,7 @@ end
function font(args...)
# defaults
family = "Helvetica"
family = "sans-serif"
pointsize = 14
halign = :hcenter
valign = :vcenter
@@ -280,40 +304,79 @@ function font(args...)
Font(family, pointsize, halign, valign, rotation, color)
end
function scalefontsize(k::Symbol, factor::Number)
f = default(k)
f = round(Int, factor * f)
default(k, f)
end
"""
scalefontsizes(factor::Number)
Scales all **current** font sizes by `factor`. For example `scalefontsizes(1.1)` increases all current font sizes by 10%. To reset to initial sizes, use `scalefontsizes()`
"""
function scalefontsizes(factor::Number)
for k in (:titlefontsize, :guidefontsize, :tickfontsize, :legendfontsize)
scalefontsize(k, factor)
end
end
"""
scalefontsizes()
Resets font sizes to initial default values.
"""
function scalefontsizes()
for k in (:titlefontsize, :guidefontsize, :tickfontsize, :legendfontsize)
f = default(k)
if k in keys(_initial_fontsizes)
factor = f / _initial_fontsizes[k]
scalefontsize(k, 1.0/factor)
end
end
end
"Wrap a string with font info"
immutable PlotText
struct PlotText
str::AbstractString
font::Font
end
PlotText(str) = PlotText(string(str), font())
"""
text(string, args...)
Create a PlotText object wrapping a string with font info, for plot annotations
"""
text(t::PlotText) = t
text(t::PlotText, font::Font) = PlotText(t.str, font)
text(str::AbstractString, f::Font) = PlotText(str, f)
function text(str, args...)
PlotText(string(str), font(args...))
end
annotations(::Void) = []
annotations(anns::AVec) = anns
annotations(anns) = Any[anns]
Base.length(t::PlotText) = length(t.str)
# -----------------------------------------------------------------------
# -----------------------------------------------------------------------
immutable Stroke
struct Stroke
width
color
alpha
style
end
"""
stroke(args...; alpha = nothing)
Define the properties of the stroke used in plotting lines
"""
function stroke(args...; alpha = nothing)
width = nothing
color = nothing
style = nothing
width = 1
color = :black
style = :solid
for arg in args
T = typeof(arg)
@@ -326,6 +389,7 @@ function stroke(args...; alpha = nothing)
elseif T <: Symbol || T <: AbstractString
try
color = parse(Colorant, string(arg))
catch
end
elseif allAlphas(arg)
alpha = arg
@@ -340,15 +404,15 @@ function stroke(args...; alpha = nothing)
end
immutable Brush
struct Brush
size # fillrange, markersize, or any other sizey attribute
color
alpha
end
function brush(args...; alpha = nothing)
size = nothing
color = nothing
size = 1
color = :black
for arg in args
T = typeof(arg)
@@ -358,6 +422,7 @@ function brush(args...; alpha = nothing)
elseif T <: Symbol || T <: AbstractString
try
color = parse(Colorant, string(arg))
catch
end
elseif allAlphas(arg)
alpha = arg
@@ -373,22 +438,174 @@ end
# -----------------------------------------------------------------------
mutable struct SeriesAnnotations
strs::AbstractVector # the labels/names
font::Font
baseshape::Union{Shape, AbstractVector{Shape}, Nothing}
scalefactor::Tuple
end
function series_annotations(strs::AbstractVector, args...)
fnt = font()
shp = nothing
scalefactor = (1,1)
for arg in args
if isa(arg, Shape) || (isa(arg, AbstractVector) && eltype(arg) == Shape)
shp = arg
elseif isa(arg, Font)
fnt = arg
elseif isa(arg, Symbol) && haskey(_shapes, arg)
shp = _shapes[arg]
elseif isa(arg, Number)
scalefactor = (arg,arg)
elseif is_2tuple(arg)
scalefactor = arg
else
warn("Unused SeriesAnnotations arg: $arg ($(typeof(arg)))")
end
end
# if scalefactor != 1
# for s in get(shp)
# scale!(s, scalefactor, scalefactor, (0,0))
# end
# end
SeriesAnnotations(strs, fnt, shp, scalefactor)
end
series_annotations(anns::SeriesAnnotations) = anns
series_annotations(::Nothing) = nothing
function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
anns = series[:series_annotations]
# msw,msh = anns.scalefactor
# ms = series[:markersize]
# msw,msh = if isa(ms, AbstractVector)
# 1,1
# elseif is_2tuple(ms)
# ms
# else
# ms,ms
# end
# @show msw msh
if anns != nothing && anns.baseshape != nothing
# we use baseshape to overwrite the markershape attribute
# with a list of custom shapes for each
msw,msh = anns.scalefactor
msize = Float64[]
shapes = Vector{Shape}(length(anns.strs))
for i in eachindex(anns.strs)
str = _cycle(anns.strs,i)
# get the width and height of the string (in mm)
sw, sh = text_size(str, anns.font.pointsize)
# how much to scale the base shape?
# note: it's a rough assumption that the shape fills the unit box [-1,-1,1,1],
# so we scale the length-2 shape by 1/2 the total length
scalar = (backend() == PyPlotBackend() ? 1.7 : 1.0)
xscale = 0.5to_pixels(sw) * scalar
yscale = 0.5to_pixels(sh) * scalar
# we save the size of the larger direction to the markersize list,
# and then re-scale a copy of baseshape to match the w/h ratio
maxscale = max(xscale, yscale)
push!(msize, maxscale)
baseshape = _cycle(get(anns.baseshape),i)
shapes[i] = scale(baseshape, msw*xscale/maxscale, msh*yscale/maxscale, (0,0))
end
series[:markershape] = shapes
series[:markersize] = msize
end
return
end
mutable struct EachAnn
anns
x
y
end
Base.start(ea::EachAnn) = 1
Base.done(ea::EachAnn, i) = ea.anns == nothing || isempty(ea.anns.strs) || i > length(ea.y)
function Base.next(ea::EachAnn, i)
tmp = _cycle(ea.anns.strs,i)
str,fnt = if isa(tmp, PlotText)
tmp.str, tmp.font
else
tmp, ea.anns.font
end
((_cycle(ea.x,i), _cycle(ea.y,i), str, fnt), i+1)
end
annotations(::Nothing) = []
annotations(anns::AVec) = anns
annotations(anns) = Any[anns]
annotations(sa::SeriesAnnotations) = sa
# Expand arrays of coordinates, positions and labels into induvidual annotations
# and make sure labels are of type PlotText
function process_annotation(sp::Subplot, xs, ys, labs, font = font())
anns = []
labs = makevec(labs)
for i in 1:max(length(xs), length(ys), length(labs))
x, y, lab = _cycle(xs, i), _cycle(ys, i), _cycle(labs, i)
if lab == :auto
alphabet = "abcdefghijklmnopqrstuvwxyz"
push!(anns, (x, y, text(string("(", alphabet[sp[:subplot_index]], ")"), font)))
else
push!(anns, (x, y, isa(lab, PlotText) ? lab : text(lab, font)))
end
end
anns
end
function process_annotation(sp::Subplot, positions::Union{AVec{Symbol},Symbol}, labs, font = font())
anns = []
positions, labs = makevec(positions), makevec(labs)
for i in 1:max(length(positions), length(labs))
pos, lab = _cycle(positions, i), _cycle(labs, i)
pos = get(_positionAliases, pos, pos)
if lab == :auto
alphabet = "abcdefghijklmnopqrstuvwxyz"
push!(anns, (pos, text(string("(", alphabet[sp[:subplot_index]], ")"), font)))
else
push!(anns, (pos, isa(lab, PlotText) ? lab : text(lab, font)))
end
end
anns
end
# Give each annotation coordinates based on specified position
function locate_annotation(sp::Subplot, pos::Symbol, lab::PlotText)
position_multiplier = Dict{Symbol, Tuple{Float64,Float64}}(
:topleft => (0.1, 0.9),
:topcenter => (0.5, 0.9),
:topright => (0.9, 0.9),
:bottomleft => (0.1, 0.1),
:bottomcenter => (0.5, 0.1),
:bottomright => (0.9, 0.1),
)
xmin, xmax = ignorenan_extrema(sp[:xaxis])
ymin, ymax = ignorenan_extrema(sp[:yaxis])
x, y = (xmin, ymin).+ position_multiplier[pos].* (xmax - xmin, ymax - ymin)
(x, y, lab)
end
locate_annotation(sp::Subplot, x, y, label::PlotText) = (x, y, label)
# -----------------------------------------------------------------------
"type which represents z-values for colors and sizes (and anything else that might come up)"
immutable ZValues
struct ZValues
values::Vector{Float64}
zrange::Tuple{Float64,Float64}
end
function zvalues{T<:Real}(values::AVec{T}, zrange::Tuple{T,T} = (minimum(values), maximum(values)))
function zvalues(values::AVec{T}, zrange::Tuple{T,T} = (ignorenan_minimum(values), ignorenan_maximum(values))) where T<:Real
ZValues(collect(float(values)), map(Float64, zrange))
end
# -----------------------------------------------------------------------
abstract AbstractSurface
abstract type AbstractSurface end
"represents a contour or surface mesh"
immutable Surface{M<:AMat} <: AbstractSurface
struct Surface{M<:AMat} <: AbstractSurface
surf::M
end
@@ -399,8 +616,8 @@ 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.eltype{T}(surf::Surface{T}) = eltype(T)
Base.copy(surf::Surface) = Surface(copy(surf.surf))
Base.eltype(surf::Surface{T}) where {T} = eltype(T)
function expand_extrema!(a::Axis, surf::Surface)
ex = a[:extrema]
@@ -411,28 +628,69 @@ function expand_extrema!(a::Axis, surf::Surface)
end
"For the case of representing a surface as a function of x/y... can possibly avoid allocations."
immutable SurfaceFunction <: AbstractSurface
struct SurfaceFunction <: AbstractSurface
f::Function
end
# -----------------------------------------------------------------------
# # I don't want to clash with ValidatedNumerics, but this would be nice:
# ..(a::T, b::T) = (a,b)
struct Volume{T}
v::Array{T,3}
x_extents::Tuple{T,T}
y_extents::Tuple{T,T}
z_extents::Tuple{T,T}
end
default_extents(::Type{T}) where {T} = (zero(T), one(T))
function Volume(v::Array{T,3},
x_extents = default_extents(T),
y_extents = default_extents(T),
z_extents = default_extents(T)) where T
Volume(v, x_extents, y_extents, z_extents)
end
Base.Array(vol::Volume) = vol.v
for f in (:length, :size)
@eval Base.$f(vol::Volume, args...) = $f(vol.v, args...)
end
Base.copy(vol::Volume{T}) where {T} = Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents)
Base.eltype(vol::Volume{T}) where {T} = T
# -----------------------------------------------------------------------
# style is :open or :closed (for now)
immutable Arrow
struct Arrow
style::Symbol
side::Symbol # :head (default), :tail, or :both
headlength::Float64
headwidth::Float64
end
"""
arrow(args...)
Define arrowheads to apply to lines - args are `style` (`:open` or `:closed`),
`side` (`:head`, `:tail` or `:both`), `headlength` and `headwidth`
"""
function arrow(args...)
style = :simple
side = :head
headlength = 0.3
headwidth = 0.3
setlength = false
for arg in args
T = typeof(arg)
if T == Symbol
style = arg
if arg in (:head, :tail, :both)
side = arg
else
style = arg
end
elseif T <: Number
# first we apply to both, but if there's more, then only change width after the first number
headwidth = Float64(arg)
@@ -446,7 +704,7 @@ function arrow(args...)
warn("Skipped arrow arg $arg")
end
end
Arrow(style, headlength, headwidth)
Arrow(style, side, headlength, headwidth)
end
@@ -465,58 +723,45 @@ function add_arrows(func::Function, x::AVec, y::AVec)
end
end
# -----------------------------------------------------------------------
type BezierCurve{T <: FixedSizeArrays.Vec}
control_points::Vector{T}
"Represents data values with formatting that should apply to the tick labels."
struct Formatted{T}
data::T
formatter::Function
end
@compat function (bc::BezierCurve)(t::Real)
p = zero(P2)
n = length(bc.control_points)-1
for i in 0:n
p += bc.control_points[i+1] * binomial(n, i) * (1-t)^(n-i) * t^i
end
p
# -----------------------------------------------------------------------
"create a BezierCurve for plotting"
mutable struct BezierCurve{T <: FixedSizeArrays.Vec}
control_points::Vector{T}
end
Base.mean(x::Real, y::Real) = 0.5*(x+y)
Base.mean{N,T<:Real}(ps::FixedSizeArrays.Vec{N,T}...) = sum(ps) / length(ps)
function (bc::BezierCurve)(t::Real)
p = zero(P2)
n = length(bc.control_points)-1
for i in 0:n
p += bc.control_points[i+1] * binomial(n, i) * (1-t)^(n-i) * t^i
end
p
end
curve_points(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, linspace(range..., n))
# mean(x::Real, y::Real) = 0.5*(x+y) #commented out as I cannot see this used anywhere and it overwrites a Base method with different functionality
# mean{N,T<:Real}(ps::FixedSizeArrays.Vec{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array
@deprecate curve_points coords
coords(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, range(range..., stop=n, length=50))
# build a BezierCurve which leaves point p vertically upwards and arrives point q vertically upwards.
# may create a loop if necessary. Assumes the view is [0,1]
function directed_curve(p::P2, q::P2; xview = 0:1, yview = 0:1)
mn = mean(p, q)
diff = q - p
minx, maxx = minimum(xview), maximum(xview)
miny, maxy = minimum(yview), maximum(yview)
diffpct = P2(diff[1] / (maxx - minx),
diff[2] / (maxy - miny))
# these points give the initial/final "rise"
# vertical_offset = P2(0, (maxy - miny) * max(0.03, min(abs(0.5diffpct[2]), 1.0)))
vertical_offset = P2(0, max(0.15, 0.5norm(diff)))
upper_control = p + vertical_offset
lower_control = q - vertical_offset
# try to figure out when to loop around vs just connecting straight
# TODO: choose loop direction based on sign of p[1]??
# x_close_together = abs(diffpct[1]) <= 0.05
p_is_higher = diff[2] <= 0
inside_control_points = if p_is_higher
# add curve points which will create a loop
sgn = mn[1] < 0.5 * (maxx + minx) ? -1 : 1
inside_offset = P2(0.3 * (maxx - minx), 0)
additional_offset = P2(sgn * diff[1], 0) # make it even loopier
[upper_control + sgn * (inside_offset + max(0, additional_offset)),
lower_control + sgn * (inside_offset + max(0, -additional_offset))]
else
[]
function directed_curve(args...; kw...)
error("directed_curve has been moved to PlotRecipes")
end
BezierCurve([p, upper_control, inside_control_points..., lower_control, q])
function extrema_plus_buffer(v, buffmult = 0.2)
vmin,vmax = ignorenan_extrema(v)
vdiff = vmax-vmin
buffer = vdiff * buffmult
vmin - buffer, vmax + buffer
end
@@ -2,7 +2,7 @@
# https://github.com/bokeh/Bokeh.jl
supported_args(::BokehBackend) = merge_with_base_supported([
supported_attrs(::BokehBackend) = merge_with_base_supported([
# :annotations,
# :axis,
# :background_color,
@@ -72,7 +72,7 @@ is_subplot_supported(::BokehBackend) = false
function _initialize_backend(::BokehBackend; kw...)
@eval begin
warn("Bokeh is no longer supported... many features will likely be broken.")
@warn("Bokeh is no longer supported... many features will likely be broken.")
import Bokeh
export Bokeh
end
@@ -194,9 +194,9 @@ end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::AbstractPlot{BokehBackend})
function Base.show(io::IO, ::MIME"image/png", plt::AbstractPlot{BokehBackend})
# TODO: write a png to io
warn("mime png not implemented")
@warn("mime png not implemented")
end
function Base.display(::PlotsDisplay, plt::Plot{BokehBackend})
@@ -2,7 +2,7 @@
# https://github.com/dcjones/Gadfly.jl
supported_args(::GadflyBackend) = merge_with_base_supported([
supported_attrs(::GadflyBackend) = merge_with_base_supported([
:annotations,
:background_color, :foreground_color, :color_palette,
:group, :label, :seriestype,
@@ -41,7 +41,7 @@ function _initialize_backend(::GadflyBackend; kw...)
@eval begin
import Gadfly, Compose
export Gadfly, Compose
include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
include(joinpath(dirname(@__FILE__), "gadfly_shapes.jl"))
end
end
@@ -244,7 +244,7 @@ function addToGadflyLegend(plt::Plot, d::KW)
# add the legend if needed
if all(g -> !isa(g, Gadfly.Guide.ManualColorKey), gplt.guides)
unshift!(gplt.guides, Gadfly.Guide.manual_color_key("", @compat(AbstractString)[], Color[]))
pushfirst!(gplt.guides, Gadfly.Guide.manual_color_key("", AbstractString[], Color[]))
end
# now add the series to the legend
@@ -334,8 +334,8 @@ end
# # create a list of vertices that go: [x1,x2,x2,x3,x3, ... ,xi,xi, ... xn,xn] (same for y)
# # then the vector passed to the "color" keyword should be a vector: [1,1,2,2,3,3,4,4, ..., i,i, ... , n,n]
# csindices = Int[mod1(i,length(cscheme.v)) for i in 1:length(d[:y])]
# cs = collect(repmat(csindices', 2, 1))[1:end-1]
# grp = collect(repmat((1:length(d[:y]))', 2, 1))[1:end-1]
# cs = collect(repeat(csindices', 2, 1))[1:end-1]
# grp = collect(repeat((1:length(d[:y]))', 2, 1))[1:end-1]
# d[:x], d[:y] = map(createSegments, (d[:x], d[:y]))
# colorgroup = [(:linecolor, cs), (:group, grp)]
@@ -456,7 +456,7 @@ function updateGadflyAxisFlips(gplt, d::KW, xlims, ylims, xfunc, yfunc)
end
function findGuideAndSet(gplt, t::DataType, args...; kw...) #s::@compat(AbstractString))
function findGuideAndSet(gplt, t::DataType, args...; kw...)
for (i,guide) in enumerate(gplt.guides)
if isa(guide, t)
gplt.guides[i] = t(args...; kw...)
@@ -537,7 +537,7 @@ end
# ----------------------------------------------------------------
function createGadflyAnnotationObject(x, y, val::@compat(AbstractString))
function createGadflyAnnotationObject(x, y, val::AbstractString)
Gadfly.Guide.annotation(Compose.compose(
Compose.context(),
Compose.text(x, y, val)
@@ -558,7 +558,7 @@ function createGadflyAnnotationObject(x, y, txt::PlotText)
))
end
function _add_annotations{X,Y,V}(plt::Plot{GadflyBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations(plt::Plot{GadflyBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
for ann in anns
push!(plt.o.guides, createGadflyAnnotationObject(ann...))
end
@@ -614,7 +614,7 @@ function getxy(plt::Plot{GadflyBackend}, i::Integer)
mapping[:x], mapping[:y]
end
function setxy!{X,Y}(plt::Plot{GadflyBackend}, xy::Tuple{X,Y}, i::Integer)
function setxy!(plt::Plot{GadflyBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
for mapping in getGadflyMappings(plt, i)
mapping[:x], mapping[:y] = xy
end
@@ -677,7 +677,7 @@ setGadflyDisplaySize(plt::Plot) = setGadflyDisplaySize(plt.attr[:size]...)
# -------------------------------------------------------------------------
function dowritemime{P<:Union{GadflyBackend,ImmerseBackend}}(io::IO, func, plt::AbstractPlot{P})
function doshow(io::IO, func, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend}
gplt = getGadflyContext(plt)
setGadflyDisplaySize(plt)
Gadfly.draw(func(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
@@ -692,9 +692,9 @@ getGadflyWriteFunc(::MIME"application/x-tex") = Gadfly.PGF
getGadflyWriteFunc(m::MIME) = error("Unsupported in Gadfly/Immerse: ", m)
for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript", MIME"application/x-tex")
@eval function Base.writemime{P<:Union{GadflyBackend,ImmerseBackend}}(io::IO, ::$mime, plt::AbstractPlot{P})
@eval function Base.show(io::IO, ::$mime, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend}
func = getGadflyWriteFunc($mime())
dowritemime(io, func, plt)
doshow(io, func, plt)
end
end
@@ -2,7 +2,7 @@
# Geometry which displays arbitrary shapes at given (x, y) positions.
# note: vertices is a list of shapes
immutable ShapeGeometry <: Gadfly.GeometryElement
struct ShapeGeometry <: Gadfly.GeometryElement
vertices::AbstractVector #{Tuple{Float64,Float64}}
tag::Symbol
@@ -84,7 +84,7 @@ function make_polygon(geom::ShapeGeometry, xs::AbstractArray, ys::AbstractArray,
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in cycle(geom.vertices, i)]
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in _cycle(geom.vertices, i)]
end
Gadfly.polygon(polys, geom.tag)
end
@@ -1,7 +1,7 @@
# https://github.com/JuliaGraphics/Immerse.jl
supported_args(::ImmerseBackend) = supported_args(GadflyBackend())
supported_attrs(::ImmerseBackend) = supported_attrs(GadflyBackend())
supported_types(::ImmerseBackend) = supported_types(GadflyBackend())
supported_styles(::ImmerseBackend) = supported_styles(GadflyBackend())
supported_markers(::ImmerseBackend) = supported_markers(GadflyBackend())
@@ -14,7 +14,7 @@ function _initialize_backend(::ImmerseBackend; kw...)
@eval begin
import Immerse, Gadfly, Compose, Gtk
export Immerse, Gadfly, Compose, Gtk
include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
include(joinpath(dirname(@__FILE__), "gadfly_shapes.jl"))
end
end
@@ -61,7 +61,7 @@ end
# ----------------------------------------------------------------
function _add_annotations{X,Y,V}(plt::Plot{ImmerseBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations(plt::Plot{ImmerseBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
for ann in anns
push!(getGadflyContext(plt).guides, createGadflyAnnotationObject(ann...))
end
@@ -76,7 +76,7 @@ function getxy(plt::Plot{ImmerseBackend}, i::Integer)
mapping[:x], mapping[:y]
end
function setxy!{X,Y}(plt::Plot{ImmerseBackend}, xy::Tuple{X,Y}, i::Integer)
function setxy!(plt::Plot{ImmerseBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
for mapping in getGadflyMappings(plt, i)
mapping[:x], mapping[:y] = xy
end
@@ -2,7 +2,7 @@
# https://github.com/tbreloff/Qwt.jl
supported_args(::QwtBackend) = merge_with_base_supported([
supported_attrs(::QwtBackend) = merge_with_base_supported([
:annotations,
:linecolor,
:fillrange,
@@ -31,7 +31,7 @@ is_subplot_supported(::QwtBackend) = true
function _initialize_backend(::QwtBackend; kw...)
@eval begin
warn("Qwt is no longer supported... many features will likely be broken.")
@warn("Qwt is no longer supported... many features will likely be broken.")
import Qwt
export Qwt
end
@@ -39,7 +39,7 @@ end
# -------------------------------
@compat const _qwtAliases = KW(
const _qwtAliases = KW(
:bins => :heatmap_n,
:fillrange => :fillto,
:linewidth => :width,
@@ -133,7 +133,7 @@ function updateLimsAndTicks(plt::Plot{QwtBackend}, d::KW, isx::Bool)
w = plt.o.widget
axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft]
if typeof(lims) <: @compat(Union{Tuple,AVec}) && length(lims) == 2
if typeof(lims) <: Union{Tuple,AVec} && length(lims) == 2
if isx
plt.o.autoscale_x = false
else
@@ -142,7 +142,7 @@ function updateLimsAndTicks(plt::Plot{QwtBackend}, d::KW, isx::Bool)
w[:setAxisScale](axisid, lims...)
end
if typeof(ticks) <: Range
if typeof(ticks) <: AbstractRange
if isx
plt.o.autoscale_x = false
else
@@ -211,14 +211,14 @@ function createQwtAnnotation(plt::Plot, x, y, val::PlotText)
marker[:attach](plt.o.widget)
end
function createQwtAnnotation(plt::Plot, x, y, val::@compat(AbstractString))
function createQwtAnnotation(plt::Plot, x, y, val::AbstractString)
marker = Qwt.QWT.QwtPlotMarker()
marker[:setValue](x, y)
marker[:setLabel](Qwt.QWT.QwtText(val))
marker[:attach](plt.o.widget)
end
function _add_annotations{X,Y,V}(plt::Plot{QwtBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations(plt::Plot{QwtBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
for ann in anns
createQwtAnnotation(plt, ann...)
end
@@ -233,7 +233,7 @@ function getxy(plt::Plot{QwtBackend}, i::Int)
series.x, series.y
end
function setxy!{X,Y}(plt::Plot{QwtBackend}, xy::Tuple{X,Y}, i::Integer)
function setxy!(plt::Plot{QwtBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
series = plt.o.lines[i]
series.x, series.y = xy
plt
@@ -242,8 +242,6 @@ end
# -------------------------------
# savepng(::QwtBackend, plt::AbstractPlot, fn::@compat(AbstractString), args...) = Qwt.savepng(plt.o, fn)
# -------------------------------
# # create the underlying object (each backend will do this differently)
@@ -282,13 +280,13 @@ end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::Plot{QwtBackend})
function Base.show(io::IO, ::MIME"image/png", plt::Plot{QwtBackend})
Qwt.refresh(plt.o)
Qwt.savepng(plt.o, "/tmp/dfskjdhfkh.png")
write(io, readall("/tmp/dfskjdhfkh.png"))
end
# function Base.writemime(io::IO, ::MIME"image/png", subplt::Subplot{QwtBackend})
# function Base.show(io::IO, ::MIME"image/png", subplt::Subplot{QwtBackend})
# for plt in subplt.plts
# Qwt.refresh(plt.o)
# end
@@ -3,7 +3,7 @@
# credit goes to https://github.com/jverzani for contributing to the first draft of this backend implementation
supported_args(::WinstonBackend) = merge_with_base_supported([
supported_attrs(::WinstonBackend) = merge_with_base_supported([
:annotations,
:linecolor,
:fillrange,
@@ -34,7 +34,7 @@ is_subplot_supported(::WinstonBackend) = false
function _initialize_backend(::WinstonBackend; kw...)
@eval begin
# ENV["WINSTON_OUTPUT"] = "gtk"
warn("Winston is no longer supported... many features will likely be broken.")
@warn("Winston is no longer supported... many features will likely be broken.")
import Winston, Gtk
export Winston, Gtk
end
@@ -44,13 +44,13 @@ end
## dictionaries for conversion of Plots.jl names to Winston ones.
@compat const winston_linestyle = KW(:solid=>"solid",
const winston_linestyle = KW(:solid=>"solid",
:dash=>"dash",
:dot=>"dotted",
:dashdot=>"dotdashed"
)
@compat const winston_marker = KW(:none=>".",
const winston_marker = KW(:none=>".",
:rect => "square",
:circle=>"circle",
:diamond=>"diamond",
@@ -185,7 +185,7 @@ end
# ----------------------------------------------------------------
@compat const _winstonNames = KW(
const _winstonNames = KW(
:xlims => :xrange,
:ylims => :yrange,
:xscale => :xlog,
@@ -213,11 +213,11 @@ end
# ----------------------------------------------------------------
function createWinstonAnnotationObject(plt::Plot{WinstonBackend}, x, y, val::@compat(AbstractString))
function createWinstonAnnotationObject(plt::Plot{WinstonBackend}, x, y, val::AbstractString)
Winston.text(x, y, val)
end
function _add_annotations{X,Y,V}(plt::Plot{WinstonBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations(plt::Plot{WinstonBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
for ann in anns
createWinstonAnnotationObject(plt, ann...)
end
@@ -238,10 +238,10 @@ function addWinstonLegend(plt::Plot, wplt)
end
end
function Base.writemime(io::IO, ::MIME"image/png", plt::AbstractPlot{WinstonBackend})
function Base.show(io::IO, ::MIME"image/png", plt::AbstractPlot{WinstonBackend})
window, canvas, wplt = getWinstonItems(plt)
addWinstonLegend(plt, wplt)
writemime(io, "image/png", wplt)
show(io, "image/png", wplt)
end
+1 -1
View File
@@ -19,7 +19,7 @@
# work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
function sample_evenly(v::AVec, n::Integer = length(v))
idx = Int[round(Int, x) for x in linspace(1, length(v), n)]
idx = Int[round(Int, x) for x in range(1, stop=length(v), length=n)]
v[idx]
end
+25 -25
View File
@@ -1,5 +1,5 @@
abstract ColorScheme
abstract type ColorScheme end
Base.getindex(scheme::ColorScheme, i::Integer) = getColor(scheme, i)
@@ -13,15 +13,15 @@ function cgrad(arg, values = nothing; alpha = nothing, scale = :identity)
values = if values != nothing
values
elseif scale in (:log, :log10)
log10(linspace(1,10,30))
log10(range(1, stop=10, length=30))
elseif scale == :log2
log2(linspace(1,2,30))
log2(range(1, stop=2, length=30))
elseif scale == :ln
log(linspace(1,pi,30))
log(range(1, stop=pi, length=30))
elseif scale in (:exp, :exp10)
(exp10(linspace(0,1,30)) - 1) / 9
(exp10(range(0, stop=1, length=30)) - 1) / 9
else
linspace(0, 1, length(colors))
range(0, stop=1, length=length(colors))
end
ColorGradient(colors, values)
end
@@ -34,9 +34,9 @@ getColorVector(scheme::ColorScheme) = [getColor(scheme)]
colorscheme(scheme::ColorScheme) = scheme
colorscheme(s::AbstractString; kw...) = colorscheme(Symbol(s); kw...)
colorscheme(s::Symbol; kw...) = haskey(_gradients, s) ? ColorGradient(s; kw...) : ColorWrapper(convertColor(s); kw...)
colorscheme{T<:Real}(s::Symbol, vals::AVec{T}; kw...) = ColorGradient(s, vals; kw...)
colorscheme(s::Symbol, vals::AVec{T}; kw...) where {T<:Real} = ColorGradient(s, vals; kw...)
colorscheme(cs::AVec, vs::AVec; kw...) = ColorGradient(cs, vs; kw...)
colorscheme{T<:Colorant}(cs::AVec{T}; kw...) = ColorGradient(cs; kw...)
colorscheme(cs::AVec{T}; kw...) where {T<:Colorant} = ColorGradient(cs; kw...)
colorscheme(f::Function; kw...) = ColorFunction(f; kw...)
colorscheme(v::AVec; kw...) = ColorVector(v; kw...)
colorscheme(m::AMat; kw...) = size(m,1) == 1 ? map(c->colorscheme(c; kw...), m) : [colorscheme(m[:,i]; kw...) for i in 1:size(m,2)]'
@@ -51,7 +51,7 @@ convertColor(c::Symbol) = parse(Colorant, string(c))
convertColor(c::Colorant) = c
convertColor(cvec::AbstractVector) = map(convertColor, cvec)
convertColor(c::ColorScheme) = c
convertColor(v::Void) = RGBA(0,0,0,0)
convertColor(v::Nothing) = RGBA(0,0,0,0)
convertColor(b::Bool) = b ? RGBA(0,0,0,1) : RGBA(0,0,0,0)
function convertColor(c, α::Real)
@@ -59,7 +59,7 @@ function convertColor(c, α::Real)
RGBA(RGB(getColor(c)), α)
end
convertColor(cs::AVec, α::Real) = map(c -> convertColor(c, α), cs)
convertColor(c, α::Void) = convertColor(c)
convertColor(c, α::Nothing) = convertColor(c)
# backup... try to convert
getColor(c) = convertColor(c)
@@ -98,7 +98,7 @@ const _gradients = KW(
:lighttest => map(c -> lighten(c, 0.3), _testColors),
)
function register_gradient_colors{C<:Colorant}(name::Symbol, colors::AVec{C})
function register_gradient_colors(name::Symbol, colors::AVec{C}) where C<:Colorant
_gradients[name] = colors
end
@@ -109,11 +109,11 @@ default_gradient() = ColorGradient(:inferno)
# --------------------------------------------------------------
"Continuous gradient between values. Wraps a list of bounding colors and the values they represent."
immutable ColorGradient <: ColorScheme
struct ColorGradient <: ColorScheme
colors::Vector
values::Vector
function ColorGradient{S<:Real}(cs::AVec, vals::AVec{S} = linspace(0, 1, length(cs)); alpha = nothing)
function ColorGradient(cs::AVec, vals::AVec{S} = range(0, stop=1, length=length(cs)); alpha = nothing) where S<:Real
if length(cs) == length(vals)
return new(convertColor(cs,alpha), collect(vals))
end
@@ -124,9 +124,9 @@ immutable ColorGradient <: ColorScheme
# new(convertColor(cs,alpha), vs)
# interpolate the colors for each value
vals = merge(linspace(0, 1, length(cs)), vals)
vals = merge(range(0, stop=1, length=length(cs)), vals)
grad = ColorGradient(cs)
cs = [getColorZ(grad, z) for z in linspace(0, 1, length(vals))]
cs = [getColorZ(grad, z) for z in range(0, stop=1, length=length(vals))]
new(convertColor(cs, alpha), vals)
end
end
@@ -138,11 +138,11 @@ Base.getindex(cs::ColorGradient, z::Number) = getColorZ(cs, z)
# create a gradient from a symbol (blues, reds, etc) and vector of boundary values
function ColorGradient{T<:Real}(s::Symbol, vals::AVec{T} = 0:0; kw...)
function ColorGradient(s::Symbol, vals::AVec{T} = 0:0; kw...) where T<:Real
haskey(_gradients, s) || error("Invalid gradient symbol. Choose from: ", sort(collect(keys(_gradients))))
cs = _gradients[s]
if vals == 0:0
vals = linspace(0, 1, length(cs))
vals = range(0, stop=1, length=length(cs))
end
ColorGradient(cs, vals; kw...)
end
@@ -208,7 +208,7 @@ end
# --------------------------------------------------------------
"Wraps a function, taking an index and returning a Colorant"
immutable ColorFunction <: ColorScheme
struct ColorFunction <: ColorScheme
f::Function
end
@@ -217,7 +217,7 @@ getColor(scheme::ColorFunction, idx::Int) = scheme.f(idx)
# --------------------------------------------------------------
"Wraps a function, taking an z-value and returning a Colorant"
immutable ColorZFunction <: ColorScheme
struct ColorZFunction <: ColorScheme
f::Function
end
@@ -226,7 +226,7 @@ getColorZ(scheme::ColorZFunction, z::Real) = scheme.f(z)
# --------------------------------------------------------------
"Wraps a vector of colors... may be vector of Symbol/String/Colorant"
immutable ColorVector <: ColorScheme
struct ColorVector <: ColorScheme
v::Vector{Colorant}
ColorVector(v::AVec; alpha = nothing) = new(convertColor(v,alpha))
end
@@ -238,7 +238,7 @@ getColorVector(scheme::ColorVector) = scheme.v
# --------------------------------------------------------------
"Wraps a single color"
immutable ColorWrapper <: ColorScheme
struct ColorWrapper <: ColorScheme
c::RGBA
ColorWrapper(c::Colorant; alpha = nothing) = new(convertColor(c, alpha))
end
@@ -247,7 +247,7 @@ ColorWrapper(s::Symbol; alpha = nothing) = ColorWrapper(convertColor(parse(Color
getColor(scheme::ColorWrapper, idx::Int) = scheme.c
getColorZ(scheme::ColorWrapper, z::Real) = scheme.c
convertColor(c::ColorWrapper, α::Void) = c.c
convertColor(c::ColorWrapper, α::Nothing) = c.c
# --------------------------------------------------------------
@@ -332,7 +332,7 @@ function generate_colorgradient(bgcolor = colorant"white";
seed_colors,
lchoices=Float64[lightness],
cchoices=Float64[chroma],
hchoices=linspace(0, 340, 20)
hchoices=range(0, stop=340, length=20)
)[2:end]
gradient_from_list(colors)
end
@@ -347,8 +347,8 @@ function get_color_palette(palette, bgcolor::Union{Colorant,ColorWrapper}, numco
RGBA[getColorZ(grad, z) for z in zrng]
end
function get_color_palette{C<:Colorant}(palette::Vector{C},
bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer)
function get_color_palette(palette::Vector{C},
bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer) where C<:Colorant
palette
end
+12 -12
View File
@@ -5,21 +5,21 @@
# This should cut down on boilerplate code and allow more focused dispatch on type
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
typealias FuncOrFuncs @compat(Union{Function, AVec{Function}})
const FuncOrFuncs = Union{Function, AVec{Function}}
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
# missing
convertToAnyVector(v::@compat(Void), d::KW) = Any[nothing], nothing
convertToAnyVector(v::Nothing, d::KW) = Any[nothing], nothing
# fixed number of blank series
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing
# numeric vector
convertToAnyVector{T<:Number}(v::AVec{T}, d::KW) = Any[v], nothing
convertToAnyVector(v::AVec{T}, d::KW) where {T<:Number} = Any[v], nothing
# string vector
convertToAnyVector{T<:@compat(AbstractString)}(v::AVec{T}, d::KW) = Any[v], nothing
convertToAnyVector(v::AVec{T}, d::KW) where {T<:AbstractString} = Any[v], nothing
function convertToAnyVector(v::AMat, d::KW)
if all3D(d)
@@ -39,7 +39,7 @@ convertToAnyVector(s::Surface, d::KW) = Any[s], nothing
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing
# dates
convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}, d::KW) = Any[dts], nothing
convertToAnyVector(dts::AVec{D}, d::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing
# list of things (maybe other vectors, functions, or something else)
function convertToAnyVector(v::AVec, d::KW)
@@ -65,19 +65,19 @@ end
# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array
# result in that array being shared. push!, etc will add too many items to that array
compute_x(x::Void, y::Void, z) = 1:size(z,1)
compute_x(x::Void, y, z) = 1:size(y,1)
compute_x(x::Nothing, y::Nothing, z) = 1:size(z,1)
compute_x(x::Nothing, y, z) = 1:size(y,1)
compute_x(x::Function, y, z) = map(x, y)
compute_x(x, y, z) = copy(x)
# compute_y(x::Void, y::Function, z) = error()
compute_y(x::Void, y::Void, z) = 1:size(z,2)
compute_y(x::Nothing, y::Nothing, z) = 1:size(z,2)
compute_y(x, y::Function, z) = map(y, x)
compute_y(x, y, z) = copy(y)
compute_z(x, y, z::Function) = map(z, x, y)
compute_z(x, y, z::AbstractMatrix) = Surface(z)
compute_z(x, y, z::Void) = nothing
compute_z(x, y, z::Nothing) = nothing
compute_z(x, y, z) = copy(z)
nobigs(v::AVec{BigFloat}) = map(Float64, v)
@@ -92,8 +92,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(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
compute_xyz(x::Nothing, y::FuncOrFuncs, z) = error("If you want to plot the function `$y`, you need to define the x values!")
compute_xyz(x::Nothing, y::Nothing, z::FuncOrFuncs) = error("If you want to plot the function `$z`, you need to define x and y values!")
compute_xyz(x::Nothing, y::Nothing, z::Nothing) = error("x/y/z are all nothing!")
# --------------------------------------------------------------------
+208 -71
View File
@@ -1,7 +1,7 @@
"""
Holds all data needed for a documentation example... header, description, and plotting expression (Expr)
"""
type PlotExample
mutable struct PlotExample
header::AbstractString
desc::AbstractString
exprs::Vector{Expr}
@@ -18,11 +18,18 @@ PlotExample("Lines",
),
PlotExample("Functions, adding data, and animations",
"Plot multiple functions. You can also put the function first, or use the form `plot(f, xmin, xmax)` where f is a Function or AbstractVector{Function}.\n\nGet series data: `x, y = plt[i]`. Set series data: `plt[i] = (x,y)`. Add to the series with `push!`/`append!`.\n\nEasily build animations. (`convert` or `ffmpeg` must be available to generate the animation.) Use command `gif(anim, filename, fps=15)` to save the animation.",
"""
Plot multiple functions. You can also put the function first, or use the form `plot(f,
xmin, xmax)` where f is a Function or AbstractVector{Function}.\n\nGet series data:
`x, y = plt[i]`. Set series data: `plt[i] = (x,y)`. Add to the series with
`push!`/`append!`.\n\nEasily build animations. (`convert` or `ffmpeg` must be available
to generate the animation.) Use command `gif(anim, filename, fps=15)` to save the
animation.
""",
[:(begin
p = plot([sin,cos], zeros(0), leg=false)
anim = Animation()
for x in linspace(0, 10π, 100)
for x in range(0, stop=10π, length=100)
push!(p, x, Float64[sin(x), cos(x)])
frame(anim)
end
@@ -37,23 +44,35 @@ PlotExample("Parametric plots",
),
PlotExample("Colors",
"Access predefined palettes (or build your own with the `colorscheme` method). Line/marker colors are auto-generated from the plot's palette, unless overridden. Set the `z` argument to turn on series gradients.",
"""
Access predefined palettes (or build your own with the `colorscheme` method).
Line/marker colors are auto-generated from the plot's palette, unless overridden. Set
the `z` argument to turn on series gradients.
""",
[:(begin
y = rand(100)
plot(0:10:100,rand(11,4),lab="lines",w=3,palette=:grays,fill=(0,:auto), α=0.6)
scatter!(y, zcolor=abs(y-.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs(y-0.5)+4, lab="grad")
y = rand(100)
plot(0:10:100,rand(11,4),lab="lines",w=3,palette=:grays,fill=0, α=0.6)
scatter!(y, zcolor=abs.(y.-0.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs.(y.-0.5).+4,
lab="grad")
end)]
),
PlotExample("Global",
"Change the guides/background/limits/ticks. Convenience args `xaxis` and `yaxis` allow you to pass a tuple or value which will be mapped to the relevant args automatically. The `xaxis` below will be replaced with `xlabel` and `xlims` args automatically during the preprocessing step. You can also use shorthand functions: `title!`, `xaxis!`, `yaxis!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`",
"""
Change the guides/background/limits/ticks. Convenience args `xaxis` and `yaxis` allow
you to pass a tuple or value which will be mapped to the relevant args automatically.
The `xaxis` below will be replaced with `xlabel` and `xlims` args automatically during
the preprocessing step. You can also use shorthand functions: `title!`, `xaxis!`,
`yaxis!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`
""",
[:(begin
y = rand(20,3)
plot(y, xaxis=("XLABEL",(-5,30),0:2:20,:flip), background_color = RGB(0.2,0.2,0.2), leg=false)
hline!(mean(y,1)+rand(1,3), line=(4,:dash,0.6,[:lightgreen :green :darkgreen]))
vline!([5,10])
title!("TITLE")
yaxis!("YLABEL", :log10)
y = rand(20,3)
plot(y, xaxis=("XLABEL",(-5,30),0:2:20,:flip), background_color = RGB(0.2,0.2,0.2),
leg=false)
hline!(mean(y, dims = 1)+rand(1,3), line=(4,:dash,0.6,[:lightgreen :green :darkgreen]))
vline!([5,10])
title!("TITLE")
yaxis!("YLABEL", :log10)
end)]
),
@@ -61,19 +80,26 @@ PlotExample("Global",
# "Use the `axis` arguments.",
# [
# :(plot(Vector[randn(100), randn(100)*100], axis = [:l :r], ylabel="LEFT", yrightlabel="RIGHT", xlabel="X", title="TITLE"))
# ]),
# ]),
PlotExample("Images",
"Plot an image. y-axis is set to flipped",
[:(begin
import Images
img = Images.load(Pkg.dir("PlotReferenceImages","Plots","pyplot","0.7.0","ref1.png"))
import FileIO
img = FileIO.load(Pkg.dir("PlotReferenceImages","Plots","pyplot","0.7.0","ref1.png"))
plot(img)
end)]
),
PlotExample("Arguments",
"Plot multiple series with different numbers of points. Mix arguments that apply to all series (marker/markersize) with arguments unique to each series (colors). Special arguments `line`, `marker`, and `fill` will automatically figure out what arguments to set (for example, we are setting the `linestyle`, `linewidth`, and `color` arguments with `line`.) Note that we pass a matrix of colors, and this applies the colors to each series.",
"""
Plot multiple series with different numbers of points. Mix arguments that apply to all
series (marker/markersize) with arguments unique to each series (colors). Special
arguments `line`, `marker`, and `fill` will automatically figure out what arguments to
set (for example, we are setting the `linestyle`, `linewidth`, and `color` arguments with
`line`.) Note that we pass a matrix of colors, and this applies the colors to each
series.
""",
[:(begin
ys = Vector[rand(10), rand(20)]
plot(ys, color=[:black :orange], line=(:dot,4), marker=([:hex :d],12,0.8,stroke(3,:gray)))
@@ -115,20 +141,23 @@ PlotExample("Line types",
PlotExample("Line styles",
"",
[:(begin
styles = filter(s -> s in supported_styles(), [:solid, :dash, :dot, :dashdot, :dashdotdot])'
n = length(styles)
y = cumsum(randn(20,n),1)
plot(y, line = (5, styles), label = map(string,styles))
end)]
styles = filter(s -> s in Plots.supported_styles(),
[:solid, :dash, :dot, :dashdot, :dashdotdot])
styles = reshape(styles, 1, length(styles)) # Julia 0.6 unfortunately gives an error when transposing symbol vectors
n = length(styles)
y = cumsum(randn(20,n), dims = 1)
plot(y, line = (5, styles), label = map(string,styles), legendtitle = "linestyle")
end)]
),
PlotExample("Marker types",
"",
[:(begin
markers = filter(m -> m in supported_markers(), Plots._shape_keys)'
markers = filter(m -> m in Plots.supported_markers(), Plots._shape_keys)
markers = reshape(markers, 1, length(markers))
n = length(markers)
x = linspace(0,10,n+2)[2:end-1]
y = repmat(reverse(x)', n, 1)
x = range(0, stop=10, length=n+2)[2:end-1]
y = repeat(reshape(reverse(x),1,:), n, 1)
scatter(x, y, m=(8,:auto), lab=map(string,markers), bg=:linen, xlim=(0,10), ylim=(0,10))
end)]
),
@@ -143,79 +172,105 @@ PlotExample("Bar",
PlotExample("Histogram",
"",
[:(begin
histogram(randn(1000), nbins=20)
histogram(randn(1000), bins = :scott, weights = repeat(1:5, outer = 200))
end)]
),
PlotExample("Subplots",
"""
Use the `layout` keyword, and optionally the convenient `@layout` macro to generate arbitrarily complex subplot layouts.
""",
"""
Use the `layout` keyword, and optionally the convenient `@layout` macro to generate
arbitrarily complex subplot layouts.
""",
[:(begin
l = @layout([a{0.1h}; b [c;d e]])
plot(randn(100,5), layout=l, t=[:line :histogram :scatter :steppre :bar], leg=false, ticks=nothing, border=false)
l = @layout([a{0.1h}; b [c;d e]])
plot(randn(100,5), layout=l, t=[:line :histogram :scatter :steppre :bar], leg=false,
ticks=nothing, border=:none)
end)]
),
PlotExample("Adding to subplots",
"Note here the automatic grid layout, as well as the order in which new series are added to the plots.",
"""
Note here the automatic grid layout, as well as the order in which new series are added
to the plots.
""",
[:(begin
plot(Plots.fakedata(100,10), layout=4, palette=[:grays :blues :heat :lightrainbow], bg_inside=[:orange :pink :darkblue :black])
plot(Plots.fakedata(100,10), layout=4, palette=[:grays :blues :heat :lightrainbow],
bg_inside=[:orange :pink :darkblue :black])
end)]
),
PlotExample("",
"",
[:(begin
srand(111)
Random.srand(111)
plot!(Plots.fakedata(100,10))
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.",
"""
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
n=20
hgt=rand(n)+1
bot=randn(n)
openpct=rand(n)
closepct=rand(n)
y = OHLC[(openpct[i]*hgt[i]+bot[i], bot[i]+hgt[i], bot[i], closepct[i]*hgt[i]+bot[i]) for i in 1:n]
ohlc(y)
n=20
hgt=rand(n).+1
bot=randn(n)
openpct=rand(n)
closepct=rand(n)
y = OHLC[(openpct[i]*hgt[i]+bot[i], bot[i]+hgt[i], bot[i],
closepct[i]*hgt[i]+bot[i]) for i in 1:n]
ohlc(y)
end)]
),
PlotExample("Annotations",
"The `annotations` keyword is used for text annotations in data-coordinates. Pass in a tuple (x,y,text) or a vector of annotations. `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`. Series annotations are used for annotating individual data points. They require only the annotation... x/y values are computed. A `PlotText` object can be build with the method `text(string, attr...)`, which wraps font and color attributes.",
"""
The `annotations` keyword is used for text annotations in data-coordinates. Pass in a
tuple (x,y,text) or a vector of annotations. `annotate!(ann)` is shorthand for `plot!(;
annotation=ann)`. Series annotations are used for annotating individual data points.
They require only the annotation... x/y values are computed. A `PlotText` object can be
build with the method `text(string, attr...)`, which wraps font and color attributes.
""",
[:(begin
y = rand(10)
plot(y, annotations = (3,y[3],text("this is #3",:left)), leg=false)
annotate!([(5, y[5], text("this is #5",16,:red,:center)), (10, y[10], text("this is #10",:right,20,"courier"))])
scatter!(linspace(2,8,6), rand(6), marker=(50,0.2,:orange), series_annotations = ["series","annotations","map","to","series",text("data",:green)])
y = rand(10)
plot(y, annotations = (3,y[3],text("this is #3",:left)), leg=false)
annotate!([(5, y[5], text("this is #5",16,:red,:center)),
(10, y[10], text("this is #10",:right,20,"courier"))])
scatter!(range(2, stop=8, length=6), rand(6), marker=(50,0.2,:orange),
series_annotations = ["series","annotations","map","to","series",
text("data",:green)])
end)]
),
PlotExample("Custom Markers",
"A `Plots.Shape` is a light wrapper around vertices of a polygon. For supported backends, pass arbitrary polygons as the marker shapes. Note: The center is (0,0) and the size is expected to be rougly the area of the unit circle.",
"""A `Plots.Shape` is a light wrapper around vertices of a polygon. For supported
backends, pass arbitrary polygons as the marker shapes. Note: The center is (0,0) and
the size is expected to be rougly the area of the unit circle.
""",
[:(begin
verts = [(-1.0,1.0),(-1.28,0.6),(-0.2,-1.4),(0.2,-1.4),(1.28,0.6),(1.0,1.0),
(-1.0,1.0),(-0.2,-0.6),(0.0,-0.2),(-0.4,0.6),(1.28,0.6),(0.2,-1.4),
(-0.2,-1.4),(0.6,0.2),(-0.2,0.2),(0.0,-0.2),(0.2,0.2),(-0.2,-0.6)]
x = 0.1:0.2:0.9
y = 0.7rand(5)+0.15
plot(x, y, line = (3,:dash,:lightblue), marker = (Shape(verts),30,RGBA(0,0,0,0.2)),
bg=:pink, fg=:darkblue, xlim = (0,1), ylim=(0,1), leg=false)
verts = [(-1.0,1.0),(-1.28,0.6),(-0.2,-1.4),(0.2,-1.4),(1.28,0.6),(1.0,1.0),
(-1.0,1.0),(-0.2,-0.6),(0.0,-0.2),(-0.4,0.6),(1.28,0.6),(0.2,-1.4),
(-0.2,-1.4),(0.6,0.2),(-0.2,0.2),(0.0,-0.2),(0.2,0.2),(-0.2,-0.6)]
x = 0.1:0.2:0.9
y = 0.7rand(5).+0.15
plot(x, y, line = (3,:dash,:lightblue), marker = (Shape(verts),30,RGBA(0,0,0,0.2)),
bg=:pink, fg=:darkblue, xlim = (0,1), ylim=(0,1), leg=false)
end)]
),
PlotExample("Contours",
"Any value for fill works here. We first build a filled contour from a function, then an unfilled contour from a matrix.",
"""
Any value for fill works here. We first build a filled contour from a function, then an
unfilled contour from a matrix.
""",
[:(begin
x = 1:0.5:20
y = 1:0.5:10
f(x,y) = (3x+y^2)*abs(sin(x)+cos(y))
X = repmat(x', length(y), 1)
Y = repmat(y, 1, length(x))
X = repeat(reshape(x,1,:), length(y), 1)
Y = repeat(y, 1, length(x))
Z = map(f, X, Y)
p1 = contour(x, y, f, fill=true)
p2 = contour(x, y, Z)
@@ -236,7 +291,7 @@ PlotExample("3D",
"",
[:(begin
n = 100
ts = linspace(0,8π,n)
ts = range(0, stop=8π, length=n)
x = ts .* map(cos,ts)
y = 0.1ts .* map(sin,ts)
z = 1:n
@@ -250,9 +305,9 @@ PlotExample("DataFrames",
[:(begin
import RDatasets
iris = RDatasets.dataset("datasets", "iris")
scatter(iris, :SepalLength, :SepalWidth, group=:Species,
@df iris scatter(:SepalLength, :SepalWidth, group=:Species,
title = "My awesome plot", xlabel = "Length", ylabel = "Width",
marker = (0.5, [:+ :h :star7], 12), bg=RGB(.2,.2,.2))
marker = (0.5, [:cross :hex :star7], 12), bg=RGB(.2,.2,.2))
end)]
),
@@ -260,15 +315,16 @@ PlotExample("Groups and Subplots",
"",
[:(begin
group = rand(map(i->"group $i",1:4),100)
plot(rand(100), layout=@layout([a b;c]), group=group, linetype=[:bar :scatter :steppre])
plot(rand(100), layout=@layout([a b;c]), group=group,
linetype=[:bar :scatter :steppre], linecolor = :match)
end)]
),
PlotExample("Polar Plots",
"",
[:(begin
Θ = linspace(0,1.5π,100)
r = abs(0.1randn(100)+sin(3Θ))
Θ = range(0, stop=1.5π, length=100)
r = abs.(0.1randn(100)+sin.(3Θ))
plot(Θ, r, proj=:polar, m=2)
end)]
),
@@ -278,7 +334,7 @@ PlotExample("Heatmap, categorical axes, and aspect_ratio",
[:(begin
xs = [string("x",i) for i=1:10]
ys = [string("y",i) for i=1:4]
z = float((1:4)*(1:10)')
z = float((1:4)*reshape(1:10,1,:))
heatmap(xs, ys, z, aspect_ratio=1)
end)]
),
@@ -286,9 +342,10 @@ PlotExample("Heatmap, categorical axes, and aspect_ratio",
PlotExample("Layouts, margins, label rotation, title location",
"",
[:(begin
using Plots.PlotMeasures # for Measures, e.g. mm and px
plot(rand(100,6),layout=@layout([a b; c]),title=["A" "B" "C"],
title_location=:left, left_margin=[20mm 0mm],
bottom_margin=50px, xrotation=60)
bottom_margin=10px, xrotation=60)
end)]
),
@@ -297,10 +354,83 @@ PlotExample("Boxplot and Violin series recipes",
[:(begin
import RDatasets
singers = RDatasets.dataset("lattice", "singer")
violin(singers, :VoicePart, :Height, line = 0, fill = (0.2, :blue))
boxplot!(singers, :VoicePart, :Height, line = (2,:black), fill = (0.3, :orange))
@df singers violin(:VoicePart, :Height, line = 0, fill = (0.2, :blue))
@df singers boxplot!(:VoicePart, :Height, line = (2,:black), fill = (0.3, :orange))
end)]
)
),
PlotExample("Animation with subplots",
"The `layout` macro can be used to create an animation with subplots.",
[:(begin
l = @layout([[a; b] c])
p = plot(plot([sin,cos],1,leg=false),
scatter([atan,cos],1,leg=false),
plot(log,1,xlims=(1,10π),ylims=(0,5),leg=false),layout=l)
anim = Animation()
for x = range(1, stop=10π, length=100)
plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)]))
frame(anim)
end
end)]
),
PlotExample("Spy",
"""
For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat` has
various different nonzero values, a colorbar is added. The colorbar can be disabled with
`legend = nothing`.
""",
[:(begin
a = spdiagm((ones(50), ones(49), ones(49), ones(40), ones(40)),(0, 1, -1, 10, -10))
b = spdiagm((1:50, 1:49, 1:49, 1:40, 1:40),(0, 1, -1, 10, -10))
plot(spy(a), spy(b), title = ["Unique nonzeros" "Different nonzeros"])
end)]
),
PlotExample("Magic grid argument",
"""
The grid lines can be modified individually for each axis with the magic `grid` argument.
""",
[:(begin
x = rand(10)
p1 = plot(x, title = "Default looks")
p2 = plot(x, grid = (:y, :olivedrab, :dot, 1, 0.9), title = "Modified y grid")
p3 = plot(deepcopy(p2), title = "Add x grid")
xgrid!(p3, :on, :cadetblue, 2, :dashdot, 0.4)
plot(p1, p2, p3, layout = (1, 3), label = "", fillrange = 0, fillalpha = 0.3)
end)]
),
PlotExample("Framestyle",
"""
The style of the frame/axes of a (sub)plot can be changed with the `framestyle`
attribute. The default framestyle is `:axes`.
""",
[:(begin
scatter(fill(randn(10), 6), fill(randn(10), 6),
framestyle = [:box :semi :origin :zerolines :grid :none],
title = [":box" ":semi" ":origin" ":zerolines" ":grid" ":none"],
color = RowVector(1:6), layout = 6, label = "", markerstrokewidth = 0,
ticks = -2:2)
end)]
),
PlotExample("Lines and markers with varying colors",
"""
You can use the `line_z` and `marker_z` properties to associate a color with
each line segment or marker in the plot.
""",
[:(begin
t = range(0, stop=1, length=100)
θ = 6π .* t
x = t .* cos.(θ)
y = t .* sin.(θ)
p1 = plot(x, y, line_z=t, linewidth=3, legend=false)
p2 = scatter(x, y, marker_z=t, color=:bluesreds, legend=false)
plot(p1, p2)
end)]
),
]
@@ -309,7 +439,7 @@ PlotExample("Boxplot and Violin series recipes",
# make and display one plot
function test_examples(pkgname::Symbol, idx::Int; debug = false, disp = true)
Plots._debugMode.on = debug
info("Testing plot: $pkgname:$idx:$(_examples[idx].header)")
@info("Testing plot: $pkgname:$idx:$(_examples[idx].header)")
backend(pkgname)
backend()
map(eval, _examples[idx].exprs)
@@ -321,6 +451,13 @@ function test_examples(pkgname::Symbol, idx::Int; debug = false, disp = true)
end
# generate all plots and create a dict mapping idx --> plt
"""
test_examples(pkgname[, idx]; debug = false, disp = true, sleep = nothing,
skip = [], only = nothing
Run the `idx` test example for a given backend, or all examples if `idx`
is not specified.
"""
function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = nothing,
skip = [], only = nothing)
Plots._debugMode.on = debug
+139 -50
View File
@@ -1,34 +1,30 @@
# NOTE: (0,0) is the top-left !!!
# allow pixels and percentages
const px = AbsoluteLength(0.254)
const pct = Length{:pct, Float64}(1.0)
to_pixels(m::AbsoluteLength) = m.value / 0.254
const _cbar_width = 5mm
@compat Base.:.*(m::Measure, n::Number) = m * n
@compat Base.:.*(n::Number, m::Measure) = m * n
@compat Base.:-(m::Measure, a::AbstractArray) = map(ai -> m - ai, a)
@compat Base.:-(a::AbstractArray, m::Measure) = map(ai -> ai - m, a)
Base.broadcast(::typeof(Base.:.*), m::Measure, n::Number) = m * n
Base.broadcast(::typeof(Base.:.*), m::Number, n::Measure) = m * n
Base.:-(m::Measure, a::AbstractArray) = map(ai -> m - ai, a)
Base.:-(a::AbstractArray, m::Measure) = map(ai -> ai - m, a)
Base.zero(::Type{typeof(mm)}) = 0mm
Base.one(::Type{typeof(mm)}) = 1mm
Base.typemin(::typeof(mm)) = -Inf*mm
Base.typemax(::typeof(mm)) = Inf*mm
Base.convert{F<:AbstractFloat}(::Type{F}, l::AbsoluteLength) = convert(F, l.value)
Base.convert(::Type{F}, l::AbsoluteLength) where {F<:AbstractFloat} = convert(F, l.value)
# TODO: these are unintuitive and may cause tricky bugs
# @compat Base.:+(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * (1 + m2.value))
# @compat Base.:+(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * (1 + m1.value))
# @compat Base.:-(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * (1 - m2.value))
# @compat Base.:-(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * (m1.value - 1))
# Base.:+(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * (1 + m2.value))
# Base.:+(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * (1 + m1.value))
# Base.:-(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * (1 - m2.value))
# Base.:-(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * (m1.value - 1))
@compat Base.:*(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * m2.value)
@compat Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value)
@compat Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value)
@compat Base.:/(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value / m1.value)
Base.:*(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * m2.value)
Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value)
Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value)
Base.:/(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value / m1.value)
Base.zero(::Type{typeof(pct)}) = 0pct
@@ -44,11 +40,11 @@ right(bbox::BoundingBox) = left(bbox) + width(bbox)
bottom(bbox::BoundingBox) = top(bbox) + height(bbox)
Base.size(bbox::BoundingBox) = (width(bbox), height(bbox))
# @compat Base.:*{T,N}(m1::Length{T,N}, m2::Length{T,N}) = Length{T,N}(m1.value * m2.value)
# Base.:*{T,N}(m1::Length{T,N}, m2::Length{T,N}) = Length{T,N}(m1.value * m2.value)
ispositive(m::Measure) = m.value > 0
# union together bounding boxes
@compat function Base.:+(bb1::BoundingBox, bb2::BoundingBox)
function Base.:+(bb1::BoundingBox, bb2::BoundingBox)
# empty boxes don't change the union
ispositive(width(bb1)) || return bb2
ispositive(height(bb1)) || return bb2
@@ -96,6 +92,32 @@ function Base.show(io::IO, bbox::BoundingBox)
print(io, "BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}")
end
# -----------------------------------------------------------
# points combined by x/y, pct, and length
mutable struct MixedMeasures
xy::Float64
pct::Float64
len::AbsoluteLength
end
function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol)
xy = mix.xy
pct = mix.pct
if mix.len != 0mm
f = (letter == :x ? width : height)
totlen = f(plotarea(sp))
@show totlen
pct += mix.len / totlen
end
if pct != 0
amin, amax = axis_limits(sp[Symbol(letter,:axis)])
xy += pct * (amax-amin)
end
xy
end
# -----------------------------------------------------------
# AbstractLayout
@@ -107,15 +129,22 @@ make_measure_hor(m::Measure) = m
make_measure_vert(n::Number) = n * h
make_measure_vert(m::Measure) = m
"""
bbox(x, y, w, h [,originargs...])
bbox(layout)
Create a bounding box for plotting
"""
function bbox(x, y, w, h, oarg1::Symbol, originargs::Symbol...)
oargs = vcat(oarg1, originargs...)
orighor = :left
origver = :top
for oarg in oargs
if oarg in (:left, :right)
if oarg == :center
orighor = origver = oarg
elseif oarg in (:left, :right, :hcenter)
orighor = oarg
elseif oarg in (:top, :bottom)
elseif oarg in (:top, :bottom, :vcenter)
origver = oarg
else
warn("Unused origin arg in bbox construction: $oarg")
@@ -132,13 +161,17 @@ function bbox(x, y, width, height; h_anchor = :left, v_anchor = :top)
height = make_measure_vert(height)
left = if h_anchor == :left
x
elseif h_anchor in (:center, :hcenter)
0.5w - 0.5width + x
else
1w - x - width
1w - x - width
end
top = if v_anchor == :top
y
elseif v_anchor in (:center, :vcenter)
0.5h - 0.5height + y
else
1h - y - height
1h - y - height
end
BoundingBox(left, top, width, height)
end
@@ -183,7 +216,7 @@ bottompad(layout::AbstractLayout) = 0mm
# RootLayout
# this is the parent of the top-level layout
immutable RootLayout <: AbstractLayout end
struct RootLayout <: AbstractLayout end
Base.parent(::RootLayout) = nothing
parent_bbox(::RootLayout) = defaultbox
@@ -193,7 +226,7 @@ bbox(::RootLayout) = defaultbox
# EmptyLayout
# contains blank space
type EmptyLayout <: AbstractLayout
mutable struct EmptyLayout <: AbstractLayout
parent::AbstractLayout
bbox::BoundingBox
attr::KW # store label, width, and height for initialization
@@ -211,7 +244,7 @@ _update_min_padding!(layout::EmptyLayout) = nothing
# GridLayout
# nested, gridded layout with optional size percentages
type GridLayout <: AbstractLayout
mutable struct GridLayout <: AbstractLayout
parent::AbstractLayout
minpad::Tuple # leftpad, toppad, rightpad, bottompad
bbox::BoundingBox
@@ -221,6 +254,13 @@ type GridLayout <: AbstractLayout
attr::KW
end
"""
grid(args...; kw...)
Create a grid layout for subplots. `args` specify the dimensions, e.g.
`grid(3,2, widths = (0.6,04))` creates a grid with three rows and two
columns of different width.
"""
grid(args...; kw...) = GridLayout(args...; kw...)
function GridLayout(dims...;
@@ -228,7 +268,7 @@ function GridLayout(dims...;
widths = zeros(dims[2]),
heights = zeros(dims[1]),
kw...)
grid = Matrix{AbstractLayout}(dims...)
grid = Matrix{AbstractLayout}(undef, dims...)
layout = GridLayout(
parent,
(20mm, 5mm, 2mm, 10mm),
@@ -239,7 +279,9 @@ function GridLayout(dims...;
# convert(Vector{Float64}, widths),
# convert(Vector{Float64}, heights),
KW(kw))
fill!(grid, EmptyLayout(layout))
for i in eachindex(grid)
grid[i] = EmptyLayout(layout)
end
layout
end
@@ -256,7 +298,7 @@ rightpad(layout::GridLayout) = layout.minpad[3]
bottompad(layout::GridLayout) = layout.minpad[4]
# here's how this works... first we recursively "update the minimum padding" (which
# here's how this works... first we recursively "update the minimum padding" (which
# means to calculate the minimum size needed from the edge of the subplot to plot area)
# for the whole layout tree. then we can compute the "padding borders" of this
# layout as the biggest padding of the children on the perimeter. then we need to
@@ -311,16 +353,14 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0
minpad_top = map(toppad, layout.grid)
minpad_right = map(rightpad, layout.grid)
minpad_bottom = map(bottompad, layout.grid)
# @show minpad_left minpad_top minpad_right minpad_bottom
# get the max horizontal (left and right) padding over columns,
# and max vertical (bottom and top) padding over rows
# TODO: add extra padding here
pad_left = maximum(minpad_left, 1)
pad_top = maximum(minpad_top, 2)
pad_right = maximum(minpad_right, 1)
pad_bottom = maximum(minpad_bottom, 2)
# @show pad_left pad_top pad_right pad_bottom
pad_left = maximum(minpad_left, dims = 1)
pad_top = maximum(minpad_top, dims = 2)
pad_right = maximum(minpad_right, dims = 1)
pad_bottom = maximum(minpad_bottom, dims = 2)
# make sure the perimeter match the parent
pad_left[1] = max(pad_left[1], minimum_perimeter[1])
@@ -331,22 +371,18 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0
# scale this up to the total padding in each direction
total_pad_horizontal = sum(pad_left + pad_right)
total_pad_vertical = sum(pad_top + pad_bottom)
# @show total_pad_horizontal total_pad_vertical
# now we can compute the total plot area in each direction
total_plotarea_horizontal = width(layout) - total_pad_horizontal
total_plotarea_vertical = height(layout) - total_pad_vertical
# @show total_plotarea_horizontal total_plotarea_vertical
# recompute widths/heights
layout.widths = recompute_lengths(layout.widths)
layout.heights = recompute_lengths(layout.heights)
# @show layout.widths layout.heights
# normalize widths/heights so they sum to 1
# denom_w = sum(layout.widths)
# denom_h = sum(layout.heights)
# @show layout.widths layout.heights denom_w, denom_h
# we have all the data we need... lets compute the plot areas and set the bounding boxes
for r=1:nr, c=1:nc
@@ -387,7 +423,6 @@ end
function update_inset_bboxes!(plt::Plot)
for sp in plt.inset_subplots
p_area = Measures.resolve(plotarea(sp.parent), sp[:relative_bbox])
# @show bbox(sp.parent) sp[:relative_bbox] p_area
plotarea!(sp, p_area)
bbox!(sp, bbox(
@@ -436,7 +471,7 @@ end
function layout_args(d::KW, n_override::Integer)
layout, n = layout_args(get(d, :layout, n_override))
if n != n_override
error("When doing layout, n != n_override. You're probably trying to force existing plots into a layout that doesn't fit them.")
error("When doing layout, n ($n) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.")
end
layout, n
end
@@ -446,12 +481,12 @@ function layout_args(n::Integer)
GridLayout(nr, nc), n
end
function layout_args{I<:Integer}(sztup::NTuple{2,I})
function layout_args(sztup::NTuple{2,I}) where I<:Integer
nr, nc = sztup
GridLayout(nr, nc), nr*nc
end
function layout_args{I<:Integer}(sztup::NTuple{3,I})
function layout_args(sztup::NTuple{3,I}) where I<:Integer
n, nr, nc = sztup
nr, nc = compute_gridsize(n, nr, nc)
GridLayout(nr, nc), n
@@ -502,6 +537,12 @@ function build_layout(layout::GridLayout, n::Integer)
i += 1
elseif isa(l, GridLayout)
# sub-grid
if get(l.attr, :width, :auto) != :auto
layout.widths[c] = attr(l,:width)
end
if get(l.attr, :height, :auto) != :auto
layout.heights[r] = attr(l,:height)
end
l, sps, m = build_layout(l, n-i)
append!(subplots, sps)
merge!(spmap, m)
@@ -525,7 +566,7 @@ function build_layout(layout::GridLayout, numsp::Integer, plts::AVec{Plot})
for r=1:nr, c=1:nc
l = layout[r,c]
if isa(l, EmptyLayout) && !get(l.attr, :blank, false)
plt = shift!(plts) # grab the first plot out of the list
plt = popfirst!(plts) # grab the first plot out of the list
layout[r,c] = plt.layout
append!(subplots, plt.subplots)
merge!(spmap, plt.spmap)
@@ -538,6 +579,12 @@ function build_layout(layout::GridLayout, numsp::Integer, plts::AVec{Plot})
i += length(plt.subplots)
elseif isa(l, GridLayout)
# sub-grid
if get(l.attr, :width, :auto) != :auto
layout.widths[c] = attr(l,:width)
end
if get(l.attr, :height, :auto) != :auto
layout.heights[r] = attr(l,:height)
end
l, sps, m = build_layout(l, numsp-i, plts)
append!(subplots, sps)
merge!(spmap, m)
@@ -597,7 +644,7 @@ function create_grid(expr::Expr)
create_grid_curly(expr)
else
# if it's something else, just return that (might be an existing layout?)
expr
esc(expr)
end
end
@@ -634,13 +681,18 @@ function create_grid_vcat(expr::Expr)
end
function create_grid_curly(expr::Expr)
s = expr.args[1]
kw = KW()
for (i,arg) in enumerate(expr.args[2:end])
add_layout_pct!(kw, arg, i, length(expr.args)-1)
end
# @show kw
:(EmptyLayout(label = $(QuoteNode(s)), width = $(get(kw, :w, QuoteNode(:auto))), height = $(get(kw, :h, QuoteNode(:auto)))))
s = expr.args[1]
if isa(s, Expr) && s.head == :call && s.args[1] == :grid
create_grid(:(grid($(s.args[2:end]...), width = $(get(kw, :w, QuoteNode(:auto))), height = $(get(kw, :h, QuoteNode(:auto))))))
elseif isa(s, Symbol)
:(EmptyLayout(label = $(QuoteNode(s)), width = $(get(kw, :w, QuoteNode(:auto))), height = $(get(kw, :h, QuoteNode(:auto)))))
else
error("Unknown use of curly brackets: $expr")
end
end
function create_grid(s::Symbol)
@@ -654,20 +706,42 @@ end
# -------------------------------------------------------------------------
# make all reference the same axis extrema/values
# make all reference the same axis extrema/values.
# merge subplot lists.
function link_axes!(axes::Axis...)
a1 = axes[1]
for i=2:length(axes)
a2 = axes[i]
expand_extrema!(a1, ignorenan_extrema(a2))
for k in (:extrema, :discrete_values, :continuous_values, :discrete_map)
a2[k] = a1[k]
end
# make a2's subplot list refer to a1's and add any missing values
sps2 = a2.sps
for sp in sps2
sp in a1.sps || push!(a1.sps, sp)
end
a2.sps = a1.sps
end
end
# figure out which subplots to link
function link_subplots(a::AbstractArray{AbstractLayout}, axissym::Symbol)
subplots = []
for l in a
if isa(l, Subplot)
push!(subplots, l)
elseif isa(l, GridLayout) && size(l) == (1,1)
push!(subplots, l[1,1])
end
end
subplots
end
# for some vector or matrix of layouts, filter only the Subplots and link those axes
function link_axes!(a::AbstractArray{AbstractLayout}, axissym::Symbol)
subplots = filter(l -> isa(l, Subplot), a)
subplots = link_subplots(a, axissym)
axes = [sp.attr[axissym] for sp in subplots]
if length(axes) > 0
link_axes!(axes...)
@@ -709,3 +783,18 @@ function link_axes!(layout::GridLayout, link::Symbol)
link_axes!(l, link)
end
end
# -------------------------------------------------------------------------
"Adds a new, empty subplot overlayed on top of `sp`, with a mirrored y-axis and linked x-axis."
function twinx(sp::Subplot)
sp[:right_margin] = max(sp[:right_margin], 30px)
plot!(sp.plt, inset = (sp[:subplot_index], bbox(0,0,1,1)))
twinsp = sp.plt.subplots[end]
twinsp[:yaxis][:mirror] = true
twinsp[:background_color_inside] = RGBA{Float64}(0,0,0,0)
link_axes!(sp[:xaxis], twinsp[:xaxis])
twinsp
end
twinx(plt::Plot = current()) = twinx(plt[1])
+172 -86
View File
@@ -5,7 +5,7 @@ defaultOutputFormat(plt::Plot) = "png"
function png(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "png")
io = open(fn, "w")
writemime(io, MIME("image/png"), plt)
show(io, MIME("image/png"), plt)
close(io)
end
png(fn::AbstractString) = png(current(), fn)
@@ -13,7 +13,7 @@ png(fn::AbstractString) = png(current(), fn)
function svg(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "svg")
io = open(fn, "w")
writemime(io, MIME("image/svg+xml"), plt)
show(io, MIME("image/svg+xml"), plt)
close(io)
end
svg(fn::AbstractString) = svg(current(), fn)
@@ -22,7 +22,7 @@ svg(fn::AbstractString) = svg(current(), fn)
function pdf(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "pdf")
io = open(fn, "w")
writemime(io, MIME("application/pdf"), plt)
show(io, MIME("application/pdf"), plt)
close(io)
end
pdf(fn::AbstractString) = pdf(current(), fn)
@@ -31,30 +31,49 @@ pdf(fn::AbstractString) = pdf(current(), fn)
function ps(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "ps")
io = open(fn, "w")
writemime(io, MIME("application/postscript"), plt)
show(io, MIME("application/postscript"), plt)
close(io)
end
ps(fn::AbstractString) = ps(current(), fn)
function eps(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "eps")
io = open(fn, "w")
show(io, MIME("image/eps"), plt)
close(io)
end
eps(fn::AbstractString) = eps(current(), fn)
function tex(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "tex")
io = open(fn, "w")
writemime(io, MIME("application/x-tex"), plt)
show(io, MIME("application/x-tex"), plt)
close(io)
end
tex(fn::AbstractString) = tex(current(), fn)
function html(plt::Plot, fn::AbstractString)
fn = addExtension(fn, "html")
io = open(fn, "w")
_use_remote[] = true
show(io, MIME("text/html"), plt)
_use_remote[] = false
close(io)
end
html(fn::AbstractString) = html(current(), fn)
# ----------------------------------------------------------------
@compat const _savemap = Dict(
const _savemap = Dict(
"png" => png,
"svg" => svg,
"pdf" => pdf,
"ps" => ps,
"eps" => eps,
"tex" => tex,
"html" => html,
)
function getExtension(fn::AbstractString)
@@ -78,6 +97,13 @@ function addExtension(fn::AbstractString, ext::AbstractString)
end
end
"""
savefig([plot,] filename)
Save a Plot (the current plot if `plot` is not passed) to file. The file
type is inferred from the file extension. All backends support png and pdf
file types, some also support svg, ps, eps, html and tex.
"""
function savefig(plt::Plot, fn::AbstractString)
# get the extension
@@ -100,75 +126,98 @@ savefig(fn::AbstractString) = savefig(current(), fn)
# ---------------------------------------------------------
"""
gui([plot])
Display a plot using the backends' gui window
"""
gui(plt::Plot = current()) = display(PlotsDisplay(), plt)
# IJulia only... inline display
function inline(plt::Plot = current())
isijulia() || error("inline() is IJulia-only")
Main.IJulia.clear_output(true)
display(Main.IJulia.InlineDisplay(), plt)
end
function Base.display(::PlotsDisplay, plt::Plot)
prepare_output(plt)
_display(plt)
end
# override the REPL display to open a gui window
Base.display(::Base.REPL.REPLDisplay, ::MIME"text/plain", plt::Plot) = gui(plt)
using REPL
Base.display(::REPL.REPLDisplay, ::MIME"text/plain", plt::Plot) = gui(plt)
_do_plot_show(plt, showval::Bool) = showval && gui(plt)
function _do_plot_show(plt, showval::Symbol)
showval == :gui && gui(plt)
showval in (:inline,:ijulia) && inline(plt)
end
# ---------------------------------------------------------
const _mimeformats = Dict(
"application/eps" => "eps",
"image/eps" => "eps",
"application/pdf" => "pdf",
"image/png" => "png",
"application/postscript" => "ps",
"image/svg+xml" => "svg",
"text/plain" => "txt",
)
const _best_html_output_type = KW(
:pyplot => :png,
:unicodeplots => :txt,
:glvisualize => :png,
:plotlyjs => :html,
:plotly => :html
)
# a backup for html... passes to svg or png depending on the html_output_format arg
function Base.writemime(io::IO, ::MIME"text/html", plt::Plot)
function _show(io::IO, ::MIME"text/html", plt::Plot)
output_type = Symbol(plt.attr[:html_output_format])
if output_type == :auto
output_type = get(_best_html_output_type, backend_name(plt.backend), :svg)
end
if output_type == :png
# info("writing png to html output")
print(io, "<img src=\"data:image/png;base64,", base64encode(writemime, MIME("image/png"), plt), "\" />")
print(io, "<img src=\"data:image/png;base64,", base64encode(show, MIME("image/png"), plt), "\" />")
elseif output_type == :svg
# info("writing svg to html output")
writemime(io, MIME("image/svg+xml"), plt)
show(io, MIME("image/svg+xml"), plt)
elseif output_type == :txt
writemime(io, MIME("text/plain"), plt)
show(io, MIME("text/plain"), plt)
else
error("only png or svg allowed. got: $output_type")
error("only png or svg allowed. got: $(repr(output_type))")
end
end
function _writemime(io::IO, m, plt::Plot)
warn("_writemime is not defined for this backend. m=", string(m))
# delegate mimewritable (showable on julia 0.7) to _show instead
function Base.mimewritable(m::M, plt::P) where {M<:MIME, P<:Plot}
return hasmethod(_show, Tuple{IO, M, P})
end
function _display(plt::Plot)
warn("_display is not defined for this backend.")
@warn("_display is not defined for this backend.")
end
# for writing to io streams... first prepare, then callback
for mime in keys(_mimeformats)
@eval function Base.writemime(io::IO, m::MIME{Symbol($mime)}, plt::Plot)
for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml",
"application/eps", "application/pdf", "application/postscript",
"application/x-tex")
@eval function Base.show(io::IO, m::MIME{Symbol($mime)}, plt::Plot)
prepare_output(plt)
_writemime(io, m, plt)
_show(io, m, plt)
end
end
# default text/plain for all backends
_show(io::IO, ::MIME{Symbol("text/plain")}, plt::Plot) = show(io, plt)
"Close all open gui windows of the current backend"
closeall() = closeall(backend())
# ---------------------------------------------------------
# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert
const PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}
if is_installed("FileIO")
@eval import FileIO
function _writemime(io::IO, ::MIME"image/png", plt::Plot)
function _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends})
fn = tempname()
# first save a pdf file
@@ -182,22 +231,18 @@ if is_installed("FileIO")
FileIO.save(pngfn, s)
# now write from the file
write(io, readall(open(pngfn)))
write(io, read(open(pngfn), String))
end
end
# function html_output_format(fmt)
# if fmt == "png"
# @eval function Base.writemime(io::IO, ::MIME"text/html", plt::Plot)
# print(io, "<img src=\"data:image/png;base64,", base64(writemime, MIME("image/png"), plt), "\" />")
# @eval function Base.show(io::IO, ::MIME"text/html", plt::Plot)
# print(io, "<img src=\"data:image/png;base64,", base64(show, MIME("image/png"), plt), "\" />")
# end
# elseif fmt == "svg"
# @eval function Base.writemime(io::IO, ::MIME"text/html", plt::Plot)
# writemime(io, MIME("image/svg+xml"), plt)
# @eval function Base.show(io::IO, ::MIME"text/html", plt::Plot)
# show(io, MIME("image/svg+xml"), plt)
# end
# else
# error("only png or svg allowed. got: $fmt")
@@ -210,67 +255,108 @@ end
# IJulia
# ---------------------------------------------------------
const _ijulia_output = Compat.ASCIIString["text/html"]
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
if IJulia.inited
function setup_ijulia()
# override IJulia inline display
if isijulia()
@eval begin
import IJulia
export set_ijulia_output
function set_ijulia_output(mimestr::AbstractString)
# info("Setting IJulia output format to $mimestr")
global _ijulia_output
_ijulia_output[1] = mimestr
end
function IJulia.display_dict(plt::Plot)
global _ijulia_output
Dict{Compat.ASCIIString, ByteString}(_ijulia_output[1] => sprint(writemime, _ijulia_output[1], plt))
end
"""
Add extra jupyter mimetypes to display_dict based on the plot backed.
# default text/plain passes to html... handles Interact issues
function Base.writemime(io::IO, m::MIME"text/plain", plt::Plot)
writemime(io, MIME("text/html"), plt)
end
The default is nothing, except for plotly based backends, where it
adds data for `application/vnd.plotly.v1+json` that is used in
frontends like jupyterlab and nteract.
"""
_extra_mime_info!(plt::Plot, out::Dict) = out
function _extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o)
out
end
set_ijulia_output("text/html")
function _extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict)
out["application/vnd.plotly.v1+json"] = Dict(
:data => plotly_series(plt),
:layout => plotly_layout(plt)
)
out
end
function IJulia.display_dict(plt::Plot)
output_type = Symbol(plt.attr[:html_output_format])
if output_type == :auto
output_type = get(_best_html_output_type, backend_name(plt.backend), :svg)
end
out = Dict()
if output_type == :txt
mime = "text/plain"
out[mime] = sprint(show, MIME(mime), plt)
elseif output_type == :png
mime = "image/png"
out[mime] = base64encode(show, MIME(mime), plt)
elseif output_type == :svg
mime = "image/svg+xml"
out[mime] = sprint(show, MIME(mime), plt)
elseif output_type == :html
mime = "text/html"
out[mime] = sprint(show, MIME(mime), plt)
else
error("Unsupported output type $output_type")
end
_extra_mime_info!(plt, out)
out
end
ENV["MPLBACKEND"] = "Agg"
end
end
# ---------------------------------------------------------
# Atom PlotPane
# ---------------------------------------------------------
@require Juno = "e5e0dc1b-0480-54bc-9374-aad01c23163d" begin
import Hiccup, Media
function setup_atom()
# @require Atom begin
if isatom() && get(ENV, "PLOTS_USE_ATOM_PLOTPANE", false) in (true, 1, "1", "true", "yes")
# @eval import Atom, Media
@eval import Atom
if Juno.isactive()
Media.media(Plot, Media.Plot)
# # connects the render function
# for T in (GadflyBackend,ImmerseBackend,PyPlotBackend,GRBackend)
# Atom.Media.media(Plot{T}, Atom.Media.Plot)
# end
Atom.Media.media(Plot, Atom.Media.Graphical)
# Atom.Media.media{T <: Union{GadflyBackend,ImmerseBackend,PyPlotBackend,GRBackend}}(Plot{T}, Atom.Media.Plot)
# Atom.displaysize(::Plot) = (535, 379)
# Atom.displaytitle(plt::Plot) = "Plots.jl (backend: $(backend(plt)))"
# this is like "display"... sends an html div with the plot to the PlotPane
function Atom.Media.render(pane::Atom.PlotPane, plt::Plot)
@show "here"
Atom.Media.render(pane, Atom.div(Atom.d(), Atom.HTML(stringmime(MIME("text/html"), plt))))
function Juno.render(e::Juno.Editor, plt::Plot)
Juno.render(e, nothing)
end
# # force text/plain to output to the PlotPane
# function Base.writemime(io::IO, ::MIME"text/plain", plt::Plot)
# # writemime(io::IO, MIME("text/html"), plt)
# Atom.Media.render(pane)
# end
if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
function Juno.render(pane::Juno.PlotPane, plt::Plot)
# temporarily overwrite size to be Atom.plotsize
sz = plt[:size]
dpi = plt[:dpi]
thickness_scaling = plt[:thickness_scaling]
jsize = Juno.plotsize()
jsize[1] == 0 && (jsize[1] = 400)
jsize[2] == 0 && (jsize[2] = 500)
# function Atom.Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyBackend})
# html = Media.render(pane, Atom.div(Atom.d(), Atom.HTML(stringmime(MIME("text/html"), plt))))
# end
scale = minimum(jsize[i] / sz[i] for i in 1:2)
plt[:size] = (s * scale for s in sz)
plt[:dpi] = Plots.DPI
plt[:thickness_scaling] *= scale
Juno.render(pane, HTML(stringmime(MIME("text/html"), plt)))
plt[:size] = sz
plt[:dpi] = dpi
plt[:thickness_scaling] = thickness_scaling
end
# special handling for PlotlyJS
function Juno.render(pane::Juno.PlotPane, plt::Plot{PlotlyJSBackend})
display(Plots.PlotsDisplay(), plt)
end
else
function Juno.render(pane::Juno.PlotPane, plt::Plot)
display(Plots.PlotsDisplay(), plt)
s = "PlotPane turned off. Unset ENV[\"PLOTS_USE_ATOM_PLOTPANE\"] and restart Julia to enable it."
Juno.render(pane, HTML(s))
end
end
# special handling for plotly... use PlotsDisplay
function Juno.render(pane::Juno.PlotPane, plt::Plot{PlotlyBackend})
display(Plots.PlotsDisplay(), plt)
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."
Juno.render(pane, HTML(s))
end
end
end
+76 -50
View File
@@ -11,11 +11,13 @@ function _expand_seriestype_array(d::KW, args)
sts = get(d, :seriestype, :path)
if typeof(sts) <: AbstractArray
delete!(d, :seriestype)
RecipeData[begin
rd = Vector{RecipeData}(undef, size(sts, 1))
for r in 1:size(sts, 1)
dc = copy(d)
dc[:seriestype] = sts[r,:]
RecipeData(dc, args)
end for r=1:size(sts,1)]
dc[:seriestype] = sts[r:r,:]
rd[r] = RecipeData(dc, args)
end
rd
else
RecipeData[RecipeData(copy(d), args)]
end
@@ -60,29 +62,26 @@ function _process_userrecipes(plt::Plot, d::KW, args)
args = _preprocess_args(d, args, still_to_process)
# for plotting recipes, swap out the args and update the parameter dictionary
# we are keeping a queue of series that still need to be processed.
# we are keeping a stack of series that still need to be processed.
# each pass through the loop, we pop one off and apply the recipe.
# the recipe will return a list a Series objects... the ones that are
# finished (no more args) get added to the kw_list, and the rest go into the queue
# for processing.
# finished (no more args) get added to the kw_list, the ones that are not
# are placed on top of the stack and are then processed further.
kw_list = KW[]
while !isempty(still_to_process)
# grab the first in line to be processed and pass it through apply_recipe
# to generate a list of RecipeData objects (data + attributes)
next_series = shift!(still_to_process)
rd_list = RecipesBase.apply_recipe(next_series.d, next_series.args...)
for recipedata in rd_list
# recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes
if !(typeof(recipedata) <: RecipeData)
error("Inputs couldn't be processed... expected RecipeData but got: $recipedata")
end
if isempty(recipedata.args)
_process_userrecipe(plt, kw_list, recipedata)
else
# args are non-empty, so there's still processing to do... add it back to the queue
push!(still_to_process, recipedata)
end
# grab the first in line to be processed and either add it to the kw_list or
# pass it through apply_recipe to generate a list of RecipeData objects (data + attributes)
# for further processing.
next_series = popfirst!(still_to_process)
# recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes
if !(typeof(next_series) <: RecipeData)
error("Inputs couldn't be processed... expected RecipeData but got: $next_series")
end
if isempty(next_series.args)
_process_userrecipe(plt, kw_list, next_series)
else
rd_list = RecipesBase.apply_recipe(next_series.d, next_series.args...)
prepend!(still_to_process,rd_list)
end
end
@@ -95,6 +94,7 @@ function _process_userrecipe(plt::Plot, kw_list::Vector{KW}, recipedata::RecipeD
# when the arg tuple is empty, that means there's nothing left to recursively
# process... finish up and add to the kw_list
kw = recipedata.d
preprocessArgs!(kw)
_preprocess_userrecipe(kw)
warnOnUnsupported_scales(plt.backend, kw)
@@ -152,8 +152,8 @@ function _add_smooth_kw(kw_list::Vector{KW}, kw::KW)
if get(kw, :smooth, false)
x, y = kw[:x], kw[:y]
β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y)
sx = [minimum(x), maximum(x)]
sy = β * sx + α
sx = [ignorenan_minimum(x), ignorenan_maximum(x)]
sy = β .* sx .+ α
push!(kw_list, merge(copy(kw), KW(
:seriestype => :path,
:x => sx,
@@ -183,6 +183,7 @@ function _process_plotrecipe(plt::Plot, kw::KW, kw_list::Vector{KW}, still_to_pr
st = kw[:seriestype] = get(_typeAliases, st, st)
datalist = RecipesBase.apply_recipe(kw, Val{st}, plt)
for data in datalist
preprocessArgs!(data.d)
if data.d[:seriestype] == st
error("Plot recipe $st returned the same seriestype: $(data.d)")
end
@@ -211,7 +212,7 @@ function _plot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
# TODO: init subplots here
_update_plot_args(plt, d)
if !plt.init
plt.o = _create_backend_figure(plt)
plt.o = Base.invokelatest(_create_backend_figure, plt)
# create the layout and subplots from the inputs
plt.layout, plt.subplots, plt.spmap = build_layout(plt.attr)
@@ -242,12 +243,13 @@ function _plot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
end
sp = Subplot(backend(), parent=parent)
sp.plt = plt
sp.attr[:relative_bbox] = bb
sp.attr[:subplot_index] = length(plt.subplots)
push!(plt.subplots, sp)
push!(plt.inset_subplots, sp)
sp.attr[:relative_bbox] = bb
sp.attr[:subplot_index] = length(plt.subplots)
end
end
plt[:inset_subplots] = nothing
end
function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
@@ -259,12 +261,12 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
for kw in kw_list
# get the Subplot object to which the series belongs.
sps = get(kw, :subplot, :auto)
sp = get_subplot(plt, cycle(sps == :auto ? plt.subplots : plt.subplots[sps], command_idx(kw_list,kw)))
sp = get_subplot(plt, _cycle(sps == :auto ? plt.subplots : plt.subplots[sps], command_idx(kw_list,kw)))
kw[:subplot] = sp
# extract subplot/axis attributes from kw and add to sp_attr
attr = KW()
for (k,v) in kw
for (k,v) in collect(kw)
if haskey(_subplot_defaults, k) || haskey(_axis_defaults_byletter, k)
attr[k] = pop!(kw, k)
end
@@ -274,13 +276,24 @@ 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
# override subplot/axis args. `sp_attrs` take precendence
for (idx,sp) in enumerate(plt.subplots)
attr = merge(d, get(sp_attrs, sp, KW()))
attr = if !haskey(d, :subplot) || d[:subplot] == idx
merge(d, get(sp_attrs, sp, KW()))
else
get(sp_attrs, sp, KW())
end
_update_subplot_args(plt, sp, attr, idx, false)
end
@@ -290,7 +303,7 @@ end
# getting ready to add the series... last update to subplot from anything
# that might have been added during series recipes
function _prepare_subplot{T}(plt::Plot{T}, d::KW)
function _prepare_subplot(plt::Plot{T}, d::KW) where T
st::Symbol = d[:seriestype]
sp::Subplot{T} = d[:subplot]
sp_idx = get_subplot_index(plt, sp)
@@ -316,9 +329,9 @@ end
function _override_seriestype_check(d::KW, st::Symbol)
# do we want to override the series type?
if !is3d(st)
if !is3d(st) && !(st in (:contour,:contour3d))
z = d[:z]
if !isa(z, Void) && (size(d[:x]) == size(d[:y]) == size(z))
if !isa(z, Nothing) && (size(d[:x]) == size(d[:y]) == size(z))
st = (st == :scatter ? :scatter3d : :path3d)
d[:seriestype] = st
end
@@ -330,33 +343,41 @@ function _prepare_annotations(sp::Subplot, d::KW)
# strip out series annotations (those which are based on series x/y coords)
# and add them to the subplot attr
sp_anns = annotations(sp[:annotations])
anns = annotations(pop!(d, :series_annotations, []))
if length(anns) > 0
x, y = d[:x], d[:y]
nx, ny, na = map(length, (x,y,anns))
n = max(nx, ny, na)
anns = [(x[mod1(i,nx)], y[mod1(i,ny)], text(anns[mod1(i,na)])) for i=1:n]
end
sp.attr[:annotations] = vcat(sp_anns, anns)
# series_anns = annotations(pop!(d, :series_annotations, []))
# if isa(series_anns, SeriesAnnotations)
# series_anns.x = d[:x]
# series_anns.y = d[:y]
# elseif length(series_anns) > 0
# x, y = d[:x], d[:y]
# nx, ny, na = map(length, (x,y,series_anns))
# n = max(nx, ny, na)
# series_anns = [(x[mod1(i,nx)], y[mod1(i,ny)], text(series_anns[mod1(i,na)])) for i=1:n]
# end
# sp.attr[:annotations] = vcat(sp_anns, series_anns)
end
function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol)
# adjust extrema and discrete info
if st == :image
w, h = size(d[:z])
expand_extrema!(sp[:xaxis], (0,w))
expand_extrema!(sp[:yaxis], (0,h))
sp[:yaxis].d[:flip] = true
elseif !(st in (:pie, :histogram, :histogram2d))
xmin, xmax = ignorenan_extrema(d[:x]); ymin, ymax = ignorenan_extrema(d[:y])
expand_extrema!(sp[:xaxis], (xmin, xmax))
expand_extrema!(sp[:yaxis], (ymin, ymax))
elseif !(st in (:pie, :histogram, :bins2d, :histogram2d))
expand_extrema!(sp, d)
end
# expand for zerolines (axes through origin)
if sp[:framestyle] in (:origin, :zerolines)
expand_extrema!(sp[:xaxis], 0.0)
expand_extrema!(sp[:yaxis], 0.0)
end
end
function _add_the_series(plt, d)
function _add_the_series(plt, sp, d)
warnOnUnsupported_args(plt.backend, d)
warnOnUnsupported(plt.backend, d)
series = Series(d)
push!(plt.series_list, series)
push!(sp.series_list, series)
_series_added(plt, series)
end
@@ -375,11 +396,12 @@ function _process_seriesrecipe(plt::Plot, d::KW)
end
# if it's natively supported, finalize processing and pass along to the backend, otherwise recurse
if st in supported_types()
if is_seriestype_supported(st)
sp = _prepare_subplot(plt, d)
_prepare_annotations(sp, d)
_expand_subplot_extrema(sp, d, st)
_add_the_series(plt, d)
_update_series_attributes!(d, plt, sp)
_add_the_series(plt, sp, d)
else
# get a sub list of series for this seriestype
@@ -388,6 +410,10 @@ function _process_seriesrecipe(plt::Plot, d::KW)
# assuming there was no error, recursively apply the series recipes
for data in datalist
if isa(data, RecipeData)
preprocessArgs!(data.d)
if data.d[:seriestype] == st
error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.")
end
_process_seriesrecipe(plt, data.d)
else
warn("Unhandled recipe: $(data)")
+57 -26
View File
@@ -1,18 +1,22 @@
type CurrentPlot
nullableplot::Nullable{AbstractPlot}
mutable struct CurrentPlot
nullableplot::Union{AbstractPlot, Nothing}
end
const CURRENT_PLOT = CurrentPlot(Nullable{AbstractPlot}())
const CURRENT_PLOT = CurrentPlot(nothing)
isplotnull() = isnull(CURRENT_PLOT.nullableplot)
isplotnull() = CURRENT_PLOT.nullableplot == nothing
"""
current()
Returns the Plot object for the current plot
"""
function current()
if isplotnull()
error("No current plot/subplot")
end
get(CURRENT_PLOT.nullableplot)
CURRENT_PLOT.nullableplot
end
current(plot::AbstractPlot) = (CURRENT_PLOT.nullableplot = Nullable(plot))
current(plot::AbstractPlot) = (CURRENT_PLOT.nullableplot = plot)
# ---------------------------------------------------------
@@ -29,7 +33,7 @@ convertSeriesIndex(plt::Plot, n::Int) = n
"""
The main plot command. Use `plot` to create a new plot object, and `plot!` to add to an existing one:
The main plot command. Use `plot` to create a new plot object, and `plot!` to add to an existing one:
```
plot(args...; kw...) # creates a new plot window, and sets it to be the current
@@ -38,11 +42,12 @@ The main plot command. Use `plot` to create a new plot object, and `plot!` to a
```
There are lots of ways to pass in data, and lots of keyword arguments... just try it and it will likely work as expected.
When you pass in matrices, it splits by columns. See the documentation for more info.
When you pass in matrices, it splits by columns. To see the list of available attributes, use the `plotattr([attr])`
function, where `attr` is the symbol `:Series:`, `:Subplot:`, `:Plot` or `:Axis`. Pass any attribute to `plotattr`
as a String to look up its docstring; e.g. `plotattr("seriestype")`.
"""
# this creates a new plot with args/kw and sets it to be the current plot
function plot(args...; kw...)
# this creates a new plot with args/kw and sets it to be the current plot
d = KW(kw)
preprocessArgs!(d)
@@ -60,7 +65,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
# build our plot vector from the args
n = length(plts_tail) + 1
plts = Array(Plot, n)
plts = Array{Plot}(undef, n)
plts[1] = plt1
for (i,plt) in enumerate(plts_tail)
plts[i+1] = plt
@@ -80,7 +85,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
# TODO: replace this with proper processing from a merged user_attr KW
# update plot args, first with existing plots, then override with d
for p in plts
_update_plot_args(plt, p.attr)
_update_plot_args(plt, copy(p.attr))
plt.n += p.n
end
_update_plot_args(plt, d)
@@ -89,8 +94,21 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
plt.o = _create_backend_figure(plt)
plt.init = true
# create the layout and initialize the subplots
series_attr = KW()
for (k,v) in d
if haskey(_series_defaults, k)
series_attr[k] = pop!(d,k)
end
end
# create the layout
plt.layout, plt.subplots, plt.spmap = build_layout(layout, num_sp, copy(plts))
# do we need to link any axes together?
link_axes!(plt.layout, plt[:link])
# initialize the subplots
cmdidx = 1
for (idx, sp) in enumerate(plt.subplots)
_initialize_subplot(plt, sp)
serieslist = series_list(sp)
@@ -100,8 +118,11 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
sp.plt = plt
sp.attr[:subplot_index] = idx
for series in serieslist
merge!(series.d, series_attr)
_add_defaults!(series.d, plt, sp, cmdidx)
push!(plt.series_list, series)
_series_added(plt, series)
cmdidx += 1
end
end
@@ -110,14 +131,9 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
_update_subplot_args(plt, sp, d, idx, false)
end
# do we need to link any axes together?
link_axes!(plt.layout, plt[:link])
# finish up
current(plt)
if get(d, :show, default(:show))
gui()
end
_do_plot_show(plt, get(d, :show, default(:show)))
plt
end
@@ -148,7 +164,12 @@ end
# a list of series KW dicts.
# note: at entry, we only have those preprocessed args which were passed in... no default values yet
function _plot!(plt::Plot, d::KW, args::Tuple)
# d[:plot_object] = plt
d[:plot_object] = plt
if !isempty(args) && !isdefined(Main, :StatPlots) &&
first(split(string(typeof(args[1])), ".")) == "DataFrames"
@warn("You're trying to plot a DataFrame, but this functionality is provided by StatPlots")
end
# --------------------------------
# "USER RECIPES"
@@ -156,6 +177,9 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
kw_list = _process_userrecipes(plt, d, args)
# info(1)
# map(DD, kw_list)
# --------------------------------
# "PLOT RECIPES"
@@ -168,10 +192,13 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
still_to_process = kw_list
kw_list = KW[]
while !isempty(still_to_process)
next_kw = shift!(still_to_process)
next_kw = popfirst!(still_to_process)
_process_plotrecipe(plt, next_kw, kw_list, still_to_process)
end
# info(2)
# map(DD, kw_list)
# --------------------------------
# Plot/Subplot/Layout setup
# --------------------------------
@@ -184,7 +211,10 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
# --------------------------------
# "SERIES RECIPES"
# --------------------------------
# info(3)
# map(DD, kw_list)
for kw in kw_list
sp::Subplot = kw[:subplot]
# idx = get_subplot_index(plt, sp)
@@ -209,9 +239,10 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
current(plt)
# do we want to force display?
if plt[:show]
gui(plt)
end
# if plt[:show]
# gui(plt)
# end
_do_plot_show(plt, plt[:show])
plt
end
@@ -242,7 +273,7 @@ function prepare_output(plt::Plot)
_update_plot_object(plt)
end
function prepared_object(plt::Plot)
function backend_object(plt::Plot)
prepare_output(plt)
plt.o
end
+62
View File
@@ -0,0 +1,62 @@
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
"""
plotattr([attr])
Look up the properties of a Plots attribute, or specify an attribute type. Call `plotattr()` for options.
The information is the same as that given on https://juliaplots.github.io/attributes/.
"""
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
-465
View File
@@ -1,468 +1,3 @@
function _precompile_()
ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
precompile(Plots.py_add_series, (Plots.Plot{Plots.PyPlotBackend}, Plots.Series,))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Array{Float64, 1},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Base.StepRange{Int64, Int64},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Function,))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Array{Plots.OHLC, 1},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Array{Float64, 1},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Base.LinSpace{Float64},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, DataFrames.DataFrame,))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Array{Int64, 1},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Array{Union{UTF8String, ASCIIString}, 1},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Array{Function, 1},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Array{ASCIIString, 1},))
precompile(Plots._plot!, (Plots.Plot{Plots.UnicodePlotsBackend}, Base.Dict{Symbol, Any},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Base.FloatRange{Float64},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any},))
precompile(Plots._plot!, (Plots.Plot{Plots.UnicodePlotsBackend}, Base.Dict{Symbol, Any}, Array{Float64, 1},))
precompile(Plots._plot!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Array{Float64, 2},))
precompile(Plots._add_defaults!, (Base.Dict{Symbol, Any}, Plots.Plot{Plots.UnicodePlotsBackend}, Plots.Subplot{Plots.UnicodePlotsBackend}, Int64,))
precompile(Plots._before_layout_calcs, (Plots.Plot{Plots.PyPlotBackend},))
precompile(Plots._apply_series_recipe, (Plots.Plot{Plots.UnicodePlotsBackend}, Base.Dict{Symbol, Any},))
precompile(Plots._add_defaults!, (Base.Dict{Symbol, Any}, Plots.Plot{Plots.PyPlotBackend}, Plots.Subplot{Plots.PyPlotBackend}, Int64,))
precompile(Plots._apply_series_recipe, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any},))
precompile(Plots.setup_ijulia, ())
precompile(Plots.call, (Type{Plots.Plot{Plots.UnicodePlotsBackend}}, Plots.UnicodePlotsBackend, Int64, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Array{Plots.Series, 1}, Void, Array{Plots.Subplot, 1}, Base.Dict{Any, Plots.Subplot}, Plots.EmptyLayout, Array{Plots.Subplot, 1}, Bool,))
precompile(Plots.expand_extrema!, (Plots.Subplot{Plots.UnicodePlotsBackend}, Base.Dict{Symbol, Any},))
precompile(Plots.create_grid_vcat, (Expr,))
precompile(Plots.expand_extrema!, (Plots.Subplot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any},))
precompile(Plots.update_child_bboxes!, (Plots.GridLayout, Array{Measures.Length{:mm, Float64}, 1},))
precompile(Plots.preprocessArgs!, (Base.Dict{Symbol, Any},))
precompile(Plots.call, (Type{Plots.Plot{Plots.PyPlotBackend}}, Plots.PyPlotBackend, Int64, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Array{Plots.Series, 1}, Void, Array{Plots.Subplot, 1}, Base.Dict{Any, Plots.Subplot}, Plots.EmptyLayout, Array{Plots.Subplot, 1}, Bool,))
precompile(Plots.fix_xy_lengths!, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any},))
precompile(Plots._update_min_padding!, (Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.warnOnUnsupported_args, (Plots.PyPlotBackend, Base.Dict{Symbol, Any},))
precompile(Plots.build_layout, (Plots.GridLayout, Int64,))
precompile(Plots.build_layout, (Plots.GridLayout, Int64, Array{Plots.Plot, 1},))
precompile(Plots.warnOnUnsupported, (Plots.UnicodePlotsBackend, Base.Dict{Symbol, Any},))
precompile(Plots.link_axes!, (Plots.GridLayout, Symbol,))
precompile(Plots.warnOnUnsupported, (Plots.PyPlotBackend, Base.Dict{Symbol, Any},))
precompile(Plots._update_plot_args, (Plots.Plot{Plots.UnicodePlotsBackend}, Base.Dict{Symbol, Any},))
precompile(Plots.font, (Int64,))
precompile(Plots.recompute_lengths, (Array{Measures.Measure, 1},))
precompile(Plots._update_plot_object, (Plots.Plot{Plots.PyPlotBackend},))
precompile(Plots.font, (Symbol,))
precompile(Plots.create_grid, (Expr,))
precompile(Plots.slice_arg!, (Array{Any, 1}, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Void, Int64,))
precompile(Plots.pickDefaultBackend, ())
precompile(Plots.default_should_widen, (Plots.Axis,))
precompile(Plots.setup_atom, ())
precompile(Plots.slice_arg!, (Array{Any, 1}, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Symbol, Int64,))
precompile(Plots.my_hist_2d, (Array{Any, 1}, Array{Float64, 1}, Array{Float64, 1}, Int64,))
precompile(Plots.slice_arg!, (Array{Any, 1}, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, ASCIIString, Int64,))
precompile(Plots.create_grid_curly, (Expr,))
precompile(Plots.slice_arg!, (Array{Any, 1}, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Bool, Int64,))
precompile(Plots.slice_arg!, (Array{Any, 1}, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Int64, Int64,))
precompile(Plots.my_hist, (Array{Any, 1}, Array{Float64, 1}, Int64,))
precompile(Plots.getpctrange, (Int64,))
precompile(Plots.call, (Type{Plots.ColorGradient}, Array{Symbol, 1},))
precompile(Plots.default, (Symbol,))
precompile(Plots.process_axis_arg!, (Base.Dict{Symbol, Any}, Symbol, Symbol,))
precompile(Plots.pie_labels, (Plots.Subplot{Plots.PyPlotBackend}, Plots.Series,))
precompile(Plots.slice_arg!, (Array{Any, 1}, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Measures.Length{:mm, Float64}, Int64,))
precompile(Plots.py_path, (Array{Float64, 1}, Array{Float64, 1},))
precompile(Plots._update_min_padding!, (Plots.GridLayout,))
precompile(Plots.warnOnUnsupported_scales, (Plots.UnicodePlotsBackend, Base.Dict{Symbol, Any},))
precompile(Plots.slice_arg!, (Array{Any, 1}, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Plots.Font, Int64,))
precompile(Plots.process_axis_arg!, (Base.Dict{Symbol, Any}, Tuple{Int64, Int64}, Symbol,))
precompile(Plots.slice_arg!, (Array{Any, 1}, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Symbol, Array{Any, 1}, Int64,))
precompile(Plots.default, (Symbol, Tuple{Int64, Int64},))
precompile(Plots.warnOnUnsupported_scales, (Plots.PyPlotBackend, Base.Dict{Symbol, Any},))
precompile(Plots.axis_limits, (Plots.Axis, Bool,))
precompile(Plots.default, (Symbol, Bool,))
precompile(Plots.getColorZ, (Plots.ColorGradient, Float64,))
precompile(Plots._update_plot_args, (Plots.Plot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any},))
precompile(Plots.call, (Type{Plots.Surface}, Function, Base.FloatRange{Float64}, Base.FloatRange{Float64},))
precompile(Plots.font, (Symbol,))
precompile(Plots.process_axis_arg!, (Base.Dict{Symbol, Any}, Base.StepRange{Int64, Int64}, Symbol,))
precompile(Plots.call, (Array{Any, 1}, Type{Plots.Subplot}, Plots.UnicodePlotsBackend,))
precompile(Plots.extractGroupArgs, (Array{ASCIIString, 1}, Array{Float64, 1},))
precompile(Plots._update_subplot_args, (Array{Any, 1}, Plots.Plot{Plots.UnicodePlotsBackend}, Plots.Subplot{Plots.UnicodePlotsBackend}, Base.Dict{Symbol, Any}, Int64,))
precompile(Plots.call, (Array{Any, 1}, Type{Plots.Subplot}, Plots.PyPlotBackend,))
precompile(Plots._update_subplot_args, (Array{Any, 1}, Plots.Plot{Plots.PyPlotBackend}, Plots.Subplot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Int64,))
precompile(Plots.extractGroupArgs, (Array{Union{UTF8String, ASCIIString}, 1},))
precompile(Plots.bbox_to_pcts, (Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}}, Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}, Bool,))
precompile(Plots.plot, (Array{Any, 1}, Array{Float64, 1},))
precompile(Plots.py_marker, (Plots.Shape,))
precompile(Plots.getindex, (Plots.Subplot{Plots.UnicodePlotsBackend}, Symbol,))
precompile(Plots.getindex, (Plots.Subplot{Plots.PyPlotBackend}, Symbol,))
precompile(Plots.discrete_value!, (Plots.Axis, Array{Union{UTF8String, ASCIIString}, 1},))
precompile(Plots.prepare_output, (Plots.Plot{Plots.PyPlotBackend},))
precompile(Plots.update_inset_bboxes!, (Plots.Plot{Plots.PyPlotBackend},))
precompile(Plots.add_layout_pct!, (Base.Dict{Symbol, Any}, Expr, Int64, Int64,))
precompile(Plots.process_axis_arg!, (Base.Dict{Symbol, Any}, ASCIIString, Symbol,))
precompile(Plots.call, (Type{Plots.Shape}, Array{Float64, 1}, Array{Float64, 1},))
precompile(Plots.plot, (Array{Any, 1}, Base.LinSpace{Float64}, Array{Float64, 2},))
precompile(Plots.call, (Array{Any, 1}, Type{Plots.EmptyLayout}, Plots.RootLayout,))
precompile(Plots.plot, (Array{Any, 1}, Function, Function,))
precompile(Plots.should_add_to_legend, (Plots.Series,))
precompile(Plots.plot, (Array{Any, 1}, DataFrames.DataFrame, Symbol,))
precompile(Plots.plot, (Array{Any, 1}, Array{Plots.OHLC, 1},))
precompile(Plots.convertToAnyVector, (Array{Float64, 2}, Base.Dict{Symbol, Any},))
precompile(Plots.plot, (Array{Any, 1}, Array{Float64, 1}, Array{Float64, 1},))
precompile(Plots.plot, (Array{Any, 1}, Array{ASCIIString, 1}, Array{Float64, 1},))
precompile(Plots.plot!, (Array{Any, 1}, Plots.Plot{Plots.PyPlotBackend}, Array{Float64, 1},))
precompile(Plots.processLineArg, (Base.Dict{Symbol, Any}, Symbol,))
precompile(Plots.aliasesAndAutopick, (Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Any}, Array{Symbol, 1}, Int64,))
precompile(Plots.plot!, (Array{Any, 1}, Plots.Plot{Plots.PyPlotBackend}, Array{Int64, 1},))
precompile(Plots.pie, (Array{Any, 1}, Array{ASCIIString, 1},))
precompile(Plots.aliasesAndAutopick, (Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Any}, Array{Any, 1}, Int64,))
precompile(Plots.merge_with_base_supported, (Array{Symbol, 1},))
precompile(Plots.histogram2d, (Array{Any, 1}, Array{Float64, 1},))
precompile(Plots.plot, (Array{Any, 1}, Base.StepRange{Int64, Int64}, Array{Float64, 2},))
precompile(Plots.plot, (Array{Any, 1}, Base.LinSpace{Float64}, Array{Float64, 1},))
precompile(Plots.plot, (Array{Any, 1}, Array{Float64, 1}, Array{Float64, 1},))
precompile(Plots.font, ())
precompile(Plots.plot, (Array{Any, 1}, Base.FloatRange{Float64}, Array{Float64, 1},))
precompile(Plots.plot, (Array{Any, 1}, Base.FloatRange{Float64}, Base.FloatRange{Float64},))
precompile(Plots.plot, (Array{Any, 1}, Array{Function, 1}, Array{Float64, 1},))
precompile(Plots.scatter, (Array{Any, 1}, Base.LinSpace{Float64},))
precompile(Plots.plot!, (Array{Any, 1}, Plots.Plot{Plots.PyPlotBackend}, Base.LinSpace{Float64},))
precompile(Plots.plot!, (Array{Any, 1}, Base.LinSpace{Float64}, Array{Float64, 1},))
precompile(Plots.get_zvalues, (Int64,))
precompile(Plots.plot, (Array{Any, 1}, Array{Union{UTF8String, ASCIIString}, 1}, Array{Union{UTF8String, ASCIIString}, 1},))
precompile(Plots.histogram, (Array{Any, 1}, Array{Float64, 1},))
precompile(Plots.hline!, (Array{Any, 1}, Array{Float64, 2},))
precompile(Plots.layout_args, (Base.Dict{Symbol, Any}, Int64,))
precompile(Plots.heatmap, (Array{Any, 1}, Array{Union{UTF8String, ASCIIString}, 1},))
precompile(Plots._replace_linewidth, (Base.Dict{Symbol, Any},))
precompile(Plots.plot!, (Array{Any, 1}, Array{Float64, 1}, Array{Float64, 1},))
precompile(Plots.plot!, (Array{Any, 1}, Plots.Plot{Plots.PyPlotBackend}, Array{Float64, 2},))
precompile(Plots.py_markercolor, (Base.Dict{Symbol, Any},))
precompile(Plots.unzip, (Array{Tuple{Float64, Float64}, 1},))
precompile(Plots.link_axes!, (Array{Plots.AbstractLayout, 2}, Symbol,))
precompile(Plots.plot!, (Array{Any, 1}, Plots.Plot{Plots.PyPlotBackend}, Array{Float64, 1},))
precompile(Plots.contour, (Array{Any, 1}, Base.FloatRange{Float64},))
precompile(Plots.scatter, (Array{Any, 1}, DataFrames.DataFrame,))
precompile(Plots.scatter!, (Array{Any, 1}, Base.LinSpace{Float64},))
precompile(Plots.scatter!, (Array{Any, 1}, Array{Float64, 1},))
precompile(Plots.getxy, (Plots.Plot{Plots.PyPlotBackend}, Int64,))
precompile(Plots.plot, (Array{Any, 1}, Array{Float64, 2},))
precompile(Plots.get_xy, (Array{Plots.OHLC, 1}, Base.UnitRange{Int64},))
precompile(Plots.convertToAnyVector, (Array{Function, 1}, Base.Dict{Symbol, Any},))
precompile(Plots.py_add_annotations, (Plots.Subplot{Plots.PyPlotBackend}, Int64, Float64, Plots.PlotText,))
precompile(Plots.plot!, (Array{Any, 1}, Array{Float64, 1},))
precompile(Plots.get_color_palette, (Symbol, ColorTypes.RGB{Float64}, Int64,))
precompile(Plots.py_add_annotations, (Plots.Subplot{Plots.PyPlotBackend}, Float64, Float64, Plots.PlotText,))
precompile(Plots.py_colormap, (Plots.ColorGradient, Float64,))
precompile(Plots.processMarkerArg, (Base.Dict{Symbol, Any}, Plots.Stroke,))
precompile(Plots.call, (Type{Plots.ColorVector}, Array{Symbol, 1},))
precompile(Plots.py_colormap, (Plots.ColorGradient, Void,))
precompile(Plots.py_fillcolor, (Base.Dict{Symbol, Any},))
precompile(Plots.processLineArg, (Base.Dict{Symbol, Any}, Float64,))
precompile(Plots.plot!, (Array{Any, 1}, Array{Float64, 2},))
precompile(Plots.processMarkerArg, (Base.Dict{Symbol, Any}, Symbol,))
precompile(Plots.call, (Type{Plots.Plot},))
precompile(Plots.call, (Type{Plots.ColorGradient}, Array{ColorTypes.RGBA{Float64}, 1},))
precompile(Plots.plot!, (Array{Any, 1}, Array{Int64, 1},))
precompile(Plots.getExtension, (UTF8String,))
precompile(Plots.call, (Array{Any, 1}, Type{Plots.EmptyLayout},))
precompile(Plots.update!, (Array{Any, 1}, Plots.Axis,))
precompile(Plots.frame, (Plots.Animation, Plots.Plot{Plots.PyPlotBackend},))
precompile(Plots.processMarkerArg, (Base.Dict{Symbol, Any}, Int64,))
precompile(Plots.link_axes!, (Array{Plots.AbstractLayout, 1}, Symbol,))
precompile(Plots.call, (Type{Plots.ColorGradient}, Array{ColorTypes.RGB{Float64}, 1},))
precompile(Plots.fakedata, (Int64,))
precompile(Plots.plot!, (Array{Any, 1}, Plots.Plot{Plots.PyPlotBackend},))
precompile(Plots.py_compute_axis_minval, (Plots.Axis,))
precompile(Plots.processLineArg, (Base.Dict{Symbol, Any}, Int64,))
precompile(Plots.command_idx, (Array{Base.Dict{Symbol, Any}, 1}, Base.Dict{Symbol, Any},))
precompile(Plots.getindex, (Plots.Axis, Symbol,))
precompile(Plots.__init__, ())
precompile(Plots.isvertical, (Base.Dict{Symbol, Any},))
precompile(Plots.getExtension, (ASCIIString,))
precompile(Plots.py_marker, (Symbol,))
precompile(Plots.py_init_subplot, (Plots.Plot{Plots.PyPlotBackend}, Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.processMarkerArg, (Base.Dict{Symbol, Any}, ColorTypes.RGBA{Float64},))
precompile(Plots.bucket_index, (Float64, Base.LinSpace{Float64},))
precompile(Plots.default, (Array{Any, 1},))
precompile(Plots.filter_data!, (Base.Dict{Symbol, Any}, Array{Int64, 1},))
precompile(Plots.call, (Type{Plots.ColorGradient}, Array{Symbol, 1}, Base.LinSpace{Float64},))
precompile(Plots.slice_arg, (Array{Symbol, 2}, Int64,))
precompile(Plots.getindex, (Plots.Plot{Plots.UnicodePlotsBackend}, Symbol,))
precompile(Plots.plot!, (Array{Any, 1},))
precompile(Plots.push!, (Plots.Plot{Plots.PyPlotBackend}, Array{Float64, 1}, Array{Float64, 1},))
precompile(Plots.processMarkerArg, (Base.Dict{Symbol, Any}, Float64,))
precompile(Plots.expand_extrema!, (Plots.Axis, Base.FloatRange{Float64},))
precompile(Plots.getindex, (Plots.Plot{Plots.PyPlotBackend}, Symbol,))
precompile(Plots.handle_dfs, (DataFrames.DataFrame, Base.Dict{Symbol, Any}, ASCIIString, Symbol,))
precompile(Plots.filter_data, (Base.UnitRange{Int64}, Array{Int64, 1},))
precompile(Plots.call, (Type{Plots.ColorWrapper}, ColorTypes.RGBA{Float64},))
precompile(Plots.processMarkerArg, (Base.Dict{Symbol, Any}, Array{Symbol, 2},))
precompile(Plots.processLineArg, (Base.Dict{Symbol, Any}, Array{Symbol, 2},))
precompile(Plots.color_or_nothing!, (Base.Dict{Symbol, Any}, Symbol,))
precompile(Plots.processMarkerArg, (Base.Dict{Symbol, Any}, Plots.Shape,))
precompile(Plots.py_fillcolormap, (Base.Dict{Symbol, Any},))
precompile(Plots.transpose_z, (Base.Dict{Symbol, Any}, Array{Float64, 2}, Bool,))
precompile(Plots.py_linecolor, (Base.Dict{Symbol, Any},))
precompile(Plots.call, (Type{Plots.OHLC}, Float64, Float64, Float64, Float64,))
precompile(Plots.setxy!, (Plots.Plot{Plots.PyPlotBackend}, Tuple{Array{Float64, 1}, Array{Float64, 1}}, Int64,))
precompile(Plots.push!, (Plots.Segments, Float64, Float64, Float64, Float64,))
precompile(Plots.handle_group, (DataFrames.DataFrame, Base.Dict{Symbol, Any},))
precompile(Plots.lightness_from_background, (ColorTypes.RGB{Float64},))
precompile(Plots.expand_extrema!, (Plots.Axis, Base.LinSpace{Float64},))
precompile(Plots.py_bbox, (Array{Any, 1},))
precompile(Plots.py_markerstrokecolor, (Base.Dict{Symbol, Any},))
precompile(Plots.arrow, ())
precompile(Plots.convert, (Type{Array{Float64, 1}}, Base.StepRange{Int64, Int64},))
precompile(Plots.expand_extrema!, (Plots.Axis, Array{Float64, 1},))
precompile(Plots.convertLegendValue, (Symbol,))
precompile(Plots.slice_arg, (Array{Measures.Length{:mm, Float64}, 2}, Int64,))
precompile(Plots.calc_num_subplots, (Plots.GridLayout,))
precompile(Plots.processFillArg, (Base.Dict{Symbol, Any}, Int64,))
precompile(Plots.slice_arg, (Array{Plots.ColorWrapper, 2}, Int64,))
precompile(Plots.slice_arg, (Array{ASCIIString, 2}, Int64,))
precompile(Plots.filter_data, (Array{Float64, 1}, Array{Int64, 1},))
precompile(Plots.py_linecolormap, (Base.Dict{Symbol, Any},))
precompile(Plots.discrete_value!, (Plots.Axis, ASCIIString,))
precompile(Plots.allShapes, (ColorTypes.RGBA{Float64},))
precompile(Plots.expand_extrema!, (Plots.Axis, Array{Int64, 1},))
precompile(Plots.py_color_fix, (Tuple{Float64, Float64, Float64, Float64}, Base.LinSpace{Float64},))
precompile(Plots.discrete_value!, (Plots.Axis, Symbol,))
precompile(Plots.push!, (Plots.Segments, Float64, Int64, Int64, Float64,))
precompile(Plots.expand_extrema!, (Plots.Axis, Plots.Surface{Array{Float64, 2}},))
precompile(Plots.heatmap_edges, (Array{Float64, 1},))
precompile(Plots.expand_extrema!, (Plots.Axis, Base.StepRange{Int64, Int64},))
precompile(Plots.handleColors!, (Base.Dict{Symbol, Any}, Plots.Shape, Symbol,))
precompile(Plots.py_color, (Plots.ColorWrapper, Float64,))
precompile(Plots.call, (Type{Plots.GridLayout}, Int64, Int64,))
precompile(Plots.handleColors!, (Base.Dict{Symbol, Any}, ColorTypes.RGBA{Float64}, Symbol,))
precompile(Plots.handleColors!, (Base.Dict{Symbol, Any}, Bool, Symbol,))
precompile(Plots.hvline_limits, (Plots.Axis,))
precompile(Plots.current, ())
precompile(Plots.handleColors!, (Base.Dict{Symbol, Any}, Float64, Symbol,))
precompile(Plots.compute_gridsize, (Int64, Int64, Int64,))
precompile(Plots.py_color, (ColorTypes.RGB{Float64}, Void,))
precompile(Plots.interpolate_rgb, (ColorTypes.RGBA{Float64}, ColorTypes.RGBA{Float64}, Float64,))
precompile(Plots.expand_extrema!, (Plots.Axis, Base.UnitRange{Int64},))
precompile(Plots.allShapes, (Float64,))
precompile(Plots.warn_on_deprecated_backend, (Symbol,))
precompile(Plots.py_color_fix, (Tuple{Float64, Float64, Float64, Float64}, Array{Int64, 1},))
precompile(Plots.setindex!, (Plots.GridLayout, Plots.EmptyLayout, Int64, Int64,))
precompile(Plots.expand_extrema!, (Plots.Axis, Tuple{Int64, Int64},))
precompile(Plots.allShapes, (Int64,))
precompile(Plots.py_markercolormap, (Base.Dict{Symbol, Any},))
precompile(Plots.interpolate_rgb, (ColorTypes.RGB{Float64}, ColorTypes.RGB{Float64}, Float64,))
precompile(Plots.get_ticks, (Plots.Axis,))
precompile(Plots.backend, ())
precompile(Plots.get_xy, (Plots.OHLC{Float64}, Int64, Float64,))
precompile(Plots.allShapes, (Plots.Stroke,))
precompile(Plots.replaceAliases!, (Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any},))
precompile(Plots._create_backend_figure, (Plots.Plot{Plots.PyPlotBackend},))
precompile(Plots.png, (Plots.Plot{Plots.PyPlotBackend}, UTF8String,))
precompile(Plots.processFillArg, (Base.Dict{Symbol, Any}, Symbol,))
precompile(Plots.allShapes, (Plots.Shape,))
precompile(Plots.handleColors!, (Base.Dict{Symbol, Any}, Plots.Stroke, Symbol,))
precompile(Plots.py_color_fix, (Tuple{Float64, Float64, Float64, Float64}, Array{Float64, 1},))
precompile(Plots.plot, (Array{Float64, 1},))
precompile(Plots.rowsize, (Expr,))
precompile(Plots.get_axis, (Plots.Subplot{Plots.PyPlotBackend}, Symbol,))
precompile(Plots.png, (Plots.Plot{Plots.PyPlotBackend}, ASCIIString,))
precompile(Plots.expand_extrema!, (Plots.Axis, Tuple{Float64, Float64},))
precompile(Plots._markershape_supported, (Plots.PyPlotBackend, Plots.Shape,))
precompile(Plots.processFillArg, (Base.Dict{Symbol, Any}, Bool,))
precompile(Plots.supported_types, (Plots.PyPlotBackend,))
precompile(Plots.get_axis, (Plots.Subplot{Plots.UnicodePlotsBackend}, Symbol,))
precompile(Plots.setindex!, (Plots.GridLayout, Plots.GridLayout, Int64, Int64,))
precompile(Plots.plot, ())
precompile(Plots.py_color_fix, (Tuple{Float64, Float64, Float64, Float64}, Base.FloatRange{Float64},))
precompile(Plots._markershape_supported, (Plots.PyPlotBackend, Symbol,))
precompile(Plots.ok, (Float64, Float64, Int64,))
precompile(Plots.allShapes, (Symbol,))
precompile(Plots._initialize_backend, (Plots.PyPlotBackend,))
precompile(Plots.plot, (Plots.Plot{Plots.PyPlotBackend}, Plots.Plot{Plots.PyPlotBackend},))
precompile(Plots.bar, (Array{Float64, 1},))
precompile(Plots.call, (Type{Plots.ColorGradient}, Array{ColorTypes.RGBA{Float64}, 1}, Base.LinSpace{Float64},))
precompile(Plots.handleColors!, (Base.Dict{Symbol, Any}, Int64, Symbol,))
precompile(Plots.nanappend!, (Array{Float64, 1}, Array{Float64, 1},))
precompile(Plots.autopick, (Array{ColorTypes.RGBA, 1}, Int64,))
precompile(Plots.compute_xyz, (Void, Array{Int64, 1}, Void,))
precompile(Plots._add_markershape, (Base.Dict{Symbol, Any},))
precompile(Plots._backend_instance, (Symbol,))
precompile(Plots.py_color, (ColorTypes.RGBA{Float64}, Float64,))
precompile(Plots.update_child_bboxes!, (Plots.GridLayout,))
precompile(Plots._replace_markershape, (Symbol,))
precompile(Plots.has_black_border_for_default, (Symbol,))
precompile(Plots._filter_input_data!, (Base.Dict{Symbol, Any},))
precompile(Plots.compute_xyz, (Array{Float64, 1}, Array{Float64, 1}, Base.UnitRange{Int64},))
precompile(Plots.text, (ASCIIString, Int64, Symbol,))
precompile(Plots.allShapes, (Array{Symbol, 2},))
precompile(Plots.py_color_fix, (Tuple{Float64, Float64, Float64, Float64}, Base.UnitRange{Int64},))
precompile(Plots.replaceAlias!, (Base.Dict{Symbol, Any}, Symbol, Base.Dict{Symbol, Any},))
precompile(Plots.compute_xyz, (Array{ASCIIString, 1}, Array{Float64, 1}, Void,))
precompile(Plots.layout_args, (Int64,))
precompile(Plots.text, (ASCIIString, Symbol, Int64,))
precompile(Plots.compute_xyz, (Base.FloatRange{Float64}, Base.FloatRange{Float64}, Plots.Surface{Array{Float64, 2}},))
precompile(Plots.all3D, (Base.Dict{Symbol, Any},))
precompile(Plots.cycle, (Array{Plots.Subplot, 1}, Int64,))
precompile(Plots.compute_xyz, (Base.StepRange{Int64, Int64}, Array{Float64, 1}, Void,))
precompile(Plots.plotarea!, (Plots.Subplot{Plots.PyPlotBackend}, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}},))
precompile(Plots.like_surface, (Symbol,))
precompile(Plots.build_layout, (Base.Dict{Symbol, Any},))
precompile(Plots.compute_xyz, (Array{Union{UTF8String, ASCIIString}, 1}, Array{Union{UTF8String, ASCIIString}, 1}, Plots.Surface{Array{Float64, 2}},))
precompile(Plots.py_linestyle, (Symbol, Symbol,))
precompile(Plots.plot!, (Array{Float64, 2},))
precompile(Plots.plot!, (Plots.Plot{Plots.PyPlotBackend}, Array{Float64, 2},))
precompile(Plots.call, (Type{Plots.ColorGradient}, Array{ColorTypes.RGB{Float64}, 1}, Base.LinSpace{Float64},))
precompile(Plots.py_color, (ColorTypes.RGBA{Float64}, Void,))
precompile(Plots.yaxis!, (ASCIIString, Symbol,))
precompile(Plots.compute_xyz, (Base.LinSpace{Float64}, Array{Float64, 1}, Void,))
precompile(Plots.isijulia, ())
precompile(Plots.addExtension, (UTF8String, ASCIIString,))
precompile(Plots.call, (Type{Plots.ColorGradient}, Array{ColorTypes.RGBA{Float64}, 1}, Array{Float64, 1},))
precompile(Plots.expand_extrema!, (Plots.Subplot{Plots.PyPlotBackend}, Float64, Float64, Float64, Float64,))
precompile(Plots.plotarea!, (Plots.GridLayout, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}},))
precompile(Plots.layout_args, (Base.Dict{Symbol, Any},))
precompile(Plots.compute_xyz, (Base.FloatRange{Float64}, Array{Float64, 1}, Void,))
precompile(Plots.addExtension, (ASCIIString, ASCIIString,))
precompile(Plots.handleColors!, (Base.Dict{Symbol, Any}, Symbol, Symbol,))
precompile(Plots._initialize_backend, (Plots.PlotlyBackend,))
precompile(Plots.push!, (Plots.Plot{Plots.PyPlotBackend}, Int64, Float64, Float64,))
precompile(Plots.bbox!, (Plots.Subplot{Plots.PyPlotBackend}, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}},))
precompile(Plots.vline!, (Array{Int64, 1},))
precompile(Plots.supported_markers, (Plots.PyPlotBackend,))
precompile(Plots.bbox!, (Plots.GridLayout, Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}},))
precompile(Plots.stroke, (Int64,))
precompile(Plots.compute_xyz, (Array{Float64, 1}, Array{Float64, 1}, Void,))
precompile(Plots.right, (Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}},))
precompile(Plots.extractGroupArgs, (Symbol, DataFrames.DataFrame, Symbol,))
precompile(Plots.generate_colorgradient, (ColorTypes.RGB{Float64},))
precompile(Plots.expand_extrema!, (Plots.Extrema, Bool,))
precompile(Plots.py_colormap, (Plots.ColorWrapper, Void,))
precompile(Plots.expand_extrema!, (Plots.Extrema, Float64,))
precompile(Plots.contour, (Base.FloatRange{Float64},))
precompile(Plots.bottom, (Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}},))
precompile(Plots.text, (ASCIIString, Symbol,))
precompile(Plots.create_grid, (Symbol,))
precompile(Plots.expand_extrema!, (Plots.Axis, Bool,))
precompile(Plots.handleColors!, (Base.Dict{Symbol, Any}, Array{Symbol, 2}, Symbol,))
precompile(Plots.convertToAnyVector, (Void, Base.Dict{Symbol, Any},))
precompile(Plots.py_dpi_scale, (Plots.Plot{Plots.PyPlotBackend}, Int64,))
precompile(Plots.png, (ASCIIString,))
precompile(Plots.supported_scales, (Plots.PyPlotBackend,))
precompile(Plots.convertColor, (ColorTypes.RGBA{Float64}, Float64,))
precompile(Plots.extendSeriesData, (Array{Float64, 1}, Float64,))
precompile(Plots.compute_xyz, (Void, Array{Float64, 1}, Void,))
precompile(Plots.py_color, (Symbol,))
precompile(Plots.expand_extrema!, (Plots.Extrema, Int64,))
precompile(Plots.supported_styles, (Plots.PyPlotBackend,))
precompile(Plots._initialize_backend, (Plots.UnicodePlotsBackend,))
precompile(Plots._initialize_backend, (Plots.GRBackend,))
precompile(Plots.is3d, (Symbol,))
precompile(Plots.supported_types, (Plots.UnicodePlotsBackend,))
precompile(Plots.compute_xyz, (Array{Float64, 1}, Function, Void,))
precompile(Plots.py_color, (Symbol, Void,))
precompile(Plots.trueOrAllTrue, (Function, Array{Symbol, 2},))
precompile(Plots.typemin, (Measures.Length{:mm, Float64},))
precompile(Plots.expand_extrema!, (Plots.Axis, Float64,))
precompile(Plots.get_subplot_index, (Plots.Plot{Plots.UnicodePlotsBackend}, Plots.Subplot{Plots.UnicodePlotsBackend},))
precompile(Plots.leftpad, (Plots.GridLayout,))
precompile(Plots._update_subplot_args, (Plots.Plot{Plots.UnicodePlotsBackend}, Plots.Subplot{Plots.UnicodePlotsBackend}, Base.Dict{Symbol, Any}, Int64,))
precompile(Plots.centers, (Base.LinSpace{Float64},))
precompile(Plots.expand_extrema!, (Plots.Axis, Int64,))
precompile(Plots.text, (ASCIIString,))
precompile(Plots.convertColor, (ColorTypes.RGB{Float64},))
precompile(Plots.py_color, (Plots.ColorWrapper, Void,))
precompile(Plots.py_color, (Plots.ColorWrapper,))
precompile(Plots.trueOrAllTrue, (Function, Int64,))
precompile(Plots.convertColor, (ColorTypes.RGBA{Float64},))
precompile(Plots.extrema, (Plots.Axis,))
precompile(Plots.top, (Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}},))
precompile(Plots.convertColor, (Symbol,))
precompile(Plots.size, (Plots.Surface{Array{Float64, 2}},))
precompile(Plots.isdark, (ColorTypes.RGB{Float64},))
precompile(Plots.rowsize, (Symbol,))
precompile(Plots.series_list, (Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.convertToAnyVector, (Array{Float64, 1}, Base.Dict{Symbol, Any},))
precompile(Plots.update!, (Plots.Axis,))
precompile(Plots.push!, (Plots.Plot{Plots.PyPlotBackend}, Float64, Array{Float64, 1},))
precompile(Plots.wraptuple, (Bool,))
precompile(Plots.call, (Type{Plots.Shape}, Array{Tuple{Float64, Float64}, 1},))
precompile(Plots.slice_arg, (Base.StepRange{Int64, Int64}, Int64,))
precompile(Plots.sticks_fillfrom, (Void, Int64,))
precompile(Plots.left, (Measures.BoundingBox{Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}, Tuple{Measures.Length{:mm, Float64}, Measures.Length{:mm, Float64}}},))
precompile(Plots.gr, ())
precompile(Plots.leftpad, (Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.supported_markers, ())
precompile(Plots.colorscheme, (Symbol,))
precompile(Plots.convertColor, (ColorTypes.RGB{Float64}, Void,))
precompile(Plots.isscalar, (Int64,))
precompile(Plots.wraptuple, (Int64,))
precompile(Plots.call, (Type{Plots.Plot}, Plots.UnicodePlotsBackend, Int64, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Array{Plots.Series, 1}, Void, Array{Plots.Subplot, 1}, Base.Dict{Any, Plots.Subplot}, Plots.EmptyLayout, Array{Plots.Subplot, 1}, Bool,))
precompile(Plots.supported_styles, ())
precompile(Plots.frame, (Plots.Animation,))
precompile(Plots.toppad, (Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.link_axes!, (Plots.Subplot{Plots.UnicodePlotsBackend}, Symbol,))
precompile(Plots.convertLegendValue, (Bool,))
precompile(Plots.convertColor, (ColorTypes.RGBA{Float64}, Void,))
precompile(Plots.plotly, ())
precompile(Plots.ispositive, (Measures.Length{:mm, Float64},))
precompile(Plots.rightpad, (Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.call, (Type{Plots.GroupBy}, Array{ASCIIString, 1}, Array{Array{Int64, 1}, 1},))
precompile(Plots.px2inch, (Int64,))
precompile(Plots.slice_arg, (Tuple{Int64, Int64}, Int64,))
precompile(Plots.call, (Type{Plots.UnicodePlotsBackend},))
precompile(Plots.trueOrAllTrue, (Function, Symbol,))
precompile(Plots.bottompad, (Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.annotate!, (Array{Tuple{Int64, Float64, Plots.PlotText}, 1},))
precompile(Plots.get_subplot_index, (Plots.Plot{Plots.PyPlotBackend}, Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.call, (Type{Plots.Plot}, Plots.PyPlotBackend, Int64, Base.Dict{Symbol, Any}, Base.Dict{Symbol, Any}, Array{Plots.Series, 1}, Void, Array{Plots.Subplot, 1}, Base.Dict{Any, Plots.Subplot}, Plots.EmptyLayout, Array{Plots.Subplot, 1}, Bool,))
precompile(Plots.title!, (ASCIIString,))
precompile(Plots.slice_arg, (Bool, Int64,))
precompile(Plots.wraptuple, (Float64,))
precompile(Plots.bottompad, (Plots.GridLayout,))
precompile(Plots.py_stepstyle, (Symbol,))
precompile(Plots.link_axes!, (Plots.Subplot{Plots.PyPlotBackend}, Symbol,))
precompile(Plots.call, (Type{Plots.GRBackend},))
precompile(Plots.unicodeplots, ())
precompile(Plots.rightpad, (Plots.GridLayout,))
precompile(Plots.call, (Type{Plots.PlotlyBackend},))
precompile(Plots.py_color, (ColorTypes.RGBA{Float64},))
precompile(Plots.toppad, (Plots.GridLayout,))
precompile(Plots.calc_edges, (Array{Float64, 1}, Int64,))
precompile(Plots.colorscheme, (ColorTypes.RGBA{Float64},))
precompile(Plots.slice_arg, (Int64, Int64,))
precompile(Plots.pyplot, ())
precompile(Plots._update_subplot_args, (Plots.Plot{Plots.PyPlotBackend}, Plots.Subplot{Plots.PyPlotBackend}, Base.Dict{Symbol, Any}, Int64,))
precompile(Plots._series_added, (Plots.Plot{Plots.PyPlotBackend}, Plots.Series,))
precompile(Plots.get_color_palette, (Array{ColorTypes.RGBA, 1}, ColorTypes.RGB{Float64}, Int64,))
precompile(Plots._initialize_subplot, (Plots.Plot{Plots.UnicodePlotsBackend}, Plots.Subplot{Plots.UnicodePlotsBackend},))
precompile(Plots.slice_arg, (Void, Int64,))
precompile(Plots.cycle, (Int64, Int64,))
precompile(Plots._initialize_subplot, (Plots.Plot{Plots.PyPlotBackend}, Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.call, (Type{Plots.PyPlotBackend},))
precompile(Plots.update_child_bboxes!, (Plots.Subplot{Plots.PyPlotBackend}, Array{Measures.Length{:mm, Float64}, 1},))
precompile(Plots.filter_data, (Void, Array{Int64, 1},))
precompile(Plots.slice_arg, (Symbol, Int64,))
precompile(Plots.slice_arg, (ASCIIString, Int64,))
precompile(Plots.layout_args, (Plots.GridLayout,))
precompile(Plots.wraptuple, (Tuple{},))
precompile(Plots.calc_num_subplots, (Plots.EmptyLayout,))
precompile(Plots.wraptuple, (Tuple{Symbol, Float64, Plots.Stroke},))
precompile(Plots.wraptuple, (Tuple{ASCIIString, Tuple{Int64, Int64}, Base.StepRange{Int64, Int64}, Symbol},))
precompile(Plots.wraptuple, (Tuple{Int64, Symbol, Float64, Array{Symbol, 2}},))
precompile(Plots.wraptuple, (Tuple{Int64, Array{Symbol, 2}},))
precompile(Plots.wraptuple, (Tuple{ASCIIString, Symbol},))
precompile(Plots._replace_markershape, (Array{Symbol, 2},))
precompile(Plots.wraptuple, (Tuple{Symbol, Int64},))
precompile(Plots.wraptuple, (Tuple{Array{Symbol, 2}, Int64},))
precompile(Plots.wraptuple, (Tuple{Int64, Symbol, Symbol},))
precompile(Plots.wraptuple, (Tuple{Int64, Float64, Symbol, Plots.Stroke},))
precompile(Plots.wraptuple, (Tuple{Float64, Array{Symbol, 2}, Int64},))
precompile(Plots.py_color, (ColorTypes.RGB{Float64},))
precompile(Plots.wraptuple, (Tuple{Int64, Float64, Symbol},))
precompile(Plots.tovec, (Array{Float64, 1},))
precompile(Plots.get_subplot, (Plots.Plot{Plots.PyPlotBackend}, Plots.Subplot{Plots.PyPlotBackend},))
precompile(Plots.eltype, (Plots.Surface{Array{Float64, 2}},))
precompile(Plots.nobigs, (Array{Float64, 1},))
precompile(Plots.get_subplot, (Plots.Plot{Plots.UnicodePlotsBackend}, Plots.Subplot{Plots.UnicodePlotsBackend},))
precompile(Plots.annotations, (Array{Any, 1},))
precompile(Plots.wraptuple, (Tuple{Int64, Symbol},))
precompile(Plots.colorscheme, (Plots.ColorWrapper,))
precompile(Plots.colorscheme, (Plots.ColorGradient,))
precompile(Plots.text, (Plots.PlotText,))
precompile(Plots._replace_markershape, (Plots.Shape,))
precompile(Plots.wraptuple, (Tuple{Array{Symbol, 2}, Int64, Float64, Plots.Stroke},))
precompile(Plots.wraptuple, (Tuple{Plots.Shape, Int64, ColorTypes.RGBA{Float64}},))
end
+598 -422
View File
File diff suppressed because it is too large Load Diff
+311 -91
View File
@@ -6,21 +6,24 @@
# This should cut down on boilerplate code and allow more focused dispatch on type
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
typealias FuncOrFuncs @compat(Union{Function, AVec{Function}})
const FuncOrFuncs{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))
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(d, :seriestype, :none))
# unknown
convertToAnyVector(x, d::KW) = error("No user recipe defined for $(typeof(x))")
# missing
convertToAnyVector(v::@compat(Void), d::KW) = Any[nothing], nothing
convertToAnyVector(v::Nothing, d::KW) = Any[nothing], nothing
# fixed number of blank series
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing
# numeric vector
convertToAnyVector{T<:Number}(v::AVec{T}, d::KW) = Any[v], nothing
convertToAnyVector(v::AVec{T}, d::KW) where {T<:Number} = Any[v], nothing
# string vector
convertToAnyVector{T<:@compat(AbstractString)}(v::AVec{T}, d::KW) = Any[v], nothing
convertToAnyVector(v::AVec{T}, d::KW) where {T<:AbstractString} = Any[v], nothing
function convertToAnyVector(v::AMat, d::KW)
if all3D(d)
@@ -36,11 +39,14 @@ convertToAnyVector(f::Function, d::KW) = Any[f], nothing
# surface
convertToAnyVector(s::Surface, d::KW) = Any[s], nothing
# volume
convertToAnyVector(v::Volume, d::KW) = Any[v], nothing
# # vector of OHLC
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing
# dates
convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}, d::KW) = Any[dts], nothing
# # dates
convertToAnyVector(dts::AVec{D}, d::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing
# list of things (maybe other vectors, functions, or something else)
function convertToAnyVector(v::AVec, d::KW)
@@ -66,19 +72,19 @@ end
# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array
# result in that array being shared. push!, etc will add too many items to that array
compute_x(x::Void, y::Void, z) = 1:size(z,1)
compute_x(x::Void, y, z) = 1:size(y,1)
compute_x(x::Nothing, y::Nothing, z) = 1:size(z,1)
compute_x(x::Nothing, y, z) = 1:size(y,1)
compute_x(x::Function, y, z) = map(x, y)
compute_x(x, y, z) = copy(x)
# compute_y(x::Void, y::Function, z) = error()
compute_y(x::Void, y::Void, z) = 1:size(z,2)
compute_y(x::Nothing, y::Nothing, z) = 1:size(z,2)
compute_y(x, y::Function, z) = map(y, x)
compute_y(x, y, z) = copy(y)
compute_z(x, y, z::Function) = map(z, x, y)
compute_z(x, y, z::AbstractMatrix) = Surface(z)
compute_z(x, y, z::Void) = nothing
compute_z(x, y, z::Nothing) = nothing
compute_z(x, y, z) = copy(z)
nobigs(v::AVec{BigFloat}) = map(Float64, v)
@@ -93,9 +99,9 @@ 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(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
compute_xyz(x::Nothing, y::FuncOrFuncs{F}, z) where {F<:Function} = error("If you want to plot the function `$y`, you need to define the x values!")
compute_xyz(x::Nothing, y::Nothing, z::FuncOrFuncs{F}) where {F<:Function} = error("If you want to plot the function `$z`, you need to define x and y values!")
compute_xyz(x::Nothing, y::Nothing, z::Nothing) = error("x/y/z are all nothing!")
# --------------------------------------------------------------------
@@ -103,63 +109,120 @@ compute_xyz(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
# we are going to build recipes to do the processing and splitting of the args
# ensure we dispatch to the slicer
immutable SliceIt end
struct SliceIt end
# the catch-all recipes
@recipe function f(::Type{SliceIt}, x, y, z)
# @show "HERE", typeof((x,y,z))
xs, _ = convertToAnyVector(x, d)
ys, _ = convertToAnyVector(y, d)
zs, _ = convertToAnyVector(z, d)
fr = pop!(d, :fillrange, nothing)
# handle data with formatting attached
if typeof(x) <: Formatted
xformatter := x.formatter
x = x.data
end
if typeof(y) <: Formatted
yformatter := y.formatter
y = y.data
end
if typeof(z) <: Formatted
zformatter := z.formatter
z = z.data
end
xs, _ = convertToAnyVector(x, plotattributes)
ys, _ = convertToAnyVector(y, plotattributes)
zs, _ = convertToAnyVector(z, plotattributes)
fr = pop!(plotattributes, :fillrange, nothing)
fillranges, _ = if typeof(fr) <: Number
([fr],nothing)
else
convertToAnyVector(fr, d)
convertToAnyVector(fr, plotattributes)
end
mf = length(fillranges)
rib = pop!(plotattributes, :ribbon, nothing)
ribbons, _ = if typeof(rib) <: Number
([fr],nothing)
else
convertToAnyVector(rib, plotattributes)
end
mr = length(ribbons)
# @show zs
mx = length(xs)
my = length(ys)
mz = length(zs)
# ret = Any[]
for i in 1:max(mx, my, mz)
# add a new series
di = copy(d)
xi, yi, zi = xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)]
# @show i, typeof((xi, yi, zi))
di[:x], di[:y], di[:z] = compute_xyz(xi, yi, zi)
# @show i, typeof((di[:x], di[:y], di[:z]))
if mx > 0 && my > 0 && mz > 0
for i in 1:max(mx, my, mz)
# add a new series
di = copy(plotattributes)
xi, yi, zi = xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)]
di[:x], di[:y], di[:z] = compute_xyz(xi, yi, zi)
# handle fillrange
fr = fillranges[mod1(i,mf)]
di[:fillrange] = isa(fr, Function) ? map(fr, di[:x]) : fr
# handle fillrange
fr = fillranges[mod1(i,mf)]
di[:fillrange] = isa(fr, Function) ? map(fr, di[:x]) : fr
# @show i, di[:x], di[:y], di[:z]
push!(series_list, RecipeData(di, ()))
# handle ribbons
rib = ribbons[mod1(i,mr)]
di[:ribbon] = isa(rib, Function) ? map(rib, di[:x]) : rib
push!(series_list, RecipeData(di, ()))
end
end
nothing # don't add a series for the main block
end
# this is the default "type recipe"... just pass the object through
@recipe f{T<:Any}(::Type{T}, v::T) = v
@recipe f(::Type{T}, v::T) where {T<:Any} = v
# this should catch unhandled "series recipes" and error with a nice message
@recipe f{V<:Val}(::Type{V}, x, y, z) = error("The backend must not support the series type $V, and there isn't a series recipe defined.")
@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.")
_apply_type_recipe(d, v) = RecipesBase.apply_recipe(d, typeof(v), v)[1].args[1]
# Handle type recipes when the recipe is defined on the elements.
# This sort of recipe should return a pair of functions... one to convert to number,
# and one to format tick values.
function _apply_type_recipe(d, v::AbstractArray)
isempty(v) && return Float64[]
args = RecipesBase.apply_recipe(d, typeof(v[1]), v[1])[1].args
if length(args) == 2 && typeof(args[1]) <: Function && typeof(args[2]) <: Function
numfunc, formatter = args
Formatted(map(numfunc, v), formatter)
else
v
end
end
# # special handling for Surface... need to properly unwrap and re-wrap
# function _apply_type_recipe(d, v::Surface)
# T = eltype(v.surf)
# @show T
# if T <: Integer || T <: AbstractFloat
# v
# else
# ret = _apply_type_recipe(d, v.surf)
# if typeof(ret) <: Formatted
# Formatted(Surface(ret.data), ret.formatter)
# else
# v
# end
# end
# end
# don't do anything for ints or floats
_apply_type_recipe(d, v::AbstractArray{T}) where {T<:Union{Integer,AbstractFloat}} = v
# handle "type recipes" by converting inputs, and then either re-calling or slicing
@recipe function f(x, y, z)
did_replace = false
newx = _apply_type_recipe(d, x)
newx = _apply_type_recipe(plotattributes, x)
x === newx || (did_replace = true)
newy = _apply_type_recipe(d, y)
newy = _apply_type_recipe(plotattributes, y)
y === newy || (did_replace = true)
newz = _apply_type_recipe(d, z)
newz = _apply_type_recipe(plotattributes, z)
z === newz || (did_replace = true)
if did_replace
newx, newy, newz
@@ -169,9 +232,9 @@ _apply_type_recipe(d, v) = RecipesBase.apply_recipe(d, typeof(v), v)[1].args[1]
end
@recipe function f(x, y)
did_replace = false
newx = _apply_type_recipe(d, x)
newx = _apply_type_recipe(plotattributes, x)
x === newx || (did_replace = true)
newy = _apply_type_recipe(d, y)
newy = _apply_type_recipe(plotattributes, y)
y === newy || (did_replace = true)
if did_replace
newx, newy
@@ -180,7 +243,7 @@ end
end
end
@recipe function f(y)
newy = _apply_type_recipe(d, y)
newy = _apply_type_recipe(plotattributes, y)
if y !== newy
newy
else
@@ -193,7 +256,7 @@ end
@recipe function f(v1, v2, v3, v4, vrest...)
did_replace = false
newargs = map(v -> begin
newv = _apply_type_recipe(d, v)
newv = _apply_type_recipe(plotattributes, v)
if newv !== v
did_replace = true
end
@@ -210,29 +273,60 @@ end
# # 1 argument
# # --------------------------------------------------------------------
@recipe f(n::Integer) = n, n, n
# 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(plotattributes,: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<:Number}(mat::AMat{T})
if all3D(d)
@recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat}
if all3D(plotattributes)
n,m = size(mat)
wrap_surfaces(plotattributes)
SliceIt, 1:m, 1:n, Surface(mat)
else
SliceIt, nothing, mat, nothing
end
end
# if a matrix is wrapped by Formatted, do similar logic, but wrap data with Surface
@recipe function f(fmt::Formatted{T}) where T<:AbstractMatrix
if all3D(plotattributes)
mat = fmt.data
n,m = size(mat)
wrap_surfaces(plotattributes)
SliceIt, 1:m, 1:n, Formatted(Surface(mat), fmt.formatter)
else
SliceIt, nothing, fmt, nothing
end
end
# assume this is a Volume, so construct one
@recipe function f(vol::AbstractArray{T,3}, args...) where T<:Number
seriestype := :volume
SliceIt, nothing, Volume(vol, args...), nothing
end
# # images - grays
@recipe function f{T<:Gray}(mat::AMat{T})
if nativeImagesSupported()
@recipe function f(mat::AMat{T}) where T<:Gray
n, m = size(mat)
if is_seriestype_supported(:image)
seriestype := :image
n, m = size(mat)
yflip --> true
SliceIt, 1:m, 1:n, Surface(mat)
else
seriestype := :heatmap
yflip --> true
cbar --> false
fillcolor --> ColorGradient([:black, :white])
SliceIt, 1:m, 1:n, Surface(convert(Matrix{Float64}, mat))
end
@@ -240,15 +334,18 @@ end
# # images - colors
@recipe function f{T<:Colorant}(mat::AMat{T})
if nativeImagesSupported()
@recipe function f(mat::AMat{T}) where T<:Colorant
n, m = size(mat)
if is_seriestype_supported(:image)
seriestype := :image
n, m = size(mat)
yflip --> true
SliceIt, 1:m, 1:n, Surface(mat)
else
seriestype := :heatmap
yflip --> true
z, d[:fillcolor] = replace_image_with_heatmap(mat)
cbar --> false
z, plotattributes[:fillcolor] = replace_image_with_heatmap(mat)
SliceIt, 1:m, 1:n, Surface(z)
end
end
@@ -258,30 +355,55 @@ end
@recipe function f(shape::Shape)
seriestype --> :shape
shape_coords(shape)
coords(shape)
end
@recipe function f(shapes::AVec{Shape})
seriestype --> :shape
shape_coords(shapes)
coords(shapes)
end
@recipe function f(shapes::AMat{Shape})
seriestype --> :shape
for j in 1:size(shapes,2)
@series shape_coords(vec(shapes[:,j]))
@series coords(vec(shapes[:,j]))
end
end
#
#
# # function without range... use the current range of the x-axis
# @recipe function f(f::FuncOrFuncs)
# plt = d[:plot_object]
# f, xmin(plt), xmax(plt)
# end
# function without range... use the current range of the x-axis
@recipe function f(f::FuncOrFuncs{F}) where F<:Function
plt = plotattributes[:plot_object]
xmin, xmax = try
axis_limits(plt[1][:xaxis])
catch
xm = tryrange(f, [-5,-1,0,0.01])
xm, tryrange(f, filter(x->x>xm, [5,1,0.99, 0, -0.01]))
end
f, xmin, xmax
end
# try some intervals over which the function may be defined
function tryrange(F::AbstractArray, vec)
rets = [tryrange(f, vec) for f in F] # get the preferred for each
maxind = maximum(indexin(rets, vec)) # get the last attempt that succeeded (most likely to fit all)
rets .= [tryrange(f, vec[maxind:maxind]) for f in F] # ensure that all functions compute there
rets[1]
end
function tryrange(F, vec)
for v in vec
try
tmp = F(v)
return v
catch
end
end
error("$F is not a Function, or is not defined at any of the values $vec")
end
#
# # --------------------------------------------------------------------
# # 2 arguments
@@ -291,8 +413,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::FuncOrFuncs{F}, x) where F<:Function
F2 = typeof(x)
@assert !(F2 <: Function || (F2 <: AbstractArray && F2.parameters[1] <: Function)) # otherwise we'd hit infinite recursion here
x, f
end
@@ -321,6 +444,7 @@ end
# seriestype := :path3d
# end
# end
wrap_surfaces(plotattributes)
SliceIt, x, y, z
end
@@ -330,6 +454,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(plotattributes)
SliceIt, x, y, Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported
end
@@ -337,12 +462,45 @@ end
# # surface-like... matrix grid
@recipe function f(x::AVec, y::AVec, z::AMat)
if !like_surface(get(d, :seriestype, :none))
d[:seriestype] = :contour
if !like_surface(get(plotattributes, :seriestype, :none))
plotattributes[:seriestype] = :contour
end
wrap_surfaces(plotattributes)
SliceIt, x, y, Surface(z)
end
# # images - grays
@recipe function f(x::AVec, y::AVec, mat::AMat{T}) where T<:Gray
if is_seriestype_supported(:image)
seriestype := :image
yflip --> true
SliceIt, x, y, Surface(mat)
else
seriestype := :heatmap
yflip --> true
cbar --> false
fillcolor --> ColorGradient([:black, :white])
SliceIt, x, y, Surface(convert(Matrix{Float64}, mat))
end
end
# # images - colors
@recipe function f(x::AVec, y::AVec, mat::AMat{T}) where T<:Colorant
if is_seriestype_supported(:image)
seriestype := :image
yflip --> true
SliceIt, x, y, Surface(mat)
else
seriestype := :heatmap
yflip --> true
cbar --> false
z, plotattributes[:fillcolor] = replace_image_with_heatmap(mat)
SliceIt, x, y, Surface(z)
end
end
#
#
# # --------------------------------------------------------------------
@@ -351,16 +509,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(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function
xs = Any[adapted_grid(f, (xmin, xmax)) for f in fs]
xs, fs
end
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, u::AVec) where {F<:Function,G<:Function} = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, umin::Number, umax::Number, n = 200) where {F<:Function,G<:Function} = 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(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, u::AVec) where {F<:Function,G<:Function,H<:Function}
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(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, umin::Number, umax::Number, numPoints = 200) where {F<:Function,G<:Function,H<:Function}
fx, fy, fz, linspace(umin, umax, numPoints)
end
@@ -375,28 +540,28 @@ end
#
# # (x,y) tuples
@recipe f{R1<:Number,R2<:Number}(xy::AVec{Tuple{R1,R2}}) = unzip(xy)
@recipe f{R1<:Number,R2<:Number}(xy::Tuple{R1,R2}) = [xy[1]], [xy[2]]
@recipe f(xy::AVec{Tuple{R1,R2}}) where {R1<:Number,R2<:Number} = unzip(xy)
@recipe f(xy::Tuple{R1,R2}) where {R1<:Number,R2<:Number} = [xy[1]], [xy[2]]
#
# # (x,y,z) tuples
@recipe f{R1<:Number,R2<:Number,R3<:Number}(xyz::AVec{Tuple{R1,R2,R3}}) = unzip(xyz)
@recipe f{R1<:Number,R2<:Number,R3<:Number}(xyz::Tuple{R1,R2,R3}) = [xyz[1]], [xyz[2]], [xyz[3]]
@recipe f(xyz::AVec{Tuple{R1,R2,R3}}) where {R1<:Number,R2<:Number,R3<:Number} = unzip(xyz)
@recipe f(xyz::Tuple{R1,R2,R3}) where {R1<:Number,R2<:Number,R3<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
# these might be points+velocity, or OHLC or something else
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(xyuv::AVec{Tuple{R1,R2,R3,R4}}) = get(d,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv)
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(xyuv::Tuple{R1,R2,R3,R4}) = [xyuv[1]], [xyuv[2]], [xyuv[3]], [xyuv[4]]
@recipe f(xyuv::AVec{Tuple{R1,R2,R3,R4}}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = get(plotattributes,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv)
@recipe f(xyuv::Tuple{R1,R2,R3,R4}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = [xyuv[1]], [xyuv[2]], [xyuv[3]], [xyuv[4]]
#
# # 2D FixedSizeArrays
@recipe f{T<:Number}(xy::AVec{FixedSizeArrays.Vec{2,T}}) = unzip(xy)
@recipe f{T<:Number}(xy::FixedSizeArrays.Vec{2,T}) = [xy[1]], [xy[2]]
@recipe f(xy::AVec{FixedSizeArrays.Vec{2,T}}) where {T<:Number} = unzip(xy)
@recipe f(xy::FixedSizeArrays.Vec{2,T}) where {T<:Number} = [xy[1]], [xy[2]]
#
# # 3D FixedSizeArrays
@recipe f{T<:Number}(xyz::AVec{FixedSizeArrays.Vec{3,T}}) = unzip(xyz)
@recipe f{T<:Number}(xyz::FixedSizeArrays.Vec{3,T}) = [xyz[1]], [xyz[2]], [xyz[3]]
@recipe f(xyz::AVec{FixedSizeArrays.Vec{3,T}}) where {T<:Number} = unzip(xyz)
@recipe f(xyz::FixedSizeArrays.Vec{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
#
# # --------------------------------------------------------------------
@@ -416,14 +581,69 @@ end
# nothing
# end
# split the group into 1 series per group, and set the label and idxfilter for each
@recipe function f(groupby::GroupBy, args...)
for (i,glab) in enumerate(groupby.groupLabels)
@series begin
label --> string(glab)
idxfilter --> groupby.groupIds[i]
args
end
end
splittable_kw(key, val, lengthGroup) = false
splittable_kw(key, val::AbstractArray, lengthGroup) = (key != :group) && size(val,1) == lengthGroup
splittable_kw(key, val::Tuple, lengthGroup) = all(splittable_kw.(key, val, lengthGroup))
splittable_kw(key, val::SeriesAnnotations, lengthGroup) = splittable_kw(key, val.strs, lengthGroup)
split_kw(key, val::AbstractArray, indices) = val[indices, fill(Colon(), ndims(val)-1)...]
split_kw(key, val::Tuple, indices) = Tuple(split_kw(key, v, indices) for v in val)
function split_kw(key, val::SeriesAnnotations, indices)
split_strs = split_kw(key, val.strs, indices)
return SeriesAnnotations(split_strs, val.font, val.baseshape, val.scalefactor)
end
function groupedvec2mat(x_ind, x, y::AbstractArray, groupby, def_val = y[1])
y_mat = Array{promote_type(eltype(y), typeof(def_val))}(length(keys(x_ind)), length(groupby.groupLabels))
fill!(y_mat, def_val)
for i in 1:length(groupby.groupLabels)
xi = x[groupby.groupIds[i]]
yi = y[groupby.groupIds[i]]
y_mat[getindex.(x_ind, xi), i] = yi
end
return y_mat
end
groupedvec2mat(x_ind, x, y::Tuple, groupby) = Tuple(groupedvec2mat(x_ind, x, v, groupby) for v in y)
group_as_matrix(t) = false
# split the group into 1 series per group, and set the label and idxfilter for each
@recipe function f(groupby::GroupBy, args...)
lengthGroup = maximum(union(groupby.groupIds...))
if !(group_as_matrix(args[1]))
for (i,glab) in enumerate(groupby.groupLabels)
@series begin
label --> string(glab)
idxfilter --> groupby.groupIds[i]
for (key,val) in plotattributes
if splittable_kw(key, val, lengthGroup)
:($key) := split_kw(key, val, groupby.groupIds[i])
end
end
args
end
end
else
g = args[1]
if length(g.args) == 1
x = zeros(Int, lengthGroup)
for indexes in groupby.groupIds
x[indexes] = 1:length(indexes)
end
last_args = g.args
else
x = g.args[1]
last_args = g.args[2:end]
end
x_u = unique(x)
x_ind = Dict(zip(x_u, 1:length(x_u)))
for (key,val) in plotattributes
if splittable_kw(key, val, lengthGroup)
:($key) := groupedvec2mat(x_ind, x, val, groupby)
end
end
label --> reshape(groupby.groupLabels, 1, :)
typeof(g)((x_u, (groupedvec2mat(x_ind, x, arg, groupby, NaN) for arg in last_args)...))
end
end
+10 -4
View File
@@ -1,8 +1,9 @@
function Subplot{T<:AbstractBackend}(::T; parent = RootLayout())
function Subplot(::T; parent = RootLayout()) where T<:AbstractBackend
Subplot{T}(
parent,
Series[],
(20mm, 5mm, 2mm, 10mm),
defaultbox,
defaultbox,
@@ -12,6 +13,11 @@ function Subplot{T<:AbstractBackend}(::T; parent = RootLayout())
)
end
"""
plotarea(subplot)
Return the bounding box of a subplot
"""
plotarea(sp::Subplot) = sp.plotarea
plotarea!(sp::Subplot, bbox::BoundingBox) = (sp.plotarea = bbox)
@@ -31,14 +37,14 @@ get_subplot(plt::Plot, k) = plt.spmap[k]
get_subplot(series::Series) = series.d[:subplot]
get_subplot_index(plt::Plot, idx::Integer) = Int(idx)
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(_ -> _ === sp, plt.subplots)
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(x -> x === sp, plt.subplots)
series_list(sp::Subplot) = filter(series -> series.d[:subplot] === sp, sp.plt.series_list)
series_list(sp::Subplot) = sp.series_list # filter(series -> series.d[:subplot] === sp, sp.plt.series_list)
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
))
+163 -60
View File
@@ -1,65 +1,168 @@
"""
theme(s::Symbol)
const _invisible = RGBA(0,0,0,0)
Specify the colour theme for plots.
"""
function theme(s::Symbol; kw...)
defaults = _get_defaults(s)
_theme(s, defaults; kw...)
end
const _themes = KW(
:default => KW(
:bg => :white,
:bglegend => :match,
:bginside => :match,
:bgoutside => :match,
:fg => :auto,
:fglegend => :match,
:fggrid => :match,
:fgaxis => :match,
:fgtext => :match,
:fgborder => :match,
:fgguide => :match,
)
function _get_defaults(s::Symbol)
thm = PlotThemes._themes[s]
if :defaults in fieldnames(thm)
return thm.defaults
else # old PlotTheme type
defaults = KW(
:bg => thm.bg_secondary,
:bginside => thm.bg_primary,
:fg => thm.lines,
:fgtext => thm.text,
:fgguide => thm.text,
:fglegend => thm.text,
:palette => thm.palette,
)
if thm.gradient != nothing
push!(defaults, :gradient => thm.gradient)
end
return defaults
end
end
function _theme(s::Symbol, defaults::KW; kw...)
# Reset to defaults to overwrite active theme
reset_defaults()
# Set the theme's gradient as default
if haskey(defaults, :gradient)
PlotUtils.clibrary(:misc)
PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s))
else
PlotUtils.clibrary(:Plots)
PlotUtils.default_cgrad(default = :sequential, sequential = :inferno)
end
# maybe overwrite the theme's gradient
kw = KW(kw)
if haskey(kw, :gradient)
kwgrad = pop!(kw, :gradient)
for clib in clibraries()
if kwgrad in cgradients(clib)
PlotUtils.clibrary(clib)
PlotUtils.default_cgrad(default = :sequential, sequential = kwgrad)
break
end
end
end
# Set the theme's defaults
default(; defaults..., kw...)
return
end
@deprecate set_theme(s) theme(s)
@userplot ShowTheme
_color_functions = KW(
:protanopic => protanopic,
:deuteranopic => deuteranopic,
:tritanopic => tritanopic,
)
_get_showtheme_args(thm::Symbol) = thm, identity
_get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func, identity)
@recipe function showtheme(st::ShowTheme)
thm, cfunc = _get_showtheme_args(st.args...)
defaults = _get_defaults(thm)
# get the gradient
gradient_colors = get(defaults, :gradient, cgrad(:inferno).colors)
gradient = cgrad(cfunc.(RGB.(gradient_colors)))
# get the palette
palette = get(defaults, :palette, get_color_palette(:auto, plot_color(:white), 17))
palette = cfunc.(RGB.(palette))
# apply the theme
for k in keys(defaults)
k in (:gradient, :palette) && continue
def = defaults[k]
arg = get(_keyAliases, k, k)
plotattributes[arg] = if typeof(def) <: Colorant
cfunc(RGB(def))
elseif eltype(def) <: Colorant
cfunc.(RGB.(def))
elseif occursin("color", string(arg))
cfunc.(RGB.(plot_color.(def)))
else
def
end
end
srand(1)
label := ""
colorbar := false
layout := (2, 3)
for j in 1:4
@series begin
subplot := 1
palette := palette
seriestype := :path
cumsum(randn(50))
end
@series begin
subplot := 2
seriestype := :scatter
palette := palette
marker := (:circle, :diamond, :star5, :square)[j]
randn(10), randn(10)
end
end
@series begin
subplot := 3
seriestype := :histogram
palette := palette
randn(1000) .+ (0:2:4)'
end
f(r) = sin(r) / r
_norm(x, y) = norm([x, y])
x = y = linspace(-3π, 3π, 30)
z = f.(_norm.(x, y'))
wi = 2:3:30
@series begin
subplot := 4
seriestype := :heatmap
seriescolor := gradient
ticks := -5:5:5
x, y, z
end
@series begin
subplot := 5
seriestype := :surface
seriescolor := gradient
x, y, z
end
n = 100
ts = linspace(0, 10π, n)
x = ts .* cos.(ts)
y = (0.1ts) .* sin.(ts)
z = 1:n
@series begin
subplot := 6
seriescolor := gradient
linewidth := 3
line_z := z
x, y, z
end
function add_theme(sym::Symbol, theme::KW)
_themes[sym] = theme
end
# add a new theme, using an existing theme as the base
function add_theme(sym::Symbol;
base = :default, # start with this theme
bg = _themes[base][:bg],
bglegend = _themes[base][:bglegend],
bginside = _themes[base][:bginside],
bgoutside = _themes[base][:bgoutside],
fg = _themes[base][:fg],
fglegend = _themes[base][:fglegend],
fggrid = _themes[base][:fggrid],
fgaxis = _themes[base][:fgaxis],
fgtext = _themes[base][:fgtext],
fgborder = _themes[base][:fgborder],
fgguide = _themes[base][:fgguide],
kw...)
_themes[sym] = merge(KW(
:bg => bg,
:bglegend => bglegend,
:bginside => bginside,
:bgoutside => bgoutside,
:fg => fg,
:fglegend => fglegend,
:fggrid => fggrid,
:fgaxis => fgaxis,
:fgtext => fgtext,
:fgborder => fgborder,
:fgguide => fgguide,
), KW(kw))
end
add_theme(:ggplot2,
bglegend = _invisible,
bginside = :lightgray,
fg = :white,
fglegend = _invisible,
fgtext = :gray,
fgguide = :black
)
function set_theme(sym::Symbol)
default(; _themes[sym]...)
end
+51 -43
View File
@@ -2,59 +2,24 @@
# TODO: I declare lots of types here because of the lacking ability to do forward declarations in current Julia
# I should move these to the relevant files when something like "extern" is implemented
typealias AVec AbstractVector
typealias AMat AbstractMatrix
typealias KW Dict{Symbol,Any}
const AVec = AbstractVector
const AMat = AbstractMatrix
const KW = Dict{Symbol,Any}
immutable PlotsDisplay <: Display end
abstract AbstractBackend
abstract AbstractPlot{T<:AbstractBackend}
abstract AbstractLayout
struct PlotsDisplay <: AbstractDisplay end
# -----------------------------------------------------------
immutable InputWrapper{T}
struct InputWrapper{T}
obj::T
end
wrap{T}(obj::T) = InputWrapper{T}(obj)
wrap(obj::T) where {T} = InputWrapper{T}(obj)
Base.isempty(wrapper::InputWrapper) = false
# -----------------------------------------------------------
# a single subplot
type Subplot{T<:AbstractBackend} <: AbstractLayout
parent::AbstractLayout
minpad::Tuple # leftpad, toppad, rightpad, bottompad
bbox::BoundingBox # the canvas area which is available to this subplot
plotarea::BoundingBox # the part where the data goes
attr::KW # args specific to this subplot
o # can store backend-specific data... like a pyplot ax
plt # the enclosing Plot object (can't give it a type because of no forward declarations)
end
# -----------------------------------------------------------
# simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place
type Axis
sp::Subplot
d::KW
end
type Extrema
emin::Float64
emax::Float64
end
Extrema() = Extrema(Inf, -Inf)
# -----------------------------------------------------------
typealias SubplotMap Dict{Any, Subplot}
# -----------------------------------------------------------
type Series
mutable struct Series
d::KW
end
@@ -63,7 +28,42 @@ attr!(series::Series, v, k::Symbol) = (series.d[k] = v)
# -----------------------------------------------------------
type Plot{T<:AbstractBackend} <: AbstractPlot{T}
# a single subplot
mutable struct Subplot{T<:AbstractBackend} <: AbstractLayout
parent::AbstractLayout
series_list::Vector{Series} # arguments for each series
minpad::Tuple # leftpad, toppad, rightpad, bottompad
bbox::BoundingBox # the canvas area which is available to this subplot
plotarea::BoundingBox # the part where the data goes
attr::KW # args specific to this subplot
o # can store backend-specific data... like a pyplot ax
plt # the enclosing Plot object (can't give it a type because of no forward declarations)
end
Base.show(io::IO, sp::Subplot) = print(io, "Subplot{$(sp[:subplot_index])}")
# -----------------------------------------------------------
# simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place
mutable struct Axis
sps::Vector{Subplot}
d::KW
end
mutable struct Extrema
emin::Float64
emax::Float64
end
Extrema() = Extrema(Inf, -Inf)
# -----------------------------------------------------------
const SubplotMap = Dict{Any, Subplot}
# -----------------------------------------------------------
mutable struct Plot{T<:AbstractBackend} <: AbstractPlot{T}
backend::T # the backend type
n::Int # number of series
attr::KW # arguments for the whole plot
@@ -86,10 +86,18 @@ end
# -----------------------------------------------------------------------
Base.getindex(plt::Plot, i::Integer) = plt.subplots[i]
Base.length(plt::Plot) = length(plt.subplots)
Base.endof(plt::Plot) = length(plt)
Base.getindex(plt::Plot, r::Integer, c::Integer) = plt.layout[r,c]
Base.size(plt::Plot) = size(plt.layout)
Base.size(plt::Plot, i::Integer) = size(plt.layout)[i]
Base.ndims(plt::Plot) = 2
# attr(plt::Plot, k::Symbol) = plt.attr[k]
# attr!(plt::Plot, v, k::Symbol) = (plt.attr[k] = v)
Base.getindex(sp::Subplot, i::Integer) = series_list(sp)[i]
Base.endof(sp::Subplot) = length(series_list(sp))
# -----------------------------------------------------------------------
+522 -93
View File
@@ -3,8 +3,8 @@ calcMidpoints(edges::AbstractVector) = Float64[0.5 * (edges[i] + edges[i+1]) for
"Make histogram-like bins of data"
function binData(data, nbins)
lo, hi = extrema(data)
edges = collect(linspace(lo, hi, nbins+1))
lo, hi = ignorenan_extrema(data)
edges = collect(range(lo, stop=hi, length=nbins+1))
midpoints = calcMidpoints(edges)
buckets = Int[max(2, min(searchsortedfirst(edges, x), length(edges)))-1 for x in data]
counts = zeros(Int, length(midpoints))
@@ -109,17 +109,17 @@ function regressionXY(x, y)
β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y)
# make a line segment
regx = [minimum(x), maximum(x)]
regx = [ignorenan_minimum(x), ignorenan_maximum(x)]
regy = β * regx + α
regx, regy
end
function replace_image_with_heatmap{T<:Colorant}(z::Array{T})
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
@show T, size(z)
n, m = size(z)
# idx = 0
colors = ColorGradient(vec(z))
newz = reshape(linspace(0, 1, n*m), n, m)
newz = reshape(range(0, stop=1, length=n*m), n, m)
newz, colors
# newz = zeros(n, m)
# for i=1:n, j=1:m
@@ -131,21 +131,21 @@ function replace_image_with_heatmap{T<:Colorant}(z::Array{T})
end
function imageHack(d::KW)
:heatmap in supported_types() || error("Neither :image or :heatmap are supported!")
is_seriestype_supported(:heatmap) || error("Neither :image or :heatmap are supported!")
d[:seriestype] = :heatmap
d[:z], d[:fillcolor] = replace_image_with_heatmap(d[:z].surf)
end
# ---------------------------------------------------------------
type Segments{T}
"Build line segments for plotting"
mutable struct Segments{T}
pts::Vector{T}
end
# Segments() = Segments{Float64}(zeros(0))
Segments() = Segments(Float64)
Segments{T}(::Type{T}) = Segments(T[])
Segments(::Type{T}) where {T} = Segments(T[])
Segments(p::Int) = Segments(NTuple{2,Float64}[])
@@ -157,7 +157,7 @@ to_nan(::Type{NTuple{2,Float64}}) = (NaN, NaN)
coords(segs::Segments{Float64}) = segs.pts
coords(segs::Segments{NTuple{2,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts]
function Base.push!{T}(segments::Segments{T}, vs...)
function Base.push!(segments::Segments{T}, vs...) where T
if !isempty(segments.pts)
push!(segments.pts, to_nan(T))
end
@@ -167,7 +167,7 @@ function Base.push!{T}(segments::Segments{T}, vs...)
segments
end
function Base.push!{T}(segments::Segments{T}, vs::AVec)
function Base.push!(segments::Segments{T}, vs::AVec) where T
if !isempty(segments.pts)
push!(segments.pts, to_nan(T))
end
@@ -181,24 +181,43 @@ end
# -----------------------------------------------------
# helper to manage NaN-separated segments
type SegmentsIterator
mutable struct SegmentsIterator
args::Tuple
n::Int
end
function iter_segments(args...)
tup = Plots.wraptuple(args)
n = maximum(map(length, tup))
SegmentsIterator(tup, n)
end
function iter_segments(series::Series)
x, y, z = series[:x], series[:y], series[:z]
if has_attribute_segments(series)
if series[:seriestype] in (:scatter, :scatter3d)
return [[i] for i in 1:length(y)]
else
return [i:(i + 1) for i in 1:(length(y) - 1)]
end
else
segs = UnitRange{Int}[]
args = is3d(series) ? (x, y, z) : (x, y)
for seg in iter_segments(args...)
push!(segs, seg)
end
return segs
end
end
# helpers to figure out if there are NaN values in a list of array types
anynan(i::Int, args::Tuple) = any(a -> !isfinite(cycle(a,i)), args)
anynan(i::Int, args::Tuple) = any(a -> try isnan(_cycle(a,i)) catch MethodError false end, args)
anynan(istart::Int, iend::Int, args::Tuple) = any(i -> anynan(i, args), istart:iend)
allnan(istart::Int, iend::Int, args::Tuple) = all(i -> anynan(i, args), istart:iend)
function Base.start(itr::SegmentsIterator)
nextidx = 1
if anynan(1, itr.args)
if !any(isempty,itr.args) && anynan(1, itr.args)
_, nextidx = next(itr, 1)
end
nextidx
@@ -228,61 +247,72 @@ function Base.next(itr::SegmentsIterator, nextidx::Int)
istart:iend, i
end
# Find minimal type that can contain NaN and x
# To allow use of NaN separated segments with categorical x axis
float_extended_type(x::AbstractArray{T}) where {T} = Union{T,Float64}
float_extended_type(x::AbstractArray{T}) where {T<:Real} = Float64
# ------------------------------------------------------------------------------------
nop() = nothing
notimpl() = error("This has not been implemented yet")
Base.cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
Base.cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
isnothing(x::Nothing) = true
isnothing(x) = false
Base.cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
Base.cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
Base.cycle(v, idx::Int) = v
_cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
_cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
Base.cycle(v::AVec, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
Base.cycle(v::AMat, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
Base.cycle(v, idx::AVec{Int}) = v
_cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
_cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
_cycle(v, idx::Int) = v
Base.cycle(grad::ColorGradient, idx::Int) = cycle(grad.colors, idx)
_cycle(v::AVec, indices::AVec{Int}) = map(i -> _cycle(v,i), indices)
_cycle(v::AMat, indices::AVec{Int}) = map(i -> _cycle(v,i), indices)
_cycle(v, indices::AVec{Int}) = fill(v, length(indices))
_cycle(grad::ColorGradient, idx::Int) = _cycle(grad.colors, idx)
_cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices)
makevec(v::AVec) = v
makevec{T}(v::T) = T[v]
makevec(v::T) where {T} = T[v]
"duplicate a single value, or pass the 2-tuple through"
maketuple(x::Real) = (x,x)
maketuple{T,S}(x::@compat(Tuple{T,S})) = x
maketuple(x::Tuple{T,S}) where {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(fs::AVec{F}, u::AVec) where {F<:Function} = [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]
unzip{X,Y,U,V}(xyuv::AVec{Tuple{X,Y,U,V}}) = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
unzip(xy::AVec{Tuple{X,Y}}) where {X,Y} = [t[1] for t in xy], [t[2] for t in xy]
unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
unzip{T}(xy::AVec{FixedSizeArrays.Vec{2,T}}) = T[t[1] for t in xy], T[t[2] for t in xy]
unzip{T}(xy::FixedSizeArrays.Vec{2,T}) = T[xy[1]], T[xy[2]]
unzip(xy::AVec{FixedSizeArrays.Vec{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy]
unzip(xy::FixedSizeArrays.Vec{2,T}) where {T} = T[xy[1]], T[xy[2]]
unzip{T}(xyz::AVec{FixedSizeArrays.Vec{3,T}}) = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
unzip{T}(xyz::FixedSizeArrays.Vec{3,T}) = T[xyz[1]], T[xyz[2]], T[xyz[3]]
unzip(xyz::AVec{FixedSizeArrays.Vec{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
unzip(xyz::FixedSizeArrays.Vec{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]]
unzip{T}(xyuv::AVec{FixedSizeArrays.Vec{4,T}}) = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
unzip{T}(xyuv::FixedSizeArrays.Vec{4,T}) = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
unzip(xyuv::AVec{FixedSizeArrays.Vec{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
unzip(xyuv::FixedSizeArrays.Vec{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
function _expand_limits(lims, x)
try
e1, e2 = extrema(x)
lims[1] = min(lims[1], e1)
lims[2] = max(lims[2], e2)
e1, e2 = ignorenan_extrema(x)
lims[1] = NaNMath.min(lims[1], e1)
lims[2] = NaNMath.max(lims[2], e2)
# catch err
# warn(err)
catch
end
nothing
end
expand_data(v, n::Integer) = [cycle(v, i) for i=1:n]
expand_data(v, n::Integer) = [_cycle(v, i) for i=1:n]
# if the type exists in a list, replace the first occurence. otherwise add it to the end
function addOrReplace(v::AbstractVector, t::DataType, args...; kw...)
@@ -314,7 +344,7 @@ function replaceAliases!(d::KW, aliases::Dict{Symbol,Symbol})
end
end
createSegments(z) = collect(repmat(z',2,1))[2:end]
createSegments(z) = collect(repeat(reshape(z,1,:),2,1))[2:end]
Base.first(c::Colorant) = c
Base.first(x::Symbol) = x
@@ -322,32 +352,55 @@ Base.first(x::Symbol) = x
sortedkeys(d::Dict) = sort(collect(keys(d)))
"create an (n+1) list of the outsides of heatmap rectangles"
function heatmap_edges(v::AVec)
vmin, vmax = extrema(v)
extra = 0.5 * (vmax-vmin) / (length(v)-1)
vcat(vmin-extra, 0.5 * (v[1:end-1] + v[2:end]), vmax+extra)
const _scale_base = Dict{Symbol, Real}(
:log10 => 10,
:log2 => 2,
:ln => ,
)
function _heatmap_edges(v::AVec)
vmin, vmax = ignorenan_extrema(v)
extra_min = (v[2] - v[1]) / 2
extra_max = (v[end] - v[end - 1]) / 2
vcat(vmin-extra_min, 0.5 * (v[1:end-1] + v[2:end]), vmax+extra_max)
end
"create an (n+1) list of the outsides of heatmap rectangles"
function heatmap_edges(v::AVec, scale::Symbol = :identity)
f, invf = scalefunc(scale), invscalefunc(scale)
map(invf, _heatmap_edges(map(f,v)))
end
function calc_r_extrema(x, y)
xmin, xmax = extrema(x)
ymin, ymax = extrema(y)
r = 0.5 * min(xmax - xmin, ymax - ymin)
extrema(r)
xmin, xmax = ignorenan_extrema(x)
ymin, ymax = ignorenan_extrema(y)
r = 0.5 * NaNMath.min(xmax - xmin, ymax - ymin)
ignorenan_extrema(r)
end
function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y))
rmin, rmax = r_extrema
phi, r = x, y
r = 0.5 * (r - rmin) / (rmax - rmin)
n = max(length(phi), length(r))
x = zeros(n)
y = zeros(n)
theta, r = filter_radial_data(x, y, r_extrema)
r = (r .- rmin) ./ (rmax .- rmin)
x = r.*cos.(theta)
y = r.*sin.(theta)
x, y
end
# Filters radial data for points within the axis limits
function filter_radial_data(theta, r, r_extrema::Tuple{Real, Real})
n = max(length(theta), length(r))
rmin, rmax = r_extrema
x, y = zeros(n), zeros(n)
for i in 1:n
x[i] = cycle(r,i) * cos(cycle(phi,i))
y[i] = cycle(r,i) * sin(cycle(phi,i))
x[i] = _cycle(theta, i)
y[i] = _cycle(r, i)
end
points = map((a, b) -> (a, b), x, y)
filter!(a -> a[2] >= rmin && a[2] <= rmax, points)
x = map(a -> a[1], points)
y = map(a -> a[2], points)
x, y
end
@@ -364,7 +417,7 @@ isatom() = isdefined(Main, :Atom) && Main.Atom.isconnected()
function is_installed(pkgstr::AbstractString)
try
Pkg.installed(pkgstr) === nothing ? false: true
Pkg.installed(pkgstr) === nothing ? false : true
catch
false
end
@@ -386,21 +439,20 @@ isvertical(d::KW) = get(d, :orientation, :vertical) in (:vertical, :v, :vert)
isvertical(series::Series) = isvertical(series.d)
# ticksType{T<:Real,S<:Real}(ticks::@compat(Tuple{T,S})) = :limits
ticksType{T<:Real}(ticks::AVec{T}) = :ticks
ticksType{T<:AbstractString}(ticks::AVec{T}) = :labels
ticksType{T<:AVec,S<:AVec}(ticks::@compat(Tuple{T,S})) = :ticks_and_labels
ticksType(ticks::AVec{T}) where {T<:Real} = :ticks
ticksType(ticks::AVec{T}) where {T<:AbstractString} = :labels
ticksType(ticks::Tuple{T,S}) where {T<:AVec,S<:AVec} = :ticks_and_labels
ticksType(ticks) = :invalid
limsType{T<:Real,S<:Real}(lims::@compat(Tuple{T,S})) = :limits
limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits
limsType(lims::Symbol) = lims == :auto ? :auto : :invalid
limsType(lims) = :invalid
# axis_Symbol(letter, postfix) = Symbol(letter * postfix)
# axis_symbols(letter, postfix...) = map(s -> axis_Symbol(letter, s), postfix)
Base.convert{T<:Real}(::Type{Vector{T}}, rng::Range{T}) = T[x for x in rng]
Base.convert{T<:Real,S<:Real}(::Type{Vector{T}}, rng::Range{S}) = T[x for x in rng]
Base.convert(::Type{Vector{T}}, rng::AbstractRange{T}) where {T<:Real} = T[x for x in rng]
Base.convert(::Type{Vector{T}}, rng::AbstractRange{S}) where {T<:Real,S<:Real} = T[x for x in rng]
Base.merge(a::AbstractVector, b::AbstractVector) = sort(unique(vcat(a,b)))
@@ -445,7 +497,8 @@ end
# for example: PyPlot sends rows to y, so transpose_on_match should be true
function transpose_z(d, z, transpose_on_match::Bool = true)
if d[:match_dimensions] == transpose_on_match
z'
# z'
permutedims(z, [2,1])
else
z
end
@@ -459,7 +512,7 @@ ok(tup::Tuple) = ok(tup...)
# compute one side of a fill range from a ribbon
function make_fillrange_side(y, rib)
frs = zeros(length(y))
for (i, (yi, ri)) in enumerate(zip(y, cycle(rib)))
for (i, (yi, ri)) in enumerate(zip(y, Base.Iterators.cycle(rib)))
frs[i] = yi + ri
end
frs
@@ -470,13 +523,186 @@ function make_fillrange_from_ribbon(kw::KW)
y, rib = kw[:y], kw[:ribbon]
rib = wraptuple(rib)
rib1, rib2 = -first(rib), last(rib)
kw[:ribbon] = nothing
# kw[:ribbon] = nothing
kw[:fillrange] = make_fillrange_side(y, rib1), make_fillrange_side(y, rib2)
(get(kw, :fillalpha, nothing) == nothing) && (kw[:fillalpha] = 0.5)
end
#turn tuple of fillranges to one path
function concatenate_fillrange(x,y::Tuple)
rib1, rib2 = first(y), last(y)
yline = vcat(rib1,(rib2)[end:-1:1])
xline = vcat(x,x[end:-1:1])
return xline, yline
end
function get_sp_lims(sp::Subplot, letter::Symbol)
axis_limits(sp[Symbol(letter, :axis)])
end
"""
xlims([plt])
Returns the x axis limits of the current plot or subplot
"""
xlims(sp::Subplot) = get_sp_lims(sp, :x)
"""
ylims([plt])
Returns the y axis limits of the current plot or subplot
"""
ylims(sp::Subplot) = get_sp_lims(sp, :y)
"""
zlims([plt])
Returns the z axis limits of the current plot or subplot
"""
zlims(sp::Subplot) = get_sp_lims(sp, :z)
xlims(plt::Plot, sp_idx::Int = 1) = xlims(plt[sp_idx])
ylims(plt::Plot, sp_idx::Int = 1) = ylims(plt[sp_idx])
zlims(plt::Plot, sp_idx::Int = 1) = zlims(plt[sp_idx])
xlims(sp_idx::Int = 1) = xlims(current(), sp_idx)
ylims(sp_idx::Int = 1) = ylims(current(), sp_idx)
zlims(sp_idx::Int = 1) = zlims(current(), sp_idx)
function get_clims(sp::Subplot)
zmin, zmax = Inf, -Inf
z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface)
for series in series_list(sp)
for vals in (series[:seriestype] in z_colored_series ? series[:z] : nothing, series[:line_z], series[:marker_z], series[:fill_z])
if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Real)
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals.surf)...)
elseif (vals != nothing) && (eltype(vals) <: Real)
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals)...)
end
end
end
clims = sp[:clims]
if is_2tuple(clims)
isfinite(clims[1]) && (zmin = clims[1])
isfinite(clims[2]) && (zmax = clims[2])
end
return zmin < zmax ? (zmin, zmax) : (-0.1, 0.1)
end
_update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax)
function hascolorbar(series::Series)
st = series[:seriestype]
hascbar = st == :heatmap
if st == :contour
hascbar = (isscalar(series[:levels]) ? (series[:levels] > 1) : (length(series[:levels]) > 1)) && (length(unique(Array(series[:z]))) > 1)
end
if series[:marker_z] != nothing || series[:line_z] != nothing || series[:fill_z] != nothing
hascbar = true
end
# no colorbar if we are creating a surface LightSource
if xor(st == :surface, series[:fill_z] != nothing)
hascbar = true
end
return hascbar
end
function hascolorbar(sp::Subplot)
cbar = sp[:colorbar]
hascbar = false
if cbar != :none
for series in series_list(sp)
if hascolorbar(series)
hascbar = true
end
end
end
hascbar
end
function get_linecolor(series, i::Int = 1)
lc = series[:linecolor]
lz = series[:line_z]
if lz == nothing
isa(lc, ColorGradient) ? lc : plot_color(_cycle(lc, i))
else
cmin, cmax = get_clims(series[:subplot])
grad = isa(lc, ColorGradient) ? lc : cgrad()
grad[clamp((_cycle(lz, i) - cmin) / (cmax - cmin), 0, 1)]
end
end
function get_linealpha(series, i::Int = 1)
_cycle(series[:linealpha], i)
end
function get_linewidth(series, i::Int = 1)
_cycle(series[:linewidth], i)
end
function get_linestyle(series, i::Int = 1)
_cycle(series[:linestyle], i)
end
function get_fillcolor(series, i::Int = 1)
fc = series[:fillcolor]
fz = series[:fill_z]
if fz == nothing
isa(fc, ColorGradient) ? fc : plot_color(_cycle(fc, i))
else
cmin, cmax = get_clims(series[:subplot])
grad = isa(fc, ColorGradient) ? fc : cgrad()
grad[clamp((_cycle(fz, i) - cmin) / (cmax - cmin), 0, 1)]
end
end
function get_fillalpha(series, i::Int = 1)
_cycle(series[:fillalpha], i)
end
function get_markercolor(series, i::Int = 1)
mc = series[:markercolor]
mz = series[:marker_z]
if mz == nothing
isa(mc, ColorGradient) ? mc : plot_color(_cycle(mc, i))
else
cmin, cmax = get_clims(series[:subplot])
grad = isa(mc, ColorGradient) ? mc : cgrad()
grad[clamp((_cycle(mz, i) - cmin) / (cmax - cmin), 0, 1)]
end
end
function get_markeralpha(series, i::Int = 1)
_cycle(series[:markeralpha], i)
end
function get_markerstrokecolor(series, i::Int = 1)
msc = series[:markerstrokecolor]
isa(msc, ColorGradient) ? msc : _cycle(msc, i)
end
function get_markerstrokealpha(series, i::Int = 1)
_cycle(series[:markerstrokealpha], i)
end
function has_attribute_segments(series::Series)
# we want to check if a series needs to be split into segments just because
# of its attributes
for letter in (:x, :y, :z)
# If we have NaNs in the data they define the segments and
# SegmentsIterator is used
series[letter] != nothing && NaN in collect(series[letter]) && return false
end
series[:seriestype] == :shape && return false
# ... else we check relevant attributes if they have multiple inputs
return any((typeof(series[attr]) <: AbstractVector && length(series[attr]) > 1) for attr in [:seriescolor, :seriesalpha, :linecolor, :linealpha, :linewidth, :fillcolor, :fillalpha, :markercolor, :markeralpha, :markerstrokecolor, :markerstrokealpha]) || any(typeof(series[attr]) <: AbstractArray{<:Real} for attr in (:line_z, :fill_z, :marker_z))
end
# ---------------------------------------------------------------
wraptuple(x::@compat(Tuple)) = x
makekw(; kw...) = KW(kw)
wraptuple(x::Tuple) = x
wraptuple(x) = (x,)
trueOrAllTrue(f::Function, x::AbstractArray) = all(f, x)
@@ -484,7 +710,7 @@ trueOrAllTrue(f::Function, x) = f(x)
allLineTypes(arg) = trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg)
allStyles(arg) = trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg)
allShapes(arg) = trueOrAllTrue(a -> get(_markerAliases, a, a) in _allMarkers, arg) ||
allShapes(arg) = trueOrAllTrue(a -> is_marker_supported(get(_markerAliases, a, a)), arg) ||
trueOrAllTrue(a -> isa(a, Shape), arg)
allAlphas(arg) = trueOrAllTrue(a -> (typeof(a) <: Real && a > 0 && a < 1) ||
(typeof(a) <: AbstractFloat && (a == zero(typeof(a)) || a == one(typeof(a)))), arg)
@@ -498,7 +724,7 @@ allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg)
"""
Allows temporary setting of backend and defaults for Plots. Settings apply only for the `do` block. Example:
```
with(:gadfly, size=(400,400), type=:histogram) do
with(:gr, size=(400,400), type=:histogram) do
plot(rand(10))
plot(rand(10))
end
@@ -583,7 +809,7 @@ end
# ---------------------------------------------------------------
# ---------------------------------------------------------------
type DebugMode
mutable struct DebugMode
on::Bool
end
const _debugMode = DebugMode(false)
@@ -620,18 +846,18 @@ end
# used in updating an existing series
extendSeriesByOne(v::UnitRange{Int}, n::Int = 1) = isempty(v) ? (1:n) : (minimum(v):maximum(v)+n)
extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + maximum(v))
extendSeriesData{T}(v::Range{T}, z::Real) = extendSeriesData(float(collect(v)), z)
extendSeriesData{T}(v::Range{T}, z::AVec) = extendSeriesData(float(collect(v)), z)
extendSeriesData{T}(v::AVec{T}, z::Real) = (push!(v, convert(T, z)); v)
extendSeriesData{T}(v::AVec{T}, z::AVec) = (append!(v, convert(Vector{T}, z)); v)
extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + ignorenan_maximum(v))
extendSeriesData(v::AbstractRange{T}, z::Real) where {T} = extendSeriesData(float(collect(v)), z)
extendSeriesData(v::AbstractRange{T}, z::AVec) where {T} = extendSeriesData(float(collect(v)), z)
extendSeriesData(v::AVec{T}, z::Real) where {T} = (push!(v, convert(T, z)); v)
extendSeriesData(v::AVec{T}, z::AVec) where {T} = (append!(v, convert(Vector{T}, z)); v)
# -------------------------------------------------------
# NOTE: backends should implement the following methods to get/set the x/y/z data objects
tovec(v::AbstractVector) = v
tovec(v::Void) = zeros(0)
tovec(v::Nothing) = zeros(0)
function getxy(plt::Plot, i::Integer)
d = plt.series_list[i].d
@@ -642,30 +868,90 @@ function getxyz(plt::Plot, i::Integer)
tovec(d[:x]), tovec(d[:y]), tovec(d[:z])
end
function setxy!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer)
function setxy!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y}
series = plt.series_list[i]
series.d[:x], series.d[:y] = xy
sp = series.d[:subplot]
expand_extrema!(sp.attr[:xaxis], xy[1])
expand_extrema!(sp.attr[:yaxis], xy[2])
reset_extrema!(sp)
_series_updated(plt, series)
end
function setxyz!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z}
series = plt.series_list[i]
series.d[:x], series.d[:y], series.d[:z] = xyz
sp = series.d[:subplot]
expand_extrema!(sp.attr[:xaxis], xyz[1])
expand_extrema!(sp.attr[:yaxis], xyz[2])
expand_extrema!(sp.attr[:zaxis], xyz[3])
reset_extrema!(sp)
_series_updated(plt, series)
end
function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z<:AbstractMatrix}
setxyz!(plt, (xyz[1], xyz[2], Surface(xyz[3])), i)
end
# -------------------------------------------------------
# indexing notation
# Base.getindex(plt::Plot, i::Integer) = getxy(plt, i)
Base.setindex!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer) = setxy!(plt, xy, i)
Base.setindex!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) = setxyz!(plt, xyz, i)
Base.setindex!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y} = (setxy!(plt, xy, i); plt)
Base.setindex!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z} = (setxyz!(plt, xyz, i); plt)
# -------------------------------------------------------
# operate on individual series
function push_x!(series::Series, xi)
push!(series[:x], xi)
expand_extrema!(series[:subplot][:xaxis], xi)
return
end
function push_y!(series::Series, yi)
push!(series[:y], yi)
expand_extrema!(series[:subplot][:yaxis], yi)
return
end
function push_z!(series::Series, zi)
push!(series[:z], zi)
expand_extrema!(series[:subplot][:zaxis], zi)
return
end
function Base.push!(series::Series, yi)
x = extendSeriesByOne(series[:x])
expand_extrema!(series[:subplot][:xaxis], x[end])
series[:x] = x
push_y!(series, yi)
end
Base.push!(series::Series, xi, yi) = (push_x!(series,xi); push_y!(series,yi))
Base.push!(series::Series, xi, yi, zi) = (push_x!(series,xi); push_y!(series,yi); push_z!(series,zi))
# -------------------------------------------------------
function attr!(series::Series; kw...)
d = KW(kw)
preprocessArgs!(d)
for (k,v) in d
if haskey(_series_defaults, k)
series[k] = v
else
warn("unused key $k in series attr")
end
end
_series_updated(series[:subplot].plt, series)
series
end
function attr!(sp::Subplot; kw...)
d = KW(kw)
preprocessArgs!(d)
for (k,v) in d
if haskey(_subplot_defaults, k)
sp[k] = v
else
warn("unused key $k in subplot attr")
end
end
sp
end
# -------------------------------------------------------
# push/append for one series
@@ -719,10 +1005,10 @@ function Base.append!(plt::Plot, i::Integer, x::AVec, y::AVec, z::AVec)
end
# tuples
Base.push!{X,Y}(plt::Plot, xy::Tuple{X,Y}) = push!(plt, 1, xy...)
Base.push!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}) = push!(plt, 1, xyz...)
Base.push!{X,Y}(plt::Plot, i::Integer, xy::Tuple{X,Y}) = push!(plt, i, xy...)
Base.push!{X,Y,Z}(plt::Plot, i::Integer, xyz::Tuple{X,Y,Z}) = push!(plt, i, xyz...)
Base.push!(plt::Plot, xy::Tuple{X,Y}) where {X,Y} = push!(plt, 1, xy...)
Base.push!(plt::Plot, xyz::Tuple{X,Y,Z}) where {X,Y,Z} = push!(plt, 1, xyz...)
Base.push!(plt::Plot, i::Integer, xy::Tuple{X,Y}) where {X,Y} = push!(plt, i, xy...)
Base.push!(plt::Plot, i::Integer, xyz::Tuple{X,Y,Z}) where {X,Y,Z} = push!(plt, i, xyz...)
# -------------------------------------------------------
# push/append for all series
@@ -786,9 +1072,152 @@ mm2px(mm::Real) = float(px / MM_PER_PX)
"Smallest x in plot"
xmin(plt::Plot) = minimum([minimum(series.d[:x]) for series in plt.series_list])
xmin(plt::Plot) = ignorenan_minimum([ignorenan_minimum(series.d[:x]) for series in plt.series_list])
"Largest x in plot"
xmax(plt::Plot) = maximum([maximum(series.d[:x]) for series in plt.series_list])
xmax(plt::Plot) = ignorenan_maximum([ignorenan_maximum(series.d[:x]) for series in plt.series_list])
"Extrema of x-values in plot"
Base.extrema(plt::Plot) = (xmin(plt), xmax(plt))
ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))
# ---------------------------------------------------------------
# get fonts from objects:
titlefont(sp::Subplot) = font(
sp[:titlefontfamily],
sp[:titlefontsize],
sp[:titlefontvalign],
sp[:titlefonthalign],
sp[:titlefontrotation],
sp[:titlefontcolor],
)
legendfont(sp::Subplot) = font(
sp[:legendfontfamily],
sp[:legendfontsize],
sp[:legendfontvalign],
sp[:legendfonthalign],
sp[:legendfontrotation],
sp[:legendfontcolor],
)
tickfont(ax::Axis) = font(
ax[:tickfontfamily],
ax[:tickfontsize],
ax[:tickfontvalign],
ax[:tickfonthalign],
ax[:tickfontrotation],
ax[:tickfontcolor],
)
guidefont(ax::Axis) = font(
ax[:guidefontfamily],
ax[:guidefontsize],
ax[:guidefontvalign],
ax[:guidefonthalign],
ax[:guidefontrotation],
ax[:guidefontcolor],
)
# ---------------------------------------------------------------
# converts unicode scientific notation unsupported by pgfplots and gr
# into a format that works
function convert_sci_unicode(label::AbstractString)
unicode_dict = Dict(
'⁰' => "0",
'¹' => "1",
'²' => "2",
'³' => "3",
'⁴' => "4",
'⁵' => "5",
'⁶' => "6",
'⁷' => "7",
'⁸' => "8",
'⁹' => "9",
'⁻' => "-",
"×10" => "×10^{",
)
for key in keys(unicode_dict)
label = replace(label, key => unicode_dict[key])
end
if occursin("10^{", label)
label = string(label, "}")
end
label
end
function straightline_data(series)
sp = series[:subplot]
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y]
n = length(x)
if n == 2
return straightline_data(xl, yl, x, y)
else
k, r = divrem(n, 3)
if r == 0
xdata, ydata = fill(NaN, n), fill(NaN, n)
for i in 1:k
inds = (3 * i - 2):(3 * i - 1)
xdata[inds], ydata[inds] = straightline_data(xl, yl, x[inds], y[inds])
end
return xdata, ydata
else
error("Misformed data. `straightline_data` either accepts vectors of length 2 or 3k. The provided series has length $n")
end
end
end
function straightline_data(xl, yl, x, y)
x_vals, y_vals = if y[1] == y[2]
if x[1] == x[2]
error("Two identical points cannot be used to describe a straight line.")
else
[xl[1], xl[2]], [y[1], y[2]]
end
elseif x[1] == x[2]
[x[1], x[2]], [yl[1], yl[2]]
else
# get a and b from the line y = a * x + b through the points given by
# the coordinates x and x
b = y[1] - (y[1] - y[2]) * x[1] / (x[1] - x[2])
a = (y[1] - y[2]) / (x[1] - x[2])
# get the data values
xdata = [clamp(x[1] + (x[1] - x[2]) * (ylim - y[1]) / (y[1] - y[2]), xl...) for ylim in yl]
xdata, a .* xdata .+ b
end
# expand the data outside the axis limits, by a certain factor too improve
# plotly(js) and interactive behaviour
factor = 100
x_vals = x_vals .+ (x_vals[2] - x_vals[1]) .* factor .* [-1, 1]
y_vals = y_vals .+ (y_vals[2] - y_vals[1]) .* factor .* [-1, 1]
return x_vals, y_vals
end
function shape_data(series)
sp = series[:subplot]
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y]
factor = 100
for i in eachindex(x)
if x[i] == -Inf
x[i] = xl[1] - factor * (xl[2] - xl[1])
elseif x[i] == Inf
x[i] = xl[2] + factor * (xl[2] - xl[1])
end
end
for i in eachindex(y)
if y[i] == -Inf
y[i] = yl[1] - factor * (yl[2] - yl[1])
elseif y[i] == Inf
y[i] = yl[2] + factor * (yl[2] - yl[1])
end
end
return x, y
end
function construct_categorical_data(x::AbstractArray, axis::Axis)
map(xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)], x)
end
+1 -11
View File
@@ -1,18 +1,8 @@
julia 0.4
RecipesBase
PlotUtils
StatPlots
Reexport
Measures
Showoff
FactCheck
Images
ImageMagick
@osx QuartzImageIO
GR
DataFrames
GR 0.31.0
RDatasets
VisualRegressionTests
UnicodePlots
Glob
+18 -22
View File
@@ -2,21 +2,20 @@
using VisualRegressionTests
# using ExamplePlots
import DataFrames, RDatasets
# import DataFrames, RDatasets
# don't let pyplot use a gui... it'll crash
# note: Agg will set gui -> :none in PyPlot
ENV["MPLBACKEND"] = "Agg"
try
@eval import PyPlot
info("Matplotlib version: $(PyPlot.matplotlib[:__version__])")
end
# ENV["MPLBACKEND"] = "Agg"
# try
# @eval import PyPlot
# info("Matplotlib version: $(PyPlot.matplotlib[:__version__])")
# end
using Plots
using StatPlots
using FactCheck
using Glob
# using StatPlots
using Test
default(size=(500,300))
@@ -24,7 +23,7 @@ default(size=(500,300))
# TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
const _current_plots_version = v"0.8.1"
const _current_plots_version = v"0.17.3"
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
@@ -43,11 +42,8 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
fn = "ref$idx.png"
# firgure out version info
G = glob(joinpath(relpath(refdir), "*"))
# @show refdir fn G
slash = (@windows ? "\\" : "/")
versions = map(fn -> VersionNumber(split(fn, slash)[end]), G)
versions = reverse(sort(versions))
vns = filter(x->x[1] != '.', readdir(refdir))
versions = sort(VersionNumber.(vns), rev = true)
versions = filter(v -> v <= _current_plots_version, versions)
# @show refdir fn versions
@@ -78,12 +74,12 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
png(fn)
end
try
run(`mkdir -p $newdir`)
catch err
display(err)
end
# reffn = joinpath(refdir, "ref$idx.png")
# try
# run(`mkdir -p $newdir`)
# catch err
# display(err)
# end
# # reffn = joinpath(refdir, "ref$idx.png")
# the test
vtest = VisualTest(func, reffn, idx)
@@ -99,7 +95,7 @@ function image_comparison_facts(pkg::Symbol;
for i in 1:length(Plots._examples)
i in skip && continue
if only == nothing || i in only
@fact image_comparison_tests(pkg, i, debug=debug, sigma=sigma, eps=eps) |> success --> true
@test image_comparison_tests(pkg, i, debug=debug, sigma=sigma, eps=eps) |> success == true
end
end
end
+5 -3
View File
@@ -5,9 +5,11 @@ set -ex
sudo apt-get -qq update
# sudo apt-get install -y wkhtmltopdf
sudo apt-get install -y xfonts-75dpi
wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2/wkhtmltox-0.12.2_linux-trusty-amd64.deb
sudo dpkg -i wkhtmltox-0.12.2_linux-trusty-amd64.deb
sudo apt-get install -y xfonts-75dpi xfonts-base
wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.2.1/wkhtmltox-0.12.2.1_linux-precise-amd64.deb
sudo dpkg -i wkhtmltox-0.12.2.1_linux-precise-amd64.deb
# wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2/wkhtmltox-0.12.2_linux-trusty-amd64.deb
# sudo dpkg -i wkhtmltox-0.12.2_linux-trusty-amd64.deb
wkhtmltoimage http://www.google.com test.png
ls
+134 -49
View File
@@ -7,85 +7,170 @@ srand(1234)
default(show=false, reuse=true)
img_eps = isinteractive() ? 1e-2 : 10e-2
# facts("Gadfly") do
# @fact gadfly() --> Plots.GadflyBackend()
# @fact backend() --> Plots.GadflyBackend()
@testset "GR" begin
ENV["PLOTS_TEST"] = "true"
ENV["GKSwstype"] = "100"
@test gr() == Plots.GRBackend()
@test backend() == Plots.GRBackend()
image_comparison_facts(:gr, eps=img_eps, skip = [25, 30])
end
#@testset "PyPlot" begin
# @test pyplot() == Plots.PyPlotBackend()
# @test backend() == Plots.PyPlotBackend()
#
# @fact typeof(plot(1:10)) --> Plots.Plot{Plots.GadflyBackend}
# @fact plot(Int[1,2,3], rand(3)) --> not(nothing)
# @fact plot(sort(rand(10)), rand(Int, 10, 3)) --> not(nothing)
# @fact plot!(rand(10,3), rand(10,3)) --> not(nothing)
# image_comparison_facts(:pyplot, eps=img_eps)
#end
@testset "UnicodePlots" begin
@test unicodeplots() == Plots.UnicodePlotsBackend()
@test backend() == Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
@test isa(plot(rand(10)), Plots.Plot) == true
end
# The plotlyjs testimages return a connection error on travis:
# connect: connection refused (ECONNREFUSED)
# @testset "PlotlyJS" begin
# @test plotlyjs() == Plots.PlotlyJSBackend()
# @test backend() == Plots.PlotlyJSBackend()
#
# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], eps=img_eps)
# if Sys.islinux() && isinteractive()
# image_comparison_facts(:plotlyjs,
# skip=[
# 2, # animation (skipped for speed)
# 27, # (polar plots) takes very long / not working
# 31, # animation (skipped for speed)
# ],
# eps=img_eps)
# end
# end
facts("PyPlot") do
@fact pyplot() --> Plots.PyPlotBackend()
@fact backend() --> Plots.PyPlotBackend()
image_comparison_facts(:pyplot, skip=[], eps=img_eps)
end
# InspectDR returns that error on travis:
# ERROR: LoadError: InitError: Cannot open display:
# in Gtk.GLib.GError(::Gtk.##229#230) at /home/travis/.julia/v0.5/Gtk/src/GLib/gerror.jl:17
facts("GR") do
@fact gr() --> Plots.GRBackend()
@fact backend() --> Plots.GRBackend()
# @linux_only image_comparison_facts(:gr, skip=[], eps=img_eps)
end
facts("Plotly") do
@fact plotly() --> Plots.PlotlyBackend()
@fact backend() --> Plots.PlotlyBackend()
# # until png generation is reliable on OSX, just test on linux
# @linux_only image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], eps=img_eps)
end
# @testset "InspectDR" begin
# @test inspectdr() == Plots.InspectDRBackend()
# @test backend() == Plots.InspectDRBackend()
#
# image_comparison_facts(:inspectdr,
# skip=[
# 2, # animation
# 6, # heatmap not defined
# 10, # heatmap not defined
# 22, # contour not defined
# 23, # pie not defined
# 27, # polar plot not working
# 28, # heatmap not defined
# 31, # animation
# ],
# eps=img_eps)
# end
# facts("Immerse") do
# @fact immerse() --> Plots.ImmerseBackend()
# @fact backend() --> Plots.ImmerseBackend()
# @testset "Plotly" begin
# @test plotly() == Plots.PlotlyBackend()
# @test backend() == Plots.PlotlyBackend()
#
# # # until png generation is reliable on OSX, just test on linux
# # @static Sys.islinux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], eps=img_eps)
# end
# @testset "Immerse" begin
# @test immerse() == Plots.ImmerseBackend()
# @test backend() == Plots.ImmerseBackend()
#
# # as long as we can plot anything without error, it should be the same as Gadfly
# image_comparison_facts(:immerse, only=[1], eps=img_eps)
# end
# facts("PlotlyJS") do
# @fact plotlyjs() --> Plots.PlotlyJSBackend()
# @fact backend() --> Plots.PlotlyJSBackend()
# @testset "PlotlyJS" begin
# @test plotlyjs() == Plots.PlotlyJSBackend()
# @test backend() == Plots.PlotlyJSBackend()
#
# # as long as we can plot anything without error, it should be the same as Plotly
# image_comparison_facts(:plotlyjs, only=[1], eps=img_eps)
# end
facts("UnicodePlots") do
@fact unicodeplots() --> Plots.UnicodePlotsBackend()
@fact backend() --> Plots.UnicodePlotsBackend()
# lets just make sure it runs without error
@fact isa(plot(rand(10)), Plot) --> true
end
# @testset "Gadfly" begin
# @test gadfly() == Plots.GadflyBackend()
# @test backend() == Plots.GadflyBackend()
#
# @test typeof(plot(1:10)) == Plots.Plot{Plots.GadflyBackend}
# @test plot(Int[1,2,3], rand(3)) == not(nothing)
# @test plot(sort(rand(10)), rand(Int, 10, 3)) == not(nothing)
# @test plot!(rand(10,3), rand(10,3)) == not(nothing)
#
# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], eps=img_eps)
# end
facts("Axes") do
@testset "Axes" begin
p = plot()
axis = p.subplots[1][:xaxis]
@fact typeof(axis) --> Axis
@fact Plots.discrete_value!(axis, "HI") --> (0.5, 1)
@fact Plots.discrete_value!(axis, :yo) --> (1.5, 2)
@fact extrema(axis) --> (0.5,1.5)
@fact axis[:discrete_map] --> Dict{Any,Any}(:yo => 2, "HI" => 1)
@test typeof(axis) == Plots.Axis
@test Plots.discrete_value!(axis, "HI") == (0.5, 1)
@test Plots.discrete_value!(axis, :yo) == (1.5, 2)
@test Plots.ignorenan_extrema(axis) == (0.5,1.5)
@test axis[:discrete_map] == Dict{Any,Any}(:yo => 2, "HI" => 1)
Plots.discrete_value!(axis, ["x$i" for i=1:5])
Plots.discrete_value!(axis, ["x$i" for i=0:2])
@fact extrema(axis) --> (0.5, 7.5)
@test Plots.ignorenan_extrema(axis) == (0.5, 7.5)
end
@testset "NoFail" begin
histogram([1, 0, 0, 0, 0, 0])
end
# tests for preprocessing recipes
# @testset "recipes" begin
# user recipe
# type T end
# @recipe function f(::T)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# bg := :yellow
# rand(10)
# end
# plot(T())
# plot recipe
# @recipe function f(::Type{Val{:hiplt}},plt::Plot)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# t := :path
# bg:=:green
# ()
# end
# plot(rand(10),t=:hiplt)
# series recipe
# @recipe function f(::Type{Val{:hi}},x,y,z)
# line := (3,0.3,:red)
# marker := (20,0.5,:blue,:o)
# t := :path
# ()
# end
# plot(rand(10),t=:hiplt)
# end
FactCheck.exitstatus()
end # module
+2 -2
View File
@@ -4,7 +4,7 @@ import SnoopCompile
# This only needs to be run once (to generate "/tmp/plots_compiles.csv")
# SnoopCompile.@snoop "/tmp/plots_compiles.csv" begin
# include(Pkg.dir("Plots", "test","runtests.jl"))
# include(joinpath(dirname(@__FILE__), "runtests.jl"))
# end
# ----------------------------------------------------------
@@ -32,5 +32,5 @@ blacklist = ["MIME"]
pc, discards = SnoopCompile.parcel(data[end:-1:1,2], subst=subst, blacklist=blacklist)
SnoopCompile.write("/tmp/precompile", pc)
pdir = Pkg.dir("Plots")
pdir = joinpath(dirname(@__FILE__), "..")
run(`cp /tmp/precompile/precompile_Plots.jl $pdir/src/precompile.jl`)
+15 -9
View File
@@ -1,28 +1,34 @@
# Pkg.clone("ImageMagick")
# Pkg.build("ImageMagick")
using Pkg
Pkg.add("ImageMagick")
Pkg.build("ImageMagick")
# Pkg.clone("GR")
# Pkg.build("GR")
Pkg.clone("https://github.com/JuliaPlots/PlotReferenceImages.jl.git")
Pkg.checkout("https://github.com/JuliaPlots/PlotReferenceImages.jl.git")
# Pkg.clone("https://github.com/JuliaStats/KernelDensity.jl.git")
Pkg.clone("StatPlots")
# Pkg.add("StatPlots")
Pkg.checkout("PlotUtils")
Pkg.checkout("RecipesBase")
# Pkg.clone("https://github.com/JunoLab/Blink.jl.git")
# Pkg.clone("Blink")
# Pkg.build("Blink")
# import Blink
# Blink.AtomShell.install()
# Pkg.clone("https://github.com/spencerlyon2/PlotlyJS.jl.git")
# Pkg.add("Rsvg")
# Pkg.add("PlotlyJS")
# Pkg.checkout("RecipesBase")
# Pkg.clone("VisualRegressionTests")
# need this to use Conda
ENV["PYTHON"] = ""
Pkg.add("PyPlot")
Pkg.build("PyPlot")
# ENV["PYTHON"] = ""
# Pkg.add("PyPlot")
# Pkg.build("PyPlot")
# Pkg.add("InspectDR")
Pkg.test("Plots"; coverage=false)