Compare commits

...

1842 Commits

Author SHA1 Message Date
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
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
Thomas Breloff 73af635be6 bump version 2016-07-19 11:17:27 -04:00
Thomas Breloff c1c97a5fc1 labelfunc for pyplot 2016-07-19 10:32:23 -04:00
Thomas Breloff 6a97dc8825 extrema fix for bool/nothing 2016-07-18 16:19:58 -04:00
Thomas Breloff d832f34733 travis 2016-07-18 15:53:02 -04:00
Thomas Breloff 859a600b92 travis 2016-07-18 15:38:07 -04:00
Thomas Breloff 6b3cf50f38 travis 2016-07-18 15:21:51 -04:00
Thomas Breloff 3ccd1bc368 added Showoff dependency; fix PLOTS_DEFAULTS; fix auto fill to 0; fix scale warning; tick labels with Showoff; fontsize in GR; travis deps 2016-07-18 15:00:02 -04:00
Thomas Breloff 624d33b96f Merge branch 'master' into dev 2016-07-18 09:13:46 -04:00
Tom Breloff 156f61f526 Merge pull request #391 from odow/axisstyle
pass axis style to PGFPlots
2016-07-16 13:13:59 -04:00
odow fd3a04fce3 pass axis style to PGFPlots 2016-07-16 16:48:46 +12:00
Thomas Breloff 62be4e1274 scalefunc fix and cleanup 2016-07-15 09:09:46 -04:00
Thomas Breloff db096196c9 Merge branch 'master' into dev 2016-07-14 15:47:40 -04:00
Thomas Breloff a0ac70be3c axes log scales, colors, ticks, and more; proper 2D axis drawing in GR 2016-07-14 15:46:44 -04:00
Tom Breloff 1f0f89f83c Merge pull request #389 from odow/patch-1
Legend location in subplot
2016-07-14 13:52:37 -04:00
Thomas Breloff ee706ad8c7 axis_drawing_info and get_ticks; parameterized Segments; GR manual drawing of 2D axes 2016-07-13 16:31:21 -04:00
Oscar Dowson ce31ea8bf3 Legend location in subplot 2016-07-13 10:01:48 +12:00
Thomas Breloff dcab8e3ac2 travis fix 2016-07-12 13:14:53 -04:00
Thomas Breloff 1ad9a7e176 fix fillrange for shape; travis fix 2016-07-12 12:53:03 -04:00
Thomas Breloff f1bd7ab1dc travis fix 2016-07-12 11:53:37 -04:00
Thomas Breloff 79399913d7 NEWS, bumped version; travis fixes; added warnings for moved recipes 2016-07-12 11:23:04 -04:00
Thomas Breloff 4a2e88a81c switched Colors dep for PlotUtils dep; removed DataFrames, boxplot, violin, density and added StatPlots to tests 2016-07-12 10:45:58 -04:00
Thomas Breloff 8d5b748b09 gr heatmap fix; pipeline reorg 2016-07-10 23:26:52 -04:00
Thomas Breloff b2dba8af73 split plot into pipeline 2016-07-10 22:59:05 -04:00
Thomas Breloff c258bc49c3 gr trisurface; closes #387 2016-07-10 22:07:00 -04:00
Thomas Breloff e3e2a354e7 reorg of update_subplot_args; add back recipe, DataFrames; random type stability fixes 2016-07-10 18:12:49 -04:00
Thomas Breloff 32c1c31139 working on _plot organization; switch alias dicts to Dict{Symbol,Symbol}; other type stability changes 2016-07-10 15:50:29 -04:00
Thomas Breloff b8b5a33833 margin default to 1mm 2016-07-09 14:54:44 -04:00
Thomas Breloff 5407fa73f8 plotly redesign for splitting shapes 2016-07-09 13:30:39 -04:00
Thomas Breloff 1cb0c0071b improvements to layout padding; handle axis attr better; fix histogram2d 2016-07-09 12:40:27 -04:00
Thomas Breloff a456ac4c90 pyplot line segments fixes; curves remove line_z logic 2016-07-08 14:36:02 -04:00
Thomas Breloff 71b48427c5 pyplot line segments fix; bar fixes 2016-07-08 13:09:36 -04:00
Thomas Breloff ec06a01b6c pgf fixes 2016-07-08 11:21:26 -04:00
Thomas Breloff e3ccc34a2c ensure_gradient; plotly fixes 2016-07-08 10:12:48 -04:00
Thomas Breloff 396721568f color fixes; add PlotUtils to travis_commands 2016-07-08 09:17:39 -04:00
Thomas Breloff e53ab85745 color fixes; pyplot shape iteration; KernelDensity in travis and warning; attribute accessors 2016-07-07 21:46:34 -04:00
Thomas Breloff 4d99b37def working on colors overhaul; fix for rationals in plotly; closes #382 2016-07-07 14:40:09 -04:00
Thomas Breloff 2e24da3dcd update matrix of Shapes recipe 2016-07-07 09:36:03 -04:00
Thomas Breloff 0cc1bd2dc6 sample ticks if too many discrete values; use get_ticks in plotly to fix discrete ticks; allow ticks==false in pyplot; closes #356 2016-07-06 16:51:54 -04:00
Thomas Breloff aec162c50e fix for discrete bars; closes #365 2016-07-06 16:22:11 -04:00
Thomas Breloff d5e9340f8f bar fix for horizontal orientation 2016-07-06 16:10:01 -04:00
Thomas Breloff 6fe87c4c69 bar_width support in bar and boxplot; close the shape for bar plots; closes #366; closes #377 2016-07-06 15:55:38 -04:00
Tom Breloff 85f0a87213 Merge pull request #372 from anowacki/rainbow_palette
Switch blue and violet in rainbow colour palette.
2016-07-05 10:22:03 -04:00
Thomas Breloff 853f85be2e bug fix for passing vectors to bins; closes #375 2016-07-05 10:18:48 -04:00
Andy Nowacki a7448e3a1d Switch blue and violet in rainbow color palette. 2016-07-04 17:43:25 +01:00
Thomas Breloff 521e753183 string fix; iter_segments change to use unused and skip initial NaNs; working on glvisualize shape type 2016-07-01 17:23:25 -04:00
Thomas Breloff 9193941fd0 version bump; NEWS 2016-07-01 09:01:38 -04:00
Tom Breloff f56c6effe4 Merge pull request #368 from jheinen/dev
Added iTerm2 inline display support for gr
2016-07-01 08:09:34 -04:00
Josef Heinen 4cfcb239c1 Added iTerm2 inline display support for gr
Example:
--------
    using Plots
    gr(display_type=:inline)
    plot(Plots.fakedata(50,5), w=3)
2016-07-01 14:03:16 +02:00
Thomas Breloff a4be274718 pyplot display hack 2016-06-30 21:05:32 -04:00
Thomas Breloff 120f861a27 surface fixes for mis-typed matrices; getindex for Series 2016-06-30 14:08:05 -04:00
Thomas Breloff 7e56d85b83 args fix 2016-06-29 21:58:07 -04:00
Thomas Breloff 20af495581 added display_type and extra_kwargs plot attributes 2016-06-29 16:34:06 -04:00
Thomas Breloff bf94c48225 pyplot fix; new flexible logic for DataFrames 2016-06-29 16:22:16 -04:00
Thomas Breloff 27a68333b1 readme 2016-06-29 14:51:24 -04:00
Thomas Breloff 63f18dd26a vector of seriestypes fix; pycall changed strings to symbols 2016-06-29 14:45:33 -04:00
Thomas Breloff 4ea787743e added contourf; getindex for plt/sp; plot/plot! on a Subplot; fix for pyplot zorder 2016-06-29 13:53:22 -04:00
Thomas Breloff 3a4b881576 switched docs url 2016-06-29 12:31:01 -04:00
Thomas Breloff f087594331 switched docs url 2016-06-29 12:23:42 -04:00
Thomas Breloff 5491e40fd1 bump version; img_eps; remove gr 30 test; attempted fixes for appveyor 2016-06-28 18:04:40 -04:00
Tom Breloff 4b690ec9ad Merge pull request #361 from jheinen/dev
gr: allow simple formulas or LaTeX equations
2016-06-28 10:03:23 -04:00
Josef Heinen 9fecb03b5f gr: allow simple formulas or LaTeX equations 2016-06-28 15:35:32 +02:00
Thomas Breloff de6e3d46ec appveyor fix 2016-06-27 21:49:45 -04:00
Thomas Breloff 3006a26500 revert precompile; add appveyor; gr fixes for markersize, shapes, and legend entries; add GR to tests again; recipe fixes and cleanup 2016-06-27 21:43:57 -04:00
Thomas Breloff 6ffed9387c snoop and precompile; bumped version 2016-06-27 16:52:50 -04:00
Thomas Breloff 558627e7a9 NEWS 2016-06-27 14:02:01 -04:00
Thomas Breloff 4b276f977c revert pyplot heatmap change 2016-06-27 12:25:45 -04:00
Thomas Breloff 99fe4f615d show arg fix; add image to all3D 2016-06-27 12:09:08 -04:00
Thomas Breloff 928c306803 dpi fixes 2016-06-27 10:06:40 -04:00
Thomas Breloff a3eddf8ba7 dpi support for pyplot 2016-06-27 09:20:42 -04:00
Thomas Breloff 78e0ae31af removed chorddiagram 2016-06-26 12:37:06 -04:00
Thomas Breloff 1a90ce0950 recoded boxplot recipe to match violin approach; switched marker to line/fill for shape seriestype: ref #347 2016-06-26 11:36:09 -04:00
Thomas Breloff 2465b3eb5a fallback warnings for missing _writemime and _display 2016-06-26 11:08:06 -04:00
Thomas Breloff 16a2e34e95 writemime fix for Interact; working on glvisualize 2016-06-26 10:34:34 -04:00
Thomas Breloff 5c52d68091 working on glvisualize 2016-06-25 18:06:27 -04:00
Thomas Breloff 1a2e180f4f working on glvisualize 2016-06-25 17:00:45 -04:00
Thomas Breloff 9048053669 working on glvisualize 2016-06-25 10:56:51 -04:00
Thomas Breloff 69b69714cb working on glvisualize 2016-06-24 12:15:21 -04:00
Thomas Breloff 1ecd9f9e19 working on glvisualize 2016-06-24 11:52:33 -04:00
Thomas Breloff 2bca9ca9ec square link 2016-06-24 11:00:28 -04:00
Thomas Breloff d66028ed0d glvisualize: support for path/path3d with or without markers, 3d markers are spheres 2016-06-23 17:00:08 -04:00
Thomas Breloff 1cf33044bc scatter and scatter3d support in glvisualize 2016-06-23 14:59:04 -04:00
Thomas Breloff 2c138c8355 readme 2016-06-22 13:22:25 -04:00
Thomas Breloff 73ffcb9bc1 changed convertToAnyVector AMat so that all matrices use the version previously for numbers; violin cleanup 2016-06-22 13:20:09 -04:00
Thomas Breloff 730025e144 recoded violin; removed try/catch around apply_recipe; default values for xtick/ytick in GR 2016-06-22 11:45:30 -04:00
Thomas Breloff 91aa1d718a animations: use tmp.gif for ijulia, remove prefix from convert call; closes #346 2016-06-22 11:01:00 -04:00
Thomas Breloff f881bfc4fc add Segments; pyplot: switch bar/hist/hist2d to recipes and path fix; change bar to shape; removed GR from tests 2016-06-20 23:11:23 -04:00
Thomas Breloff e76c3fff69 refactored gr markers fixing bugs and enabling features; clear subplot/axis args from d in _plot 2016-06-20 19:51:03 -04:00
Thomas Breloff 9f168071ff subplot attributes fixes 2016-06-20 15:11:25 -04:00
Thomas Breloff b6652b7619 improvements to bbox construction and inset subplots 2016-06-20 10:13:03 -04:00
Thomas Breloff f6d501f69e plot recipe fixes 2016-06-20 00:11:06 -04:00
Thomas Breloff 4c052cb3b3 colors cgrad and getindex 2016-06-19 11:25:25 -04:00
Thomas Breloff ea8ccf38db plot recipe fixes 2016-06-18 22:30:47 -04:00
Thomas Breloff cf12ff8070 plot logic cleanup; added plot recipes 2016-06-18 09:33:34 -04:00
Thomas Breloff b7a95244db handle seriestype aliases; handle vector of seriestypes; hvline_limits; added cycle for InputWrapper; turn on GR tests for OSX 2016-06-18 00:14:20 -04:00
Tom Breloff 4c884651a8 Merge pull request #343 from jheinen/dev
Added suport for marker borders
2016-06-18 00:02:42 -04:00
Thomas Breloff e9eca577aa plotlyjs supported_scales; violin check 2016-06-17 15:31:01 -04:00
Josef Heinen cff78b477c Added suport for marker borders 2016-06-17 20:21:07 +02:00
Tom Breloff b232410d25 Merge pull request #338 from jheinen/dev
use temporary files when generating MIME files
2016-06-17 08:09:53 -04:00
Josef Heinen 5ff338d4ac use temporary files when generating MIME files 2016-06-17 09:34:10 +02:00
Thomas Breloff a5ceea153d bump plots version 0.7.3 2016-06-16 21:00:25 -04:00
Thomas Breloff f3544dc826 plotlyjs png fix; NEWS update for 0.7.2 2016-06-16 20:58:44 -04:00
Thomas Breloff b0bc68ae8a orientation aliases dir/direction; removed native support for sticks/hline/vline in pyplot; commented out arcdiagram 2016-06-16 17:31:10 -04:00
Thomas Breloff c38e947dc6 animation default file tempname; raised group warning to 100; check for empty vec in axis; use command_idx for slicing; move deletion of smooth outside loop 2016-06-16 10:03:01 -04:00
Thomas Breloff ec826fc8ce moved series_annotations into series recipe processing; change pyplot clf to fig clear 2016-06-16 00:48:35 -04:00
Thomas Breloff e5c4f782a5 anynan isfinite; error on reusing layout 2016-06-15 15:36:36 -04:00
Thomas Breloff a5ddebf44d curves fix 2016-06-15 13:02:31 -04:00
Thomas Breloff 38804898c5 iter_segments and curve series type 2016-06-15 12:52:36 -04:00
Thomas Breloff 2bd67f3519 pyplot 3d line segments 2016-06-15 02:15:51 -04:00
Thomas Breloff c8ed611c9c unicodeplots cleanup: ijulia output fixes, ascii canvas 2016-06-15 01:45:13 -04:00
Thomas Breloff 3d7d8caa82 moved pyplot methods _series_added and _initialize_subplot into the display pipeline 2016-06-14 18:02:44 -04:00
Thomas Breloff f64108523c line_z arg and pyplot implementation 2016-06-14 15:39:21 -04:00
Tom Breloff a7493504ed Merge pull request #334 from jheinen/dev
conserve user defined GR workstation type
2016-06-14 13:31:40 -04:00
Josef Heinen bc5293b5a4 conserve user defined GR workstation type 2016-06-14 18:03:03 +02:00
Thomas Breloff c4bdc5b856 NEWS.md 2016-06-14 00:27:22 -04:00
Thomas Breloff b5b4023056 axis link arg; change those subplot/axis args set in kwlist to apply just to its own subplot; markerstrokealpha matches markeralpha 2016-06-14 00:10:26 -04:00
Thomas Breloff 0e598cc51d resolve relative coords for inset subplots 2016-06-13 17:46:19 -04:00
Thomas Breloff 9fd09924eb _shape_keys for consistent shape ordering 2016-06-13 16:57:26 -04:00
Thomas Breloff 10d218089f working on glvisualize 2016-06-13 16:15:45 -04:00
Thomas Breloff 1ba0d198a7 rename ellipse to circle; cleanup glvisualize 2016-06-13 15:59:51 -04:00
Thomas Breloff c44132d29d merge_with_base_supported updates 2016-06-13 15:45:35 -04:00
Thomas Breloff a018a2c07a series type dependencies and cleanup; bbox anchors in construction; fix for insets 2016-06-13 14:53:28 -04:00
Thomas Breloff 266d2efde5 inset_subplots; GR log axes fix 2016-06-13 12:27:48 -04:00
Thomas Breloff 3b33b054d3 plotly hover and scattergl 2016-06-13 11:04:56 -04:00
Thomas Breloff 1140b51e91 PLOTS_DEFAULTS and removed pyplot finalizer 2016-06-13 09:42:50 -04:00
Thomas Breloff 9d25c8fcd4 added PLOTS_DEFAULTS env var; check isfinite in axis_limits 2016-06-13 09:27:49 -04:00
Thomas Breloff e8ade18d47 code and utils for plotly shapes 2016-06-13 01:45:53 -04:00
Thomas Breloff ed243f4e3e added hover attribute and desc; fixed plotly title location; already_warned check 2016-06-13 00:15:28 -04:00
Thomas Breloff e0af4b7925 pyplot log scale fix; plotly title as annotation, title_location, hover placeholder 2016-06-12 23:48:18 -04:00
Thomas Breloff 80e53adbd8 getting plotly/plotlyjs up to speed 2016-06-12 21:03:11 -04:00
Thomas Breloff 36a29357a3 only widen axis limits for identity scale; closes #326 2016-06-12 20:22:57 -04:00
Thomas Breloff 5bb9aceaac pyplot log scale threshold fix; imgcomp fix to filter out higher versions 2016-06-12 13:06:15 -04:00
Thomas Breloff 02d893b316 big cleanup: changed camelcase to underscores; removed supportedAxes; changed pyplot methods to be py_ which matches gr_/plotly_/etc convention 2016-06-12 12:34:41 -04:00
Thomas Breloff b1850e58f4 gr cleanup commented code; bump version in imgcomp 2016-06-12 11:35:24 -04:00
Thomas Breloff f1e566dddc fix scale aliases 2016-06-12 11:00:42 -04:00
Thomas Breloff 2f60da33b7 changed pyplot log scale to symlog; #326 2016-06-12 10:28:41 -04:00
Thomas Breloff b0456d155a allow nothing for colorbar; gr fixes: marker_z colors, check colorbar arg 2016-06-11 15:55:55 -04:00
Tom Breloff 5f57a48996 Merge pull request #322 from jheinen/dev
Fixed GR output problem
2016-06-11 15:54:00 -04:00
Josef Heinen bc9d137001 Fixed GR output problem 2016-06-11 11:11:57 +02:00
Thomas Breloff 483946787a big GR refactor: axes drawing and cleanup; convert_to_polar and GR polar fill; should_add_to_legend fix; rename get_mod to Base.cycle 2016-06-11 02:03:46 -04:00
Thomas Breloff b165f233a8 animation fix; gr transparency 2016-06-10 16:17:30 -04:00
Thomas Breloff 3b325b2482 pyplot figure finalizer; accept 2-len AVec for limits (#289); sleep/skip/only options in test_examples 2016-06-10 10:04:33 -04:00
Tom Breloff 2dd480a3a6 Merge pull request #313 from jheinen/dev
Improved GR output
2016-06-10 08:56:53 -04:00
Josef Heinen df33ed40d6 Improved GR output
- slightly reduced the nominal marker size
- use character height as line spacing criterion when plotting legends
- use GR surface function for filled contours
- avoid calling GR setwindow/adjust* functions with Inf arguments
- corrected bounding box for legend
2016-06-10 13:39:57 +02:00
Thomas Breloff cf4d78c87c added clims attribute and support it in pyplot 2016-06-10 01:25:34 -04:00
Thomas Breloff 8007d0dd6a smarter cleanup of dicts; layout fixes: split out update_min_padding and added minimum_perimeter logic; check for nonempty axes when linking; add subplot processing and linking when combining plots 2016-06-10 00:16:13 -04:00
Thomas Breloff d7098f77c2 pgfplots display popup 2016-06-09 17:31:06 -04:00
Thomas Breloff 514284e784 pyplot display fixes for #308; setxyz fix; generic png conversion from pdf; pgfplots pdf output 2016-06-09 17:13:16 -04:00
Thomas Breloff 2a3029edb4 add build.jl 2016-06-09 12:08:36 -04:00
Thomas Breloff 45a1ed69d4 removed plotly-latest.min.js and added build.jl which downloads it; fix for quiver_using_hack; working on pyplot display behavior 2016-06-09 11:44:05 -04:00
Thomas Breloff 7248d8d7ce several fixes for type recipes; collect/zmin fixes in pgfplots; scatter3d recipe 2016-06-09 01:48:43 -04:00
Tom Breloff fa84401866 Merge pull request #310 from diegozea/dev
Add trim kw arg to violin and density
2016-06-09 01:45:43 -04:00
Diego Javier Zea 910b94c5fd Add trim kw arg to violin and density 2016-06-09 02:38:19 -03:00
Thomas Breloff 40cbddab29 updated NEWS; export shorthands macro; new example 16 2016-06-08 23:32:03 -04:00
Thomas Breloff 853cda4b80 moved stuff to PlotDocs 2016-06-08 17:34:15 -04:00
Thomas Breloff 91ec0ad077 allow false for color; properly expand extrema for tuple fillrange; make_fillrange_from_ribbon 2016-06-08 09:51:27 -04:00
Thomas Breloff 4be2304ec1 working on arg_desc; violin fix for groups 2016-06-08 00:52:16 -04:00
Tom Breloff d0ee402939 Merge pull request #306 from diegozea/dev
Solve a bug with whisker lengths (#210)
2016-06-07 23:01:29 -04:00
Diego Javier Zea 2d095daddc Solve a bug with whisker lengths (#210) 2016-06-07 23:44:41 -03:00
Thomas Breloff cf4fcf3351 fixed boxplot grouping; cleaned up GroupBy recipe; added arg_descs 2016-06-07 21:12:59 -04:00
Thomas Breloff 42d57fb8c2 working on arg_desc 2016-06-07 18:17:27 -04:00
Thomas Breloff ba13c1528f working on arg_desc 2016-06-07 17:59:30 -04:00
Thomas Breloff 857fb3342a fakedata fix 2016-06-07 17:16:14 -04:00
Thomas Breloff 17189e3125 default_should_widen; symbol in userplot macro; cleanup in recipes 2016-06-07 16:44:15 -04:00
Thomas Breloff d0209d945d widen further; added zorder to pyplot annotations 2016-06-07 12:38:35 -04:00
Tom Breloff 1b6bfa1259 Merge pull request #305 from diegozea/dev
Add notch and outliers to boxplot
2016-06-07 12:09:55 -04:00
Thomas Breloff 4ea813c983 pyplot scatter fix 2016-06-07 12:07:16 -04:00
Diego Javier Zea 71d2af07da Add notch and outliers to boxplot 2016-06-07 13:06:13 -03:00
Thomas Breloff b36f8c701e type recipes 2016-06-07 11:59:38 -04:00
Thomas Breloff d64d3ef101 pgfplots fixes 2016-06-07 01:57:02 -04:00
Thomas Breloff 05fa4a92de fixes in plotly/plotlyjs; smooth primary false 2016-06-07 01:42:33 -04:00
Thomas Breloff 990314cefc fixes for gr markers; add cbar to example 24; turn on gr tests 2016-06-07 01:23:07 -04:00
Thomas Breloff 60d97ad9c9 added density recipe 2016-06-07 00:18:07 -04:00
Thomas Breloff 6bfa31a89f added primary kw for series counting; added sticks recipe; gr_set_font and related fixes 2016-06-06 23:43:06 -04:00
Thomas Breloff 8d8ac10429 step recipes 2016-06-06 18:19:46 -04:00
Thomas Breloff 56f398fb55 histogram2d recipe; handle smoothing generically 2016-06-06 17:55:09 -04:00
Thomas Breloff cf5aed00e2 test fix 2016-06-06 16:12:22 -04:00
Thomas Breloff de616dfdf0 update_min_padding fix; shape support in GR; GR attr fixes; image extrema and fixes; hline/vline recipes; nobigs closes #303 2016-06-06 15:34:51 -04:00
Thomas Breloff 3cf428d7ea pyplot colorbar fix; annotation fix; new contour example; travis fix 2016-06-06 14:06:55 -04:00
Thomas Breloff 29d93ba33e changed axis defaults byletter to match; cleaned up examples; pyplot extrema fixes; commented out gr tests 2016-06-06 12:34:24 -04:00
Thomas Breloff 76c84c7615 attr fixes; allow_fail for nightly travis; series_new cleanup 2016-06-06 01:36:07 -04:00
Thomas Breloff e129c29e2f postpone match logic and add color_or_nothing; update pyplot for attr changes; move some pyplot logic later 2016-06-06 01:19:25 -04:00
Thomas Breloff 52d325b446 Merge remote-tracking branch 'origin/master' into dev 2016-06-05 23:59:06 -04:00
Thomas Breloff 74efd98699 added user_attr field to Plot; fillrange fix; pyplot title fix 2016-06-05 23:58:35 -04:00
Tom Breloff 28effaea36 Merge pull request #298 from dhoegh/fix_animation
Make animation use ImageMagick.jl if it is installed.
2016-06-05 23:16:05 -04:00
Daniel Høegh 6256549f44 Make animation use ImageMagick.jl if it is installed. 2016-06-05 09:31:44 +02:00
Thomas Breloff 2adec2fa7b examples 2016-06-02 20:34:25 -05:00
Thomas Breloff 32e816b713 working on axis limit fixes 2016-06-02 20:22:58 -05:00
Thomas Breloff 6c7b113de5 working on new tests 2016-06-02 17:59:24 -05:00
Thomas Breloff 1d5cce61ac working on switch to PlotReferenceImages 2016-06-02 17:23:40 -05:00
Thomas Breloff 85f91b9075 fix for plotting function; closes #291 2016-06-01 14:45:35 -05:00
Thomas Breloff aa64a0d3ce pyplot color fix 2016-06-01 14:29:36 -05:00
Thomas Breloff e9d95a85b7 proper grid layout in macro; pyplot isx fix 2016-05-30 14:56:32 -05:00
Thomas Breloff 625c92a985 working on 0.5 changes 2016-05-28 11:17:34 -04:00
Thomas Breloff 3cc9425219 working on 0.5 changes -- String 2016-05-28 11:00:19 -04:00
Thomas Breloff 0a86ccb142 working on 0.5 changes 2016-05-28 10:42:41 -04:00
Thomas Breloff ce82e07dc9 Extrema type and link_axis; link keyword, removed old link logic 2016-05-27 22:03:56 -04:00
Thomas Breloff 048c60614c check _axis_defaults in default 2016-05-27 16:31:07 -04:00
Thomas Breloff 148fa6d151 discrete_values handling; pyplot lims/widen; cleanup 2016-05-27 16:23:46 -04:00
Thomas Breloff 088543176f recompute_lengths fix; renamed hist to histogram, hist2d to histogram2d to match methods; fix tests 2016-05-27 15:08:05 -04:00
Thomas Breloff 536746d47e switch order for Surface function constructor; closes #273 2016-05-27 14:38:23 -04:00
Thomas Breloff c15cbad396 shorthands macro; pyplot bar fill fix; userplot macro; nicer error message in convertToAnyVector 2016-05-27 14:25:14 -04:00
Thomas Breloff d3baa58c7e series ordering bug fix 2016-05-27 12:55:29 -04:00
Thomas Breloff 7c885de6c7 improved trickery with layout macro 2016-05-27 12:16:34 -04:00
Thomas Breloff 010b8a382e working on building plot from existing plots 2016-05-27 10:58:45 -04:00
Thomas Breloff 314053af54 gr hist2d fix; closes #253 2016-05-27 09:05:48 -04:00
Thomas Breloff 34a7f8a99c prepared_object; closes #267 2016-05-27 00:19:12 -04:00
Thomas Breloff 87031984d9 widen gr limits; fixes #265 2016-05-27 00:14:22 -04:00
Thomas Breloff 83687f96a5 PLOTS_USE_ATOM_PLOTPANE env var; closes #270 2016-05-26 23:56:11 -04:00
Thomas Breloff f33905ed80 fixes for images/heatmaps/surfaces 2016-05-26 23:47:09 -04:00
Thomas Breloff f91c4d586c html_output_format 2016-05-26 20:57:51 -04:00
Thomas Breloff 77ec4adcad default minpad fix; html_output_format 2016-05-26 17:04:28 -04:00
Thomas Breloff b5a8186d99 working on pgfplots; default minpad calcs; moved subplot/layout init later to allow setting in recipes 2016-05-26 16:01:46 -04:00
Thomas Breloff ed25e554e1 working on pgfplots 2016-05-26 15:02:04 -04:00
Thomas Breloff a388ec71e3 working on pgfplots 2016-05-26 14:18:57 -04:00
Thomas Breloff bde3c2e19d working on pgfplots 2016-05-26 13:47:00 -04:00
Thomas Breloff d1d8d196ba sticks recipe; fixed up unicodeplots backend 2016-05-26 11:19:47 -04:00
Thomas Breloff 7be5aebbc9 gr fixes: polar markers, empty legends, pie labels, scale and flip 2016-05-25 16:52:07 -04:00
Thomas Breloff d15fcb6b24 gr_polyline fixes 2016-05-25 16:01:18 -04:00
Thomas Breloff b3ac38a6f1 working on gr 2016-05-25 15:17:51 -04:00
Thomas Breloff dae9dad2f7 working on GR; series_list and should_add_to_legend; series recipes fix; hist and bar recipes 2016-05-25 13:06:08 -04:00
Thomas Breloff 603dc30bb1 backend callback changes; output callbacks; prepare_output; fixes for pyplot, plotly, plotlyjs; and more 2016-05-24 23:19:51 -04:00
Tom Breloff 71070da13e Merge pull request #276 from spencerlyon2/dev
Fix plotlyjs subplots
2016-05-24 20:48:25 -04:00
Spencer Lyon 8fa1d4eb9b Fix plotlyjs subplots 2016-05-24 17:21:07 -07:00
Thomas Breloff 41f91f9cfb working on GR rebuild 2016-05-24 18:01:20 -04:00
Thomas Breloff 5699f3c6bc begin GR cleanup 2016-05-24 15:22:16 -04:00
Thomas Breloff 300babd6b1 deprecated gadfly/immerse 2016-05-24 14:46:53 -04:00
Thomas Breloff c1baca181c plotly subplot layouts 2016-05-24 14:25:03 -04:00
Thomas Breloff 851fe9f72c plotlyjs fixes 2016-05-24 12:38:52 -04:00
Thomas Breloff cf635cbdd9 renamed plotargs to attr; working on plotly backend 2016-05-24 12:20:03 -04:00
Thomas Breloff abbd8635dd pyplot hist in legend fix; closes #254 2016-05-24 11:03:38 -04:00
Thomas Breloff 2c2218bcb9 layouts fixed 2016-05-24 10:34:02 -04:00
Thomas Breloff bb6c06d3f7 working on layouts 2016-05-24 08:30:46 -04:00
Thomas Breloff 90e22f179e discrete value fixes; margin args; check for fillrange in contourf; skip test 6 2016-05-23 18:15:33 -04:00
Thomas Breloff 0a00d1fbf3 suppress_warnings fix; discrete values fixes 2016-05-23 16:42:24 -04:00
Thomas Breloff 6f0b8d1d7b group fix; ohlc fix 2016-05-23 15:13:20 -04:00
Thomas Breloff ef0d99340a backend template renaming/reorg/cleanup, pyplot fixes 2016-05-23 10:29:35 -04:00
Thomas Breloff d4d388a94b pyplot colorbar labels bbox 2016-05-21 23:03:55 -04:00
Thomas Breloff 7022ce7553 fixes for push/append/set_xy 2016-05-21 10:03:47 -04:00
Thomas Breloff 4a96122067 colorbar layout fixes; process_axis_arg and related fix 2016-05-21 00:04:33 -04:00
Thomas Breloff 862ac3af8a fixes/improvements to annotations; added series_annotations keyword 2016-05-20 11:38:07 -04:00
Thomas Breloff 333c2765fe ohlc recipe and related fixes; removed ohlc-specific code from gadfly and gr 2016-05-20 10:06:15 -04:00
Thomas Breloff 89feb68b7c pyplot lims fix 2016-05-20 08:15:27 -04:00
Thomas Breloff 1b901673fc fixes for guide/dataframes; 3d/polar projections; delayed subplot init; fg_title 2016-05-19 23:45:07 -04:00
Thomas Breloff fb60c244f6 bar_width and bar_edges keywords; small fixes 2016-05-19 17:34:37 -04:00
Thomas Breloff 3cea2df459 fix get_subplot_index; fix pyplot colorbar 2016-05-19 14:00:39 -04:00
Thomas Breloff 1cf514d1e6 merged dev into tb_recipes 2016-05-19 13:03:01 -04:00
Thomas Breloff 65e18a8669 upper bound on RecipesBase in REQUIRE; added NEWS.md; closes #259 2016-05-19 12:36:34 -04:00
Thomas Breloff 3e8f325ddc reorg/cleanup; removed old layouts and subplots; created axes.jl and layouts.jl 2016-05-19 10:42:59 -04:00
Thomas Breloff 0d96c49f4a layout macro; attr rename; getindex; fixes and cleanup 2016-05-18 23:55:03 -04:00
Thomas Breloff bfc3fc1dec titles and sub-layouts 2016-05-18 15:53:00 -04:00
Thomas Breloff 327f235af9 working on subplot/axis arg processing 2016-05-18 14:08:44 -04:00
Thomas Breloff df7fc0c4df fixes; basic layout works 2016-05-17 23:37:47 -04:00
Thomas Breloff 33d9664df5 working on layouts 2016-05-17 21:24:34 -04:00
Thomas Breloff 0d237028e7 redo the bbox logic 2016-05-17 17:41:03 -04:00
Thomas Breloff 80b9115393 fixes 2016-05-17 15:55:54 -04:00
Thomas Breloff 606229a08f trying out measures 2016-05-17 15:45:05 -04:00
Thomas Breloff 2ac17afe30 fixes 2016-05-17 10:33:10 -04:00
Tom Breloff 70f23e695b Merge pull request #252 from pkofod/join
Replace string cats with join() in pgfplots (and more).
2016-05-17 09:09:04 -04:00
Thomas Breloff 3084b0c41c working on arg overhaul 2016-05-17 00:57:42 -04:00
Thomas Breloff b75db9e473 arg defaults 2016-05-16 21:56:27 -04:00
Thomas Breloff c89e9c5f73 refactored and renamed plot defaults into plot,subplot,axis defaults, plus some associated fixes 2016-05-16 20:57:50 -04:00
Thomas Breloff 61107b8577 working on layout 2016-05-16 17:12:45 -04:00
Thomas Breloff 35ff449dc3 working on layout 2016-05-16 15:56:12 -04:00
Thomas Breloff ae1f5b8b06 working on layouts 2016-05-16 14:24:45 -04:00
Thomas Breloff c5bcae1e34 working on subplots 2016-05-16 01:07:33 -04:00
Thomas Breloff e9ab6e7301 started subplots/layouts 2016-05-15 12:32:10 -04:00
Thomas Breloff a6ce2e691d changed add_series to accept Series and push to list automatically; default add_series simplifies; removed old supported.jl 2016-05-15 12:14:18 -04:00
Thomas Breloff bfe04bdd15 changed to _create_backend_figure; started subplot removal 2016-05-15 11:23:27 -04:00
Thomas Breloff 2d0f9f01d5 cleanup 2016-05-14 17:34:44 -04:00
Thomas Breloff 87a967ad9c working on Axis 2016-05-14 00:10:58 -04:00
Thomas Breloff 290b17a5f9 fixes 2016-05-13 22:53:32 -04:00
Thomas Breloff 76572b990b fix gr linetype 2016-05-13 21:00:02 -04:00
Thomas Breloff 54efb48d62 changed linetype to seriestype 2016-05-13 20:55:26 -04:00
Thomas Breloff 83bd780f2a working on Axis type 2016-05-13 16:46:15 -04:00
Thomas Breloff 2ba4ac6d20 working on Axis type 2016-05-13 14:42:11 -04:00
Thomas Breloff 98dc52f124 working on Axis type 2016-05-13 13:45:30 -04:00
Thomas Breloff fbb2f30f3f errorbars, ribbons, and marker_z 2016-05-13 11:58:29 -04:00
Thomas Breloff 8ec3d18339 boxplot, violin, quiver, and line series recipes; plus some fixes 2016-05-13 11:21:32 -04:00
Thomas Breloff 26779cbf4a series recipes 2016-05-13 08:03:28 -04:00
Thomas Breloff 4f429fb536 recipe overhaul; groups, annotations, SliceIt 2016-05-13 00:17:58 -04:00
Thomas Breloff 7e1706f700 working on core recipes 2016-05-12 21:30:52 -04:00
Thomas Breloff d491b29037 working on recipes overhaul 2016-05-12 16:35:57 -04:00
Thomas Breloff cf9b60660d working on recipes overhaul 2016-05-12 14:51:53 -04:00
Thomas Breloff a5e9ad9f19 working on recipes overhaul 2016-05-12 14:00:47 -04:00
Thomas Breloff 6049a9fa0a working on recipes overhaul 2016-05-12 12:31:47 -04:00
Patrick Kofod Mogensen 5196ce5263 Add PGFPlots support for the size kw. 2016-05-12 17:32:54 +02:00
Patrick Kofod Mogensen 9231da4610 Clean up wall of pushes in _pgfplots_get_marker, and lines starting with kwarg. 2016-05-12 17:32:54 +02:00
Patrick Kofod Mogensen 89f8030ba1 Add markerstrokewidth to pgfplots. 2016-05-12 17:32:54 +02:00
Patrick Kofod Mogensen 534f57b227 Replace string cats with join() in pgfplots. 2016-05-12 17:32:54 +02:00
Thomas Breloff 4d3ebf31d4 add series_new.jl 2016-05-12 10:28:04 -04:00
Tom Breloff d778c7922d Merge pull request #255 from jheinen/dev
Fixed some bugs in gr.jl
2016-05-12 10:12:29 -04:00
Josef Heinen 5109c6f72b Fixed some bugs in gr.jl
- Turn off interpolation for heatmaps
- Fixed bug plotting scatter after heatmap (scatter drew to the colorbar
  viewport)
- Don't draw superfluous legends
2016-05-12 15:29:43 +02:00
Thomas Breloff 5005d32afd recipes overhaul; is_installed and dataframes logic; removed requires 2016-05-11 22:12:51 -04:00
Thomas Breloff 88be655dca started recipe reorg 2016-05-11 17:56:18 -04:00
Tom Breloff fe5789d747 Merge pull request #251 from jheinen/dev
Added (native) image support
2016-05-11 10:41:39 -04:00
Josef Heinen 00201b5f9c Added (native) image support 2016-05-11 16:18:03 +02:00
Thomas Breloff 85f7acf9d5 add PyPlot.ioff to init; closes #229 2016-05-11 09:45:44 -04:00
Thomas Breloff 44d1cdc2b2 pgfplots aspect_ratio 2016-05-11 09:18:40 -04:00
Tom Breloff 90c2202f6e Merge pull request #250 from KristofferC/kc/fix_pgfplots_color
Fix bug in some linecolors in PGFPlots
2016-05-11 09:11:13 -04:00
Kristoffer Carlsson d30574de24 workaround a bug in engineering notation for colors in pgfplot 2016-05-11 15:01:17 +02:00
Tom Breloff dec3748fe5 Merge pull request #249 from KristofferC/kc/pgfplots_label
add support for legend and label in pgfplots
2016-05-11 08:51:38 -04:00
Kristoffer Carlsson e8cdff2310 add support for legend and label in pgfplots
also adds some extra kwargs for legend positions
2016-05-11 13:59:32 +02:00
Thomas Breloff a0ca9d675f add_arrows function; plotly cleanup and arrows attempt 2016-05-10 17:22:47 -04:00
Thomas Breloff baf410c712 remove pyplot dash_capstyle option 2016-05-10 14:34:28 -04:00
Thomas Breloff a81af2b449 arrow conveniences 2016-05-10 13:57:38 -04:00
Thomas Breloff 678dde710b arrows with updated quiver recipe; only pyplot so far 2016-05-10 13:40:25 -04:00
Tom Breloff 93a35d8fdc Merge pull request #244 from jheinen/dev
Improved scaling of plots with error bars
2016-05-10 12:21:18 -04:00
Josef Heinen 0878f44b09 Improved scaling of plots with error bars 2016-05-10 18:14:08 +02:00
Thomas Breloff b89ae245ec removed heatmap assert 2016-05-09 22:44:22 -04:00
Thomas Breloff 536da01714 boxplot nan fix; add match_dimensions to pyplot supportedargs 2016-05-09 22:13:53 -04:00
Thomas Breloff a1b991aaeb image fixes and support in pyplot 2016-05-09 15:53:33 -04:00
Thomas Breloff 7bee9a5829 setTicksFromStringVector fixes; travis 2016-05-09 14:36:09 -04:00
Thomas Breloff 17a90e3b00 revamped setTicksFromStringVector; dataframes label fix 2016-05-09 14:00:07 -04:00
Tom Breloff 43ba9b1172 Merge pull request #239 from jheinen/dev
Fix axes offset bug (#221)
2016-05-09 11:28:04 -04:00
Thomas Breloff fdb01046e6 plotly zaxis, tick rotation, 3d axis fix; dataframes recipe fixes 2016-05-09 11:19:20 -04:00
Josef Heinen 09421c9189 Fix axes offset bug (#221) 2016-05-09 17:10:20 +02:00
Thomas Breloff c563204b0a added RecipesBase dep 2016-05-09 09:01:05 -04:00
Thomas Breloff 33b3ee89f3 replaced dataframes with recipes 2016-05-09 08:31:50 -04:00
Tom Breloff 008b61c9f6 Merge pull request #236 from jheinen/dev
Fixed colormap problem
2016-05-09 06:12:55 -04:00
Josef Heinen 7546db4d42 Fixed colormap problem 2016-05-09 11:44:37 +02:00
Thomas Breloff 925243969c attempted colormap fix for gr 2016-05-08 11:02:20 -04:00
Tom Breloff 7bce4a963e Merge pull request #233 from jheinen/dev
gr: support for colormaps
2016-05-08 10:30:40 -04:00
Josef Heinen 42d09a6d80 Working on colormaps 2016-05-08 14:06:11 +02:00
Josef Heinen b6334176e4 Added support for :nbins keyword 2016-05-07 13:24:11 +02:00
Josef Heinen 42a175bd53 Added support for :zlims keyword 2016-05-07 12:45:09 +02:00
Josef Heinen b4fb9af8e4 Fixed a problem with Julia v0.3 2016-05-07 07:47:13 +02:00
Thomas Breloff ed6c9fe432 add is_key_supported definition 2016-05-06 15:17:56 -04:00
Thomas Breloff 7e04aa438f removed RecipesBase from REQUIRE 2016-05-06 15:09:53 -04:00
Thomas Breloff f1679f82c1 remove recipe macro; add dependency on RecipesBase 2016-05-06 14:55:42 -04:00
Thomas Breloff 1808b81d59 recipe fix for empty args in subplot 2016-05-06 11:51:23 -04:00
Thomas Breloff cd25c7acb2 markershape fix; added require option for recipes 2016-05-06 11:39:17 -04:00
Thomas Breloff cf03779c5b handle user keywords properly for recipes 2016-05-06 10:50:54 -04:00
Thomas Breloff d3439f0d7e recipe macro handle curly 2016-05-05 16:58:04 -04:00
Thomas Breloff 2df7f84939 recipe macro 2016-05-05 16:18:56 -04:00
Thomas Breloff 74c76c48d5 working on plotrecipe 2016-05-05 12:22:31 -04:00
Thomas Breloff cdc0d22b01 changed recipe to plotrecipe and improved it 2016-05-05 11:51:50 -04:00
Thomas Breloff 5a520aadc0 removed some debugging 2016-05-05 10:35:04 -04:00
Thomas Breloff ec87489dd4 working on image type; working on ijulia display_dict 2016-05-05 00:13:45 -04:00
Thomas Breloff e30affdfc2 made center calc centroid 2016-05-04 21:36:15 -04:00
Thomas Breloff 66bd2559b9 recipe macro; markershape fix; moved/fixed themes 2016-05-04 16:09:09 -04:00
Thomas Breloff c8d6b1fab0 linewidth fix; kw macro 2016-05-04 14:24:15 -04:00
Thomas Breloff 548c59719b linewidth default 2016-05-04 13:38:08 -04:00
Thomas Breloff 59c1e24371 default_kw and force_kw macros for recipes 2016-05-04 13:24:44 -04:00
Thomas Breloff 3c09921cbd x/y/z ticklabel rotation; new supported graphs using heatmap 2016-05-03 17:14:52 -04:00
Thomas Breloff 00f3d450f9 fix for integer arg in process_inputs 2016-05-03 14:43:34 -04:00
Thomas Breloff e676387c16 shapes change verts to x/y; translate/scale/rotate/center; x/y scale alias fix 2016-05-02 16:37:10 -04:00
Thomas Breloff 2e2e8a2230 move plotargs merge and handlePlotColors before series 2016-05-02 12:16:41 -04:00
Thomas Breloff 8c8ede361e removed plotly tests 2016-04-29 17:00:56 -04:00
Thomas Breloff 672bf05856 travis 2016-04-29 14:03:50 -04:00
Thomas Breloff 67ec31c75a travis 2016-04-29 13:52:22 -04:00
Thomas Breloff 59d13a7810 travis; readme 2016-04-29 13:41:28 -04:00
Thomas Breloff 010a25f4cb travis; readme 2016-04-29 13:29:58 -04:00
Thomas Breloff a0ac7b4a1e travis; readme 2016-04-29 13:02:11 -04:00
Thomas Breloff ab7eb89466 travis; gitter badge 2016-04-29 12:44:05 -04:00
Thomas Breloff 649d362b85 travis install_wkhtmltoimage.sh 2016-04-29 12:20:18 -04:00
Thomas Breloff cb80860d6f travis install_wkhtmltoimage.sh 2016-04-29 12:15:42 -04:00
Thomas Breloff a8ef9e66fc travis install_wkhtmltoimage.sh 2016-04-29 12:05:38 -04:00
Thomas Breloff d27212e0b7 travis 2016-04-29 11:30:47 -04:00
Thomas Breloff 65650a7ae5 travis 2016-04-29 11:26:53 -04:00
Thomas Breloff 6ab5b8eb68 travis 2016-04-29 10:59:10 -04:00
Thomas Breloff c618e0577a travis and tests 2016-04-29 10:49:11 -04:00
Thomas Breloff 0e84c91451 split out supported.jl, added tests for more backends; closes #206 2016-04-29 10:13:41 -04:00
Thomas Breloff 005ce11313 InputWrapper and pyplot surface zcolor 2016-04-28 22:03:52 -04:00
Tom Breloff db118d4f5a Merge pull request #208 from pkofod/newpgf
Further changes to PGFPlots backend.
2016-04-28 15:13:58 -04:00
Patrick Kofod Mogensen c92b30a741 Further changes to PGFPlots backend. 2016-04-28 20:52:56 +02:00
Thomas Breloff d67aec6fec gr fixes and tests; fillrange convertToAnyVector 2016-04-28 12:51:08 -04:00
Tom Breloff ce58f25488 Merge pull request #209 from jheinen/dev
GR - Added polar plots
2016-04-28 11:09:56 -04:00
Josef Heinen e8d77a3c61 Added polar plots 2016-04-28 16:25:32 +02:00
Thomas Breloff d6d7fc1edd gr fix zcolor to marker_z 2016-04-27 12:10:33 -04:00
Thomas Breloff 7ce7f8bfce gr tests 2016-04-27 09:20:19 -04:00
Tom Breloff f0f46e5272 Merge pull request #166 from pkofod/pkm/pgfplots
PGFPlots.jl support
2016-04-27 09:17:45 -04:00
Patrick Kofod Mogensen f9473cc8bc Initial functionality added to PGFPlots backend. 2016-04-27 10:05:48 +02:00
Thomas Breloff 5c7d31157b spy fixes; closes #196 2016-04-26 17:02:16 -04:00
Thomas Breloff 982a512ebd pyplot support for pie charts 2016-04-26 16:01:50 -04:00
Thomas Breloff 5dfd3d2f5d added aspect_ratio keyword and implemented in pyplot 2016-04-26 15:35:26 -04:00
Thomas Breloff 8d6974f67d contours keyword for surface and wireframe plots 2016-04-26 15:09:18 -04:00
Thomas Breloff 8b569e3cd8 contour3d 2016-04-26 14:35:51 -04:00
Thomas Breloff b9d20142a2 pyplot trisurface support 2016-04-26 14:20:07 -04:00
Thomas Breloff 6c9e818abd discrete colorbar for pyplot 2016-04-26 13:19:22 -04:00
Thomas Breloff d2a287d43c gr tests linux_only 2016-04-26 11:59:08 -04:00
Thomas Breloff d6ce2e364f fixes and cleanup: colorbars, fills, polar 2016-04-26 11:18:48 -04:00
Thomas Breloff 36ca485a74 added fg_guide coloring; allow markers for bar/sticks and sticks fixes; legend text color 2016-04-25 16:57:16 -04:00
Thomas Breloff b3230c5671 pyplot shapes 2016-04-25 15:14:54 -04:00
Thomas Breloff ebf490838c pyplot surface, wireframe, heatmap; sorting fixes; default linewidth is :auto 2016-04-25 15:01:24 -04:00
Thomas Breloff 7921cf18b6 pyplot contours 2016-04-25 12:47:35 -04:00
Thomas Breloff 0e0450ced5 gadfly color fixes; pyplot fill_between fix; pyplot hline/vline 2016-04-25 12:24:03 -04:00
Thomas Breloff 096064ac09 subplot layout fix; closes #202 2016-04-25 12:00:43 -04:00
Thomas Breloff 77c2d7d846 subcategories for background/foreground colors, implemented in pyplot; add_theme/set_theme and ggplot2; add_aliases function; nbins renamed bins 2016-04-25 11:37:14 -04:00
Thomas Breloff 40a121198d added weights kw; pyplot hist2d and hexbin 2016-04-24 23:33:51 -04:00
Thomas Breloff 44079a7bf7 added normalize kw, and added to pyplot 2016-04-24 22:47:32 -04:00
Thomas Breloff 50fa013801 working on pyplot refactor; barh added 2016-04-23 09:32:57 -04:00
Thomas Breloff d4ccf0ec62 PLOTS_DEFAULT_BACKEND env variable; closes #200 2016-04-23 09:04:02 -04:00
Thomas Breloff 04842974e7 working on pyplot refactor 2016-04-22 16:46:02 -04:00
Thomas Breloff 6161b08f82 working on pyplot refactor; path/scatter in 2d/3d done 2016-04-22 12:53:40 -04:00
Thomas Breloff b9818a4480 working on seriescolor and pyplot reorgs 2016-04-22 10:44:12 -04:00
Thomas Breloff e2ae22421b working on seriescolor and pyplot reorgs 2016-04-22 10:09:55 -04:00
Thomas Breloff b64677e14a changed kw splatting to passing in KW: _add_series and _create_plot; removed plotly tests 2016-04-22 08:56:54 -04:00
Thomas Breloff c910445634 quiet flag for wkhtmltoimage 2016-04-21 15:10:25 -04:00
Thomas Breloff c4683a754e plotly png generation using wkhtmltoimage 2016-04-20 17:34:55 -04:00
Thomas Breloff 1da8fdb588 plotlyjs travis 2016-04-20 15:35:23 -04:00
Thomas Breloff 4bf8e342dc plotlyjs travis; plotly/plotlyjs polar 2016-04-20 14:44:27 -04:00
Thomas Breloff 18fc50fcbf plotlyjs travis 2016-04-20 12:33:32 -04:00
Thomas Breloff 2fb10b7076 plotlyjs travis 2016-04-20 11:59:17 -04:00
Thomas Breloff 967291c2ef export KW; plotlyjs travis 2016-04-20 11:27:02 -04:00
Thomas Breloff 392ae871d5 plotlyjs travis 2016-04-20 10:57:07 -04:00
Thomas Breloff 27b3070480 Merge remote-tracking branch 'origin/master' into dev 2016-04-20 10:20:55 -04:00
Tom Breloff 325f59e03d Merge pull request #190 from mfalt/master
Better handling of xlims in Gadfly
2016-04-20 10:17:29 -04:00
Thomas Breloff 217ffb36e6 plotlyjs tests and fixes 2016-04-20 10:10:07 -04:00
Mattias Fält 4afad93ff6 Missing changes 2016-04-20 15:51:33 +02:00
Thomas Breloff e8858cb1b7 removed sort in ticks 2016-04-20 09:12:36 -04:00
Mattias Fält 52de31c9a6 Proper implementation of gadfly min/max in Cartesian 2016-04-20 14:37:34 +02:00
Mattias Fält 60660a1f1a Fixed Gadfly axis scale inversion 2016-04-20 10:48:13 +02:00
Thomas Breloff a2ea9db90e added bar_position; fixed orientation handling; pyplot cleanup 2016-04-18 15:12:13 -04:00
Thomas Breloff 236a7dadc6 added matplotlib colormaps; default changed to inferno; pyplot subplot fix 2016-04-13 13:49:03 -04:00
Thomas Breloff 82d2cc943d working on get/set xy/xyz indexing overhaul 2016-04-11 18:19:06 -04:00
Thomas Breloff d70f462899 z axis args; pyplot z axis; major pyplot cleanup; other cleanup/fixes 2016-04-11 16:16:47 -04:00
Thomas Breloff 0a636b5899 polar coords for pyplot 2016-04-11 06:46:28 -04:00
Thomas Breloff e0b2749188 added support for shape linetype in pyplot 2016-04-08 17:10:15 -04:00
Thomas Breloff 2fc973245d added quiver plot/arg; fixed gadfly shapes to allow vector of shapes 2016-04-08 16:05:20 -04:00
Thomas Breloff 9bfcb64542 asymmetric errorbars 2016-04-08 12:06:12 -04:00
Thomas Breloff 61e34b7ef8 ribbons; changed errorbar to yerror and added xerror 2016-04-08 11:52:02 -04:00
Thomas Breloff 3c3078875a errorbars 2016-04-08 10:35:17 -04:00
Thomas Breloff 5293e2c13d sort string ticks 2016-04-07 17:27:12 -04:00
Thomas Breloff fdf3b3f581 added violin plot 2016-04-07 17:05:31 -04:00
Thomas Breloff f3f29fb54f apply_series_recipe framework and boxplot; fix Gadfly scales for tick labels 2016-04-07 15:56:09 -04:00
Thomas Breloff e8ed79a6bb pyplot zlim fixes 2016-03-29 11:01:16 -06:00
Thomas Breloff cca730d927 atom abstractplot 2016-03-29 09:24:23 -06:00
Tom Breloff 0693cb7840 Merge pull request #176 from abelsiqueira/feat/zlim
Implement zlims!
2016-03-29 09:23:07 -06:00
Abel Soares Siqueira 3f1958cce1 Implement zlims! 2016-03-28 22:41:32 -03:00
Thomas Breloff fb708bed90 Atom fixes 2016-03-25 09:23:10 -06:00
Thomas Breloff 1636587a82 surface fix 2016-03-19 19:40:27 -06:00
Thomas Breloff 1f1ccd81bb shapes 2016-03-18 11:38:51 -04:00
Thomas Breloff 5efb0eb582 more Dict to KW renaming 2016-03-17 22:11:29 -04:00
Thomas Breloff be5f71c123 subplot groups; lots of Dict to KW replace 2016-03-17 22:02:50 -04:00
Thomas Breloff a0df6bfc12 groupby overhaul 2016-03-17 18:27:33 -04:00
Thomas Breloff 2ab0dc20d7 working on series reorg 2016-03-17 16:52:09 -04:00
Thomas Breloff 175ce3613a working on series reorg 2016-03-17 15:07:07 -04:00
Thomas Breloff eecb5c3754 started series reorg 2016-03-17 13:38:22 -04:00
Thomas Breloff b34360901f test/REQUIRE 2016-03-17 11:33:18 -04:00
Thomas Breloff 21bbd21ae9 travis 2016-03-17 10:33:39 -04:00
Thomas Breloff 0b403a4c5d changed createKWArgsList to build_series_args and moved into series_args.jl; added Cairo and Fontconfig to test/REQUIRE 2016-03-17 10:08:03 -04:00
Thomas Breloff 1d1e1beca5 pyplot surface fix 2016-03-17 08:59:43 -04:00
Tom Breloff 3d4d844e72 Merge pull request #169 from diegozea/dev
Arc and chord diagram
2016-03-17 08:39:27 -04:00
Diego Javier Zea 1f9aa72bdb clean previous commit 2016-03-17 00:18:13 -03:00
Diego Javier Zea c29f68e35d Arc and chord diagrams 2016-03-17 00:11:41 -03:00
Tom Breloff c7c10e769d Merge pull request #168 from jheinen/dev
GR.jl improvements
2016-03-16 14:55:35 -04:00
Josef Heinen 7264c01b85 Added :heatmap linetype 2016-03-16 18:27:59 +01:00
Josef Heinen 97faa7413f gr: improved subplot layout 2016-03-16 18:27:59 +01:00
Thomas Breloff 7531c48e38 shape linetype; supported in gadfly; gadfly cleanup 2016-03-16 13:12:01 -04:00
Thomas Breloff 16799d8b75 cleanup plotly 2016-03-16 11:38:20 -04:00
Thomas Breloff 901115ed10 working on plotly/interact fix 2016-03-15 13:16:14 -04:00
Tom Breloff 596ca08446 Merge pull request #162 from diegozea/dev
arcdiagram
2016-03-15 11:29:24 -04:00
Thomas Breloff 4d864d8cad working on atom integration 2016-03-14 16:58:01 -04:00
Diego Javier Zea c458a35670 arcdiagram 2016-03-13 16:27:35 -03:00
Thomas Breloff c203bfe5ad working on atom/plotly 2016-03-11 14:59:11 -05:00
Thomas Breloff 8b2a838388 fixed dataframes loading; added dataframes to tests; started atom integration 2016-03-11 13:07:25 -05:00
Thomas Breloff b08212e2f9 more layouts 2016-03-10 23:38:14 -05:00
Thomas Breloff b5f08838b3 renaming: AbstractPlot and AbstractBackend 2016-03-10 23:08:04 -05:00
Thomas Breloff 5501605a1f more cleanup; backends.jl; removed depr dir 2016-03-10 22:47:53 -05:00
Thomas Breloff 7a5197df63 started work on new FlexLayout, some reorg/cleaning 2016-03-10 22:43:02 -05:00
Tom Breloff 09d45aa64b Merge pull request #161 from dlfivefifty/dev
Update GLVisualize
2016-03-10 19:24:24 -05:00
Sheehan Olver 552810359e Merge updated glvisualize 2016-03-11 10:44:51 +11:00
Sheehan Olver a68a6885d0 updated glvisualize 2016-03-11 10:42:55 +11:00
Thomas Breloff b32589f7e7 removed plotly debugging 2016-03-10 16:20:34 -05:00
Thomas Breloff 2e6b8a067d pyplot heatmaps working; ColorGradient fix 2016-03-09 23:34:56 -05:00
Thomas Breloff 581fdfdfe0 pyplot heatmap 2016-03-09 21:55:09 -05:00
Thomas Breloff 8e4ff39738 loosen ColorGradient constructor 2016-03-09 20:31:46 -05:00
Thomas Breloff f568803af2 heatmaps, colorscales, and spy... oh my 2016-03-09 17:48:43 -05:00
Thomas Breloff 6db06857ba changed heatmap to hist2d, see #147 for details 2016-03-09 15:26:30 -05:00
116 changed files with 19363 additions and 7933 deletions
+1
View File
@@ -4,3 +4,4 @@
.DS_Store
examples/.ipynb_checkpoints/*
examples/meetup/.ipynb_checkpoints/*
deps/plotly-latest.min.js
+47 -11
View File
@@ -2,22 +2,58 @@
language: julia
os:
- linux
- osx
# - osx
julia:
- 0.4
#- nightly
- 0.6
matrix:
allow_failures:
- julia: nightly
# # before install:
# # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
# # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install wkhtmltopdf; fi
# ref: http://askubuntu.com/a/556672 for the wkhtmltopdf apt repository info
sudo: required
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pwd ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./test/install_wkhtmltoimage.sh ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:pov/wkhtmltopdf ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y wkhtmltopdf ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wkhtmltopdf -V ; fi
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wkhtmltoimage -V ; fi
# echo 'exec xvfb-run -a -s "-screen 0 640x480x16" wkhtmltopdf "$@"' | sudo tee /usr/local/bin/wkhtmltopdf.sh >/dev/null
# sudo chmod a+x /usr/local/bin/wkhtmltopdf.sh
# # borrowed from Blink.jl's travis file
# matrix:
# include:
# - os: linux
# julia: 0.4
# env: TESTCMD="xvfb-run julia"
# - os: osx
# julia: 0.4
# env: TESTCMD="julia"
notifications:
email: true
# 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 'Pkg.clone("https://github.com/tbreloff/Images.jl.git"); Pkg.checkout("Images","tom_imgcompare");'
# - julia -e 'Pkg.clone("Images"); Pkg.build("Images")'
- julia test/travis_commands.jl
# - julia -e 'Pkg.clone("ImageMagick"); Pkg.build("ImageMagick")'
- julia -e 'Pkg.clone("https://github.com/tbreloff/VisualRegressionTests.jl.git");'
- julia -e 'Pkg.clone("https://github.com/tbreloff/ExamplePlots.jl.git");'
- julia -e 'Pkg.clone("Cairo"); Pkg.build("Cairo")'
- julia -e 'ENV["PYTHON"] = ""; Pkg.clone("PyPlot"); Pkg.build("PyPlot")'
- julia -e 'Pkg.test("Plots"; coverage=false)'
# - julia -e 'cd(Pkg.dir("Plots")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())'
# - julia -e 'Pkg.clone("GR"); Pkg.build("GR")'
# # - julia -e 'Pkg.clone("https://github.com/tbreloff/ImageMagick.jl.git"); Pkg.checkout("ImageMagick","tb_write"); Pkg.build("ImageMagick")'
# - julia -e 'Pkg.clone("https://github.com/tbreloff/ExamplePlots.jl.git");'
# # - julia -e 'Pkg.clone("https://github.com/JunoLab/Blink.jl.git"); Pkg.build("Blink"); import Blink; Blink.AtomShell.install()'
# # - julia -e 'Pkg.clone("https://github.com/spencerlyon2/PlotlyJS.jl.git")'
# - julia -e 'ENV["PYTHON"] = ""; Pkg.add("PyPlot"); Pkg.build("PyPlot")'
#
# # - $TESTCMD -e 'Pkg.test("Plots"; coverage=false)'
# - julia -e 'Pkg.test("Plots"; coverage=false)'
# # - julia -e 'cd(Pkg.dir("Plots")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())'
+650
View File
@@ -0,0 +1,650 @@
# Plots.jl NEWS
#### notes on release changes, ongoing development, and future planned work
- 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
#### 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
- added dependency on PlotUtils
- BREAKING: removed DataFrames support (now in StatPlots.jl)
- BREAKING: removed boxplot/violin/density recipes (now in StatPlots.jl)
- GR:
- inline iterm2 support
- trisurface support
- heatmap fix
- PyPlot:
- ijulia display fix
- GLVisualize:
- first try with shapes
- iter_segments improvements
- bar_width support
- horizontal bars
- improve tick display
- better shape handling in pyplot, plotly
- improved padding calcs
- internal reorg of _plots method, add pipeline.jl
---
## 0.7
#### 0.7.5
- GR: LaTeX support
- Changed docs url to juliaplots.github.io
- added `contourf` seriestype
- allow `plt[1]` to return first Subplot
- allow `sp[1]` to return the first Series of the Subplot
- `series[k]` now passes through to `series.d[k]`
- allow calling `plot!(sp, ...)` to update a target Subplot
- PyPlot: zorder fix
- new DataFrames logic/recipe: more flexible/robust and allow Symbols for:
- `(:fillrange, :line_z, :marker_z, :markersize, :ribbon, :weights, :xerror, :yerror)`
- new `display_type` and `extra_kwargs` plot attributes
- surface fix
#### 0.7.4
- added snooped precompiles, but left commented out
- GR fixes: markersize, shapes, legends
- fixes to recipes
- turned on Appveyor
#### 0.7.3
- rebuild violin and boxplot recipes
- "plot recipes"
- `cgrad` method for easy color gradient creation
- improvements to inset subplots
- Segments and iter_segments for NaN-separated vectors
- `bar` recipe now creates a `shape` series
- writemime fix for Interact.jl
- `link = :square` option
- !!! set `shape` attributes with line/fill, NOT marker/markerstroke !!!
- basic DPI support
- moved chorddiagram to PlotRecipes
- GR:
- use temp files for img output
- basic support for marker strokes and other marker fixes
- PyPlot:
- Switch to recipes for bar, histogram, histogram2d
- GLVisualize
- subplots
- path/scatter and path3d/scatter3d
- initial drawing of axes
- many smaller fixes and improvements
#### 0.7.2
- line_z arg for multicolored line segments
- pyplot
- line_z (2d and 3d)
- pushed all fig updates into display pipeline
- remove native sticks/hline/vline in favor of recipes
- unicodeplots cleanup, ijulia fixes, ascii canvas
- `curves` series type
- `iter_segments` iterator
- moved arcdiagram out and into PlotRecipes (thanks @diegozea)
- several other fixes/checks
#### 0.7.1
- inset (floating) subplots
- change: when setting subplot/axis args from user recipes, they should apply only to their own subplot
- trim for violin/boxplot
- scatter3d recipe
- removed plotly.js in favor of build.jl download
- improvements/fixes to pgfplots backend
- improvements/fixes to plotly/plotlyjs backends
- titles are annotations and properly placed with title_position
- hover attribute
- shapes (almost)
- scattergl
- minimum perimeter logic in layout calc... fixed misaligned subplots
- new clims attribute
- more options for test_examples
- GR refactor
- added transparency
- moved axis/grid logic out of series loop
- generalized 3d and polar projections
- renamed get_mod to Base.cycle
- pyplot log scale fixes
- PLOTS_DEFAULTS environment var processing
- rename :ellipse to :circle, :ellipse is now an alias
- supported args/types cleanup
- seriestype dependency methods and `@deps` macro
- bbox `h_anchor`/`v_anchor`
- new axis arg: `:link` is a list of subplots to link axes with
- cleanup/simplification of glvisualize backend
#### 0.7.0
- Check out [the summary](http://juliaplots.github.io/plots_v0.7/)
- Revamped and simplified internals
- [Recipes, recipes, recipes](https://github.com/JuliaPlots/RecipesBase.jl/issues/6)
- [Layouts and Subplots](https://github.com/tbreloff/Plots.jl/issues/60)
- DataFrames is loaded automatically when installed
- Overhaul to GroupBy mechanic (now offloads to a recipe)
- Replaced much of the argument processing with recipes
- Added series recipes, and began to strip down un-needed backend code. Some recipes:
- line, step, sticks, bar, histogram, histogram2d, boxplot, violin, quiver, errorbars, density, ohlc
- Added `@shorthands` and `@userplot` macros for recipe convenience
- Better handling of errorbars and ribbons
- New Axis type
- Tracks extrema and discrete values
- New `link_axes` functionality
- `linetype` has been renamed `seriestype` (the alias is reversed)
- Many fixes and huge cleanup in GR
- Brand new subplot layout mechanics:
- `@layout` macro
- AbstractLayout, Subplot, GridLayout, and everything related
- Added dependency on Measures.jl
- Computations of axis/guide sizes and precise positioning
- Refactored and compartmentalized default dictionaries for attributes
- Deprecated Gadfly and Immerse backends
- Added `series_annotations` attribute (previously that functionality was merged with `annotations`, which are not series-specific)
- Removed `axis` attribute... currently not supporting twin (right) y axes
- Check for `ENV["PLOTS_USE_ATOM_PLOTPANE"]` and default to false
- Improved backend interface to reduce redundant code. Template updated.
- Added `html_output_format`, primarily for choosing between png and svg output in IJulia.
- Partial support of Julia v0.5
- Switched testing to dump reference images to JuliaPlots/PlotReferenceImages.jl
- Moved docs-specific code to new JuliaPlots/PlotDocs.jl
- Moved example list from ExamplePlots into Plots.
- Added several examples and improved others.
- Many other smaller changes and bug fixes.
---
## Version 0.6
#### 0.6.2
- `linewidth` fixes
- `markershape` fix
- converted center calc to centroid for shapes
- new dependency on [RecipesBase](https://github.com/JuliaPlots/RecipesBase.jl)
- REQUIRE upper limit for RecipesBase: 0.0.1
- GR fixes/improvements (@jheinen)
- support `zlims`, `bins`
- allow Plots colormaps
- other bug fixes
- native image support
- PGFPlots fixes/improvements (@pkofod)
- DataFrames are handled by recipes
- Plotly: zaxis, tick rotation, 3d axis fix
- Improvements in handling discrete data
- Support for image display
- `arrow` keyword and support for adding arrows to paths
- changed quiver recipe to use arrows
- Bug fixes for boxplots, heatmaps, and more
#### 0.6.1
- `rotation` keyword
- improved supported graphs
- subplot bug fix
#### 0.6.0
- `apply_series_recipe` framework for built-in recipes
- [boxplot/violin recipes](https://github.com/tbreloff/ExamplePlots.jl/blob/master/notebooks/boxplot.ipynb)
- [errorbar/ribbon recipes](https://github.com/tbreloff/ExamplePlots.jl/blob/master/notebooks/errorbars.ipynb)
- [quiver recipe](https://github.com/tbreloff/ExamplePlots.jl/blob/master/notebooks/quiver.ipynb)
- `polar` coordinates
- better support for shapes and custom polygons (see [batman](https://github.com/tbreloff/ExamplePlots.jl/blob/master/notebooks/batman.ipynb))
- z-axis keywords
- 3D indexing overhaul: `push!`, `append!` support
- matplotlib colormap constants (`:inferno` is the new default colormap for Plots)
- `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
- `add_theme`/`set_theme` and ggplot2 theme (see [this issue](https://github.com/tbreloff/Plots.jl/issues/201))
- `PLOTS_DEFAULT_BACKEND` environment variable
- `barh` linetype
- support for non-gridded surfaces with pyplot's trisurface
- pyplot surface zcolor
- internal refactor of supported.jl
- `wrap` method to bypass input processing
- `translate`, `scale` and `rotate` methods for coordinates and shapes
- and many more minor fixes and improvements
---
## Version 0.5
#### 0.5.4
- old heatmaps have been renamed to hist2d, and true heatmaps implemented (see https://github.com/tbreloff/Plots.jl/issues/147)
- lots of reorganization and redesign of the internals
- lots of renaming to keep to conventions: AbstractPlot, AbstractBackend, etc
- initial redesign of layouts
- integration with Atom PlotPane
- arc diagram and chord diagram (thanks to @diegozea: see https://github.com/tbreloff/Plots.jl/issues/163)
- work on GR, GLVisualize, and PGFPlots backends (thanks @jheinen @dlfivefifty @pkofod)
- improvements to Plotly setup (thanks @spencerlyon2)
- overhaul to series creation logic and groupby mechanic
- replace Dict with `typealias KW Dict{Symbol,Any}` in many places, also replacing keyword arg splatting
- new `shape` linetype for plotting polygons in plot-coordinates (see https://github.com/tbreloff/ExamplePlots.jl/blob/master/notebooks/batman.ipynb)
- many other fixes
#### 0.5.3
- `@gif` macro with `every`/`when` syntax
- bezier curves and other graph drawing helpers
- added FixedSizeArrays dependency with relevant functionality
- merged lots of improvements to GR (thanks @jheinen)
- `overwrite_figure`/`reuse` arg for reusing the same figure window
- deprecated Qwt, Winston, and Bokeh backends
- improved handling of 3D inputs (call `z=rand(10,10); surface(z)` for example)
- fix IJulia display issue
- lots of progress on PlotlyJS backend
- and many other changes and fixes...
#### 0.5.2
- Added [GR.jl](https://github.com/jheinen/GR.jl) as a backend (unfinished but functional) All credit to @jheinen
- Set defaults within backend calls (i.e. `gadfly(legend=false)`)
- `abline!`; also extrema allows plotting functions without giving x (i.e. `plot(cos, 0, 10); plot!(sin)`) @pkofod @joshday
- Integration with [PlotlyJS.jl](https://github.com/spencerlyon2/PlotlyJS.jl) for using Plotly inside a Blink window @spencerlyon2
- The Plotly backend has been split into my built-in version (`plotly()`) and @spencerlyon2's backend (`plotlyjs()`)
- Revamped backend setup code for easily adding new backends
- New docs (WIP) at http://juliaplots.github.io/
- Overhaul to `:legend` keyword (see https://github.com/tbreloff/Plots.jl/issues/135)
- New dependency on Requires, allows auto-loading of DataFrames support
- Support for plotting lists of Tuples and FixedSizeArrays
- new `@animate` macro for super simple animations (see https://github.com/tbreloff/Plots.jl/issues/111#issuecomment-181515616)
- allow Function for `:fillrange` and `zcolor` arguments (for example: `scatter(sin, 0:10, marker=15, fill=(cos,0.4), zcolor=sin)`)
- allow vectors of PlotText without x/y coords (for example: `scatter(rand(10), m=20, ann=map(text, 1:10))`)
- Lots and lots of fixes
#### 0.5.1
#### 0.5.0
- `with` function for temporary defaults
- contours
- basic 3D plotting
- preliminary support for Bokeh
- `stroke` and `brush` for more fine-tuned control over visuals
- smarter "magic" arguments: `line`, `marker`
+14 -10
View File
@@ -1,21 +1,25 @@
# Plots
[![Build Status](https://travis-ci.org/tbreloff/Plots.jl.svg?branch=master)](https://travis-ci.org/tbreloff/Plots.jl)
[![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)
[![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:
- **Intuitive**. Start generating complex plots without reading volumes of documentation. Commands should "just work".
- **Powerful**. Do more with less. Complex visualizations become easy.
- **Intuitive**. Stop reading so much documentation. Commands should "just work".
- **Concise**. Less code means fewer mistakes and more efficient development/analysis.
- **Flexible**. Produce your favorite plots from your favorite package, but quicker and simpler.
- **Consistent**. Don't commit to one graphics package. Use the same code and access the strengths of all backends.
- **Lightweight**. Very few dependencies, since backends are loaded and initialized dynamically.
- **Consistent**. Don't commit to one graphics package, use the same code everywhere.
- **Lightweight**. Very few dependencies.
- **Smart**. Attempts to figure out what you **want** it to do... not just what you **tell** it.
Use the preprocessing pipeline in Plots to fully describe your visualization before it calls the backend code. This maintains modularity and allows for efficient separation of front end code, algorithms, and backend graphics. New graphical backends can be added with minimal effort.
View the [full documentation](http://plots.readthedocs.org).
View the [full documentation](http://docs.juliaplots.org/latest).
+13 -4
View File
@@ -1,7 +1,16 @@
julia 0.4
julia 0.6
Colors
RecipesBase 0.2.3
PlotUtils 0.4.1
PlotThemes 0.1.3
Reexport
Compat
StaticArrays 0.5
FixedPointNumbers 0.3
Measures
Showoff
StatsBase 0.14.0
JSON
NaNMath
Requires
FixedSizeArrays
Contour
GR 0.31.0
+19 -14
View File
@@ -1,14 +1,15 @@
environment:
matrix:
- JULIAVERSION: "julialang/bin/winnt/x86/0.3/julia-0.3-latest-win32.exe"
- JULIAVERSION: "julialang/bin/winnt/x64/0.3/julia-0.3-latest-win64.exe"
- JULIAVERSION: "julianightlies/bin/winnt/x86/julia-latest-win32.exe"
- JULIAVERSION: "julianightlies/bin/winnt/x64/julia-latest-win64.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.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"
branches:
only:
- master
- /release-.*/
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
@@ -17,18 +18,22 @@ notifications:
on_build_status_changed: false
install:
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
# If there's a newer build queued for the same PR, cancel this one
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
throw "There are newer queued builds for this pull request, failing early." }
# Download most recent Julia Windows binary
- ps: (new-object net.webclient).DownloadFile(
$("http://s3.amazonaws.com/"+$env:JULIAVERSION),
"C:\projects\julia-binary.exe")
- ps: (new-object net.webclient).DownloadFile($env:JULIA_URL, "C:\projects\julia-binary.exe")
# Run installer silently, output to C:\projects\julia
- C:\projects\julia-binary.exe /S /D=C:\projects\julia
build_script:
# Need to convert from shallow to complete for Pkg.clone to work
- IF EXIST .git\shallow (git fetch --unshallow)
- C:\projects\julia\bin\julia -e "versioninfo();
Pkg.clone(pwd(), \"Plots\"); Pkg.build(\"Plots\")"
- C:\projects\julia\bin\julia -e "versioninfo(); Pkg.clone(pwd(), \"Plots\"); Pkg.build(\"Plots\")"
test_script:
- C:\projects\julia\bin\julia --check-bounds=yes -e "Pkg.test(\"Plots\")"
# - C:\projects\julia\bin\julia -e "Pkg.test(\"Plots\")"
- C:\projects\julia\bin\julia -e "include(Pkg.dir(\"Plots\", \"test\", \"travis_commands.jl\"))"
-419
View File
@@ -1,419 +0,0 @@
module PlotExamples
using Plots
using Colors
using Compat
const DOCDIR = Pkg.dir("Plots") * "/docs"
const IMGDIR = Pkg.dir("Plots") * "/img"
"""
Holds all data needed for a documentation example... header, description, and plotting expression (Expr)
"""
type PlotExample
header::@compat(AbstractString)
desc::@compat(AbstractString)
exprs::Vector{Expr}
end
# the examples we'll run for each
const examples = PlotExample[
PlotExample("Lines",
"A simple line plot of the columns.",
[
:(plot(Plots.fakedata(50,5), w=3))
]),
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.",
[
:(p = plot([sin,cos], zeros(0), leg=false)),
:(anim = Animation()),
:(for x in linspace(0, 10π, 100)
push!(p, x, Float64[sin(x), cos(x)])
frame(anim)
end)
]),
PlotExample("Parametric plots",
"Plot function pair (x(u), y(u)).",
[
:(plot(sin, x->sin(2x), 0, 2π, line=4, leg=false, fill=(0,:orange)))
]),
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.",
[
:(y = rand(100)),
:(plot(0:10:100,rand(11,4),lab="lines",w=3, palette=:grays, fill=(0.5,:auto))),
:(scatter!(y, zcolor=abs(y-.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs(y-0.5)+4, lab="grad"))
]),
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!`",
[
:(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))
]),
PlotExample("Two-axis",
"Use the `axis` arguments.\n\nNote: Currently only supported with Qwt and PyPlot",
[
:(plot(Vector[randn(100), randn(100)*100], axis = [:l :r], ylabel="LEFT", yrightlabel="RIGHT", xlabel="X", title="TITLE"))
]),
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.",
[
:(ys = Vector[rand(10), rand(20)]),
:(plot(ys, line=(:dot,4,[:black :orange]), marker=([:hex :d],12,0.8,stroke(3,:gray))))
]),
PlotExample("Build plot in pieces",
"Start with a base plot...",
[
:(plot(rand(100)/3, reg=true, fill=(0,:green)))
]),
PlotExample("",
"and add to it later.",
[
:(scatter!(rand(100), markersize=6, c=:orange))
]),
PlotExample("Heatmaps",
"",
[
:(heatmap(randn(10000),randn(10000), nbins=20))
]),
PlotExample("Line types",
"",
[
:(types = intersect(supportedTypes(), [:line, :path, :steppre, :steppost, :sticks, :scatter])'),
:(n = length(types)),
:(x = Vector[sort(rand(20)) for i in 1:n]),
:(y = rand(20,n)),
:(plot(x, y, line=(types,3), lab=map(string,types), ms=15))
]),
PlotExample("Line styles",
"",
[
:(styles = setdiff(supportedStyles(), [:auto])'),
:(plot(cumsum(randn(20,length(styles)),1), style=:auto, label=map(string,styles), w=5))
]),
PlotExample("Marker types",
"",
[
:(markers = setdiff(supportedMarkers(), [:none,:auto,Shape])'),
:(n = length(markers)),
:(x = linspace(0,10,n+2)[2:end-1]),
:(y = repmat(reverse(x)', n, 1)),
:(scatter(x, y, m=(8,:auto), lab=map(string,markers), bg=:linen))
]),
PlotExample("Bar",
"x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
[
:(bar(randn(999)))
]),
PlotExample("Histogram",
"",
[
:(histogram(randn(1000), nbins=20))
]),
PlotExample("Subplots",
"""
subplot and subplot! are distinct commands which create many plots and add series to them in a circular fashion.
You can define the layout with keyword params... either set the number of plots `n` (and optionally number of rows `nr` or
number of columns `nc`), or you can set the layout directly with `layout`.
""",
[
:(subplot(randn(100,5), layout=[1,1,3], t=[:line :hist :scatter :step :bar], nbins=10, leg=false))
]),
PlotExample("Adding to subplots",
"Note here the automatic grid layout, as well as the order in which new series are added to the plots.",
[
:(subplot(Plots.fakedata(100,10), n=4, palette=[:grays :blues :heat :lightrainbow], bg=[:orange :pink :darkblue :black]))
]),
PlotExample("",
"",
[
:(subplot!(Plots.fakedata(100,10)))
]),
PlotExample("Open/High/Low/Close",
"Create an OHLC chart. Pass in a vector of OHLC objects as your `y` argument. Adjust the tick width with arg `markersize`.",
[
:(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; markersize=8))
]),
PlotExample("Annotations",
"Currently only text annotations are supported. Pass in a tuple or vector-of-tuples: (x,y,text). `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`",
[
:(y = rand(10)),
:(plot(y, ann=(3,y[3],text("this is #3",:left)))),
:(annotate!([(5,y[5],text("this is #5",16,:red,:center)),
(10,y[10],text("this is #10",:right,20,"courier"))]))
]),
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.",
[
:(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)])
:(plot(0.1:0.2:0.9, 0.7rand(5)+0.15,
l=(3,:dash,:lightblue),
m=(Shape(verts),30,RGBA(0,0,0,0.2)),
bg=:pink, fg=:darkblue,
xlim = (0,1), ylim=(0,1), leg=false))
]),
PlotExample("Contours",
"",
[
:(x = 1:0.3:20),
:(y = x),
:(f(x,y) = sin(x)+cos(y)),
:(contour(x, y, f, fill=true))
]),
PlotExample("Pie",
"",
[
:(x = ["Nerds", "Hackers", "Scientists"]),
:(y = [0.4, 0.35, 0.25]),
:(pie(x, y, title="The Julia Community", l=0.5))
]),
PlotExample("3D",
"",
[
:(n = 100),
:(ts = linspace(0,8π,n)),
:(x = ts .* map(cos,ts)),
:(y = 0.1ts .* map(sin,ts)),
:(z = 1:n),
:(plot(x, y, z, zcolor=reverse(z), m=(10,0.8,:blues,stroke(0)), leg=false, w=5)),
:(plot!(zeros(n),zeros(n),1:n, w=10))
])
]
function createStringOfMarkDownCodeValues(arr, prefix = "")
string("`", prefix, join(sort(map(string, arr)), "`, `$prefix"), "`")
end
createStringOfMarkDownSymbols(arr) = isempty(arr) ? "" : createStringOfMarkDownCodeValues(arr, ":")
function generate_markdown(pkgname::Symbol)
# set up the backend, and don't show the plots by default
pkg = backend(pkgname)
# default(:show, false)
# mkdir if necessary
try
mkdir("$IMGDIR/$pkgname")
end
# open the markdown file
md = open("$DOCDIR/$(pkgname)_examples.md", "w")
write(md, "## Examples for backend: $pkgname\n\n")
write(md, "### Initialize\n\n```julia\nusing Plots\n$(pkgname)()\n```\n\n")
for (i,example) in enumerate(examples)
try
# we want to always produce consistent results
srand(1234)
# run the code
map(eval, example.exprs)
# # save the png
# imgname = "$(pkgname)_example_$i.png"
# NOTE: uncomment this to overwrite the images as well
if i == 2
imgname = "$(pkgname)_example_$i.gif"
gif(anim, "$IMGDIR/$pkgname/$imgname", fps=15)
else
imgname = "$(pkgname)_example_$i.png"
png("$IMGDIR/$pkgname/$imgname")
end
# write out the header, description, code block, and image link
write(md, "### $(example.header)\n\n")
write(md, "$(example.desc)\n\n")
write(md, "```julia\n$(join(map(string, example.exprs), "\n"))\n```\n\n")
write(md, "![](../img/$pkgname/$imgname)\n\n")
catch ex
# TODO: put error info into markdown?
warn("Example $pkgname:$i failed with: $ex")
end
#
end
write(md, "- Supported arguments: $(createStringOfMarkDownCodeValues(supportedArgs(pkg)))\n")
write(md, "- Supported values for axis: $(createStringOfMarkDownSymbols(supportedAxes(pkg)))\n")
write(md, "- Supported values for linetype: $(createStringOfMarkDownSymbols(supportedTypes(pkg)))\n")
write(md, "- Supported values for linestyle: $(createStringOfMarkDownSymbols(supportedStyles(pkg)))\n")
write(md, "- Supported values for marker: $(createStringOfMarkDownSymbols(supportedMarkers(pkg)))\n")
write(md, "- Is `subplot`/`subplot!` supported? $(subplotSupported(pkg) ? "Yes" : "No")\n\n")
write(md, "(Automatically generated: $(now()))")
close(md)
end
# make and display one plot
function test_examples(pkgname::Symbol, idx::Int; debug = true)
Plots._debugMode.on = debug
println("Testing plot: $pkgname:$idx:$(examples[idx].header)")
backend(pkgname)
backend()
map(eval, examples[idx].exprs)
plt = current()
gui(plt)
plt
end
# generate all plots and create a dict mapping idx --> plt
function test_examples(pkgname::Symbol; debug = false)
Plots._debugMode.on = debug
plts = Dict()
for i in 1:length(examples)
# if examples[i].header == "Subplots" && !subplotSupported()
# break
# end
try
plt = test_examples(pkgname, i, debug=debug)
plts[i] = plt
catch ex
# TODO: put error info into markdown?
warn("Example $pkgname:$i:$(examples[i].header) failed with: $ex")
end
end
plts
end
# axis # :left or :right
# color # can be a string ("red") or a symbol (:red) or a ColorsTypes.jl
# # Colorant (RGB(1,0,0)) or :auto (which lets the package pick)
# label # string or symbol, applies to that line, may go in a legend
# width # width of a line
# linetype # :line, :step, :stepinverted, :sticks, :scatter, :none, :heatmap, :hexbin, :hist, :bar
# linestyle # :solid, :dash, :dot, :dashdot, :dashdotdot
# marker # :none, :ellipse, :rect, :diamond, :utriangle, :dtriangle,
# # :cross, :xcross, :star1, :star2, :hexagon
# markercolor # same choices as `color`, or :match will set the color to be the same as `color`
# markersize # size of the marker
# nbins # number of bins for heatmap/hexbin and histograms
# heatmap_c # color cutoffs for Qwt heatmaps
# fill # fill value for area plots
# title # string or symbol, title of the plot
# xlabel # string or symbol, label on the bottom (x) axis
# ylabel # string or symbol, label on the left (y) axis
# yrightlabel # string or symbol, label on the right (y) axis
# reg # true or false, add a regression line for each line
# size # (Int,Int), resize the enclosing window
# pos # (Int,Int), move the enclosing window to this position
# windowtitle # string or symbol, set the title of the enclosing windowtitle
# screen # Integer, move enclosing window to this screen number (for multiscreen desktops)
@compat const _ltdesc = Dict(
:none => "No line",
:line => "Lines with sorted x-axis",
:path => "Lines",
:steppre => "Step plot (vertical then horizontal)",
:steppost => "Step plot (horizontal then vertical)",
:sticks => "Vertical lines",
:scatter => "Points, no lines",
:heatmap => "Colored regions by density",
:hexbin => "Similar to heatmap",
:hist => "Histogram (doesn't use x)",
:bar => "Bar plot (centered on x values)",
:hline => "Horizontal line (doesn't use x)",
:vline => "Vertical line (doesn't use x)",
:ohlc => "Open/High/Low/Close chart (expects y is AbstractVector{Plots.OHLC})",
:contour => "Contour lines (uses z)",
:path3d => "3D path (uses z)",
:scatter3d => "3D scatter plot (uses z)",
)
function buildReadme()
readme = readall("$DOCDIR/readme_template.md")
# build keyword arg table
table = "Keyword | Default | Type | Aliases \n---- | ---- | ---- | ----\n"
allseries = merge(Plots._seriesDefaults, @compat(Dict(:line=>nothing, :marker=>nothing, :fill=>nothing)))
allplots = merge(Plots._plotDefaults, @compat(Dict(:xaxis=>nothing, :yaxis=>nothing)))
alldefs = merge(allseries, allplots)
for k in Plots.sortedkeys(alldefs)
# for d in (Plots._seriesDefaults, Plots._plotDefaults)
# for k in Plots.sortedkeys(d)
aliasstr = createStringOfMarkDownSymbols(aliases(Plots._keyAliases, k))
table = string(table, "`:$k` | `$(alldefs[k])` | $(haskey(allseries,k) ? "Series" : "Plot") | $aliasstr \n")
# end
end
readme = replace(readme, "[[KEYWORD_ARGS_TABLE]]", table)
# build linetypes table
table = "Type | Desc | Aliases\n---- | ---- | ----\n"
for lt in Plots._allTypes
aliasstr = createStringOfMarkDownSymbols(aliases(Plots._typeAliases, lt))
table = string(table, "`:$lt` | $(_ltdesc[lt]) | $aliasstr \n")
end
readme = replace(readme, "[[LINETYPES_TABLE]]", table)
# build linestyles table
table = "Type | Aliases\n---- | ----\n"
for s in Plots._allStyles
aliasstr = createStringOfMarkDownSymbols(aliases(Plots._styleAliases, s))
table = string(table, "`:$s` | $aliasstr \n")
end
readme = replace(readme, "[[LINESTYLES_TABLE]]", table)
# build markers table
table = "Type | Aliases\n---- | ----\n"
for s in Plots._allMarkers
aliasstr = createStringOfMarkDownSymbols(aliases(Plots._markerAliases, s))
table = string(table, "`:$s` | $aliasstr \n")
end
readme = replace(readme, "[[MARKERS_TABLE]]", table)
readme_fn = Pkg.dir("Plots") * "/README.md"
f = open(readme_fn, "w")
write(f, readme)
close(f)
gadfly()
Plots.dumpSupportGraphs()
end
default(size=(500,300))
# run it!
# note: generate separately so it's easy to comment out
# @osx_only generate_markdown(:unicodeplots)
# generate_markdown(:qwt)
# generate_markdown(:gadfly)
# generate_markdown(:pyplot)
# generate_markdown(:immerse)
# generate_markdown(:winston)
end # module
-305
View File
@@ -1,305 +0,0 @@
# Plots
[![Build Status](https://travis-ci.org/tbreloff/Plots.jl.svg?branch=master)](https://travis-ci.org/tbreloff/Plots.jl)
[![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)
Plots is a plotting API and toolset. My goals with the package are:
- **Intuitive**. Start generating complex plots without reading volumes of documentation. Commands should "just work".
- **Concise**. Less code means fewer mistakes and more efficient development/analysis.
- **Flexible**. Produce your favorite plots from your favorite package, but quicker and simpler.
- **Consistent**. Don't commit to one graphics package. Use the same code and access the strengths of all backends.
- **Lightweight**. Very few dependencies, since backends are loaded and initialized dynamically.
Use the preprocessing pipeline in Plots to fully describe your visualization before it calls the backend code. This maintains modularity and allows for efficient separation of front end code, algorithms, and backend graphics. New graphical backends can be added with minimal effort.
Check out the [summary graphs](img/supported/supported.md) for the features that each backend supports.
Please add wishlist items, bugs, or any other comments/questions to the issues list.
## Examples for each implemented backend:
- [Gadfly.jl/Immerse.jl](https://github.com/tbreloff/ExamplePlots.jl/tree/master/docs/gadfly_examples.md)
- [PyPlot.jl](https://github.com/tbreloff/ExamplePlots.jl/tree/master/docs/pyplot_examples.md)
- [UnicodePlots.jl](https://github.com/tbreloff/ExamplePlots.jl/tree/master/docs/unicodeplots_examples.md)
- [Qwt.jl](https://github.com/tbreloff/ExamplePlots.jl/tree/master/docs/qwt_examples.md)
Also check out the many [IJulia notebooks](http://nbviewer.ipython.org/github/tbreloff/ExamplePlots.jl/tree/master/examples/) with many examples.
## Installation
First, add the package
```julia
Pkg.add("Plots")
# if you want the latest features:
Pkg.checkout("Plots")
# or for the bleeding edge:
Pkg.checkout("Plots", "dev")
```
then get any plotting packages you need (obviously, you should get at least one backend).
```julia
Pkg.add("Gadfly")
Pkg.add("Immerse")
Pkg.add("PyPlot")
Pkg.add("UnicodePlots")
Pkg.add("Qwt")
Pkg.add("Bokeh")
```
## Use
Load it in. The underlying plotting backends are not imported until `backend()` is called (which happens
on your first call to `plot` or `subplot`). This means that you don't need any backends to be installed when you call `using Plots`.
Plots will try to figure out a good default backend for you automatically based on what backends are installed.
```julia
using Plots
```
Do a plot in Gadfly (inspired by [this example](http://gadflyjl.org/geom_point.html)), then save a png:
```julia
gadfly() # switch to Gadfly as a backend
dataframes() # turn on support for DataFrames inputs
# load some data
using RDatasets
iris = dataset("datasets", "iris");
# This will bring up a browser window with the plot. Add a semicolon at the end to skip display.
scatter(iris, :SepalLength, :SepalWidth, group=:Species, m=([:+ :d :s], 12), smooth=0.99, bg=:black)
# save a png (equivalent to png("gadfly1.png") and savefig("gadfly1.png"))
png("gadfly1")
```
![gadfly_plt](img/gadfly1.png)
## API
Call `backend(backend::Symbol)` or the shorthands (`gadfly()`, `qwt()`, `unicodeplots()`, etc) to set the current plotting backend.
Subsequent commands are converted into the relevant plotting commands for that package:
```julia
gadfly()
plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)`
qwt()
plot(1:10) # this effectively calls `Qwt.plot(1:10)`
```
Use `plot` to create a new plot object, and `plot!` to add to an existing one:
```julia
plot(args...; kw...) # creates a new plot window, and sets it to be the `current`
plot!(args...; kw...) # adds to the `current`
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
```
Now that you know which plot object you're updating (new, current, or other), I'll leave it off for simplicity.
There are many ways to pass in data to the plot functions... some examples:
- Vector-like (subtypes of AbstractArray{T,1})
- Matrix-like (subtypes of AbstractArray{T,2})
- Vectors of Vectors
- Functions
- Vectors of Functions
- DataFrames with column symbols (initialize with `dataframes()`)
In general, you can pass in a `y` only, or an `x` and `y`, both of whatever type(s) you want, and Plots will slice up the data as needed.
For matrices, data is split by columns. For functions, data is mapped. For DataFrames, a Symbol/Symbols in place of x/y will map to
the relevant column(s).
Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `current()`.
```julia
plot() # empty plot object
plot(4) # initialize with 4 empty series
plot(rand(10)) # plot 1 series... x = 1:10
plot(rand(10,5)) # plot 5 series... x = 1:10
plot(rand(10), rand(10)) # plot 1 series
plot(rand(10,5), rand(10)) # plot 5 series... y is the same for all
plot(sin, rand(10)) # y = sin(x)
plot(rand(10), sin) # same... y = sin(x)
plot([sin,cos], 0:0.1:π) # plot 2 series, sin(x) and cos(x)
plot([sin,cos], 0, π) # plot sin and cos on the range [0, π]
plot(1:10, Any[rand(10), sin]) # plot 2 series, y = rand(10) for the first, y = sin(x) for the second... x = 1:10 for both
plot(dataset("Ecdat", "Airline"), :Cost) # plot from a DataFrame (call `dataframes()` first to import DataFrames and initialize)
```
All plot methods accept a number of keyword arguments (see the tables below), which follow some rules:
- Many arguments have aliases which are replaced during preprocessing. `c` is the same as `color`, `m` is the same as `marker`, etc. You can choose how verbose you'd like to be. (see the tables below)
- There are some special arguments (`xaxis`, `yaxis`, `line`, `marker`, `fill` and the aliases `l`, `m`, `f`) which magically set many related things at once. (see the __Tip__ below)
- If the argument is a "matrix-type", then each column will map to a series, cycling through columns if there are fewer columns than series. Anything else will apply the argument value to every series.
- Many arguments accept many different types... for example the `color` (also `markercolor`, `fillcolor`, etc) argument will accept strings or symbols with a color name, or any `Colors.Colorant`, or a `ColorScheme`, or a symbol representing a `ColorGradient`, or an AbstractVector of colors/symbols/etc...
You can update certain plot settings after plot creation (not supported on all backends):
```julia
plot!(title = "New Title", xlabel = "New xlabel", ylabel = "New ylabel")
plot!(xlims = (0, 5.5), ylims = (-2.2, 6), xticks = 0:0.5:10, yticks = [0,1,5,10])
# using shorthands:
xaxis!("mylabel", :log10, :flip)
```
With `subplot`, create multiple plots at once, with flexible layout options:
```julia
y = rand(100,3)
subplot(y; n = 3) # create an automatic grid, and let it figure out the shape
subplot(y; n = 3, nr = 1) # create an automatic grid, but fix the number of rows
subplot(y; n = 3, nc = 1) # create an automatic grid, but fix the number of columns
subplot(y; layout = [1, 2]) # explicit layout. Lists the number of plots in each row
```
__Tip__: You can call `subplot!(args...; kw...)` to add to an existing subplot.
__Tip__: Calling `subplot!` on a `Plot` object, or `plot!` on a `Subplot` object will throw an error.
Shorthands:
```julia
scatter(args...; kw...) = plot(args...; kw..., linetype = :scatter)
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :scatter)
bar(args...; kw...) = plot(args...; kw..., linetype = :bar)
bar!(args...; kw...) = plot!(args...; kw..., linetype = :bar)
histogram(args...; kw...) = plot(args...; kw..., linetype = :hist)
histogram!(args...; kw...) = plot!(args...; kw..., linetype = :hist)
heatmap(args...; kw...) = plot(args...; kw..., linetype = :heatmap)
heatmap!(args...; kw...) = plot!(args...; kw..., linetype = :heatmap)
sticks(args...; kw...) = plot(args...; kw..., linetype = :sticks, marker = :ellipse)
sticks!(args...; kw...) = plot!(args...; kw..., linetype = :sticks, marker = :ellipse)
hline(args...; kw...) = plot(args...; kw..., linetype = :hline)
hline!(args...; kw...) = plot!(args...; kw..., linetype = :hline)
vline(args...; kw...) = plot(args...; kw..., linetype = :vline)
vline!(args...; kw...) = plot!(args...; kw..., linetype = :vline)
ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
title!(s::AbstractString) = plot!(title = s)
xlabel!(s::AbstractString) = plot!(xlabel = s)
ylabel!(s::AbstractString) = plot!(ylabel = s)
xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(xlims = lims)
ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(ylims = lims)
xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v)
yticks!{T<:Real}(v::AVec{T}) = plot!(yticks = v)
xflip!(flip::Bool = true) = plot!(xflip = flip)
yflip!(flip::Bool = true) = plot!(yflip = flip)
xaxis!(args...) = plot!(xaxis = args)
yaxis!(args...) = plot!(yaxis = args)
annotate!(anns) = plot!(annotation = anns)
```
### Keyword arguments:
[[KEYWORD_ARGS_TABLE]]
### Plot types:
[[LINETYPES_TABLE]]
### Line styles:
[[LINESTYLES_TABLE]]
### Markers:
[[MARKERS_TABLE]]
__Tip__: With supported backends, you can pass a `Plots.Shape` object for the `marker`/`markershape` arguments. `Shape` takes a vector of 2-tuples in the constructor, defining the points of the polygon's shape in a unit-scaled coordinate space. To make a square, for example, you could do `Shape([(1,1),(1,-1),(-1,-1),(-1,1)])`
__Tip__: You can see the default value for a given argument with `default(arg::Symbol)`, and set the default value with `default(arg::Symbol, value)` or `default(; kw...)`. For example set the default window size and whether we should show a legend with `default(size=(600,400), leg=false)`.
__Tip__: There are some helper arguments you can set: `xaxis`, `yaxis`, `line`, `marker`, `fill`. These go through special preprocessing to extract values into individual arguments. The order doesn't matter, and if you pass a single value it's equivalent to wrapping it in a Tuple. Examples:
```
plot(y, xaxis = ("mylabel", :log, :flip, (-1,1))) # this sets the `xlabel`, `xscale`, `xflip`, and `xlims` arguments automatically
plot(y, line = (:bar, :blue, :dot, 10)) # this sets the `linetype`, `color`, `linestyle`, and `linewidth` arguments automatically
plot(y, marker = (:rect, :red, 10)) # this sets the `markershape`, `markercolor`, and `markersize` arguments automatically
plot(y, fill = (:green, 10)) # this sets the `fillcolor` and `fillrange` arguments automatically
# Note: `fillrange` can be:
a number (fill to horizontal line)
a vector of numbers (different for each data point)
a tuple of vectors (fill a band)
```
__Tip__: When plotting multiple lines, you can set all series to use the same value, or pass in a matrix to cycle through values. Example:
```julia
plot(rand(100,4); color = [:red RGB(0,0,1)], # (Matrix) lines 1 and 3 are red, lines 2 and 4 are blue
axis = :auto, # lines 1 and 3 are on the left axis, lines 2 and 4 are on the right
markershape = [:rect, :star] # (Vector) ALL lines are passed the vector [:rect, :star1]
width = 5) # all lines have a width of 5
```
__Tip__: Not all features are supported for each backend, but you can see what's supported by calling the functions: `supportedArgs()`, `supportedAxes()`, `supportedTypes()`, `supportedStyles()`, `supportedMarkers()`, `subplotSupported()`
__Tip__: Call `gui()` to display the plot in a window. Interactivity depends on backend. Plotting at the REPL (without semicolon) implicitly calls `gui()`.
### Animations
Animations are created in 3 steps (see example #2):
- Initialize an `Animation` object.
- Save each frame of the animation with `frame(anim)`.
- Convert the frames to an animated gif with `gif(anim, filename, fps=15)`
## TODO features:
- [x] Plot vectors/matrices/functions
- [x] Plot DataFrames
- [x] Histograms
- [x] Grouping
- [x] Annotations
- [x] Scales
- [x] Categorical Inputs (strings, etc... for hist, bar? or can split one series into multiple?)
- [x] Custom markers
- [x] Animations
- [x] Subplots
- [ ] Contours
- [ ] Boxplots
- [ ] 3D plotting
- [ ] Scenes/Drawing
- [ ] Graphs
- [ ] Interactivity (GUIs)
## TODO backends:
- [x] Gadfly.jl
- [x] Immerse.jl
- [x] PyPlot.jl
- [x] UnicodePlots.jl
- [x] Qwt.jl
- [x] Winston.jl (deprecated)
- [ ] GLPlot.jl
- [ ] Bokeh.jl
- [ ] Vega.jl
- [ ] Gaston.jl
- [ ] Plotly.jl
- [ ] GoogleCharts.jl
- [ ] PLplot.jl
- [ ] TextPlots.jl
- [ ] ASCIIPlots.jl
- [ ] Sparklines.jl
- [ ] Hinton.jl
- [ ] ImageTerm.jl
- [ ] GraphViz.jl
- [ ] TikzGraphs.jl
- [ ] GraphLayout.jl
## More information on backends (both supported and unsupported)
See the wiki at: https://github.com/JuliaPlot/juliaplot_docs/wiki
Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

-23
View File
@@ -1,23 +0,0 @@
## Supported keyword arguments
![args](Plots.supportGraphArgs.png)
## Supported plot types
![types](Plots.supportGraphTypes.png)
## Supported markers
![markers](Plots.supportGraphMarkers.png)
## Supported line styles
![styles](Plots.supportGraphStyles.png)
## Supported scales
![scales](Plots.supportGraphScales.png)
## Supported axes
![axes](Plots.supportGraphAxes.png)
-333
View File
@@ -1,333 +0,0 @@
immutable GadflyPackage <: PlottingPackage end
immutable ImmersePackage <: PlottingPackage end
immutable PyPlotPackage <: PlottingPackage end
immutable QwtPackage <: PlottingPackage end
immutable UnicodePlotsPackage <: PlottingPackage end
immutable WinstonPackage <: PlottingPackage end
immutable BokehPackage <: PlottingPackage end
immutable PlotlyPackage <: PlottingPackage end
immutable GRPackage <: PlottingPackage end
immutable GLVisualizePackage <: PlottingPackage end
immutable NoPackage <: PlottingPackage end
typealias GadflyOrImmerse @compat(Union{GadflyPackage, ImmersePackage})
export
gadfly,
immerse,
pyplot,
qwt,
unicodeplots,
bokeh,
plotly,
gr,
glvisualize
# winston
gadfly(; kw...) = (default(; kw...); backend(:gadfly))
immerse(; kw...) = (default(; kw...); backend(:immerse))
pyplot(; kw...) = (default(; kw...); backend(:pyplot))
qwt(; kw...) = (default(; kw...); backend(:qwt))
unicodeplots(; kw...) = (default(; kw...); backend(:unicodeplots))
bokeh(; kw...) = (default(; kw...); backend(:bokeh))
plotly(; kw...) = (default(; kw...); backend(:plotly))
gr(; kw...) = (default(; kw...); backend(:gr))
glvisualize(; kw...) = (default(; kw...); backend(:glvisualize))
# winston(; kw...) = (default(; kw...); backend(:winston))
backend_name(::GadflyPackage) = :gadfly
backend_name(::ImmersePackage) = :immerse
backend_name(::PyPlotPackage) = :pyplot
backend_name(::UnicodePlotsPackage) = :unicodeplots
backend_name(::QwtPackage) = :qwt
backend_name(::BokehPackage) = :bokeh
backend_name(::PlotlyPackage) = :plotly
backend_name(::GRPackage) = :gr
backend_name(::GLVisualizePackage) = :glvisualize
backend_name(::NoPackage) = :none
include("backends/supported.jl")
include("backends/qwt.jl")
include("backends/gadfly.jl")
include("backends/unicodeplots.jl")
include("backends/pyplot.jl")
include("backends/immerse.jl")
include("backends/winston.jl")
include("backends/web.jl")
include("backends/bokeh.jl")
include("backends/plotly.jl")
include("backends/gr.jl")
include("backends/glvisualize.jl")
# ---------------------------------------------------------
plot(pkg::PlottingPackage; kw...) = error("plot($pkg; kw...) is not implemented")
plot!(pkg::PlottingPackage, plt::Plot; kw...) = error("plot!($pkg, plt; kw...) is not implemented")
_update_plot(pkg::PlottingPackage, plt::Plot, d::Dict) = error("_update_plot($pkg, plt, d) is not implemented")
# Base.display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not implemented")
_update_plot_pos_size{P<:PlottingPackage}(plt::PlottingObject{P}, d::Dict) = nothing #error("_update_plot_pos_size(plt,d) is not implemented for $P")
subplot(pkg::PlottingPackage; kw...) = error("subplot($pkg; kw...) is not implemented")
subplot!(pkg::PlottingPackage, subplt::Subplot; kw...) = error("subplot!($pkg, subplt; kw...) is not implemented")
# Base.display(pkg::PlottingPackage, subplt::Subplot) = error("display($pkg, subplt) is not implemented")
# ---------------------------------------------------------
const BACKENDS = [:qwt, :gadfly, :unicodeplots, :pyplot, :immerse, :bokeh, :plotly, :gr]
const _initialized_backends = Set{Symbol}()
backends() = BACKENDS
function _backend_instance(sym::Symbol)
sym == :qwt && return QwtPackage()
sym == :gadfly && return GadflyPackage()
sym == :unicodeplots && return UnicodePlotsPackage()
sym == :pyplot && return PyPlotPackage()
sym == :immerse && return ImmersePackage()
sym == :winston && return WinstonPackage()
sym == :bokeh && return BokehPackage()
sym == :plotly && return PlotlyPackage()
sym == :gr && return GRPackage()
sym == :glvisualize && return GLVisualizePackage()
sym == :none && return NoPackage()
error("Unsupported backend $sym")
end
type CurrentBackend
sym::Symbol
pkg::PlottingPackage
end
CurrentBackend(sym::Symbol) = CurrentBackend(sym, _backend_instance(sym))
# ---------------------------------------------------------
function pickDefaultBackend()
for pkgstr in ("PyPlot", "Immerse", "Qwt", "Gadfly", "GR", "UnicodePlots", "Bokeh", "GLVisualize")
if Pkg.installed(pkgstr) != nothing
return backend(symbol(lowercase(pkgstr)))
end
end
backend(:plotly)
end
# ---------------------------------------------------------
"""
Returns the current plotting package name. Initializes package on first call.
"""
function backend()
global CURRENT_BACKEND
if CURRENT_BACKEND.sym == :none
pickDefaultBackend()
end
currentBackendSymbol = CURRENT_BACKEND.sym
if !(currentBackendSymbol in _initialized_backends)
# initialize
println("[Plots.jl] Initializing backend: ", CURRENT_BACKEND.sym)
if currentBackendSymbol == :qwt
try
@eval import Qwt
@eval export Qwt
catch err
warn("Couldn't import Qwt. Install it with: Pkg.clone(\"https://github.com/tbreloff/Qwt.jl.git\")\n (Note: also requires pyqt and pyqwt).")
rethrow(err)
end
elseif currentBackendSymbol == :gadfly
try
@eval import Gadfly, Compose
@eval export Gadfly, Compose
@eval include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
catch err
warn("Couldn't import Gadfly. Install it with: Pkg.add(\"Gadfly\").")
rethrow(err)
end
elseif currentBackendSymbol == :unicodeplots
try
@eval import UnicodePlots
@eval export UnicodePlots
catch err
warn("Couldn't import UnicodePlots. Install it with: Pkg.add(\"UnicodePlots\").")
rethrow(err)
end
elseif currentBackendSymbol == :pyplot
try
@eval import PyPlot
@eval export PyPlot
@eval const pycolors = PyPlot.pywrap(PyPlot.pyimport("matplotlib.colors"))
@eval const pypath = PyPlot.pywrap(PyPlot.pyimport("matplotlib.path"))
@eval const mplot3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d"))
# @eval const pycolorbar = PyPlot.pywrap(PyPlot.pyimport("matplotlib.colorbar"))
if !isa(Base.Multimedia.displays[end], Base.REPL.REPLDisplay)
PyPlot.ioff() # stops wierd behavior of displaying incomplete graphs in IJulia
# # TODO: how the hell can I use PyQt4??
# "pyqt4"=>:qt_pyqt4
# PyPlot.backend[1] = "pyqt4"
# PyPlot.gui[1] = :qt_pyqt4
# PyPlot.switch_backend("Qt4Agg")
# only turn on the gui if we want it
if PyPlot.gui != :none
PyPlot.pygui(true)
end
end
catch err
warn("Couldn't import PyPlot. Install it with: Pkg.add(\"PyPlot\").")
rethrow(err)
end
elseif currentBackendSymbol == :immerse
try
@eval import Immerse, Gadfly, Compose, Gtk
@eval export Immerse, Gadfly, Compose, Gtk
@eval include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
catch err
# error("Couldn't import Immerse. Install it with: Pkg.add(\"Immerse\").\n Error: ", err)
warn("Couldn't import Immerse. Install it with: Pkg.add(\"Immerse\").")
rethrow(err)
end
elseif currentBackendSymbol == :bokeh
try
@eval import Bokeh
@eval export Bokeh
catch err
warn("Couldn't import Bokeh. Install it with: Pkg.add(\"Bokeh\").")
rethrow(err)
end
elseif currentBackendSymbol == :plotly
try
@eval begin
import JSON
JSON._print(io::IO, state::JSON.State, dt::Union{Date,DateTime}) = print(io, '"', dt, '"')
############################
# borrowed from https://github.com/spencerlyon2/Plotlyjs.jl/blob/master/src/display.jl
_js_path = joinpath(Pkg.dir("Plots"), "deps", "plotly-latest.min.js")
# if we're in IJulia call setupnotebook to load js and css
if isijulia()
# the first script is some hack I needed to do in order for the notebook
# to not complain about Plotly being undefined
display("text/html", """
<script type="text/javascript">
require=requirejs=define=undefined;
</script>
<script type="text/javascript">
$(open(readall, _js_path, "r"))
</script>
""")
# display("text/html", "<p>Plotly javascript loaded.</p>")
end
# end borrowing (thanks :)
###########################
try
include(joinpath(Pkg.dir("Plots"), "src", "backends", "plotly_blink.jl"))
catch err
warn("Error including PlotlyJS: $err\n Note: Will fall back to built-in display.")
end
end
catch err
warn("Couldn't setup Plotly")
rethrow(err)
end
elseif currentBackendSymbol == :gr
try
@eval import GR
catch err
warn("Couldn't import GR. Install it with: Pkg.add(\"GR\").")
end
elseif currentBackendSymbol == :glvisualize
try
@eval import GLVisualize
@eval export GLVisualize
catch err
warn("Couldn't setup GLVisualize")
rethrow(err)
end
elseif currentBackendSymbol == :winston
warn("Winston support is deprecated and broken. Try another backend: $BACKENDS")
try
@eval ENV["WINSTON_OUTPUT"] = "gtk"
@eval import Winston, Gtk
@eval export Winston, Gtk
catch err
warn("Couldn't import Winston. Install it with: Pkg.add(\"Winston\").")
rethrow(err)
end
else
error("Unknown backend $currentBackendSymbol. Choose from: $BACKENDS")
end
push!(_initialized_backends, currentBackendSymbol)
end
CURRENT_BACKEND.pkg
end
"""
Set the plot backend. Choose from: :qwt, :gadfly, :unicodeplots, :immerse, :pyplot
"""
function backend(pkg::PlottingPackage)
CURRENT_BACKEND.sym = backend_name(pkg)
CURRENT_BACKEND.pkg = pkg
end
function backend(modname)
# set the PlottingPackage
if modname == :qwt
CURRENT_BACKEND.pkg = QwtPackage()
elseif modname == :gadfly
CURRENT_BACKEND.pkg = GadflyPackage()
elseif modname == :unicodeplots
CURRENT_BACKEND.pkg = UnicodePlotsPackage()
elseif modname == :pyplot
CURRENT_BACKEND.pkg = PyPlotPackage()
elseif modname == :immerse
CURRENT_BACKEND.pkg = ImmersePackage()
elseif modname == :winston
CURRENT_BACKEND.pkg = WinstonPackage()
elseif modname == :bokeh
CURRENT_BACKEND.pkg = BokehPackage()
elseif modname == :plotly
CURRENT_BACKEND.pkg = PlotlyPackage()
elseif modname == :gr
CURRENT_BACKEND.pkg = GRPackage()
elseif modname == :glvisualize
CURRENT_BACKEND.pkg = GLVisualizePackage()
else
error("Unknown backend $modname. Choose from: $BACKENDS")
end
# update the symbol
CURRENT_BACKEND.sym = modname
# println("[Plots.jl] Switched to backend: ", modname)
# return the package
CURRENT_BACKEND.pkg
end
Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

-21
View File
@@ -1,21 +0,0 @@
function testplot_line1()
plot(rand(100,3))
end
function testplot_fn1()
plot(0:0.01:4π, [sin,cos])
end
function testplot_guides1()
plot(rand(10); title="TITLE", xlabel="XLABEL", ylabel="YLABEL", background_color=:red)
end
function testplot_points1()
plot(Vector[rand(10), rand(20)]; marker=:ellipse, markersize=8)
end
function testplot_points2()
plot(Vector[rand(10), rand(20)]; marker=:ellipse, markersize=8, markercolors=[:red,:blue])
end
+8
View File
@@ -0,0 +1,8 @@
#TODO: download https://cdn.plot.ly/plotly-latest.min.js to deps/ if it doesn't exist
local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js")
if !isfile(local_fn)
info("Cannot find deps/plotly-latest.min.js... downloading latest version.")
download("https://cdn.plot.ly/plotly-latest.min.js", local_fn)
end
-41
View File
File diff suppressed because one or more lines are too long
+257 -185
View File
@@ -1,237 +1,309 @@
__precompile__()
__precompile__(true)
module Plots
using Compat
using Reexport
@reexport using Colors
import StaticArrays
using StaticArrays.FixedSizeArrays
@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
using FixedSizeArrays
export
Plot,
Subplot,
SubplotLayout,
GridLayout,
FlexLayout,
AVec,
AMat,
grid,
bbox,
plotarea,
@layout,
KW,
plot,
plot!,
subplot,
subplot!,
wrap,
theme,
current,
default,
with,
scatter,
scatter!,
bar,
bar!,
histogram,
histogram!,
density,
density!,
heatmap,
heatmap!,
hexbin,
hexbin!,
sticks,
sticks!,
hline,
hline!,
vline,
vline!,
ohlc,
ohlc!,
pie,
pie!,
contour,
contour!,
surface,
surface!,
wireframe,
wireframe!,
path3d,
path3d!,
plot3d,
plot3d!,
scatter3d,
scatter3d!,
abline!,
plot,
plot!,
attr!,
title!,
xlabel!,
ylabel!,
xlims!,
ylims!,
xticks!,
yticks!,
annotate!,
xflip!,
yflip!,
xaxis!,
yaxis!,
current,
default,
with,
twinx,
savefig,
png,
gui,
pie,
pie!,
plot3d,
plot3d!,
backend,
backends,
backend_name,
aliases,
dataframes,
title!,
xlabel!,
ylabel!,
xlims!,
ylims!,
zlims!,
xticks!,
yticks!,
annotate!,
xflip!,
yflip!,
xaxis!,
yaxis!,
xgrid!,
ygrid!,
Shape,
text,
font,
stroke,
brush,
Surface,
OHLC,
xlims,
ylims,
zlims,
colorscheme,
ColorScheme,
ColorGradient,
ColorVector,
ColorWrapper,
ColorFunction,
ColorZFunction,
getColor,
getColorZ,
savefig,
png,
gui,
inline,
closeall,
debugplots,
backend,
backends,
backend_name,
backend_object,
add_backend,
aliases,
supportedArgs,
supportedAxes,
supportedTypes,
supportedStyles,
supportedMarkers,
subplotSupported,
Shape,
text,
font,
stroke,
brush,
Surface,
OHLC,
arrow,
Segments,
Formatted,
Animation,
frame,
gif,
@animate,
@gif,
Animation,
frame,
gif,
mov,
mp4,
animate,
@animate,
@gif,
# recipes
PlotRecipe,
# EllipseRecipe,
# spy,
corrplot
test_examples,
iter_segments,
coords,
translate,
translate!,
rotate,
rotate!,
center,
P2,
P3,
BezierCurve,
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
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("colors.jl")
include("components.jl")
include("plotter2.jl")
include("axes.jl")
include("args.jl")
include("themes.jl")
include("plot.jl")
include("subplot.jl")
include("pipeline.jl")
include("series.jl")
include("layouts.jl")
include("subplots.jl")
include("recipes.jl")
include("animation.jl")
include("examples.jl")
include("arg_desc.jl")
include("plotattr.jl")
include("backends.jl")
include("output.jl")
# ---------------------------------------------------------
scatter(args...; kw...) = plot(args...; kw..., linetype = :scatter)
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :scatter)
bar(args...; kw...) = plot(args...; kw..., linetype = :bar)
bar!(args...; kw...) = plot!(args...; kw..., linetype = :bar)
histogram(args...; kw...) = plot(args...; kw..., linetype = :hist)
histogram!(args...; kw...) = plot!(args...; kw..., linetype = :hist)
density(args...; kw...) = plot(args...; kw..., linetype = :density)
density!(args...; kw...) = plot!(args...; kw..., linetype = :density)
heatmap(args...; kw...) = plot(args...; kw..., linetype = :heatmap)
heatmap!(args...; kw...) = plot!(args...; kw..., linetype = :heatmap)
hexbin(args...; kw...) = plot(args...; kw..., linetype = :hexbin)
hexbin!(args...; kw...) = plot!(args...; kw..., linetype = :hexbin)
sticks(args...; kw...) = plot(args...; kw..., linetype = :sticks, marker = :ellipse)
sticks!(args...; kw...) = plot!(args...; kw..., linetype = :sticks, marker = :ellipse)
hline(args...; kw...) = plot(args...; kw..., linetype = :hline)
hline!(args...; kw...) = plot!(args...; kw..., linetype = :hline)
vline(args...; kw...) = plot(args...; kw..., linetype = :vline)
vline!(args...; kw...) = plot!(args...; kw..., linetype = :vline)
ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
pie(args...; kw...) = plot(args...; kw..., linetype = :pie)
pie!(args...; kw...) = plot!(args...; kw..., linetype = :pie)
contour(args...; kw...) = plot(args...; kw..., linetype = :contour)
contour!(args...; kw...) = plot!(args...; kw..., linetype = :contour)
surface(args...; kw...) = plot(args...; kw..., linetype = :surface)
surface!(args...; kw...) = plot!(args...; kw..., linetype = :surface)
wireframe(args...; kw...) = plot(args...; kw..., linetype = :wireframe)
wireframe!(args...; kw...) = plot!(args...; kw..., linetype = :wireframe)
path3d(args...; kw...) = plot(args...; kw..., linetype = :path3d)
path3d!(args...; kw...) = plot!(args...; kw..., linetype = :path3d)
plot3d(args...; kw...) = plot(args...; kw..., linetype = :path3d)
plot3d!(args...; kw...) = plot!(args...; kw..., linetype = :path3d)
scatter3d(args...; kw...) = plot(args...; kw..., linetype = :scatter3d)
scatter3d!(args...; kw...) = plot!(args...; kw..., linetype = :scatter3d)
@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
@shorthands contour3d
@shorthands surface
@shorthands wireframe
@shorthands path3d
@shorthands scatter3d
@shorthands boxplot
@shorthands violin
@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...)
"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...)
title!(s::@compat(AbstractString); kw...) = plot!(; title = s, kw...)
xlabel!(s::@compat(AbstractString); kw...) = plot!(; xlabel = s, kw...)
ylabel!(s::@compat(AbstractString); kw...) = plot!(; ylabel = s, kw...)
xlims!{T<:Real,S<:Real}(lims::@compat(Tuple{T,S}); kw...) = plot!(; xlims = lims, kw...)
ylims!{T<:Real,S<:Real}(lims::@compat(Tuple{T,S}); kw...) = plot!(; ylims = lims, kw...)
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...)
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), 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<:@compat(AbstractString)}(
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; xticks = (ticks,labels), kw...)
yticks!{T<:Real,S<:@compat(AbstractString)}(
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; yticks = (ticks,labels), kw...)
zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), 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::@compat(AbstractString); kw...) = plot!(plt; title = s, kw...)
xlabel!(plt::Plot, s::@compat(AbstractString); kw...) = plot!(plt; xlabel = s, kw...)
ylabel!(plt::Plot, s::@compat(AbstractString); kw...) = plot!(plt; ylabel = s, kw...)
xlims!{T<:Real,S<:Real}(plt::Plot, lims::@compat(Tuple{T,S}); kw...) = plot!(plt; xlims = lims, kw...)
ylims!{T<:Real,S<:Real}(plt::Plot, lims::@compat(Tuple{T,S}); kw...) = plot!(plt; ylims = 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...)
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<:@compat(AbstractString)}(plt::Plot,
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; xticks = (ticks,labels), kw...)
yticks!{T<:Real,S<:@compat(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}
title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
xlabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; xlabel = s, kw...)
ylabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; ylabel = s, kw...)
xlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; xlims = lims, kw...)
ylims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; ylims = lims, kw...)
zlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; zlims = lims, kw...)
xlims!(plt::PlotOrSubplot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin,xmax), kw...)
ylims!(plt::PlotOrSubplot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin,ymax), kw...)
zlims!(plt::PlotOrSubplot, zmin::Real, zmax::Real; kw...) = plot!(plt; zlims = (zmin,zmax), kw...)
xticks!(plt::PlotOrSubplot, ticks::AVec{T}; kw...) where {T<:Real} = plot!(plt; xticks = ticks, kw...)
yticks!(plt::PlotOrSubplot, ticks::AVec{T}; kw...) where {T<:Real} = plot!(plt; yticks = ticks, kw...)
xticks!(plt::PlotOrSubplot,
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; xticks = (ticks,labels), kw...)
yticks!(plt::PlotOrSubplot,
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; yticks = (ticks,labels), kw...)
xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...)
ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...)
annotate!(plt::PlotOrSubplot, anns...; kw...) = plot!(plt; annotation = anns, kw...)
annotate!(plt::PlotOrSubplot, anns::AVec{T}; kw...) where {T<:Tuple} = plot!(plt; annotation = anns, kw...)
xflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...)
yflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; yflip = flip, kw...)
xaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xaxis = args, kw...)
yaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; yaxis = args, kw...)
end
# ---------------------------------------------------------
const CURRENT_BACKEND = CurrentBackend(:none)
function __init__()
# override IJulia inline display
if isijulia()
@eval import IJulia
IJulia.display_dict(plt::PlottingObject) = Dict{ASCIIString, ByteString}("text/html" => sprint(writemime, "text/html", plt))
end
# 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
k == :theme || default(k, v)
end
end
end
# ---------------------------------------------------------
+91 -36
View File
@@ -1,55 +1,108 @@
immutable Animation
dir::ASCIIString
frames::Vector{ASCIIString}
"Represents an animation object"
struct Animation
dir::String
frames::Vector{String}
end
function Animation()
tmpdir = convert(ASCIIString, mktempdir())
Animation(tmpdir, ASCIIString[])
tmpdir = convert(String, mktempdir())
Animation(tmpdir, String[])
end
function frame{P<:PlottingObject}(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::ASCIIString
struct AnimatedGif
filename::String
end
function gif(anim::Animation, fn::@compat(AbstractString) = "tmp.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)
run(`convert -delay $speed -loop 0 $(anim.dir)/*.png -alpha off $fn`)
catch err
warn("Tried to create gif using convert (ImageMagick), but got error: $err\nWill try ffmpeg, but it's lower quality...)")
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)
# 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
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
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
@@ -63,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
@@ -75,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
@@ -95,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
@@ -115,7 +170,7 @@ Example:
```
"""
macro gif(forloop::Expr, args...)
_animate(forloop, args...; callgif = true)
_animate(forloop, args...; callgif = true)
end
"""
@@ -124,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
+145
View File
@@ -0,0 +1,145 @@
const _arg_desc = KW(
# series args
:label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.",
:seriescolor => "Color Type. The base color for this series. `:auto` (the default) will select a color from the subplot's `color_palette`, based on the order it was added to the subplot",
:seriesalpha => "Number in [0,1]. The alpha/opacity override for the series. `nothing` (the default) means it will take the alpha value of the color.",
:seriestype => "Symbol. This is the identifier of the type of visualization for this series. Choose from $(_allTypes) or any series recipes which are defined.",
:linestyle => "Symbol. Style of the line (for path and bar stroke). Choose from $(_allStyles)",
:linewidth => "Number. Width of the line (in pixels)",
:linecolor => "Color Type. Color of the line (for path and bar stroke). `:match` will take the value from `:seriescolor`, (though histogram/bar types use `:black` as a default).",
:linealpha => "Number in [0,1]. The alpha/opacity override for the line. `nothing` (the default) means it will take the alpha value of linecolor.",
:fillrange => "Number or AbstractVector. Fills area from this to y for line-types, sets the base for bar/stick types, and similar for other types.",
:fillcolor => "Color Type. Color of the filled area of path or bar types. `:match` will take the value from `:seriescolor`.",
:fillalpha => "Number in [0,1]. The alpha/opacity override for the fill area. `nothing` (the default) means it will take the alpha value of fillcolor.",
:markershape => "Symbol, Shape, or AbstractVector. Choose from $(_allMarkers).",
:markercolor => "Color Type. Color of the interior of the marker or shape. `:match` will take the value from `:seriescolor`.",
:markeralpha => "Number in [0,1]. The alpha/opacity override for the marker interior. `nothing` (the default) means it will take the alpha value of markercolor.",
: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 `:foreground_color_subplot`.",
:markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.",
:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto (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",
:y => "Various. Input data. Second Dimension",
: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)",
:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).",
:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?",
:xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)",
:yerror => "AbstractVector or 2-Tuple of Vectors. y (vertical) error relative to y-value. If 2-tuple of vectors, the first vector corresponds to the bottom error (and the second to the top)",
: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 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.",
:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.",
:hover => "nothing or vector of strings. Text to display when hovering over each data point.",
# plot args
:plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)",
:background_color => "Color Type. Base color for all backgrounds.",
:background_color_outside => "Color Type or `:match` (matches `:background_color`). Color outside the plot area(s)",
:foreground_color => "Color Type. Base color for all foregrounds.",
:size => "NTuple{2,Int}. (width_px, height_px) of the whole Plot",
:pos => "NTuple{2,Int}. (left_px, top_px) position of the GUI window (note: currently unimplemented)",
:window_title => "String. Title of the window.",
:show => "Bool. Should this command open/refresh a GUI/display? This allows displaying in scripts or functions without explicitly calling `display`",
:layout => "Integer (number of subplots), NTuple{2,Integer} (grid dimensions), AbstractLayout (for example `grid(2,2)`), or the return from the `@layout` macro. This builds the layout of subplots.",
:link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).",
:overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).",
: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`",
: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_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.",
: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. 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} 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?",
: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`.",
)
+1342 -573
View File
File diff suppressed because it is too large Load Diff
+655
View File
@@ -0,0 +1,655 @@
# xaxis(args...; kw...) = Axis(:x, args...; kw...)
# yaxis(args...; kw...) = Axis(:y, args...; kw...)
# zaxis(args...; kw...) = Axis(:z, args...; kw...)
# -------------------------------------------------------------------------
function Axis(sp::Subplot, letter::Symbol, args...; kw...)
# init with values from _plot_defaults
d = KW(
:letter => letter,
# :extrema => (Inf, -Inf),
:extrema => Extrema(),
:discrete_map => Dict(), # map discrete values to discrete indices
:continuous_values => zeros(0),
:use_minor => false,
:show => true, # show or hide the axis? (useful for linked subplots)
)
# get defaults from letter version, unless match
for (k,v) in _axis_defaults
lk = Symbol(letter, k)
lv = _axis_defaults_byletter[lk]
d[k] = (lv == :match ? v : lv)
end
# merge!(d, _axis_defaults)
d[:discrete_values] = []
# update the defaults
attr!(Axis([sp], d), args...; kw...)
end
function get_axis(sp::Subplot, letter::Symbol)
axissym = Symbol(letter, :axis)
if haskey(sp.attr, axissym)
sp.attr[axissym]
else
sp.attr[axissym] = Axis(sp, letter)
end::Axis
end
function process_axis_arg!(d::KW, arg, letter = "")
T = typeof(arg)
arg = get(_scaleAliases, arg, arg)
if typeof(arg) <: Font
d[Symbol(letter,:tickfont)] = arg
d[Symbol(letter,:guidefont)] = arg
elseif arg in _allScales
d[Symbol(letter,:scale)] = arg
elseif arg in (:flip, :invert, :inverted)
d[Symbol(letter,:flip)] = true
elseif T <: AbstractString
d[Symbol(letter,:guide)] = arg
# xlims/ylims
elseif (T <: Tuple || T <: AVec) && length(arg) == 2
sym = typeof(arg[1]) <: Number ? :lims : :ticks
d[Symbol(letter,sym)] = arg
# xticks/yticks
elseif T <: AVec
d[Symbol(letter,:ticks)] = arg
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
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 attr!(axis::Axis, args...; kw...)
# first process args
d = axis.d
for arg in args
process_axis_arg!(d, arg)
end
# then override for any keywords... only those keywords that already exists in d
for (k,v) in kw
if haskey(d, k)
if k == :discrete_values
# add these discrete values to the axis
for vi in v
discrete_value!(axis, vi)
end
else
d[k] = v
end
end
end
# replace scale aliases
if haskey(_scaleAliases, d[:scale])
d[:scale] = _scaleAliases[d[:scale]]
end
axis
end
# -------------------------------------------------------------------------
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)
ignorenan_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
const _scale_funcs = Dict{Symbol,Function}(
:log10 => log10,
:log2 => log2,
:ln => log,
)
const _inv_scale_funcs = Dict{Symbol,Function}(
:log10 => exp10,
:log2 => exp2,
: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",
:ln => x -> "e^$x",
)
scalefunc(scale::Symbol) = x -> get(_scale_funcs, scale, identity)(Float64(x))
invscalefunc(scale::Symbol) = x -> get(_inv_scale_funcs, scale, identity)(Float64(x))
labelfunc(scale::Symbol, backend::AbstractBackend) = get(_label_func, scale, string)
function optimal_ticks_and_labels(axis::Axis, ticks = nothing)
amin,amax = axis_limits(axis)
# scale the limits
scale = axis[:scale]
sf = scalefunc(scale)
# If the axis input was a Date or DateTime use a special logic to find
# "round" Date(Time)s as ticks
# This bypasses the rest of optimal_ticks_and_labels, because
# optimize_datetime_ticks returns ticks AND labels: the label format (Date
# or DateTime) is chosen based on the time span between amin and amax
# rather than on the input format
# TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime
if ticks == nothing && scale == :identity
if axis[:formatter] == dateformatter
# optimize_datetime_ticks returns ticks and labels(!) based on
# integers/floats corresponding to the DateTime type. Thus, the axes
# limits, which resulted from converting the Date type to integers,
# are converted to 'DateTime integers' (actually floats) before
# being passed to optimize_datetime_ticks.
# (convert(Int, convert(DateTime, convert(Date, i))) == 87600000*i)
ticks, labels = optimize_datetime_ticks(864e5 * amin, 864e5 * amax;
k_min = 2, k_max = 4)
# Now the ticks are converted back to floats corresponding to Dates.
return ticks / 864e5, labels
elseif axis[:formatter] == datetimeformatter
return optimize_datetime_ticks(amin, amax; k_min = 2, k_max = 4)
end
end
# get a list of well-laid-out ticks
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
)[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
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
# @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 = _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 typeof(ticks) <: Symbol
if !isempty(dvals)
# discrete ticks...
n = length(dvals)
rng = if ticks == :auto
Int[round(Int,i) for i in linspace(1, n, 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 linspace(1, length(dvals), 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
error("Unknown ticks type in get_ticks: $(typeof(ticks))")
end
# @show ticks dvals cv dv
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 = isfinite(v) ? min(v, ex.emin) : ex.emin
ex.emax = isfinite(v) ? max(v, ex.emax) : ex.emax
ex
end
function expand_extrema!(axis::Axis, v::Number)
expand_extrema!(axis[:extrema], v)
end
# these shouldn't impact the extrema
expand_extrema!(axis::Axis, ::Void) = axis[:extrema]
expand_extrema!(axis::Axis, ::Bool) = axis[:extrema]
function expand_extrema!(axis::Axis, v::Tuple{MIN,MAX}) where {MIN<:Number,MAX<:Number}
ex = axis[:extrema]
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!(axis::Axis, v::AVec{N}) where N<:Number
ex = axis[:extrema]
for vi in v
expand_extrema!(ex, vi)
end
ex
end
function expand_extrema!(sp::Subplot, d::KW)
vert = isvertical(d)
# first expand for the data
for letter in (:x, :y, :z)
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))
end
expand_extrema!(axis, data)
elseif data != nothing
# TODO: need more here... gotta track the discrete reference value
# as well as any coord offset (think of boxplot shape coords... they all
# correspond to the same x-value)
d[letter], d[Symbol(letter,"_discrete_indices")] = discrete_value!(axis, data)
expand_extrema!(axis, d[letter])
end
end
# # expand for fillrange/bar_width
# fillaxis, baraxis = sp.attr[:yaxis], sp.attr[:xaxis]
# if isvertical(d)
# fillaxis, baraxis = baraxis, fillaxis
# end
# expand for fillrange
fr = d[:fillrange]
if fr == nothing && d[:seriestype] == :bar
fr = 0.0
end
if fr != nothing && !all3D(d)
axis = sp.attr[vert ? :yaxis : :xaxis]
if typeof(fr) <: Tuple
for fri in fr
expand_extrema!(axis, fri)
end
else
expand_extrema!(axis, fr)
end
end
# expand for bar_width
if d[:seriestype] == :bar
dsym = vert ? :x : :y
data = d[dsym]
bw = d[:bar_width]
if bw == nothing
bw = d[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data))))
end
axis = sp.attr[Symbol(dsym, :axis)]
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)
expand_extrema!(sp[:xaxis], (xmin, xmax))
expand_extrema!(sp[:yaxis], (ymin, ymax))
end
# -------------------------------------------------------------------------
# push the limits out slightly
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.
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 !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]
amin, amax = ex.emin, ex.emax
lims = axis[:lims]
if (isa(lims, Tuple) || isa(lims, AVec)) && length(lims) == 2
if isfinite(lims[1])
amin = lims[1]
end
if isfinite(lims[2])
amax = lims[2]
end
end
if amax <= amin && isfinite(amin)
amax = amin + 1.0
end
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
end
# -------------------------------------------------------------------------
# these methods track the discrete (categorical) values which correspond to axis continuous values (cv)
# whenever we have discrete values, we automatically set the ticks to match.
# we return (continuous_value, discrete_index)
function discrete_value!(axis::Axis, dv)
cv_idx = get(axis[:discrete_map], dv, -1)
# @show axis[:discrete_map], axis[:discrete_values], dv
if cv_idx == -1
ex = axis[:extrema]
cv = NaNMath.max(0.5, ex.emax + 1.0)
expand_extrema!(axis, cv)
push!(axis[:discrete_values], dv)
push!(axis[:continuous_values], cv)
cv_idx = length(axis[:discrete_values])
axis[:discrete_map][dv] = cv_idx
cv, cv_idx
else
cv = axis[:continuous_values][cv_idx]
cv, cv_idx
end
end
# continuous value... just pass back with axis negative index
function discrete_value!(axis::Axis, cv::Number)
cv, -1
end
# add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AVec)
n = length(v)
cvec = zeros(n)
discrete_indices = zeros(Int, n)
for i=1:n
cvec[i], discrete_indices[i] = discrete_value!(axis, v[i])
end
cvec, discrete_indices
end
# add the discrete value for each item. return the continuous values and the indices
function discrete_value!(axis::Axis, v::AMat)
n,m = size(v)
cmat = zeros(n,m)
discrete_indices = zeros(Int, n, m)
for i=1:n, j=1:m
cmat[i,j], discrete_indices[i,j] = discrete_value!(axis, v[i,j])
end
cmat, discrete_indices
end
function discrete_value!(axis::Axis, v::Surface)
map(Surface, discrete_value!(axis, v.surf))
end
# -------------------------------------------------------------------------
function pie_labels(sp::Subplot, series::Series)
d = series.d
if haskey(d,:x_discrete_indices)
dvals = sp.attr[:xaxis].d[:discrete_values]
[dvals[idx] for idx in d[:x_discrete_indices]]
else
d[:x]
end
end
# -------------------------------------------------------------------------
# compute the line segments which should be drawn for this axis
function axis_drawing_info(sp::Subplot)
xaxis, yaxis = sp[:xaxis], sp[:yaxis]
xmin, xmax = axis_limits(xaxis)
ymin, ymax = axis_limits(yaxis)
xticks = get_ticks(xaxis)
yticks = get_ticks(yaxis)
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 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)
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
xticks, yticks, xaxis_segs, yaxis_segs, xtick_segs, ytick_segs, xgrid_segs, ygrid_segs, xborder_segs, yborder_segs
end
+310
View File
@@ -0,0 +1,310 @@
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")
macro init_backend(s)
str = lowercase(string(s))
sym = Symbol(str)
T = Symbol(string(s) * "Backend")
esc(quote
struct $T <: AbstractBackend end
export $sym
$sym(; kw...) = (default(; kw...); backend(Symbol($str)))
backend_name(::$T) = Symbol($str)
push!(_backends, Symbol($str))
_backendType[Symbol($str)] = $T
_backendSymbol[$T] = Symbol($str)
include("backends/" * $str * ".jl")
end)
end
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
_initialize_subplot(plt::Plot, sp::Subplot) = nothing
_series_added(plt::Plot, series::Series) = nothing
_series_updated(plt::Plot, series::Series) = nothing
_before_layout_calcs(plt::Plot) = nothing
title_padding(sp::Subplot) = sp[:title] == "" ? 0mm : sp[:titlefontsize] * pt
guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefontsize] * pt
"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)
ticks = get_ticks(axis)
if ticks == nothing
0mm
else
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
# 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)
# TODO: something different when `is3d(sp) == true`
leftpad = tick_padding(sp[:yaxis]) + sp[:left_margin] + guide_padding(sp[:yaxis])
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
_update_plot_object(plt::Plot) = nothing
# ---------------------------------------------------------
mutable struct CurrentBackend
sym::Symbol
pkg::AbstractBackend
end
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
sym = Symbol(lowercase(env_default))
if haskey(_backendType, sym)
return backend(sym)
else
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
warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not installed.")
end
end
# 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 ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR", "GLVisualize")
if Pkg.installed(pkgstr) != nothing
return backend(Symbol(lowercase(pkgstr)))
end
end
# the default if nothing else is installed
backend(:plotly)
end
# ---------------------------------------------------------
"""
Returns the current plotting package name. Initializes package on first call.
"""
function backend()
global CURRENT_BACKEND
if CURRENT_BACKEND.sym == :none
pickDefaultBackend()
end
sym = CURRENT_BACKEND.sym
if !(sym in _initialized_backends)
# # 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
push!(_initialized_backends, sym)
end
CURRENT_BACKEND.pkg
end
"""
Set the plot backend.
"""
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]
function warn_on_deprecated_backend(bsym::Symbol)
if bsym in _deprecated_backends
warn("Backend $bsym has been deprecated. It may not work as originally intended.")
end
end
# ---------------------------------------------------------
# these are args which every backend supports because they're not used in the backend code
const _base_supported_args = [
:color_palette,
:background_color, :background_color_subplot,
:foreground_color, :foreground_color_subplot,
:group,
:seriestype,
:seriescolor, :seriesalpha,
:smooth,
:xerror, :yerror,
:subplot,
:x, :y, :z,
:show, :size,
:margin,
:left_margin,
:right_margin,
:top_margin,
:bottom_margin,
:html_output_format,
:layout,
:link,
:primary,
:series_annotations,
:subplot_index,
:discrete_values,
:projection,
]
function merge_with_base_supported(v::AVec)
v = vcat(v, _base_supported_args)
for vi in v
if haskey(_axis_defaults, vi)
for letter in (:x,:y,:z)
push!(v, Symbol(letter,vi))
end
end
end
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())
-176
View File
@@ -1,176 +0,0 @@
# https://github.com/bokeh/Bokeh.jl
function _initialize_backend(::BokehPackage; kw...)
@eval begin
warn("Bokeh is no longer supported... many features will likely be broken.")
import Bokeh
export Bokeh
end
end
# make255(x) = round(Int, 255 * x)
# function bokehcolor(c::Colorant)
# @sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c))
# end
# bokehcolor(cs::ColorScheme) = bokehcolor(getColor(cs))
const _glyphtypes = Dict(
:ellipse => :Circle,
:rect => :Square,
:diamond => :Diamond,
:utriangle => :Triangle,
:dtriangle => :InvertedTriangle,
# :pentagon =>
# :hexagon =>
# :heptagon =>
# :octagon =>
:cross => :Cross,
:xcross => :X,
:star5 => :Asterisk,
)
function bokeh_glyph_type(d::Dict)
lt = d[:linetype]
mt = d[:markershape]
if lt == :scatter && mt == :none
mt = :ellipse
end
# if we have a marker, use that
if lt == :scatter || mt != :none
return _glyphtypes[mt]
end
# otherwise return a line
return :Line
end
function get_stroke_vector(linestyle::Symbol)
dash = 12
dot = 3
gap = 2
linestyle == :solid && return Int[]
linestyle == :dash && return Int[dash, gap]
linestyle == :dot && return Int[dot, gap]
linestyle == :dashdot && return Int[dash, gap, dot, gap]
linestyle == :dashdotdot && return Int[dash, gap, dot, gap, dot, gap]
error("unsupported linestyle: ", linestyle)
end
# ---------------------------------------------------------------------------
function _create_plot(pkg::BokehPackage; kw...)
d = Dict(kw)
# dumpdict(d, "plot", true)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
datacolumns = Bokeh.BokehDataSet[]
tools = Bokeh.tools()
filename = tempname() * ".html"
title = d[:title]
w, h = d[:size]
xaxis_type = d[:xscale] == :log10 ? :log : :auto
yaxis_type = d[:yscale] == :log10 ? :log : :auto
# legend = d[:legend] ? xxxx : nothing
legend = nothing
extra_args = Dict() # TODO: we'll put extra settings (xlim, etc) here
bplt = Bokeh.Plot(datacolumns, tools, filename, title, w, h, xaxis_type, yaxis_type, legend) #, extra_args)
Plot(bplt, pkg, 0, d, Dict[])
end
function _add_series(::BokehPackage, plt::Plot; kw...)
d = Dict(kw)
# dumpdict(d, "plot!", true)
bdata = Dict{Symbol, Vector}(:x => collect(d[:x]), :y => collect(d[:y]))
glyph = Bokeh.Bokehjs.Glyph(
glyphtype = bokeh_glyph_type(d),
linecolor = webcolor(d[:linecolor]), # shape's stroke or line color
linewidth = d[:linewidth], # shape's stroke width or line width
fillcolor = webcolor(d[:markercolor]),
size = ceil(Int, d[:markersize] * 2.5), # magic number 2.5 to keep in same scale as other backends
dash = get_stroke_vector(d[:linestyle])
)
legend = nothing # TODO
push!(plt.o.datacolumns, Bokeh.BokehDataSet(bdata, glyph, legend))
push!(plt.seriesargs, d)
plt
end
# ----------------------------------------------------------------
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{BokehPackage}, d::Dict)
end
function _update_plot_pos_size(plt::PlottingObject{BokehPackage}, d::Dict)
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{BokehPackage}, i::Int)
series = plt.o.datacolumns[i].data
series[:x], series[:y]
end
function Base.setindex!(plt::Plot{BokehPackage}, xy::Tuple, i::Integer)
series = plt.o.datacolumns[i].data
series[:x], series[:y] = xy
plt
end
# ----------------------------------------------------------------
function _add_annotations{X,Y,V}(plt::Plot{BokehPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
# TODO: add the annotation to the plot
end
end
# ----------------------------------------------------------------
function _create_subplot(subplt::Subplot{BokehPackage}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
end
function _expand_limits(lims, plt::Plot{BokehPackage}, isx::Bool)
# TODO: call expand limits for each plot data
end
function _remove_axis(plt::Plot{BokehPackage}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{BokehPackage})
# TODO: write a png to io
warn("mime png not implemented")
end
function Base.display(::PlotsDisplay, plt::Plot{BokehPackage})
Bokeh.showplot(plt.o)
end
function Base.display(::PlotsDisplay, plt::Subplot{BokehPackage})
# TODO: display/show the subplot
end
-744
View File
@@ -1,744 +0,0 @@
# https://github.com/dcjones/Gadfly.jl
function _initialize_backend(::GadflyPackage; kw...)
@eval begin
import Gadfly, Compose
export Gadfly, Compose
include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
end
end
# ---------------------------------------------------------------------------
# immutable MissingVec <: AbstractVector{Float64} end
# Base.size(v::MissingVec) = (1,)
# Base.getindex(v::MissingVec, i::Integer) = 0.0
function createGadflyPlotObject(d::Dict)
gplt = Gadfly.Plot()
gplt.mapping = Dict()
gplt.data_source = Gadfly.DataFrames.DataFrame()
# gplt.layers = gplt.layers[1:0]
gplt.layers = [Gadfly.layer(Gadfly.Geom.point(tag=:remove), x=zeros(1), y=zeros(1));] # x=MissingVec(), y=MissingVec());]
gplt.guides = Gadfly.GuideElement[Gadfly.Guide.xlabel(d[:xlabel]),
Gadfly.Guide.ylabel(d[:ylabel]),
Gadfly.Guide.title(d[:title])]
gplt
end
# ---------------------------------------------------------------------------
function getLineGeom(d::Dict)
lt = d[:linetype]
xbins, ybins = maketuple(d[:nbins])
if lt == :hexbin
Gadfly.Geom.hexbin(xbincount = xbins, ybincount = ybins)
elseif lt == :heatmap
Gadfly.Geom.histogram2d(xbincount = xbins, ybincount = ybins)
elseif lt == :hist
Gadfly.Geom.histogram(bincount = xbins)
elseif lt == :path
Gadfly.Geom.path
elseif lt in (:bar, :sticks)
Gadfly.Geom.bar
elseif lt == :steppost
Gadfly.Geom.step
elseif lt == :steppre
Gadfly.Geom.step(direction = :vh)
elseif lt == :hline
Gadfly.Geom.hline
elseif lt == :vline
Gadfly.Geom.vline
elseif lt == :contour
Gadfly.Geom.contour(levels = d[:levels])
else
nothing
end
end
function get_extra_theme_args(d::Dict, k::Symbol)
# gracefully handles old Gadfly versions
extra_theme_args = Dict()
try
extra_theme_args[:line_style] = Gadfly.get_stroke_vector(d[k])
catch err
if string(err) == "UndefVarError(:get_stroke_vector)"
Base.warn_once("Gadfly.get_stroke_vector failed... do you have an old version of Gadfly?")
else
rethrow()
end
end
extra_theme_args
end
function getGadflyLineTheme(d::Dict)
lc = convertColor(getColor(d[:linecolor]), d[:linealpha])
# lc = getColor(d[:linecolor])
# α = d[:linealpha]
# if α != nothing
# lc = RGBA(lc, α)
# end
fc = convertColor(getColor(d[:fillcolor]), d[:fillalpha])
# fc = getColor(d[:fillcolor])
# α = d[:fillalpha]
# if α != nothing
# fc = RGBA(fc, α)
# end
Gadfly.Theme(;
default_color = lc,
line_width = (d[:linetype] == :sticks ? 1 : d[:linewidth]) * Gadfly.px,
# line_style = Gadfly.get_stroke_vector(d[:linestyle]),
lowlight_color = x->RGB(fc), # fill/ribbon
lowlight_opacity = alpha(fc), # fill/ribbon
bar_highlight = RGB(lc), # bars
get_extra_theme_args(d, :linestyle)...
)
end
# add a line as a new layer
function addGadflyLine!(plt::Plot, numlayers::Int, d::Dict, geoms...)
gplt = getGadflyContext(plt)
gfargs = vcat(geoms...,
getGadflyLineTheme(d))
kwargs = Dict()
lt = d[:linetype]
# add a fill?
if d[:fillrange] != nothing && lt != :contour
fillmin, fillmax = map(makevec, maketuple(d[:fillrange]))
nmin, nmax = length(fillmin), length(fillmax)
kwargs[:ymin] = Float64[min(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(d[:y])]
kwargs[:ymax] = Float64[max(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(d[:y])]
push!(gfargs, Gadfly.Geom.ribbon)
end
if lt in (:hline, :vline)
kwargs[lt == :hline ? :yintercept : :xintercept] = d[:y]
else
if lt == :sticks
w = 0.01 * mean(diff(d[:x]))
kwargs[:xmin] = d[:x] - w
kwargs[:xmax] = d[:x] + w
elseif lt == :contour
# d[:y] = reverse(d[:y])
kwargs[:z] = d[:z].surf
addGadflyContColorScale(plt, d[:linecolor])
end
kwargs[:x] = d[lt == :hist ? :y : :x]
kwargs[:y] = d[:y]
end
# # h/vlines
# if lt == :hline
# kwargs[:yintercept] = d[:y]
# elseif lt == :vline
# kwargs[:xintercept] = d[:y]
# elseif lt == :sticks
# w = 0.01 * mean(diff(d[:x]))
# kwargs[:xmin] = d[:x] - w
# kwargs[:xmax] = d[:x] + w
# elseif lt == :contour
# d[:y] = reverse(d[:y])
# kwargs[:z] = d[:surface]
# end
# if lt == :hist
# kwargs[:x] = kwargs[:y] = d[:y]
# elseif lt != :hline && lt != :vline
# kwargs[:x] = d[:x]
# kwargs[:y] = d[:y]
# end
# # add the layer
# x = d[d[:linetype] == :hist ? :y : :x]
# Gadfly.layer(gfargs...; x = x, y = d[:y], order=numlayers, kwargs...)
Gadfly.layer(gfargs...; order=numlayers, kwargs...)
end
# ---------------------------------------------------------------------------
# extract the underlying ShapeGeometry object(s)
getMarkerGeom(shape::Shape) = gadflyshape(shape)
getMarkerGeom(shape::Symbol) = gadflyshape(_shapes[shape])
getMarkerGeom(shapes::AVec) = map(getMarkerGeom, shapes)
getMarkerGeom(d::Dict) = getMarkerGeom(d[:markershape])
# function getMarkerGeom(d::Dict)
# shape = d[:markershape]
# gadflyshape(isa(shape, Shape) ? shape : _shapes[shape])
# end
function getGadflyMarkerTheme(d::Dict, plotargs::Dict)
c = getColor(d[:markercolor])
α = d[:markeralpha]
if α != nothing
c = RGBA(RGB(c), α)
end
ms = d[:markersize]
ms = if typeof(ms) <: AVec
warn("Gadfly doesn't support variable marker sizes... using the average: $(mean(ms))")
mean(ms) * Gadfly.px
else
ms * Gadfly.px
end
# fg = getColor(plotargs[:foreground_color])
Gadfly.Theme(;
default_color = c,
default_point_size = ms,
discrete_highlight_color = c -> RGB(getColor(d[:markerstrokecolor])),
highlight_width = d[:markerstrokewidth] * Gadfly.px,
# get_extra_theme_args(d, :markerstrokestyle)...
)
end
function addGadflyContColorScale(plt::Plot{GadflyPackage}, c)
plt.plotargs[:colorbar] == :none && return
if !isa(c, ColorGradient)
c = colorscheme(:bluesreds)
end
push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(c, p))))
end
function addGadflyMarker!(plt::Plot, numlayers::Int, d::Dict, plotargs::Dict, geoms...)
gfargs = vcat(geoms...,
getGadflyMarkerTheme(d, plotargs),
getMarkerGeom(d))
kwargs = Dict()
# handle continuous color scales for the markers
zcolor = d[:zcolor]
if zcolor != nothing && typeof(zcolor) <: AVec
kwargs[:color] = zcolor
addGadflyContColorScale(plt, d[:markercolor])
# if !isa(d[:markercolor], ColorGradient)
# d[:markercolor] = colorscheme(:bluesreds)
# end
# push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(d[:markercolor], p))))
end
Gadfly.layer(gfargs...; x = d[:x], y = d[:y], order=numlayers, kwargs...)
end
# ---------------------------------------------------------------------------
function addToGadflyLegend(plt::Plot, d::Dict)
# add the legend?
if plt.plotargs[:legend] != :none && d[:label] != ""
gplt = getGadflyContext(plt)
# 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[]))
end
# now add the series to the legend
for guide in gplt.guides
if isa(guide, Gadfly.Guide.ManualColorKey)
# TODO: there's a BUG in gadfly if you pass in the same color more than once,
# since gadfly will call unique(colors), but doesn't also merge the rows that match
# Should ensure from this side that colors which are the same are merged together
c = getColor(d[d[:markershape] == :none ? :linecolor : :markercolor])
foundit = false
# extend the label if we found this color
for i in 1:length(guide.colors)
if RGB(c) == guide.colors[i]
guide.labels[i] *= ", " * d[:label]
foundit = true
end
end
# didn't find the color, so add a new entry into the legend
if !foundit
push!(guide.labels, d[:label])
push!(guide.colors, c)
end
end
end
end
end
getGadflySmoothing(smooth::Bool) = smooth ? [Gadfly.Geom.smooth(method=:lm)] : Any[]
getGadflySmoothing(smooth::Real) = [Gadfly.Geom.smooth(method=:loess, smoothing=float(smooth))]
function addGadflySeries!(plt::Plot, d::Dict)
layers = Gadfly.Layer[]
gplt = getGadflyContext(plt)
# add a regression line?
# TODO: make more flexible
smooth = getGadflySmoothing(d[:smooth])
# lines
geom = getLineGeom(d)
if geom != nothing
prepend!(layers, addGadflyLine!(plt, length(gplt.layers), d, geom, smooth...))
# don't add a regression for markers too
smooth = Any[]
end
# special handling for ohlc and scatter
lt = d[:linetype]
if lt == :ohlc
error("Haven't re-implemented after refactoring")
elseif lt in (:heatmap, :hexbin) && (isa(d[:linecolor], ColorGradient) || isa(d[:linecolor], ColorFunction))
push!(gplt.scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(d[:linecolor], p))))
elseif lt == :scatter && d[:markershape] == :none
d[:markershape] = :ellipse
end
# markers
if d[:markershape] != :none
prepend!(layers, addGadflyMarker!(plt, length(gplt.layers), d, plt.plotargs, smooth...))
end
lt in (:heatmap, :hexbin, :contour) || addToGadflyLegend(plt, d)
# now save the layers that apply to this series
d[:gadflylayers] = layers
prepend!(gplt.layers, layers)
end
# ---------------------------------------------------------------------------
# NOTE: I'm leaving this here and commented out just in case I want to implement again... it was hacky code to create multi-colored line segments
# # colorgroup
# z = d[:z]
# # handle line segments of different colors
# cscheme = d[:linecolor]
# if isa(cscheme, ColorVector)
# # create a color scale, and set the color group to the index of the color
# push!(gplt.scales, Gadfly.Scale.color_discrete_manual(cscheme.v...))
# # this is super weird, but... oh well... for some reason this creates n separate line segments...
# # 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]
# d[:x], d[:y] = map(createSegments, (d[:x], d[:y]))
# colorgroup = [(:linecolor, cs), (:group, grp)]
# ---------------------------------------------------------------------------
function addGadflyTicksGuide(gplt, ticks, isx::Bool)
ticks == :auto && return
# remove the ticks?
if ticks in (:none, false, nothing)
return addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
end
ttype = ticksType(ticks)
# just the values... put ticks here, but use standard labels
if ttype == :ticks
gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks
replaceType(gplt.guides, gtype(ticks = collect(ticks)))
# set the ticks and the labels
elseif ttype == :ticks_and_labels
gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks
replaceType(gplt.guides, gtype(ticks = collect(ticks[1])))
# TODO add xtick_label function (given tick, return label??)
# Scale.x_discrete(; labels=nothing, levels=nothing, order=nothing)
filterGadflyScale(gplt, isx)
gfunc = isx ? Gadfly.Scale.x_discrete : Gadfly.Scale.y_discrete
labelmap = Dict(zip(ticks...))
labelfunc = val -> labelmap[val]
push!(gplt.scales, gfunc(levels = collect(ticks[1]), labels = labelfunc))
else
error("Invalid input for $(isx ? "xticks" : "yticks"): ", ticks)
end
end
continuousAndSameAxis(scale, isx::Bool) = isa(scale, Gadfly.Scale.ContinuousScale) && scale.vars[1] == (isx ? :x : :y)
filterGadflyScale(gplt, isx::Bool) = filter!(scale -> !continuousAndSameAxis(scale, isx), gplt.scales)
function getGadflyScaleFunction(d::Dict, isx::Bool)
scalekey = isx ? :xscale : :yscale
hasScaleKey = haskey(d, scalekey)
if hasScaleKey
scale = d[scalekey]
scale == :ln && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey
scale == :log2 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2, hasScaleKey
scale == :log10 && return isx ? Gadfly.Scale.x_log10 : Gadfly.Scale.y_log10, hasScaleKey
scale == :asinh && return isx ? Gadfly.Scale.x_asinh : Gadfly.Scale.y_asinh, hasScaleKey
scale == :sqrt && return isx ? Gadfly.Scale.x_sqrt : Gadfly.Scale.y_sqrt, hasScaleKey
end
isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous, hasScaleKey
end
function addGadflyLimitsScale(gplt, d::Dict, isx::Bool)
# get the correct scale function
gfunc, hasScaleKey = getGadflyScaleFunction(d, isx)
# do we want to add min/max limits for the axis?
limsym = isx ? :xlims : :ylims
limargs = Any[]
# map :auto to nothing, otherwise add to limargs
lims = get(d, limsym, :auto)
# lims == :auto && return
if lims == :auto
lims = nothing
else
if limsType(lims) == :limits
push!(limargs, (:minvalue, min(lims...)))
push!(limargs, (:maxvalue, max(lims...)))
else
error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims)
end
end
# replace any current scales with this one
if hasScaleKey || !isempty(limargs)
filterGadflyScale(gplt, isx)
push!(gplt.scales, gfunc(; limargs...))
end
lims
end
function updateGadflyAxisFlips(gplt, d::Dict, xlims, ylims)
if isa(gplt.coord, Gadfly.Coord.Cartesian)
gplt.coord = Gadfly.Coord.cartesian(
gplt.coord.xvars,
gplt.coord.yvars;
xmin = xlims == nothing ? gplt.coord.xmin : minimum(xlims),
xmax = xlims == nothing ? gplt.coord.xmax : maximum(xlims),
ymin = ylims == nothing ? gplt.coord.ymin : minimum(ylims),
ymax = ylims == nothing ? gplt.coord.ymax : maximum(ylims),
xflip = get(d, :xflip, gplt.coord.xflip),
yflip = get(d, :yflip, gplt.coord.yflip),
fixed = gplt.coord.fixed,
aspect_ratio = gplt.coord.aspect_ratio,
raster = gplt.coord.raster
)
else
gplt.coord = Gadfly.Coord.Cartesian(
xflip = get(d, :xflip, false),
yflip = get(d, :yflip, false)
)
end
end
function findGuideAndSet(gplt, t::DataType, args...; kw...) #s::@compat(AbstractString))
for (i,guide) in enumerate(gplt.guides)
if isa(guide, t)
gplt.guides[i] = t(args...; kw...)
end
end
end
function updateGadflyGuides(plt::Plot, d::Dict)
gplt = getGadflyContext(plt)
haskey(d, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, string(d[:title]))
haskey(d, :xlabel) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, string(d[:xlabel]))
haskey(d, :ylabel) && findGuideAndSet(gplt, Gadfly.Guide.ylabel, string(d[:ylabel]))
xlims = addGadflyLimitsScale(gplt, d, true)
ylims = addGadflyLimitsScale(gplt, d, false)
ticks = get(d, :xticks, :auto)
if ticks == :none
_remove_axis(plt, true)
else
addGadflyTicksGuide(gplt, ticks, true)
end
ticks = get(d, :yticks, :auto)
if ticks == :none
_remove_axis(plt, false)
else
addGadflyTicksGuide(gplt, ticks, false)
end
# haskey(d, :yticks) && addGadflyTicksGuide(gplt, d[:yticks], false)
updateGadflyAxisFlips(gplt, d, xlims, ylims)
end
function updateGadflyPlotTheme(plt::Plot, d::Dict)
kwargs = Dict()
# # get the full plotargs, overriding any new settings
# # TODO: should this be part of the main `plot` command in plot.jl???
# d = merge!(plt.plotargs, d)
# # hide the legend?
# if !get(d, :legend, true)
# kwargs[:key_position] = :none
# end
leg = d[d[:legend] == :none ? :colorbar : :legend]
if leg != :best
kwargs[:key_position] = leg == :inside ? :right : leg
end
if !get(d, :grid, true)
kwargs[:grid_color] = getColor(d[:background_color])
end
# fonts
tfont, gfont, lfont = d[:tickfont], d[:guidefont], d[:legendfont]
fg = getColor(d[:foreground_color])
getGadflyContext(plt).theme = Gadfly.Theme(;
background_color = getColor(d[:background_color]),
minor_label_color = fg,
minor_label_font = tfont.family,
minor_label_font_size = tfont.pointsize * Gadfly.pt,
major_label_color = fg,
major_label_font = gfont.family,
major_label_font_size = gfont.pointsize * Gadfly.pt,
key_title_color = fg,
key_title_font = gfont.family,
key_title_font_size = gfont.pointsize * Gadfly.pt,
key_label_color = fg,
key_label_font = lfont.family,
key_label_font_size = lfont.pointsize * Gadfly.pt,
plot_padding = 1 * Gadfly.mm,
kwargs...
)
end
# ----------------------------------------------------------------
function createGadflyAnnotationObject(x, y, val::@compat(AbstractString))
Gadfly.Guide.annotation(Compose.compose(
Compose.context(),
Compose.text(x, y, val)
))
end
function createGadflyAnnotationObject(x, y, txt::PlotText)
halign = (txt.font.halign == :hcenter ? Compose.hcenter : (txt.font.halign == :left ? Compose.hleft : Compose.hright))
valign = (txt.font.valign == :vcenter ? Compose.vcenter : (txt.font.valign == :top ? Compose.vtop : Compose.vbottom))
rotations = (txt.font.rotation == 0.0 ? [] : [Compose.Rotation(txt.font.rotation, Compose.Point(Compose.x_measure(x), Compose.y_measure(y)))])
Gadfly.Guide.annotation(Compose.compose(
Compose.context(),
Compose.text(x, y, txt.str, halign, valign, rotations...),
Compose.font(string(txt.font.family)),
Compose.fontsize(txt.font.pointsize * Gadfly.pt),
Compose.stroke(txt.font.color),
Compose.fill(txt.font.color)
))
end
function _add_annotations{X,Y,V}(plt::Plot{GadflyPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
push!(plt.o.guides, createGadflyAnnotationObject(ann...))
end
end
# ---------------------------------------------------------------------------
# create a blank Gadfly.Plot object
function _create_plot(pkg::GadflyPackage; kw...)
d = Dict(kw)
gplt = createGadflyPlotObject(d)
Plot(gplt, pkg, 0, d, Dict[])
end
# plot one data series
function _add_series(::GadflyPackage, plt::Plot; kw...)
# first clear out the temporary layer
gplt = getGadflyContext(plt)
if gplt.layers[1].geom.tag == :remove
gplt.layers = gplt.layers[2:end]
end
d = Dict(kw)
addGadflySeries!(plt, d)
push!(plt.seriesargs, d)
plt
end
function _update_plot(plt::Plot{GadflyPackage}, d::Dict)
updateGadflyGuides(plt, d)
updateGadflyPlotTheme(plt, d)
end
# ----------------------------------------------------------------
# accessors for x/y data
# TODO: need to save all the layer indices which apply to this series
function getGadflyMappings(plt::Plot, i::Integer)
@assert i > 0 && i <= plt.n
mappings = [l.mapping for l in plt.seriesargs[i][:gadflylayers]]
end
function Base.getindex(plt::Plot{GadflyPackage}, i::Integer)
mapping = getGadflyMappings(plt, i)[1]
mapping[:x], mapping[:y]
end
function Base.setindex!(plt::Plot{GadflyPackage}, xy::Tuple, i::Integer)
for mapping in getGadflyMappings(plt, i)
mapping[:x], mapping[:y] = xy
end
plt
end
# ----------------------------------------------------------------
# create the underlying object (each backend will do this differently)
function _create_subplot(subplt::Subplot{GadflyPackage}, isbefore::Bool)
isbefore && return false # wait until after plotting to create the subplots
subplt.o = nothing
true
end
function _remove_axis(plt::Plot{GadflyPackage}, isx::Bool)
gplt = getGadflyContext(plt)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "")
end
function _expand_limits(lims, plt::Plot{GadflyPackage}, isx::Bool)
for l in getGadflyContext(plt).layers
_expand_limits(lims, l.mapping[isx ? :x : :y])
end
end
# ----------------------------------------------------------------
getGadflyContext(plt::Plot{GadflyPackage}) = plt.o
getGadflyContext(subplt::Subplot{GadflyPackage}) = buildGadflySubplotContext(subplt)
# create my Compose.Context grid by hstacking and vstacking the Gadfly.Plot objects
function buildGadflySubplotContext(subplt::Subplot)
rows = Any[]
row = Any[]
for (i,(r,c)) in enumerate(subplt.layout)
# add the Plot object to the row
push!(row, getGadflyContext(subplt.plts[i]))
# add the row
if c == ncols(subplt.layout, r)
push!(rows, Gadfly.hstack(row...))
row = Any[]
end
end
# stack the rows
Gadfly.vstack(rows...)
end
setGadflyDisplaySize(w,h) = Compose.set_default_graphic_size(w * Compose.px, h * Compose.px)
setGadflyDisplaySize(plt::Plot) = setGadflyDisplaySize(plt.plotargs[:size]...)
setGadflyDisplaySize(subplt::Subplot) = setGadflyDisplaySize(getplotargs(subplt, 1)[:size]...)
# -------------------------------------------------------------------------
function dowritemime{P<:Union{GadflyPackage,ImmersePackage}}(io::IO, func, plt::PlottingObject{P})
gplt = getGadflyContext(plt)
setGadflyDisplaySize(plt)
Gadfly.draw(func(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
end
getGadflyWriteFunc(::MIME"image/png") = Gadfly.PNG
getGadflyWriteFunc(::MIME"image/svg+xml") = Gadfly.SVG
# getGadflyWriteFunc(::MIME"text/html") = Gadfly.SVGJS
getGadflyWriteFunc(::MIME"application/pdf") = Gadfly.PDF
getGadflyWriteFunc(::MIME"application/postscript") = Gadfly.PS
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{GadflyPackage,ImmersePackage}}(io::IO, ::$mime, plt::PlottingObject{P})
func = getGadflyWriteFunc($mime())
dowritemime(io, func, plt)
end
end
function Base.display(::PlotsDisplay, plt::Plot{GadflyPackage})
setGadflyDisplaySize(plt.plotargs[:size]...)
display(plt.o)
end
function Base.display(::PlotsDisplay, subplt::Subplot{GadflyPackage})
setGadflyDisplaySize(getplotargs(subplt,1)[:size]...)
ctx = buildGadflySubplotContext(subplt)
# taken from Gadfly since I couldn't figure out how to do it directly
filename = string(Gadfly.tempname(), ".html")
output = open(filename, "w")
plot_output = IOBuffer()
Gadfly.draw(Gadfly.SVGJS(plot_output, Compose.default_graphic_width,
Compose.default_graphic_height, false), ctx)
plotsvg = takebuf_string(plot_output)
write(output,
"""
<!DOCTYPE html>
<html>
<head>
<title>Gadfly Plot</title>
<meta charset="utf-8">
</head>
<body>
<script charset="utf-8">
$(readall(Compose.snapsvgjs))
</script>
<script charset="utf-8">
$(readall(Gadfly.gadflyjs))
</script>
$(plotsvg)
</body>
</html>
""")
close(output)
Gadfly.open_file(filename)
end
File diff suppressed because it is too large Load Diff
+1359 -737
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 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, Void}
end
#==Useful constants
===============================================================================#
const _hdf5_plotroot = "plot"
const _hdf5_dataroot = "data" #TODO: Eventually move data to different root (easier to locate)?
const _hdf5plot_datatypeid = "TYPE" #Attribute identifying type
const _hdf5plot_countid = "COUNT" #Attribute for storing count
#Dict has problems using "Types" as keys. Initialize in "_initialize_backend":
const HDF5PLOT_MAP_STR2TELEM = Dict{String, Type}()
const HDF5PLOT_MAP_TELEM2STR = Dict{Type, String}()
#Don't really like this global variable... Very hacky
const HDF5PLOT_PLOTREF = HDF5Plot_PlotRef(nothing)
#Simple sub-structures that can just be written out using _hdf5plot_gwritefields:
const HDF5PLOT_SIMPLESUBSTRUCT = Union{Font, BoundingBox,
GridLayout, RootLayout, ColorGradient, SeriesAnnotations, PlotText
}
#==
===============================================================================#
const _hdf5_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
:label,
:linecolor, :linestyle, :linewidth, :linealpha,
:markershape, :markercolor, :markersize, :markeralpha,
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
:fillrange, :fillcolor, :fillalpha,
:bins, :bar_width, :bar_edges, :bar_position,
:title, :title_location, :titlefont,
:window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
:orientation,
:overwrite_figure,
:polar,
:normalize, :weights,
:contours, :aspect_ratio,
:match_dimensions,
:clims,
:inset_subplots,
:dpi,
:colorbar_title,
])
const _hdf5_seriestype = [
:path, :steppre, :steppost, :shape, :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:
const telem2str = Dict{String, Type}(
"NATIVE" => HDF5PlotNative,
"VOID" => Void,
"BOOL" => Bool,
"SYMBOL" => Symbol,
"TUPLE" => Tuple,
"CTUPLE" => HDF5CTuple, #Tuple of complex structures
"RGBA" => ARGB{N0f8},
"EXTREMA" => Extrema,
"LENGTH" => Length,
"ARRAY" => Array, #Dict won't allow Array to be key in HDF5PLOT_MAP_TELEM2STR
#Sub-structure types:
"FONT" => Font,
"BOUNDINGBOX" => BoundingBox,
"GRIDLAYOUT" => GridLayout,
"ROOTLAYOUT" => RootLayout,
"SERIESANNOTATIONS" => SeriesAnnotations,
# "PLOTTEXT" => PlotText,
"COLORGRADIENT" => ColorGradient,
"AXIS" => Axis,
"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::Void)
grp[k] = 0
_hdf5plot_writetype(grp, k, Void)
end
function _hdf5plot_gwrite(grp, k::String, v::Bool)
grp[k] = Int(v)
_hdf5plot_writetype(grp, k, Bool)
end
function _hdf5plot_gwrite(grp, k::String, v::Symbol)
grp[k] = string(v)
_hdf5plot_writetype(grp, k, Symbol)
end
function _hdf5plot_gwrite(grp, k::String, v::Tuple)
varr = [v...]
elt = eltype(varr)
# if isleaftype(elt)
_hdf5plot_gwrite(grp, k, varr)
if elt <: Number
#We just wrote a simple dataset
_hdf5plot_overwritetype(grp, k, Tuple)
else #Used a more complex scheme (using subgroups):
_hdf5plot_overwritetype(grp[k], HDF5CTuple)
end
#NOTE: _hdf5plot_overwritetype overwrites "Array" type with "Tuple".
end
function _hdf5plot_gwrite(grp, k::String, d::Dict)
# warn("Cannot write dict: $k=$d")
end
function _hdf5plot_gwrite(grp, k::String, v::Range)
_hdf5plot_gwrite(grp, k, collect(v)) #For now
end
function _hdf5plot_gwrite(grp, k::String, v::ARGB{N0f8})
grp[k] = [v.r.i, v.g.i, v.b.i, v.alpha.i]
_hdf5plot_writetype(grp, k, ARGB{N0f8})
end
function _hdf5plot_gwrite(grp, k::String, v::Colorant)
_hdf5plot_gwrite(grp, k, ARGB{N0f8}(v))
end
#Custom vector (when not using simple numeric type):
function _hdf5plot_gwritearray(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 = ind2sub(sz, iter)
elem = v[iter]
idxstr = join(coord, "_")
_hdf5plot_gwrite(vgrp, "v$idxstr", v[iter])
end
_hdf5plot_gwrite(vgrp, "dim", [sz...])
return
end
_hdf5plot_gwrite(grp, k::String, v::Array) =
_hdf5plot_gwritearray(grp, k, v)
function _hdf5plot_gwrite(grp, k::String, v::Extrema)
grp[k] = [v.emin, v.emax]
_hdf5plot_writetype(grp, k, Extrema)
end
function _hdf5plot_gwrite(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{Void}, v) = nothing
_hdf5plot_convert(T::Type{Bool}, v) = (v!=0)
_hdf5plot_convert(T::Type{Symbol}, v) = Symbol(v)
_hdf5plot_convert(T::Type{Tuple}, v) = tuple(v...) #With Vector{T<:Number}
function _hdf5plot_convert(T::Type{ARGB{N0f8}}, v)
r, g, b, a = reinterpret(N0f8, v)
return Colors.ARGB{N0f8}(r, g, b, a)
end
_hdf5plot_convert(T::Type{Extrema}, v) = Extrema(v[1], v[2])
# Read data structures:
# ----------------------------------------------------------------
function _hdf5plot_read(grp, k::String, T::Type, dtid)
v = HDF5.d_read(grp, k)
return _hdf5plot_convert(T, v)
end
function _hdf5plot_read(grp, k::String, T::Type{Length}, dtid::Vector)
v = HDF5.d_read(grp, k)
TU = Symbol(dtid[2])
T = typeof(v)
return Length{TU,T}(v)
end
# Read more complex data structures:
# ----------------------------------------------------------------
function _hdf5plot_read(grp, k::String, T::Type{Font}, dtid)
grp = HDF5.g_open(grp, k)
family = _hdf5plot_read(grp, "family")
pointsize = _hdf5plot_read(grp, "pointsize")
halign = _hdf5plot_read(grp, "halign")
valign = _hdf5plot_read(grp, "valign")
rotation = _hdf5plot_read(grp, "rotation")
color = _hdf5plot_read(grp, "color")
return Font(family, pointsize, halign, valign, rotation, color)
end
function _hdf5plot_read(grp, k::String, T::Type{Array}, dtid) #ANY
grp = HDF5.g_open(grp, k)
sz = _hdf5plot_read(grp, "dim")
if [0] == sz; return []; end
sz = tuple(sz...)
result = Array{Any}(sz)
for iter in eachindex(result)
coord = ind2sub(sz, iter)
idxstr = join(coord, "_")
result[iter] = _hdf5plot_read(grp, "v$idxstr")
end
#Hack: Implicitly make Julia detect element type.
# (Should probably write it explicitly to file)
result = [result[iter] for iter in eachindex(result)] #Potentially make more specific
return reshape(result, sz)
end
function _hdf5plot_read(grp, k::String, T::Type{HDF5CTuple}, dtid)
v = _hdf5plot_read(grp, k, Array, dtid)
return tuple(v...)
end
function _hdf5plot_read(grp, k::String, T::Type{ColorGradient}, dtid)
grp = HDF5.g_open(grp, k)
colors = _hdf5plot_read(grp, "colors")
values = _hdf5plot_read(grp, "values")
return ColorGradient(colors, values)
end
function _hdf5plot_read(grp, k::String, T::Type{BoundingBox}, dtid)
grp = HDF5.g_open(grp, k)
x0 = _hdf5plot_read(grp, "x0")
a = _hdf5plot_read(grp, "a")
return BoundingBox(x0, a)
end
_hdf5plot_read(grp, k::String, T::Type{RootLayout}, dtid) = RootLayout()
function _hdf5plot_read(grp, k::String, T::Type{GridLayout}, dtid)
grp = HDF5.g_open(grp, k)
# parent = _hdf5plot_read(grp, "parent")
parent = RootLayout()
minpad = _hdf5plot_read(grp, "minpad")
bbox = _hdf5plot_read(grp, "bbox")
grid = _hdf5plot_read(grp, "grid")
widths = _hdf5plot_read(grp, "widths")
heights = _hdf5plot_read(grp, "heights")
attr = KW() #TODO support attr: _hdf5plot_read(grp, "attr")
return GridLayout(parent, minpad, bbox, grid, widths, heights, attr)
end
function _hdf5plot_read(grp, k::String, T::Type{Axis}, dtid)
grp = HDF5.g_open(grp, k)
kwlist = KW()
_hdf5plot_read(grp, kwlist)
return Axis([], kwlist)
end
function _hdf5plot_read(grp, k::String, T::Type{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
-173
View File
@@ -1,173 +0,0 @@
# https://github.com/JuliaGraphics/Immerse.jl
function _initialize_backend(::ImmersePackage; kw...)
@eval begin
import Immerse, Gadfly, Compose, Gtk
export Immerse, Gadfly, Compose, Gtk
include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
end
end
function createImmerseFigure(d::Dict)
w,h = d[:size]
figidx = Immerse.figure(; name = d[:windowtitle], width = w, height = h)
Immerse.Figure(figidx)
end
# ----------------------------------------------------------------
# create a blank Gadfly.Plot object
function _create_plot(pkg::ImmersePackage; kw...)
d = Dict(kw)
# create the underlying Gadfly.Plot object
gplt = createGadflyPlotObject(d)
# save both the Immerse.Figure and the Gadfly.Plot
Plot((nothing,gplt), pkg, 0, d, Dict[])
end
# plot one data series
function _add_series(::ImmersePackage, plt::Plot; kw...)
d = Dict(kw)
addGadflySeries!(plt, d)
push!(plt.seriesargs, d)
plt
end
function _update_plot(plt::Plot{ImmersePackage}, d::Dict)
updateGadflyGuides(plt, d)
updateGadflyPlotTheme(plt, d)
end
# ----------------------------------------------------------------
function _add_annotations{X,Y,V}(plt::Plot{ImmersePackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
push!(getGadflyContext(plt).guides, createGadflyAnnotationObject(ann...))
end
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{ImmersePackage}, i::Integer)
mapping = getGadflyMappings(plt, i)[1]
mapping[:x], mapping[:y]
end
function Base.setindex!(plt::Plot{ImmersePackage}, xy::Tuple, i::Integer)
for mapping in getGadflyMappings(plt, i)
mapping[:x], mapping[:y] = xy
end
plt
end
# ----------------------------------------------------------------
function _create_subplot(subplt::Subplot{ImmersePackage}, isbefore::Bool)
return false
# isbefore && return false
end
function showSubplotObject(subplt::Subplot{ImmersePackage})
# create the Gtk window with vertical box vsep
d = getplotargs(subplt,1)
w,h = d[:size]
vsep = Gtk.GtkBoxLeaf(:v)
win = Gtk.GtkWindowLeaf(vsep, d[:windowtitle], w, h)
figindices = []
row = Gtk.GtkBoxLeaf(:h)
push!(vsep, row)
for (i,(r,c)) in enumerate(subplt.layout)
plt = subplt.plts[i]
# get the components... box is the main plot GtkBox, and canvas is the GtkCanvas where it's plotted
box, toolbar, canvas = Immerse.createPlotGuiComponents()
# add the plot's box to the row
push!(row, box)
# create the figure and store the index returned for destruction later
figidx = Immerse.figure(canvas)
push!(figindices, figidx)
fig = Immerse.figure(figidx)
plt.o = (fig, plt.o[2])
# add the row
if c == ncols(subplt.layout, r)
row = Gtk.GtkBoxLeaf(:h)
push!(vsep, row)
end
end
# destructor... clean up plots
Gtk.on_signal_destroy((x...) -> ([Immerse.dropfig(Immerse._display,i) for i in figindices]; subplt.o = nothing), win)
subplt.o = win
true
end
function _remove_axis(plt::Plot{ImmersePackage}, isx::Bool)
gplt = getGadflyContext(plt)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "")
end
function _expand_limits(lims, plt::Plot{ImmersePackage}, isx::Bool)
for l in getGadflyContext(plt).layers
_expand_limits(lims, l.mapping[isx ? :x : :y])
end
end
# ----------------------------------------------------------------
getGadflyContext(plt::Plot{ImmersePackage}) = plt.o[2]
getGadflyContext(subplt::Subplot{ImmersePackage}) = buildGadflySubplotContext(subplt)
function Base.display(::PlotsDisplay, plt::Plot{ImmersePackage})
fig, gplt = plt.o
if fig == nothing
fig = createImmerseFigure(plt.plotargs)
Gtk.on_signal_destroy((x...) -> (Immerse.dropfig(Immerse._display, fig.figno); plt.o = (nothing,gplt)), fig.canvas)
plt.o = (fig, gplt)
end
Immerse.figure(fig.figno; displayfig = false)
display(gplt)
end
function Base.display(::PlotsDisplay, subplt::Subplot{ImmersePackage})
# if we haven't created the window yet, do it
if subplt.o == nothing
showSubplotObject(subplt)
end
# display the plots by creating a fresh Immerse.Figure object from the GtkCanvas and Gadfly.Plot
for plt in subplt.plts
fig, gplt = plt.o
Immerse.figure(fig.figno; displayfig = false)
display(gplt)
end
# o is the window... show it
showall(subplt.o)
end
+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 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:
const INSPECTDR_GLYPH_SHAPE = InspectDR.GlyphPolyline(
2*InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y
)
mutable struct InspecDRPlotRef
mplot::Union{Void, InspectDR.Multiplot}
gui::Union{Void, InspectDR.GtkPlot}
end
_inspectdr_getmplot(::Any) = nothing
_inspectdr_getmplot(r::InspecDRPlotRef) = r.mplot
_inspectdr_getgui(::Any) = nothing
_inspectdr_getgui(gplot::InspectDR.GtkPlot) = (gplot.destroyed ? nothing : gplot)
_inspectdr_getgui(r::InspecDRPlotRef) = _inspectdr_getgui(r.gui)
end
end
# ---------------------------------------------------------------------------
# Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o)
gplot = _inspectdr_getgui(plt.o)
#:overwrite_figure: want to reuse current figure
if plt[:overwrite_figure] && mplot != nothing
mplot.subplots = [] #Reset
if gplot != nothing #Ensure still references current plot
gplot.src = mplot
end
else #want new one:
mplot = InspectDR.Multiplot()
gplot = nothing #Will be created later
end
#break link with old subplots
for sp in plt.subplots
sp.o = nothing
end
return InspecDRPlotRef(mplot, gplot)
end
# ---------------------------------------------------------------------------
# # this is called early in the pipeline, use it to make the plot current or something
# function _prepare_plot_object(plt::Plot{InspectDRBackend})
# end
# ---------------------------------------------------------------------------
# Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend})
plot = sp.o
#Don't do anything without a "subplot" object: Will process later.
if nothing == plot; return; end
plot.data = []
plot.userannot = [] #Clear old markers/text annotation/polyline "annotation"
return plot
end
# ---------------------------------------------------------------------------
# Add one series to the underlying backend object.
# Called once per series
# NOTE: Seems to be called when user calls plot()... even if backend
# plot, sp.o has not yet been constructed...
function _series_added(plt::Plot{InspectDRBackend}, series::Series)
st = series[:seriestype]
sp = series[:subplot]
plot = sp.o
#Don't do anything without a "subplot" object: Will process later.
if nothing == plot; return; end
_vectorize(v) = isa(v, Vector) ? v : collect(v) #InspectDR only supports vectors
x, 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})
const plot = sp.o
const 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})
const mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end
mplot.title = plt[:plot_title]
if "" == mplot.title
#Don't use window_title... probably not what you want.
#mplot.title = plt[:window_title]
end
mplot.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, ::Void, w, h) =
throw(ErrorException("Cannot show(::IO, ...) plot - not yet generated"))
function _inspectdr_show(io::IO, mime::MIME, mplot, w, h)
InspectDR._show(io, mime, mplot, Float64(w), Float64(h))
end
for (mime, fmt) in _inspectdr_mimeformats_dpi
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
dpi = plt[:dpi]#TODO: support
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o), plt[:size]...)
end
end
for (mime, fmt) in _inspectdr_mimeformats_nodpi
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o), plt[:size]...)
end
end
# ----------------------------------------------------------------
# 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
+598 -70
View File
@@ -1,107 +1,635 @@
# https://github.com/sisl/PGFPlots.jl
function _initialize_backend(::PGFPlotsPackage; kw...)
@eval begin
import PGFPlots
export PGFPlots
# TODO: other initialization that needs to be eval-ed
end
# TODO: other initialization
# significant contributions by: @pkofod
@require Revise 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,
:label,
:seriescolor, :seriesalpha,
:linecolor, :linestyle, :linewidth, :linealpha,
:markershape, :markercolor, :markersize, :markeralpha,
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle,
:fillrange, :fillcolor, :fillalpha,
:bins,
# :bar_width, :bar_edges,
:title,
# :window_title,
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend,
:colorbar,
:fill_z, :line_z, :marker_z, :levels,
# :ribbon, :quiver, :arrow,
# :orientation,
# :overwrite_figure,
:polar,
# :normalize, :weights, :contours,
:aspect_ratio,
# :match_dimensions,
:tick_direction,
:framestyle,
:camera,
:contour_labels,
])
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 _create_plot(pkg::PGFPlotsPackage; kw...)
d = Dict{Symbol,Any}(kw)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
Plot(nothing, pkg, 0, d, Dict[])
# --------------------------------------------------------------------------------------
function add_backend_string(::PGFPlotsBackend)
"""
Pkg.add("PGFPlots")
Pkg.build("PGFPlots")
"""
end
function _initialize_backend(::PGFPlotsBackend; kw...)
@eval begin
import PGFPlots
export PGFPlots
end
end
function _add_series(::PGFPlotsPackage, plt::Plot; kw...)
d = Dict{Symbol,Any}(kw)
# TODO: add one series to the underlying package
push!(plt.seriesargs, d)
plt
# --------------------------------------------------------------------------------------
const _pgfplots_linestyles = KW(
:solid => "solid",
:dash => "dashed",
:dot => "dotted",
:dashdot => "dashdotted",
:dashdotdot => "dashdotdotted",
)
const _pgfplots_markers = KW(
:none => "none",
:cross => "+",
:xcross => "x",
:+ => "+",
:x => "x",
:utriangle => "triangle*",
:dtriangle => "triangle*",
:circle => "*",
:rect => "square*",
:star5 => "star",
:star6 => "asterisk",
:diamond => "diamond*",
:pentagon => "pentagon*",
:hline => "-"
)
const _pgfplots_legend_pos = KW(
:bottomleft => "south west",
:bottomright => "south east",
:topright => "north east",
:topleft => "north west",
:outertopright => "outer north east",
)
const _pgf_series_extrastyle = KW(
:steppre => "const plot mark right",
:stepmid => "const plot mark mid",
:steppost => "const plot",
:sticks => "ycomb",
:ysticks => "ycomb",
: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
function _add_annotations{X,Y,V}(plt::Plot{PGFPlotsPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
# set or add to the annotation_list
if haskey(plt.plotargs, :annotation_list)
append!(plt.plotargs[:annotation_list], anns)
else
plt.plotargs[:annotation_list] = anns
end
# --------------------------------------------------------------------------------------
# takes in color,alpha, and returns color and alpha appropriate for pgf style
function pgf_color(c::Colorant)
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", red(c), green(c), blue(c))
cstr, alpha(c)
end
function pgf_color(grad::ColorGradient)
# Can't handle ColorGradient here, fallback to defaults.
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", 0.0, 0.60560316,0.97868012)
cstr, 1
end
# Generates a colormap for pgfplots based on a ColorGradient
function pgf_colormap(grad::ColorGradient)
join(map(grad.colors) do c
@sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c),blue(c))
end,", ")
end
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(linewidth::Real, color, α = 1, linestyle = "solid")
cstr, a = pgf_color(plot_color(color, α))
"""
color = $cstr,
draw opacity = $a,
line width = $linewidth,
$(get(_pgfplots_linestyles, linestyle, "solid"))"""
end
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 = $(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 = $(pgf_thickness_scaling(d) * _cycle(d[:markerstrokewidth], i)),
rotate = $(shape == :dtriangle ? 180 : 0),
$(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]
series_collection = PGFPlots.Plot[]
# function args
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
# PGFPlots can't handle non-Vector?
args = map(a -> if typeof(a) <: AbstractVector && typeof(a) != Vector
collect(a)
else
a
end, args)
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
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
else
PGFPlots.Linear
end
return func(([arg[1]] for arg in args)...; kw...)
end
# ----------------------------------------------------------------
function _before_update_plot(plt::Plot{PGFPlotsPackage})
end
function pgf_axis(sp::Subplot, letter)
axis = sp[Symbol(letter,:axis)]
style = []
kw = KW()
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{PGFPlotsPackage}, d::Dict)
end
# turn off scaled ticks
push!(style, "scaled $(letter) ticks = false")
function _update_plot_pos_size(plt::PlottingObject{PGFPlotsPackage}, d::Dict)
end
# set to supported framestyle
framestyle = pgf_framestyle(sp[:framestyle])
# ----------------------------------------------------------------
# axis guide
kw[Symbol(letter,:label)] = axis[:guide]
# accessors for x/y data
# 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], "}"))
function Base.getindex(plt::Plot{PGFPlotsPackage}, i::Int)
d = plt.seriesargs[i]
d[:x], d[:y]
end
# flip/reverse?
axis[:flip] && push!(style, "$letter dir=reverse")
function Base.setindex!(plt::Plot{PGFPlotsPackage}, xy::Tuple, i::Integer)
d = plt.seriesargs[i]
d[:x], d[:y] = xy
plt
end
# scale
scale = axis[:scale]
if scale in (:log2, :ln, :log10)
kw[Symbol(letter,:mode)] = "log"
scale == :ln || push!(style, "log basis $letter=$(scale == :log2 ? 2 : 10)")
end
# ----------------------------------------------------------------
# ticks on or off
if axis[:ticks] in (nothing, false, :none) || framestyle == :none
push!(style, "$(letter)majorticks=false")
end
function _create_subplot(subplt::Subplot{PGFPlotsPackage}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
true
end
# grid on or off
if axis[:grid] && framestyle != :none
push!(style, "$(letter)majorgrids = true")
else
push!(style, "$(letter)majorgrids = false")
end
function _expand_limits(lims, plt::Plot{PGFPlotsPackage}, isx::Bool)
# TODO: call expand limits for each plot data
end
# limits
# TODO: support zlims
if letter != :z
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
function _remove_axis(plt::Plot{PGFPlotsPackage}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
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 = String[begin
base, power = split(label, "^")
power = string("{", power, "}")
string(base, "^", power)
end for label in ticks[2]]
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
# ----------------------------------------------------------------
# ----------------------------------------------------------------
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))
################# This is the important method to implement!!! #################
function _make_pgf_plot(plt::Plot{PGFPlotsPackage})
# TODO: convert plt.plotargs and plt.seriesargs into PGFPlots calls
# TODO: return the PGFPlots object
for sp in plt.subplots
# first build the PGFPlots.Axis object
style = ["unbounded coords=jump"]
kw = KW()
# add to style/kw for each axis
for letter in (:x, :y, :z)
if letter != :z || is3d(sp)
axisstyle, axiskw = pgf_axis(sp, letter)
append!(style, axisstyle)
merge!(kw, axiskw)
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 = $(round((total_height - (bottom(bb))).value,2))mm,
axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])}
""")
kw[:width] = "$(width(bb).value)mm"
kw[:height] = "$(height(bb).value)mm"
if 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
if sp[:aspect_ratio] in (1, :equal)
kw[:axisEqual] = "true"
end
legpos = sp[:legend]
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)), "}"))
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))
# 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 Base.writemime(io::IO, mime::MIME"image/png", plt::PlottingObject{PGFPlotsPackage})
plt.o = _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 Base.writemime(io::IO, ::MIME"text/html", plt::PlottingObject{PGFPlotsPackage})
# end
function _show(io::IO, mime::MIME"application/pdf", plt::Plot{PGFPlotsBackend})
# prepare the object
pgfplt = PGFPlots.plot(plt.o)
function Base.display(::PlotsDisplay, plt::PlottingObject{PGFPlotsPackage})
plt.o = _make_pgf_plot(plt)
display(plt.o)
# save a pdf
fn = tempname()*".pdf"
PGFPlots.save(PGFPlots.PDF(fn), pgfplt)
# read it into io
write(io, readstring(open(fn)))
# cleanup
PGFPlots.cleanup(plt.o)
end
# function Base.display(::PlotsDisplay, plt::Subplot{PGFPlotsPackage})
# # TODO: display/show the subplot
# end
function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend})
fn = tempname()*".tex"
PGFPlots.save(fn, backend_object(plt), include_preamble=false)
write(io, readstring(open(fn)))
end
function _display(plt::Plot{PGFPlotsBackend})
# prepare the object
pgfplt = PGFPlots.plot(plt.o)
# save an svg
fn = string(tempname(), ".svg")
PGFPlots.save(PGFPlots.SVG(fn), pgfplt)
# show it
open_browser_window(fn)
# cleanup
PGFPlots.cleanup(plt.o)
end
+839 -376
View File
File diff suppressed because it is too large Load Diff
+96 -90
View File
@@ -1,128 +1,134 @@
@require Revise begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "plotlyjs.jl"))
end
# https://github.com/spencerlyon2/PlotlyJS.jl
function _initialize_backend(::PlotlyJSPackage; kw...)
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
export PlotlyJS
end
for (mime, fmt) in PlotlyJS._mimeformats
@eval Base.writemime(io::IO, m::MIME{symbol($mime)}, p::Plot{PlotlyJSPackage}) = writemime(io, m, p.o)
end
# override IJulia inline display
if isijulia()
IJulia.display_dict(plt::PlottingObject{PlotlyJSPackage}) = IJulia.display_dict(plt.o)
end
# # override IJulia inline display
# if isijulia()
# IJulia.display_dict(plt::AbstractPlot{PlotlyJSBackend}) = IJulia.display_dict(plt.o)
# end
end
# ---------------------------------------------------------------------------
function _create_plot(pkg::PlotlyJSPackage; kw...)
d = Dict(kw)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
# o = PlotlyJS.Plot(PlotlyJS.GenericTrace[], PlotlyJS.Layout(),
# Base.Random.uuid4(), PlotlyJS.ElectronDisplay())
# T = isijulia() ? PlotlyJS.JupyterPlot : PlotlyJS.ElectronPlot
# o = T(PlotlyJS.Plot())
o = PlotlyJS.plot()
Plot(o, pkg, 0, d, Dict[])
function _create_backend_figure(plt::Plot{PlotlyJSBackend})
if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot)
PlotlyJS.SyncPlot(PlotlyJS.Plot(), current().o.view)
else
PlotlyJS.plot()
end
end
function _add_series(::PlotlyJSPackage, plt::Plot; kw...)
d = Dict(kw)
function _series_added(plt::Plot{PlotlyJSBackend}, series::Series)
syncplot = plt.o
# dumpdict(d, "addseries", true)
# add to the data array
pdict = plotly_series(d)
typ = pop!(pdict, :type)
gt = PlotlyJS.GenericTrace(typ; pdict...)
PlotlyJS.addtraces!(syncplot, gt)
push!(plt.seriesargs, d)
plt
end
# ---------------------------------------------------------------------------
function _add_annotations{X,Y,V}(plt::Plot{PlotlyJSPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
# set or add to the annotation_list
if !haskey(plt.plotargs, :annotation_list)
plt.plotargs[:annotation_list] = Any[]
pdicts = plotly_series(plt, series)
for pdict in pdicts
typ = pop!(pdict, :type)
gt = PlotlyJS.GenericTrace(typ; pdict...)
PlotlyJS.addtraces!(syncplot, gt)
end
append!(plt.plotargs[:annotation_list], anns)
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
)
end
# ----------------------------------------------------------------
function _before_update_plot(plt::Plot{PlotlyJSPackage})
end
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{PlotlyJSPackage}, d::Dict)
pdict = plotly_layout(d)
# dumpdict(pdict, "pdict updateplot", true)
function _update_plot_object(plt::Plot{PlotlyJSBackend})
pdict = plotly_layout(plt)
syncplot = plt.o
w,h = d[:size]
w,h = plt[:size]
PlotlyJS.relayout!(syncplot, pdict, width = w, height = h)
end
function _update_plot_pos_size(plt::PlottingObject{PlotlyJSPackage}, d::Dict)
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{PlotlyJSPackage}, i::Int)
d = plt.seriesargs[i]
d[:x], d[:y]
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 Base.setindex!(plt::Plot{PlotlyJSPackage}, xy::Tuple, i::Integer)
d = plt.seriesargs[i]
d[:x], d[:y] = xy
# TODO: this is likely ineffecient... we should make a call that ONLY changes the plot data
# PlotlyJS.restyle!(plt.o, i, plotly_series(d))
PlotlyJS.restyle!(plt.o, i, Dict(:x=>(d[:x],), :y=>(d[:y],)))
plt
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 _create_subplot(subplt::Subplot{PlotlyJSPackage}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
true
function _display(plt::Plot{PlotlyJSBackend})
if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
display(plt.o)
else
standalone_html_window(plt)
end
end
function _expand_limits(lims, plt::Plot{PlotlyJSPackage}, isx::Bool)
# TODO: call expand limits for each plot data
@require WebIO begin
function WebIO.render(plt::Plot{PlotlyJSBackend})
prepare_output(plt)
WebIO.render(plt.o)
end
end
function _remove_axis(plt::Plot{PlotlyJSPackage}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
function closeall(::PlotlyJSBackend)
if !isplotnull() && isa(current().o, PlotlyJS.SyncPlot)
close(current().o)
end
end
# ----------------------------------------------------------------
function Base.writemime(io::IO, m::MIME"text/html", plt::PlottingObject{PlotlyJSPackage})
Base.writemime(io, m, plt.o)
end
function Base.display(::PlotsDisplay, plt::Plot{PlotlyJSPackage})
display(plt.o)
end
function Base.display(::PlotsDisplay, plt::Subplot{PlotlyJSPackage})
error()
end
+1251 -778
View File
File diff suppressed because it is too large Load Diff
-773
View File
@@ -1,773 +0,0 @@
supportedAxes(::PlottingPackage) = [:left]
supportedTypes(::PlottingPackage) = []
supportedStyles(::PlottingPackage) = [:solid]
supportedMarkers(::PlottingPackage) = [:none]
supportedScales(::PlottingPackage) = [:identity]
subplotSupported(::PlottingPackage) = false
stringsSupported(::PlottingPackage) = false
supportedAxes() = supportedAxes(backend())
supportedTypes() = supportedTypes(backend())
supportedStyles() = supportedStyles(backend())
supportedMarkers() = supportedMarkers(backend())
supportedScales() = supportedScales(backend())
subplotSupported() = subplotSupported(backend())
stringsSupported() = stringsSupported(backend())
# --------------------------------------------------------------------------------------
supportedArgs(::GadflyPackage) = [
:annotation,
# :axis,
:background_color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
:fillalpha,
:foreground_color,
:group,
:label,
:layout,
:legend,
:colorbar,
:linestyle,
:linetype,
:linewidth,
:linealpha,
:markershape,
:markercolor,
:markersize,
:markeralpha,
:markerstrokewidth,
:markerstrokecolor,
:markerstrokealpha,
# :markerstrokestyle,
:n,
:nbins,
:nc,
:nr,
# :pos,
:smooth,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
:yticks,
:xscale,
:yscale,
:xflip,
:yflip,
:z,
:zcolor,
:tickfont,
:guidefont,
:legendfont,
:grid,
# :surface,
:levels,
]
supportedAxes(::GadflyPackage) = [:auto, :left]
supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppre, :steppost, :sticks,
:scatter, :heatmap, :hexbin, :hist, :bar,
:hline, :vline, :contour]
supportedStyles(::GadflyPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::GadflyPackage) = vcat(_allMarkers, Shape)
supportedScales(::GadflyPackage) = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
subplotSupported(::GadflyPackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::ImmersePackage) = supportedArgs(GadflyPackage())
supportedAxes(::ImmersePackage) = supportedAxes(GadflyPackage())
supportedTypes(::ImmersePackage) = supportedTypes(GadflyPackage())
supportedStyles(::ImmersePackage) = supportedStyles(GadflyPackage())
supportedMarkers(::ImmersePackage) = supportedMarkers(GadflyPackage())
supportedScales(::ImmersePackage) = supportedScales(GadflyPackage())
subplotSupported(::ImmersePackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::PyPlotPackage) = [
:annotation,
:axis,
:background_color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
:foreground_color,
:group,
:label,
:layout,
:legend,
:colorbar,
:linestyle,
:linetype,
:linewidth,
:markershape,
:markercolor,
:markersize,
:markerstrokewidth,
:markerstrokecolor,
:markerstrokealpha,
# :markerstrokestyle,
:n,
:nbins,
:nc,
:nr,
# :pos,
:smooth,
# :ribbon,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
:yrightlabel,
:yticks,
:xscale,
:yscale,
:xflip,
:yflip,
:z,
:zcolor, # only supported for scatter/scatter3d
:tickfont,
:guidefont,
:legendfont,
:grid,
# :surface,
:levels,
:fillalpha,
:linealpha,
:markeralpha,
:overwrite_figure,
]
supportedAxes(::PyPlotPackage) = _allAxes
supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, #:sticks,
:scatter, :heatmap, :hexbin, :hist, :density, :bar,
:hline, :vline, :contour, :path3d, :scatter3d, :surface, :wireframe]
supportedStyles(::PyPlotPackage) = [:auto, :solid, :dash, :dot, :dashdot]
# supportedMarkers(::PyPlotPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :hexagon]
supportedMarkers(::PyPlotPackage) = vcat(_allMarkers, Shape)
supportedScales(::PyPlotPackage) = [:identity, :ln, :log2, :log10]
subplotSupported(::PyPlotPackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::GRPackage) = [
:annotation,
:axis,
:background_color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
:foreground_color,
:group,
:label,
:layout,
:legend,
:colorbar,
:linestyle,
:linetype,
:linewidth,
:markershape,
:markercolor,
:markersize,
:markerstrokewidth,
:markerstrokecolor,
# :markerstrokestyle,
:n,
:nbins,
:nc,
:nr,
# :pos,
:smooth,
# :ribbon,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
:yrightlabel,
:yticks,
:xscale,
:yscale,
:xflip,
:yflip,
:z,
:zcolor, # only supported for scatter/scatter3d
:tickfont,
:guidefont,
:legendfont,
:grid,
# :surface,
:nlevels,
:fillalpha,
:linealpha,
:markeralpha,
]
supportedAxes(::GRPackage) = _allAxes
supportedTypes(::GRPackage) = [:none, :line, :path, :steppre, :steppost, :sticks,
:scatter, :heatmap, :hexbin, :hist, :density, :bar,
:hline, :vline, :contour, :path3d, :scatter3d, :surface,
:wireframe, :ohlc, :pie]
supportedStyles(::GRPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::GRPackage) = vcat(_allMarkers, Shape)
supportedScales(::GRPackage) = [:identity, :log10]
subplotSupported(::GRPackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::QwtPackage) = [
:annotation,
# :args,
:axis,
:background_color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
:foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
:layout,
:legend,
:linestyle,
:linetype,
:linewidth,
:markershape,
:markercolor,
:markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
:n,
:nbins,
:nc,
:nr,
:pos,
:smooth,
# :ribbon,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
:yrightlabel,
:yticks,
:xscale,
:yscale,
# :xflip,
# :yflip,
# :z,
]
supportedTypes(::QwtPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline]
supportedMarkers(::QwtPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :star8, :hexagon]
supportedScales(::QwtPackage) = [:identity, :log10]
subplotSupported(::QwtPackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::UnicodePlotsPackage) = [
# :annotation,
# :args,
# :axis,
# :background_color,
# :linecolor,
# :fill,
# :foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
# :layout,
:legend,
:linestyle,
:linetype,
# :linewidth,
:markershape,
# :markercolor,
# :markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
:nbins,
# :nc,
# :nr,
# :pos,
# :reg,
# :ribbon,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
# :xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
# :yticks,
# :xscale,
# :yscale,
# :xflip,
# :yflip,
# :z,
]
supportedAxes(::UnicodePlotsPackage) = [:auto, :left]
supportedTypes(::UnicodePlotsPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline]
supportedStyles(::UnicodePlotsPackage) = [:auto, :solid]
supportedMarkers(::UnicodePlotsPackage) = [:none, :auto, :ellipse]
supportedScales(::UnicodePlotsPackage) = [:identity]
subplotSupported(::UnicodePlotsPackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::WinstonPackage) = [
:annotation,
# :args,
# :axis,
# :background_color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
# :foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
# :layout,
:legend,
:linestyle,
:linetype,
:linewidth,
:markershape,
:markercolor,
:markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
:nbins,
# :nc,
# :nr,
# :pos,
:smooth,
# :ribbon,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
# :xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
# :yticks,
:xscale,
:yscale,
# :xflip,
# :yflip,
# :z,
]
supportedAxes(::WinstonPackage) = [:auto, :left]
supportedTypes(::WinstonPackage) = [:none, :line, :path, :sticks, :scatter, :hist, :bar]
supportedStyles(::WinstonPackage) = [:auto, :solid, :dash, :dot, :dashdot]
supportedMarkers(::WinstonPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5]
supportedScales(::WinstonPackage) = [:identity, :log10]
subplotSupported(::WinstonPackage) = false
# --------------------------------------------------------------------------------------
supportedArgs(::BokehPackage) = [
# :annotation,
# :axis,
# :background_color,
:linecolor,
# :color_palette,
# :fillrange,
# :fillcolor,
# :fillalpha,
# :foreground_color,
:group,
# :label,
# :layout,
# :legend,
:linestyle,
:linetype,
:linewidth,
# :linealpha,
:markershape,
:markercolor,
:markersize,
# :markeralpha,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
# :nbins,
# :nc,
# :nr,
# :pos,
# :smooth,
# :show,
:size,
:title,
# :windowtitle,
:x,
# :xlabel,
# :xlims,
# :xticks,
:y,
# :ylabel,
# :ylims,
# :yrightlabel,
# :yticks,
# :xscale,
# :yscale,
# :xflip,
# :yflip,
# :z,
# :tickfont,
# :guidefont,
# :legendfont,
# :grid,
# :surface,
# :levels,
]
supportedAxes(::BokehPackage) = [:auto, :left]
supportedTypes(::BokehPackage) = [:none, :path, :scatter] #,:steppre, :steppost, :sticks, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
supportedStyles(::BokehPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::BokehPackage) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] #vcat(_allMarkers, Shape)
supportedScales(::BokehPackage) = [:identity, :ln] #, :ln, :log2, :log10, :asinh, :sqrt]
subplotSupported(::BokehPackage) = false
# --------------------------------------------------------------------------------------
supportedArgs(::PlotlyPackage) = [
:annotation,
# :axis,
:background_color,
:color_palette,
:fillrange,
:fillcolor,
:fillalpha,
:foreground_color,
:group,
:label,
:layout,
:legend,
:linecolor,
:linestyle,
:linetype,
:linewidth,
:linealpha,
:markershape,
:markercolor,
:markersize,
:markeralpha,
:markerstrokewidth,
:markerstrokecolor,
:markerstrokestyle,
:n,
:nbins,
:nc,
:nr,
# :pos,
# :smooth,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
:yticks,
:xscale,
:yscale,
:xflip,
:yflip,
:z,
:zcolor,
:tickfont,
:guidefont,
:legendfont,
:grid,
:levels,
]
supportedAxes(::PlotlyPackage) = [:auto, :left]
supportedTypes(::PlotlyPackage) = [:none, :line, :path, :scatter, :steppre, :steppost,
:heatmap, :hist, :density, :bar, :contour, :surface, :path3d, :scatter3d,
:pie] #,, :sticks, :hexbin, :hline, :vline]
supportedStyles(::PlotlyPackage) = [:auto, :solid, :dash, :dot, :dashdot]
supportedMarkers(::PlotlyPackage) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross,
:pentagon, :hexagon, :octagon, :vline, :hline] #vcat(_allMarkers, Shape)
supportedScales(::PlotlyPackage) = [:identity, :log10] #, :ln, :log2, :log10, :asinh, :sqrt]
subplotSupported(::PlotlyPackage) = true
stringsSupported(::PlotlyPackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::PlotlyJSPackage) = [
:annotation,
# :axis,
:background_color,
:color_palette,
:fillrange,
:fillcolor,
:fillalpha,
:foreground_color,
:group,
:label,
:layout,
:legend,
:linecolor,
:linestyle,
:linetype,
:linewidth,
:linealpha,
:markershape,
:markercolor,
:markersize,
:markeralpha,
:markerstrokewidth,
:markerstrokecolor,
:markerstrokestyle,
:n,
:nbins,
:nc,
:nr,
# :pos,
# :smooth,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
:yticks,
:xscale,
:yscale,
:xflip,
:yflip,
:z,
:zcolor,
:tickfont,
:guidefont,
:legendfont,
:grid,
:levels,
]
supportedAxes(::PlotlyJSPackage) = [:auto, :left]
supportedTypes(::PlotlyJSPackage) = [:none, :line, :path, :scatter, :steppre, :steppost,
:heatmap, :hist, :density, :bar, :contour, :surface, :path3d, :scatter3d,
:pie] #,, :sticks, :hexbin, :hline, :vline]
supportedStyles(::PlotlyJSPackage) = [:auto, :solid, :dash, :dot, :dashdot]
supportedMarkers(::PlotlyJSPackage) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross,
:pentagon, :hexagon, :octagon, :vline, :hline] #vcat(_allMarkers, Shape)
supportedScales(::PlotlyJSPackage) = [:identity, :log10] #, :ln, :log2, :log10, :asinh, :sqrt]
subplotSupported(::PlotlyJSPackage) = true
stringsSupported(::PlotlyJSPackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::GLVisualizePackage) = [
# :annotation,
# :axis,
# :background_color,
# :color_palette,
# :fillrange,
# :fillcolor,
# :fillalpha,
# :foreground_color,
# :group,
# :label,
# :layout,
# :legend,
# :linecolor,
# :linestyle,
# :linetype,
# :linewidth,
# :linealpha,
# :markershape,
# :markercolor,
# :markersize,
# :markeralpha,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
# :nbins,
# :nc,
# :nr,
# :pos,
# :smooth,
# :show,
# :size,
# :title,
# :windowtitle,
# :x,
# :xlabel,
# :xlims,
# :xticks,
# :y,
# :ylabel,
# :ylims,
# :yrightlabel,
# :yticks,
# :xscale,
# :yscale,
# :xflip,
# :yflip,
# :z,
# :tickfont,
# :guidefont,
# :legendfont,
# :grid,
# :surface
# :levels,
]
supportedAxes(::GLVisualizePackage) = [:auto, :left]
supportedTypes(::GLVisualizePackage) = [:contour] #, :path, :scatter ,:steppre, :steppost, :sticks, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
supportedStyles(::GLVisualizePackage) = [:auto, :solid] #, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::GLVisualizePackage) = [:none, :auto, :ellipse] #, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] #vcat(_allMarkers, Shape)
supportedScales(::GLVisualizePackage) = [:identity] #, :log, :log2, :log10, :asinh, :sqrt]
subplotSupported(::GLVisualizePackage) = false
# --------------------------------------------------------------------------------------
supportedArgs(::PGFPlotsPackage) = [
# :annotation,
# :axis,
# :background_color,
# :color_palette,
# :fillrange,
# :fillcolor,
# :fillalpha,
# :foreground_color,
# :group,
# :label,
# :layout,
# :legend,
# :linecolor,
# :linestyle,
# :linetype,
# :linewidth,
# :linealpha,
# :markershape,
# :markercolor,
# :markersize,
# :markeralpha,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
# :nbins,
# :nc,
# :nr,
# :pos,
# :smooth,
# :show,
# :size,
# :title,
# :windowtitle,
# :x,
# :xlabel,
# :xlims,
# :xticks,
# :y,
# :ylabel,
# :ylims,
# :yrightlabel,
# :yticks,
# :xscale,
# :yscale,
# :xflip,
# :yflip,
# :z,
# :tickfont,
# :guidefont,
# :legendfont,
# :grid,
# :surface
# :levels,
]
supportedAxes(::PGFPlotsPackage) = [:auto, :left]
supportedTypes(::PGFPlotsPackage) = [:contour] #, :path, :scatter ,:steppre, :steppost, :sticks, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
supportedStyles(::PGFPlotsPackage) = [:auto, :solid] #, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::PGFPlotsPackage) = [:none, :auto, :ellipse] #, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] #vcat(_allMarkers, Shape)
supportedScales(::PGFPlotsPackage) = [:identity] #, :log, :log2, :log10, :asinh, :sqrt]
subplotSupported(::PGFPlotsPackage) = false
+57 -71
View File
@@ -1,89 +1,75 @@
# TODO: find/replace all [PkgName] with CamelCase, all [pkgname] with lowercase
# TODO: find/replace all [PkgName] with CamelCase
# [WEBSITE]
# [ADD BACKEND WEBSITE]
function _initialize_backend(::[PkgName]Package; kw...)
@eval begin
import [PkgName]
export [PkgName]
# TODO: other initialization that needs to be eval-ed
end
# TODO: other initialization
function _initialize_backend(::[PkgName]Backend; kw...)
@eval begin
import [PkgName]
export [PkgName]
# todo: other initialization that needs to be eval-ed
end
# todo: other initialization
end
# ---------------------------------------------------------------------------
function _create_plot(pkg::[PkgName]Package; kw...)
d = Dict(kw)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
Plot(nothing, pkg, 0, d, Dict[])
# Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{[PkgName]Backend})
nothing
end
# # this is called early in the pipeline, use it to make the plot current or something
# function _prepare_plot_object(plt::Plot{[PkgName]Backend})
# end
# Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{[PkgName]Backend}, sp::Subplot{[PkgName]Backend})
end
# ---------------------------------------------------------------------------
# Add one series to the underlying backend object.
function _series_added(plt::Plot{[PkgName]Backend}, series::Series)
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{[PkgName]Backend}, series::Series)
end
# ---------------------------------------------------------------------------
# called just before updating layout bounding boxes... in case you need to prep
# for the calcs
function _before_layout_calcs(plt::Plot{[PkgName]Backend})
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{[PkgName]Backend})
sp.minpad = (20mm, 5mm, 2mm, 10mm)
end
function _add_series(::[PkgName]Package, plt::Plot; kw...)
d = Dict(kw)
# TODO: add one series to the underlying package
push!(plt.seriesargs, d)
plt
end
# ----------------------------------------------------------------
function _add_annotations{X,Y,V}(plt::Plot{[PkgName]Package}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
# TODO: add the annotation to the plot
end
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations])
function _update_plot_object(plt::Plot{[PkgName]Backend})
end
# ----------------------------------------------------------------
function _before_update_plot(plt::Plot{[PkgName]Package})
# Write a png to io. You could define methods for:
# "application/eps" => "eps",
# "image/eps" => "eps",
# "application/pdf" => "pdf",
# "image/png" => "png",
# "application/postscript" => "ps",
# "image/svg+xml" => "svg"
function _show(io::IO, ::MIME"image/png", plt::Plot{[PkgName]Backend})
end
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{[PkgName]Package}, d::Dict)
end
function _update_plot_pos_size(plt::PlottingObject{[PkgName]Package}, d::Dict)
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{[PkgName]Package}, i::Int)
# TODO: return a tuple of (x, y) vectors
end
function Base.setindex!(plt::Plot{[PkgName]Package}, xy::Tuple, i::Integer)
# TODO: set the plot data from the (x,y) tuple
plt
end
# ----------------------------------------------------------------
function _create_subplot(subplt::Subplot{[PkgName]Package}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
end
function _expand_limits(lims, plt::Plot{[PkgName]Package}, isx::Bool)
# TODO: call expand limits for each plot data
end
function _remove_axis(plt::Plot{[PkgName]Package}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{[PkgName]Package})
# TODO: write a png to io
end
function Base.display(::PlotsDisplay, plt::Plot{[PkgName]Package})
# TODO: display/show the plot
end
function Base.display(::PlotsDisplay, plt::Subplot{[PkgName]Package})
# TODO: display/show the subplot
# Display/show the plot (open a GUI window, or browser page, for example).
function _display(plt::Plot{[PkgName]Backend})
end
+182 -161
View File
@@ -1,203 +1,224 @@
# https://github.com/Evizero/UnicodePlots.jl
function _initialize_backend(::UnicodePlotsPackage; kw...)
@eval begin
import UnicodePlots
export UnicodePlots
end
@require Revise begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "unicodeplots.jl"))
end
const _unicodeplots_attr = merge_with_base_supported([
:label,
:legend,
:seriescolor,
:seriesalpha,
:linestyle,
:markershape,
:bins,
:title,
:guide, :lims,
])
const _unicodeplots_seriestype = [
:path, :scatter, :straightline,
# :bar,
:shape,
:histogram2d,
:spy
]
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(::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
export UnicodePlots
end
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 = []
# figure out the plotting area xlim = [xmin, xmax] and ylim = [ymin, ymax]
sargs = plt.seriesargs
iargs = plt.plotargs
for sp in plt.subplots
xaxis = sp[:xaxis]
yaxis = sp[:yaxis]
xlim = axis_limits(xaxis)
ylim = axis_limits(yaxis)
# get the x/y limits
if get(iargs, :xlims, :auto) == :auto
xlim = [Inf, -Inf]
for d in sargs
_expand_limits(xlim, d[:x])
# make vectors
xlim = [xlim[1], xlim[2]]
ylim = [ylim[1], ylim[2]]
# we set x/y to have a single point, since we need to create the plot with some data.
# since this point is at the bottom left corner of the plot, it shouldn't actually be shown
x = Float64[xlim[1]]
y = Float64[ylim[1]]
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
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,
title = sp[:title],
xlim = xlim,
ylim = ylim,
border = isijulia() ? :ascii : :solid
)
# set the axis labels
UnicodePlots.xlabel!(o, xaxis[:guide])
UnicodePlots.ylabel!(o, yaxis[:guide])
# now use the ! functions to add to the plot
for series in series_list(sp)
addUnicodeSeries!(o, series.d, sp[:legend] != :none, xlim, ylim)
end
# save the object
push!(plt.o, o)
end
else
xmin, xmax = iargs[:xlims]
xlim = [xmin, xmax]
end
if get(iargs, :ylims, :auto) == :auto
ylim = [Inf, -Inf]
for d in sargs
_expand_limits(ylim, d[:y])
end
else
ymin, ymax = iargs[:ylims]
ylim = [ymin, ymax]
end
# we set x/y to have a single point, since we need to create the plot with some data.
# since this point is at the bottom left corner of the plot, it shouldn't actually be shown
x = Float64[xlim[1]]
y = Float64[ylim[1]]
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
width, height = iargs[:size]
o = UnicodePlots.Plot(x, y; width = width,
height = height,
title = iargs[:title],
# labels = iargs[:legend],
xlim = xlim,
ylim = ylim)
# set the axis labels
UnicodePlots.xlabel!(o, iargs[:xlabel])
UnicodePlots.ylabel!(o, iargs[:ylabel])
# now use the ! functions to add to the plot
for d in sargs
addUnicodeSeries!(o, d, iargs[:legend] != :none, xlim, ylim)
end
# save the object
plt.o = o
end
# add a single series
function addUnicodeSeries!(o, d::Dict, addlegend::Bool, xlim, ylim)
# get the function, or special handling for step/bar/hist
lt = d[:linetype]
# handle hline/vline separately
if lt in (:hline,:vline)
for yi in d[:y]
if lt == :hline
UnicodePlots.lineplot!(o, xlim, [yi,yi])
else
UnicodePlots.lineplot!(o, [yi,yi], ylim)
end
function addUnicodeSeries!(o, d::KW, addlegend::Bool, xlim, ylim)
# get the function, or special handling for step/bar/hist
st = d[:seriestype]
if st == :histogram2d
UnicodePlots.densityplot!(o, d[:x], d[:y])
return
end
return
end
stepstyle = :post
if lt == :path
func = UnicodePlots.lineplot!
elseif lt == :scatter || d[:markershape] != :none
func = UnicodePlots.scatterplot!
elseif lt == :steppost
func = UnicodePlots.stairs!
elseif lt == :steppre
func = UnicodePlots.stairs!
stepstyle = :pre
else
error("Linestyle $lt not supported by UnicodePlots")
end
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)]
label = addlegend ? d[:label] : ""
# get the series data and label
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
# 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
func(o, x, y; color = color, name = label, style = stepstyle)
end
function handlePlotColors(::UnicodePlotsPackage, d::Dict)
# TODO: something special for unicodeplots, since it doesn't take kindly to people messing with its color palette
d[:color_palette] = [RGB(0,0,0)]
# 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 `show`
function png(plt::AbstractPlot{UnicodePlotsBackend}, fn::AbstractString)
fn = addExtension(fn, "png")
function _create_plot(pkg::UnicodePlotsPackage; kw...)
plt = Plot(nothing, pkg, 0, Dict(kw), Dict[])
# make some whitespace and show the plot
println("\n\n\n\n\n\n")
gui(plt)
# do we want to give a new default size?
if !haskey(plt.plotargs, :size) || plt.plotargs[:size] == _plotDefaults[:size]
plt.plotargs[:size] = (60,20)
end
# @osx_only begin
@static if is_apple()
# BEGIN HACK
plt
end
# wait while the plot gets drawn
sleep(0.5)
function _add_series(::UnicodePlotsPackage, plt::Plot; kw...)
d = Dict(kw)
if d[:linetype] in (:sticks, :bar)
d = barHack(; d...)
elseif d[:linetype] == :hist
d = barHack(; histogramHack(; d...)...)
end
push!(plt.seriesargs, d)
plt
end
# use osx screen capture when my terminal is maximized and cursor starts at the bottom (I know, right?)
# TODO: compute size of plot to adjust these numbers (or maybe implement something good??)
run(`screencapture -R50,600,700,420 $fn`)
function _update_plot(plt::Plot{UnicodePlotsPackage}, d::Dict)
for k in (:title, :xlabel, :ylabel, :xlims, :ylims)
if haskey(d, k)
plt.plotargs[k] = d[k]
# END HACK (phew)
return
end
end
end
# -------------------------------
# since this is such a hack, it's only callable using `png`... should error during normal `writemime`
function png(plt::PlottingObject{UnicodePlotsPackage}, fn::@compat(AbstractString))
fn = addExtension(fn, "png")
# make some whitespace and show the plot
println("\n\n\n\n\n\n")
gui(plt)
@osx_only begin
# BEGIN HACK
# wait while the plot gets drawn
sleep(0.5)
# use osx screen capture when my terminal is maximized and cursor starts at the bottom (I know, right?)
# TODO: compute size of plot to adjust these numbers (or maybe implement something good??)
run(`screencapture -R50,600,700,420 $fn`)
# END HACK (phew)
return
end
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)")
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)")
end
# -------------------------------
# we don't do very much for subplots... just stack them vertically
function _create_subplot(subplt::Subplot{UnicodePlotsPackage}, isbefore::Bool)
isbefore && return false
true
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 _show(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
unicodeplots_rebuild(plt)
foreach(x -> show(io, x), plt.o)
nothing
end
function Base.display(::PlotsDisplay, plt::Plot{UnicodePlotsPackage})
rebuildUnicodePlot!(plt)
show(plt.o)
function _display(plt::Plot{UnicodePlotsBackend})
unicodeplots_rebuild(plt)
map(show, plt.o)
nothing
end
function Base.display(::PlotsDisplay, subplt::Subplot{UnicodePlotsPackage})
for plt in subplt.plts
gui(plt)
end
end
+39 -8
View File
@@ -2,14 +2,17 @@
# NOTE: backend should implement `html_body` and `html_head`
# CREDIT: parts of this implementation were inspired by @joshday's PlotlyLocal.jl
@require Revise begin
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "web.jl"))
end
function standalone_html(plt::PlottingObject; title::AbstractString = get(plt.plotargs, :window_title, "Plots.jl"))
function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr, :window_title, "Plots.jl"))
"""
<!DOCTYPE html>
<html>
<head>
<title>$title</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
$(html_head(plt))
</head>
<body>
@@ -20,19 +23,47 @@ function standalone_html(plt::PlottingObject; title::AbstractString = get(plt.pl
end
function open_browser_window(filename::AbstractString)
@osx_only return run(`open $(filename)`)
@linux_only return run(`xdg-open $(filename)`)
@windows_only return run(`$(ENV["COMSPEC"]) /c start $(filename)`)
@static if is_apple()
return run(`open $(filename)`)
end
@static if is_linux() || is_bsd() # is_bsd() addition is as yet untested, but based on suggestion in https://github.com/JuliaPlots/Plots.jl/issues/681
return run(`xdg-open $(filename)`)
end
@static if is_windows()
return run(`$(ENV["COMSPEC"]) /c start "" "$(filename)"`)
end
warn("Unknown OS... cannot open browser window.")
end
function standalone_html_window(plt::PlottingObject; kw...)
html = standalone_html(plt; kw...)
# println(html)
function write_temp_html(plt::AbstractPlot)
html = standalone_html(plt; title = plt.attr[:window_title])
filename = string(tempname(), ".html")
output = open(filename, "w")
write(output, html)
close(output)
filename
end
function standalone_html_window(plt::AbstractPlot)
filename = write_temp_html(plt)
open_browser_window(filename)
end
# uses wkhtmltopdf/wkhtmltoimage: http://wkhtmltopdf.org/downloads.html
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 show_png_from_html(io::IO, plt::AbstractPlot)
# write html to a temporary file
html_fn = write_temp_html(plt)
# convert that html file to a temporary png file using wkhtmltoimage
png_fn = tempname() * ".png"
w, h = plt.attr[:size]
html_to_png(html_fn, png_fn, w, h)
# now read that file data into io
pngdata = readall(png_fn)
write(io, pngdata)
end
+547 -110
View File
@@ -1,11 +1,64 @@
immutable Shape
vertices::AVec
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))
nanpush!(a::AbstractVector{P3}, b) = (push!(a, P3(NaN,NaN,NaN)); push!(a, b))
nanappend!(a::AbstractVector{P3}, b) = (push!(a, P3(NaN,NaN,NaN)); append!(a, b))
compute_angle(v::P2) = (angle = atan2(v[2], v[1]); angle < 0 ? 2π - angle : angle)
# -------------------------------------------------------------
struct Shape
x::Vector{Float64}
y::Vector{Float64}
# function Shape(x::AVec, y::AVec)
# # if x[1] != x[end] || y[1] != y[end]
# # new(vcat(x, x[1]), vcat(y, y[1]))
# # else
# new(x, y)
# 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
"return the vertex points from a Shape or Segments object"
function coords(shape::Shape)
shape.x, shape.y
end
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, coords(shapes[1]))
for shape in shapes[2:end]
nanappend!(x, shape.x)
nanappend!(y, shape.y)
end
x, y
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 linspace(start_θ, end_θ, n)]
end
"interleave 2 vectors into each other (like a zipper's teeth)"
@@ -17,9 +70,6 @@ function weave(x,y; ordering = Vector[x,y])
try
push!(ret, shift!(o))
end
# try
# push!(ret, shift!(y))
# end
end
done = isempty(x) && isempty(y)
end
@@ -33,13 +83,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
@@ -48,17 +98,52 @@ function makecross(; offset = -0.5, radius = 1.0)
z1 = z2 - π/8
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])
Shape(weave(outercircle, innercircle,
ordering=Vector[outercircle,innercircle,outercircle]))
end
const _shapes = @compat Dict(
:ellipse => makeshape(20),
from_polar(angle, dist) = P2(dist*cos(angle), dist*sin(angle))
function makearrowhead(angle; h = 2.0, w = 0.4)
tip = from_polar(angle, h)
Shape(P2[(0,0), from_polar(angle - 0.5π, w) - tip,
from_polar(angle + 0.5π, w) - tip, (0,0)])
end
const _shape_keys = Symbol[
:circle,
:rect,
:star5,
:diamond,
:hexagon,
:cross,
:xcross,
:utriangle,
:dtriangle,
:rtriangle,
:ltriangle,
:pentagon,
:heptagon,
:octagon,
:star4,
:star6,
:star7,
: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),
@@ -70,13 +155,98 @@ const _shapes = @compat Dict(
)
for n in [4,5,6,7,8]
_shapes[symbol("star$n")] = makestar(n)
_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 = coords(shape)
n = length(x)
A, Cx, Cy = 0.0, 0.0, 0.0
for i=1:n
ip1 = i==n ? 1 : i+1
A += x[i] * y[ip1] - x[ip1] * y[i]
end
A *= 0.5
for i=1:n
ip1 = i==n ? 1 : i+1
m = (x[i] * y[ip1] - x[ip1] * y[i])
Cx += (x[i] + x[ip1]) * m
Cy += (y[i] + y[ip1]) * m
end
Cx / 6A, Cy / 6A
end
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
sy[i] = (sy[i] - cy) * y + cy
end
shape
end
function scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
shapecopy = deepcopy(shape)
scale!(shapecopy, x, y, c)
end
"translate a Shape in space"
function translate!(shape::Shape, x::Real, y::Real = x)
sx, sy = coords(shape)
for i=1:length(sx)
sx[i] += x
sy[i] += y
end
shape
end
function translate(shape::Shape, x::Real, y::Real = x)
shapecopy = deepcopy(shape)
translate!(shapecopy, x, y)
end
function rotate_x(x::Real, y::Real, Θ::Real, centerx::Real, centery::Real)
(x - centerx) * cos(Θ) - (y - centery) * sin(Θ) + centerx
end
function rotate_y(x::Real, y::Real, Θ::Real, centerx::Real, centery::Real)
(y - centery) * cos(Θ) + (x - centerx) * sin(Θ) + centery
end
function rotate(x::Real, y::Real, θ::Real, c = center(shape))
cx, cy = c
rotate_x(x, y, Θ, cx, cy), rotate_y(x, y, Θ, cx, cy)
end
function rotate!(shape::Shape, Θ::Real, c = center(shape))
x, y = coords(shape)
cx, cy = c
for i=1:length(x)
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)
end
# -----------------------------------------------------------------------
immutable Font
mutable struct Font
family::AbstractString
pointsize::Int
halign::Symbol
@@ -87,9 +257,9 @@ end
"Create a Font from a list of unordered features"
function font(args...)
# defaults
family = "Helvetica"
family = "sans-serif"
pointsize = 14
halign = :hcenter
valign = :vcenter
@@ -99,7 +269,14 @@ function font(args...)
for arg in args
T = typeof(arg)
if arg == :center
if T == Font
family = arg.family
pointsize = arg.pointsize
halign = arg.halign
valign = arg.valign
rotation = arg.rotation
color = arg.color
elseif arg == :center
halign = :hcenter
valign = :vcenter
elseif arg in (:hcenter, :left, :right)
@@ -108,7 +285,7 @@ function font(args...)
valign = arg
elseif T <: Colorant
color = arg
elseif T <: @compat Union{Symbol,AbstractString}
elseif T <: Symbol || T <: AbstractString
try
color = parse(Colorant, string(arg))
catch
@@ -126,34 +303,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
str::@compat(AbstractString)
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
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)
# defaults
# width = 1
# color = colorant"black"
# style = :solid
width = nothing
color = nothing
style = nothing
width = 1
color = :black
style = :solid
for arg in args
T = typeof(arg)
@@ -163,14 +385,12 @@ function stroke(args...; alpha = nothing)
style = arg
elseif T <: Colorant
color = arg
elseif T <: @compat Union{Symbol,AbstractString}
elseif T <: Symbol || T <: AbstractString
try
color = parse(Colorant, string(arg))
end
# elseif trueOrAllTrue(a -> typeof(a) <: Real && a > 0 && a < 1, arg)
elseif allAlphas(arg)
alpha = arg
# elseif typeof(arg) <: Real
elseif allReals(arg)
width = arg
else
@@ -182,32 +402,27 @@ 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)
# defaults
# sz = 1
# color = colorant"black"
size = nothing
color = nothing
size = 1
color = :black
for arg in args
T = typeof(arg)
if T <: Colorant
color = arg
elseif T <: @compat Union{Symbol,AbstractString}
elseif T <: Symbol || T <: AbstractString
try
color = parse(Colorant, string(arg))
end
# elseif trueOrAllTrue(a -> typeof(a) <: Real && a > 0 && a < 1, arg)
elseif allAlphas(arg)
alpha = arg
# elseif typeof(arg) <: Real
elseif allReals(arg)
size = arg
else
@@ -220,26 +435,177 @@ end
# -----------------------------------------------------------------------
mutable struct SeriesAnnotations
strs::AbstractVector # the labels/names
font::Font
baseshape::Nullable
scalefactor::Tuple
end
function series_annotations(strs::AbstractVector, args...)
fnt = font()
shp = Nullable{Any}()
scalefactor = (1,1)
for arg in args
if isa(arg, Shape) || (isa(arg, AbstractVector) && eltype(arg) == Shape)
shp = Nullable(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(::Void) = 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 && !isnull(anns.baseshape)
# we use baseshape to overwrite the markershape attribute
# with a list of custom shapes for each
msw,msh = anns.scalefactor
msize = Float64[]
shapes = Shape[begin
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)
shape = scale(baseshape, msw*xscale/maxscale, msh*yscale/maxscale, (0,0))
end for i=1:length(anns.strs)]
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(::Void) = []
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 type AbstractSurface end
"represents a contour or surface mesh"
immutable Surface{M<:AMat}
# x::AVec
# y::AVec
struct Surface{M<:AMat} <: AbstractSurface
surf::M
end
Surface(f::Function, x, y) = Surface(Float64[f(xi,yi) for xi in x, yi in y])
Surface(f::Function, x, y) = Surface(Float64[f(xi,yi) for yi in y, xi in x])
Base.Array(surf::Surface) = surf.surf
@@ -247,80 +613,151 @@ for f in (:length, :size)
@eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...)
end
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]
for vi in surf.surf
expand_extrema!(ex, vi)
end
ex
end
type OHLC{T<:Real}
open::T
high::T
low::T
close::T
"For the case of representing a surface as a function of x/y... can possibly avoid allocations."
struct SurfaceFunction <: AbstractSurface
f::Function
end
# @require FixedSizeArrays begin
# -----------------------------------------------------------------------
export
P2,
P3,
BezierCurve,
curve_points,
directed_curve
typealias P2 FixedSizeArrays.Vec{2,Float64}
typealias P3 FixedSizeArrays.Vec{3,Float64}
# # I don't want to clash with ValidatedNumerics, but this would be nice:
# ..(a::T, b::T) = (a,b)
type BezierCurve{T <: FixedSizeArrays.Vec}
control_points::Vector{T}
end
struct Volume{T}
v::Array{T,3}
x_extents::Tuple{T,T}
y_extents::Tuple{T,T}
z_extents::Tuple{T,T}
end
function Base.call(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
default_extents(::Type{T}) where {T} = (zero(T), one(T))
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 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
curve_points(curve::BezierCurve, n::Integer = 30; range = [0,1]) = map(curve, linspace(range..., n))
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
# 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
# style is :open or :closed (for now)
struct Arrow
style::Symbol
side::Symbol # :head (default), :tail, or :both
headlength::Float64
headwidth::Float64
end
# 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
[]
"""
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
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)
if !setlength
headlength = headwidth
end
setlength = true
elseif T <: Tuple && length(arg) == 2
headlength, headwidth = Float64(arg[1]), Float64(arg[2])
else
warn("Skipped arrow arg $arg")
end
end
BezierCurve([p, upper_control, inside_control_points..., lower_control, q])
end
Arrow(style, side, headlength, headwidth)
end
# end
# allow for do-block notation which gets called on every valid start/end pair which
# we need to draw an arrow
function add_arrows(func::Function, x::AVec, y::AVec)
for i=2:length(x)
xyprev = (x[i-1], y[i-1])
xy = (x[i], y[i])
if ok(xyprev) && ok(xy)
if i==length(x) || !ok(x[i+1], y[i+1])
# add the arrow from xyprev to xy
func(xyprev, xy)
end
end
end
end
# -----------------------------------------------------------------------
"Represents data values with formatting that should apply to the tick labels."
struct Formatted{T}
data::T
formatter::Function
end
# -----------------------------------------------------------------------
"create a BezierCurve for plotting"
mutable struct BezierCurve{T <: FixedSizeArrays.Vec}
control_points::Vector{T}
end
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
# 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, linspace(range..., n))
# 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(args...; kw...)
error("directed_curve has been moved to PlotRecipes")
end
function extrema_plus_buffer(v, buffmult = 0.2)
vmin,vmax = ignorenan_extrema(v)
vdiff = vmax-vmin
buffer = vdiff * buffmult
vmin - buffer, vmax + buffer
end
+208
View File
@@ -0,0 +1,208 @@
# https://github.com/bokeh/Bokeh.jl
supported_attrs(::BokehBackend) = merge_with_base_supported([
# :annotations,
# :axis,
# :background_color,
:linecolor,
# :color_palette,
# :fillrange,
# :fillcolor,
# :fillalpha,
# :foreground_color,
:group,
# :label,
# :layout,
# :legend,
:seriescolor, :seriesalpha,
:linestyle,
:seriestype,
:linewidth,
# :linealpha,
:markershape,
:markercolor,
:markersize,
# :markeralpha,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
# :bins,
# :nc,
# :nr,
# :pos,
# :smooth,
# :show,
:size,
:title,
# :window_title,
:x,
# :xguide,
# :xlims,
# :xticks,
:y,
# :yguide,
# :ylims,
# :yrightlabel,
# :yticks,
# :xscale,
# :yscale,
# :xflip,
# :yflip,
# :z,
# :tickfont,
# :guidefont,
# :legendfont,
# :grid,
# :surface,
# :levels,
])
supported_types(::BokehBackend) = [:path, :scatter]
supported_styles(::BokehBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supported_markers(::BokehBackend) = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5]
supported_scales(::BokehBackend) = [:identity, :ln]
is_subplot_supported(::BokehBackend) = false
# --------------------------------------------------------------------------------------
function _initialize_backend(::BokehBackend; kw...)
@eval begin
warn("Bokeh is no longer supported... many features will likely be broken.")
import Bokeh
export Bokeh
end
end
const _glyphtypes = KW(
:circle => :Circle,
:rect => :Square,
:diamond => :Diamond,
:utriangle => :Triangle,
:dtriangle => :InvertedTriangle,
# :pentagon =>
# :hexagon =>
# :heptagon =>
# :octagon =>
:cross => :Cross,
:xcross => :X,
:star5 => :Asterisk,
)
function bokeh_glyph_type(d::KW)
st = d[:seriestype]
mt = d[:markershape]
if st == :scatter && mt == :none
mt = :circle
end
# if we have a marker, use that
if st == :scatter || mt != :none
return _glyphtypes[mt]
end
# otherwise return a line
return :Line
end
function get_stroke_vector(linestyle::Symbol)
dash = 12
dot = 3
gap = 2
linestyle == :solid && return Int[]
linestyle == :dash && return Int[dash, gap]
linestyle == :dot && return Int[dot, gap]
linestyle == :dashdot && return Int[dash, gap, dot, gap]
linestyle == :dashdotdot && return Int[dash, gap, dot, gap, dot, gap]
error("unsupported linestyle: ", linestyle)
end
# ---------------------------------------------------------------------------
# function _create_plot(pkg::BokehBackend, d::KW)
function _create_backend_figure(plt::Plot{BokehBackend})
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
datacolumns = Bokeh.BokehDataSet[]
tools = Bokeh.tools()
filename = tempname() * ".html"
title = plt.attr[:title]
w, h = plt.attr[:size]
xaxis_type = plt.attr[:xscale] == :log10 ? :log : :auto
yaxis_type = plt.attr[:yscale] == :log10 ? :log : :auto
# legend = plt.attr[:legend] ? xxxx : nothing
legend = nothing
extra_args = KW() # TODO: we'll put extra settings (xlim, etc) here
Bokeh.Plot(datacolumns, tools, filename, title, w, h, xaxis_type, yaxis_type, legend) #, extra_args)
# Plot(bplt, pkg, 0, d, KW[])
end
# function _series_added(::BokehBackend, plt::Plot, d::KW)
function _series_added(plt::Plot{BokehBackend}, series::Series)
bdata = Dict{Symbol, Vector}(:x => collect(series.d[:x]), :y => collect(series.d[:y]))
glyph = Bokeh.Bokehjs.Glyph(
glyphtype = bokeh_glyph_type(d),
linecolor = webcolor(d[:linecolor]), # shape's stroke or line color
linewidth = d[:linewidth], # shape's stroke width or line width
fillcolor = webcolor(d[:markercolor]),
size = ceil(Int, d[:markersize] * 2.5), # magic number 2.5 to keep in same scale as other backends
dash = get_stroke_vector(d[:linestyle])
)
legend = nothing # TODO
push!(plt.o.datacolumns, Bokeh.BokehDataSet(bdata, glyph, legend))
# push!(plt.seriesargs, d)
# plt
end
# ----------------------------------------------------------------
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot_object(plt::Plot{BokehBackend}, d::KW)
end
# ----------------------------------------------------------------
# accessors for x/y data
# function getxy(plt::Plot{BokehBackend}, i::Int)
# series = plt.o.datacolumns[i].data
# series[:x], series[:y]
# end
#
# function setxy!(plt::Plot{BokehBackend}, xy::Tuple{X,Y}, i::Integer)
# series = plt.o.datacolumns[i].data
# series[:x], series[:y] = xy
# plt
# end
# ----------------------------------------------------------------
# ----------------------------------------------------------------
function Base.show(io::IO, ::MIME"image/png", plt::AbstractPlot{BokehBackend})
# TODO: write a png to io
warn("mime png not implemented")
end
function Base.display(::PlotsDisplay, plt::Plot{BokehBackend})
Bokeh.showplot(plt.o)
end
# function Base.display(::PlotsDisplay, plt::Subplot{BokehBackend})
# # TODO: display/show the subplot
# end
+744
View File
@@ -0,0 +1,744 @@
# https://github.com/dcjones/Gadfly.jl
supported_attrs(::GadflyBackend) = merge_with_base_supported([
:annotations,
:background_color, :foreground_color, :color_palette,
:group, :label, :seriestype,
:seriescolor, :seriesalpha,
:linecolor, :linestyle, :linewidth, :linealpha,
:markershape, :markercolor, :markersize, :markeralpha,
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
:fillrange, :fillcolor, :fillalpha,
:bins, :n, :nc, :nr, :layout, :smooth,
:title, :window_title, :show, :size,
:x, :xguide, :xlims, :xticks, :xscale, :xflip,
:y, :yguide, :ylims, :yticks, :yscale, :yflip,
:z,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :levels,
:xerror, :yerror,
:ribbon, :quiver,
:orientation,
])
supported_types(::GadflyBackend) = [
:path,
:scatter, :hexbin,
:bar,
:contour, :shape
]
supported_styles(::GadflyBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supported_markers(::GadflyBackend) = vcat(_allMarkers, Shape)
supported_scales(::GadflyBackend) = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
is_subplot_supported(::GadflyBackend) = true
# --------------------------------------------------------------------------------------
function _initialize_backend(::GadflyBackend; kw...)
@eval begin
import Gadfly, Compose
export Gadfly, Compose
include(joinpath(dirname(@__FILE__), "gadfly_shapes.jl"))
end
end
# ---------------------------------------------------------------------------
# immutable MissingVec <: AbstractVector{Float64} end
# Base.size(v::MissingVec) = (1,)
# Base.getindex(v::MissingVec, i::Integer) = 0.0
function createGadflyPlotObject(d::KW)
gplt = Gadfly.Plot()
gplt.mapping = Dict()
gplt.data_source = Gadfly.DataFrames.DataFrame()
# gplt.layers = gplt.layers[1:0]
gplt.layers = [Gadfly.layer(Gadfly.Geom.point(tag=:remove), x=zeros(1), y=zeros(1));] # x=MissingVec(), y=MissingVec());]
gplt.guides = Gadfly.GuideElement[Gadfly.Guide.xlabel(d[:xguide]),
Gadfly.Guide.ylabel(d[:yguide]),
Gadfly.Guide.title(d[:title])]
gplt
end
# ---------------------------------------------------------------------------
function getLineGeom(d::KW)
st = d[:seriestype]
xbins, ybins = maketuple(d[:bins])
if st == :hexb
Gadfly.Geom.hexbin(xbincount = xbins, ybincount = ybins)
elseif st == :histogram2d
Gadfly.Geom.histogram2d(xbincount = xbins, ybincount = ybins)
elseif st == :histogram
Gadfly.Geom.histogram(bincount = xbins,
orientation = isvertical(d) ? :vertical : :horizontal,
position = d[:bar_position] == :stack ? :stack : :dodge)
elseif st == :path
Gadfly.Geom.path
elseif st in (:bar, :sticks)
Gadfly.Geom.bar
elseif st == :steppost
Gadfly.Geom.step
elseif st == :steppre
Gadfly.Geom.step(direction = :vh)
elseif st == :hline
Gadfly.Geom.hline
elseif st == :vline
Gadfly.Geom.vline
elseif st == :contour
Gadfly.Geom.contour(levels = d[:levels])
# elseif st == :shape
# Gadfly.Geom.polygon(fill = true, preserve_order = true)
else
nothing
end
end
function get_extra_theme_args(d::KW, k::Symbol)
# gracefully handles old Gadfly versions
extra_theme_args = KW()
try
extra_theme_args[:line_style] = Gadfly.get_stroke_vector(d[k])
catch err
if string(err) == "UndefVarError(:get_stroke_vector)"
Base.warn_once("Gadfly.get_stroke_vector failed... do you have an old version of Gadfly?")
else
rethrow()
end
end
extra_theme_args
end
function getGadflyLineTheme(d::KW)
st = d[:seriestype]
lc = convertColor(getColor(d[:linecolor]), d[:linealpha])
fc = convertColor(getColor(d[:fillcolor]), d[:fillalpha])
Gadfly.Theme(;
default_color = (st in (:histogram,:histogram2d,:hexbin,:bar,:sticks) ? fc : lc),
line_width = (st == :sticks ? 1 : d[:linewidth]) * Gadfly.px,
# line_style = Gadfly.get_stroke_vector(d[:linestyle]),
lowlight_color = x->RGB(fc), # fill/ribbon
lowlight_opacity = alpha(fc), # fill/ribbon
bar_highlight = RGB(lc), # bars
get_extra_theme_args(d, :linestyle)...
)
end
# add a line as a new layer
function addGadflyLine!(plt::Plot, numlayers::Int, d::KW, geoms...)
gplt = getGadflyContext(plt)
gfargs = vcat(geoms..., getGadflyLineTheme(d))
kwargs = KW()
st = d[:seriestype]
# add a fill?
if d[:fillrange] != nothing && st != :contour
fillmin, fillmax = map(makevec, maketuple(d[:fillrange]))
nmin, nmax = length(fillmin), length(fillmax)
kwargs[:ymin] = Float64[min(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(d[:y])]
kwargs[:ymax] = Float64[max(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(d[:y])]
push!(gfargs, Gadfly.Geom.ribbon)
end
if st in (:hline, :vline)
kwargs[st == :hline ? :yintercept : :xintercept] = d[:y]
else
if st == :sticks
w = 0.01 * mean(diff(d[:x]))
kwargs[:xmin] = d[:x] - w
kwargs[:xmax] = d[:x] + w
elseif st == :contour
kwargs[:z] = d[:z].surf
addGadflyContColorScale(plt, d[:linecolor])
end
kwargs[:x] = d[st == :histogram ? :y : :x]
kwargs[:y] = d[:y]
end
# # add the layer
Gadfly.layer(gfargs...; order=numlayers, kwargs...)
end
# ---------------------------------------------------------------------------
get_shape(sym::Symbol) = _shapes[sym]
get_shape(shape::Shape) = shape
# extract the underlying ShapeGeometry object(s)
getMarkerGeom(shapes::AVec) = gadflyshape(map(get_shape, shapes))
getMarkerGeom(other) = gadflyshape(get_shape(other))
# getMarkerGeom(shape::Shape) = gadflyshape(shape)
# getMarkerGeom(shape::Symbol) = gadflyshape(_shapes[shape])
# getMarkerGeom(shapes::AVec) = gadflyshape(map(gadflyshape, shapes)) # map(getMarkerGeom, shapes)
function getMarkerGeom(d::KW)
if d[:seriestype] == :shape
Gadfly.Geom.polygon(fill = true, preserve_order = true)
else
getMarkerGeom(d[:markershape])
end
end
function getGadflyMarkerTheme(d::KW, attr::KW)
c = getColor(d[:markercolor])
α = d[:markeralpha]
if α != nothing
c = RGBA(RGB(c), α)
end
ms = d[:markersize]
ms = if typeof(ms) <: AVec
warn("Gadfly doesn't support variable marker sizes... using the average: $(mean(ms))")
mean(ms) * Gadfly.px
else
ms * Gadfly.px
end
Gadfly.Theme(;
default_color = c,
default_point_size = ms,
discrete_highlight_color = c -> RGB(getColor(d[:markerstrokecolor])),
highlight_width = d[:markerstrokewidth] * Gadfly.px,
line_width = d[:markerstrokewidth] * Gadfly.px,
# get_extra_theme_args(d, :markerstrokestyle)...
)
end
function addGadflyContColorScale(plt::Plot{GadflyBackend}, c)
plt.attr[:colorbar] == :none && return
if !isa(c, ColorGradient)
c = default_gradient()
end
push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(c, p))))
end
function addGadflyMarker!(plt::Plot, numlayers::Int, d::KW, attr::KW, geoms...)
gfargs = vcat(geoms..., getGadflyMarkerTheme(d, attr), getMarkerGeom(d))
kwargs = KW()
# handle continuous color scales for the markers
zcolor = d[:marker_z]
if zcolor != nothing && typeof(zcolor) <: AVec
kwargs[:color] = zcolor
addGadflyContColorScale(plt, d[:markercolor])
end
Gadfly.layer(gfargs...; x = d[:x], y = d[:y], order=numlayers, kwargs...)
end
# ---------------------------------------------------------------------------
function addToGadflyLegend(plt::Plot, d::KW)
if plt.attr[:legend] != :none && d[:label] != ""
gplt = getGadflyContext(plt)
# add the legend if needed
if all(g -> !isa(g, Gadfly.Guide.ManualColorKey), gplt.guides)
unshift!(gplt.guides, Gadfly.Guide.manual_color_key("", AbstractString[], Color[]))
end
# now add the series to the legend
for guide in gplt.guides
if isa(guide, Gadfly.Guide.ManualColorKey)
# TODO: there's a BUG in gadfly if you pass in the same color more than once,
# since gadfly will call unique(colors), but doesn't also merge the rows that match
# Should ensure from this side that colors which are the same are merged together
c = getColor(d[d[:markershape] == :none ? :linecolor : :markercolor])
foundit = false
# extend the label if we found this color
for i in 1:length(guide.colors)
if RGB(c) == guide.colors[i]
guide.labels[i] *= ", " * d[:label]
foundit = true
end
end
# didn't find the color, so add a new entry into the legend
if !foundit
push!(guide.labels, d[:label])
push!(guide.colors, c)
end
end
end
end
end
getGadflySmoothing(smooth::Bool) = smooth ? [Gadfly.Geom.smooth(method=:lm)] : Any[]
getGadflySmoothing(smooth::Real) = [Gadfly.Geom.smooth(method=:loess, smoothing=float(smooth))]
function addGadflySeries!(plt::Plot, d::KW)
layers = Gadfly.Layer[]
gplt = getGadflyContext(plt)
# add a regression line?
# TODO: make more flexible
smooth = getGadflySmoothing(d[:smooth])
# lines
geom = getLineGeom(d)
if geom != nothing
prepend!(layers, addGadflyLine!(plt, length(gplt.layers), d, geom, smooth...))
smooth = Any[] # don't add a regression for markers too
end
# special handling for ohlc and scatter
st = d[:seriestype]
# if st == :ohlc
# error("Haven't re-implemented after refactoring")
if st in (:histogram2d, :hexbin) && (isa(d[:fillcolor], ColorGradient) || isa(d[:fillcolor], ColorFunction))
push!(gplt.scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(d[:fillcolor], p))))
elseif st == :scatter && d[:markershape] == :none
d[:markershape] = :circle
end
# markers
if d[:markershape] != :none || st == :shape
prepend!(layers, addGadflyMarker!(plt, length(gplt.layers), d, plt.attr, smooth...))
end
st in (:histogram2d, :hexbin, :contour) || addToGadflyLegend(plt, d)
# now save the layers that apply to this series
d[:gadflylayers] = layers
prepend!(gplt.layers, layers)
end
# ---------------------------------------------------------------------------
# NOTE: I'm leaving this here and commented out just in case I want to implement again... it was hacky code to create multi-colored line segments
# # colorgroup
# z = d[:z]
# # handle line segments of different colors
# cscheme = d[:linecolor]
# if isa(cscheme, ColorVector)
# # create a color scale, and set the color group to the index of the color
# push!(gplt.scales, Gadfly.Scale.color_discrete_manual(cscheme.v...))
# # this is super weird, but... oh well... for some reason this creates n separate line segments...
# # 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]
# d[:x], d[:y] = map(createSegments, (d[:x], d[:y]))
# colorgroup = [(:linecolor, cs), (:group, grp)]
# ---------------------------------------------------------------------------
function addGadflyTicksGuide(gplt, ticks, isx::Bool)
ticks == :auto && return
# remove the ticks?
if ticks in (:none, false, nothing)
return addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
end
ttype = ticksType(ticks)
# just the values... put ticks here, but use standard labels
if ttype == :ticks
gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks
replaceType(gplt.guides, gtype(ticks = collect(ticks)))
# set the ticks and the labels
# Note: this is pretty convoluted, but I think it works. We set the ticks using Gadfly.Guide,
# and then set the label function (wraps a dict lookup) through a continuous Gadfly.Scale.
elseif ttype == :ticks_and_labels
gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks
replaceType(gplt.guides, gtype(ticks = collect(ticks[1])))
# # TODO add xtick_label function (given tick, return label??)
# # Scale.x_discrete(; labels=nothing, levels=nothing, order=nothing)
# filterGadflyScale(gplt, isx)
# gfunc = isx ? Gadfly.Scale.x_discrete : Gadfly.Scale.y_discrete
# labelmap = Dict(zip(ticks...))
# labelfunc = val -> labelmap[val]
# push!(gplt.scales, gfunc(levels = collect(ticks[1]), labels = labelfunc))
filterGadflyScale(gplt, isx)
gfunc = isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous
labelmap = Dict(zip(ticks...))
labelfunc = val -> labelmap[val]
push!(gplt.scales, gfunc(labels = labelfunc))
else
error("Invalid input for $(isx ? "xticks" : "yticks"): ", ticks)
end
end
continuousAndSameAxis(scale, isx::Bool) = isa(scale, Gadfly.Scale.ContinuousScale) && scale.vars[1] == (isx ? :x : :y)
filterGadflyScale(gplt, isx::Bool) = filter!(scale -> !continuousAndSameAxis(scale, isx), gplt.scales)
function getGadflyScaleFunction(d::KW, isx::Bool)
scalekey = isx ? :xscale : :yscale
hasScaleKey = haskey(d, scalekey)
if hasScaleKey
scale = d[scalekey]
scale == :ln && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey, log
scale == :log2 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2, hasScaleKey, log2
scale == :log10 && return isx ? Gadfly.Scale.x_log10 : Gadfly.Scale.y_log10, hasScaleKey, log10
scale == :asinh && return isx ? Gadfly.Scale.x_asinh : Gadfly.Scale.y_asinh, hasScaleKey, asinh
scale == :sqrt && return isx ? Gadfly.Scale.x_sqrt : Gadfly.Scale.y_sqrt, hasScaleKey, sqrt
end
isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous, hasScaleKey, identity
end
function addGadflyLimitsScale(gplt, d::KW, isx::Bool)
gfunc, hasScaleKey, func = getGadflyScaleFunction(d, isx)
# do we want to add min/max limits for the axis?
limsym = isx ? :xlims : :ylims
limargs = Any[]
# map :auto to nothing, otherwise add to limargs
lims = get(d, limsym, :auto)
if lims == :auto
lims = nothing
else
if limsType(lims) == :limits
push!(limargs, (:minvalue, min(lims...)))
push!(limargs, (:maxvalue, max(lims...)))
else
error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims)
end
end
# replace any current scales with this one
if hasScaleKey || !isempty(limargs)
filterGadflyScale(gplt, isx)
push!(gplt.scales, gfunc(; limargs...))
end
lims, func
end
function updateGadflyAxisFlips(gplt, d::KW, xlims, ylims, xfunc, yfunc)
if isa(gplt.coord, Gadfly.Coord.Cartesian)
gplt.coord = Gadfly.Coord.cartesian(
gplt.coord.xvars,
gplt.coord.yvars;
xmin = xlims == nothing ? gplt.coord.xmin : xfunc(minimum(xlims)),
xmax = xlims == nothing ? gplt.coord.xmax : xfunc(maximum(xlims)),
ymin = ylims == nothing ? gplt.coord.ymin : yfunc(minimum(ylims)),
ymax = ylims == nothing ? gplt.coord.ymax : yfunc(maximum(ylims)),
xflip = get(d, :xflip, gplt.coord.xflip),
yflip = get(d, :yflip, gplt.coord.yflip),
fixed = gplt.coord.fixed,
aspect_ratio = gplt.coord.aspect_ratio,
raster = gplt.coord.raster
)
else
gplt.coord = Gadfly.Coord.Cartesian(
xflip = get(d, :xflip, false),
yflip = get(d, :yflip, false)
)
end
end
function findGuideAndSet(gplt, t::DataType, args...; kw...)
for (i,guide) in enumerate(gplt.guides)
if isa(guide, t)
gplt.guides[i] = t(args...; kw...)
end
end
end
function updateGadflyGuides(plt::Plot, d::KW)
gplt = getGadflyContext(plt)
haskey(d, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, string(d[:title]))
haskey(d, :xguide) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, string(d[:xguide]))
haskey(d, :yguide) && findGuideAndSet(gplt, Gadfly.Guide.ylabel, string(d[:yguide]))
xlims, xfunc = addGadflyLimitsScale(gplt, d, true)
ylims, yfunc = addGadflyLimitsScale(gplt, d, false)
ticks = get(d, :xticks, :auto)
if ticks == :none
_remove_axis(plt, true)
else
addGadflyTicksGuide(gplt, ticks, true)
end
ticks = get(d, :yticks, :auto)
if ticks == :none
_remove_axis(plt, false)
else
addGadflyTicksGuide(gplt, ticks, false)
end
updateGadflyAxisFlips(gplt, d, xlims, ylims, xfunc, yfunc)
end
function updateGadflyPlotTheme(plt::Plot, d::KW)
kwargs = KW()
# colors
insidecolor, gridcolor, textcolor, guidecolor, legendcolor =
map(s -> getColor(d[s]), (
:background_color_inside,
:foreground_color_grid,
:foreground_color_text,
:foreground_color_guide,
:foreground_color_legend
))
# # hide the legend?
leg = d[d[:legend] == :none ? :colorbar : :legend]
if leg != :best
kwargs[:key_position] = leg == :inside ? :right : leg
end
if !get(d, :grid, true)
kwargs[:grid_color] = gridcolor
end
# fonts
tfont, gfont, lfont = d[:tickfont], d[:guidefont], d[:legendfont]
getGadflyContext(plt).theme = Gadfly.Theme(;
background_color = insidecolor,
minor_label_color = textcolor,
minor_label_font = tfont.family,
minor_label_font_size = tfont.pointsize * Gadfly.pt,
major_label_color = guidecolor,
major_label_font = gfont.family,
major_label_font_size = gfont.pointsize * Gadfly.pt,
key_title_color = guidecolor,
key_title_font = gfont.family,
key_title_font_size = gfont.pointsize * Gadfly.pt,
key_label_color = legendcolor,
key_label_font = lfont.family,
key_label_font_size = lfont.pointsize * Gadfly.pt,
plot_padding = 1 * Gadfly.mm,
kwargs...
)
end
# ----------------------------------------------------------------
function createGadflyAnnotationObject(x, y, val::AbstractString)
Gadfly.Guide.annotation(Compose.compose(
Compose.context(),
Compose.text(x, y, val)
))
end
function createGadflyAnnotationObject(x, y, txt::PlotText)
halign = (txt.font.halign == :hcenter ? Compose.hcenter : (txt.font.halign == :left ? Compose.hleft : Compose.hright))
valign = (txt.font.valign == :vcenter ? Compose.vcenter : (txt.font.valign == :top ? Compose.vtop : Compose.vbottom))
rotations = (txt.font.rotation == 0.0 ? [] : [Compose.Rotation(txt.font.rotation, Compose.Point(Compose.x_measure(x), Compose.y_measure(y)))])
Gadfly.Guide.annotation(Compose.compose(
Compose.context(),
Compose.text(x, y, txt.str, halign, valign, rotations...),
Compose.font(string(txt.font.family)),
Compose.fontsize(txt.font.pointsize * Gadfly.pt),
Compose.stroke(txt.font.color),
Compose.fill(txt.font.color)
))
end
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
end
# ---------------------------------------------------------------------------
# create a blank Gadfly.Plot object
# function _create_plot(pkg::GadflyBackend, d::KW)
# gplt = createGadflyPlotObject(d)
# Plot(gplt, pkg, 0, d, KW[])
# end
function _create_backend_figure(plt::Plot{GadflyBackend})
createGadflyPlotObject(plt.attr)
end
# plot one data series
# function _series_added(::GadflyBackend, plt::Plot, d::KW)
function _series_added(plt::Plot{GadflyBackend}, series::Series)
# first clear out the temporary layer
gplt = getGadflyContext(plt)
if gplt.layers[1].geom.tag == :remove
gplt.layers = gplt.layers[2:end]
end
addGadflySeries!(plt, series.d)
# push!(plt.seriesargs, d)
# plt
end
function _update_plot_object(plt::Plot{GadflyBackend}, d::KW)
updateGadflyGuides(plt, d)
updateGadflyPlotTheme(plt, d)
end
# ----------------------------------------------------------------
# accessors for x/y data
# TODO: need to save all the layer indices which apply to this series
function getGadflyMappings(plt::Plot, i::Integer)
@assert i > 0 && i <= plt.n
mappings = [l.mapping for l in plt.seriesargs[i][:gadflylayers]]
end
function getxy(plt::Plot{GadflyBackend}, i::Integer)
mapping = getGadflyMappings(plt, i)[1]
mapping[:x], mapping[:y]
end
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
plt
end
# ----------------------------------------------------------------
# # create the underlying object (each backend will do this differently)
# function _create_subplot(subplt::Subplot{GadflyBackend}, isbefore::Bool)
# isbefore && return false # wait until after plotting to create the subplots
# subplt.o = nothing
# true
# end
function _remove_axis(plt::Plot{GadflyBackend}, isx::Bool)
gplt = getGadflyContext(plt)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "")
end
function _expand_limits(lims, plt::Plot{GadflyBackend}, isx::Bool)
for l in getGadflyContext(plt).layers
_expand_limits(lims, l.mapping[isx ? :x : :y])
end
end
# ----------------------------------------------------------------
getGadflyContext(plt::Plot{GadflyBackend}) = plt.o
# getGadflyContext(subplt::Subplot{GadflyBackend}) = buildGadflySubplotContext(subplt)
# # create my Compose.Context grid by hstacking and vstacking the Gadfly.Plot objects
# function buildGadflySubplotContext(subplt::Subplot)
# rows = Any[]
# row = Any[]
# for (i,(r,c)) in enumerate(subplt.layout)
#
# # add the Plot object to the row
# push!(row, getGadflyContext(subplt.plts[i]))
#
# # add the row
# if c == ncols(subplt.layout, r)
# push!(rows, Gadfly.hstack(row...))
# row = Any[]
# end
# end
#
# # stack the rows
# Gadfly.vstack(rows...)
# end
setGadflyDisplaySize(w,h) = Compose.set_default_graphic_size(w * Compose.px, h * Compose.px)
setGadflyDisplaySize(plt::Plot) = setGadflyDisplaySize(plt.attr[:size]...)
# setGadflyDisplaySize(subplt::Subplot) = setGadflyDisplaySize(getattr(subplt, 1)[:size]...)
# -------------------------------------------------------------------------
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)
end
getGadflyWriteFunc(::MIME"image/png") = Gadfly.PNG
getGadflyWriteFunc(::MIME"image/svg+xml") = Gadfly.SVG
# getGadflyWriteFunc(::MIME"text/html") = Gadfly.SVGJS
getGadflyWriteFunc(::MIME"application/pdf") = Gadfly.PDF
getGadflyWriteFunc(::MIME"application/postscript") = Gadfly.PS
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.show(io::IO, ::$mime, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend}
func = getGadflyWriteFunc($mime())
doshow(io, func, plt)
end
end
function Base.display(::PlotsDisplay, plt::Plot{GadflyBackend})
setGadflyDisplaySize(plt.attr[:size]...)
display(plt.o)
end
# function Base.display(::PlotsDisplay, subplt::Subplot{GadflyBackend})
# setGadflyDisplaySize(getattr(subplt,1)[:size]...)
# ctx = buildGadflySubplotContext(subplt)
#
# # taken from Gadfly since I couldn't figure out how to do it directly
#
# filename = string(Gadfly.tempname(), ".html")
# output = open(filename, "w")
#
# plot_output = IOBuffer()
# Gadfly.draw(Gadfly.SVGJS(plot_output, Compose.default_graphic_width,
# Compose.default_graphic_height, false), ctx)
# plotsvg = takebuf_string(plot_output)
#
# write(output,
# """
# <!DOCTYPE html>
# <html>
# <head>
# <title>Gadfly Plot</title>
# <meta charset="utf-8">
# </head>
# <body>
# <script charset="utf-8">
# $(readall(Compose.snapsvgjs))
# </script>
# <script charset="utf-8">
# $(readall(Gadfly.gadflyjs))
# </script>
# $(plotsvg)
# </body>
# </html>
# """)
# close(output)
# Gadfly.open_file(filename)
# end
@@ -1,8 +1,9 @@
# Geometry which displays arbitrary shapes at given (x, y) positions.
immutable ShapeGeometry <: Gadfly.GeometryElement
vertices::AbstractVector{@compat(Tuple{Float64,Float64})}
# note: vertices is a list of shapes
struct ShapeGeometry <: Gadfly.GeometryElement
vertices::AbstractVector #{Tuple{Float64,Float64}}
tag::Symbol
function ShapeGeometry(shape; tag::Symbol=Gadfly.Geom.empty_tag)
@@ -66,24 +67,27 @@ function Gadfly.render(geom::ShapeGeometry, theme::Gadfly.Theme, aes::Gadfly.Aes
end
function gadflyshape(sv::Shape)
ShapeGeometry(sv.vertices)
ShapeGeometry(Any[vertices(sv)])
end
function gadflyshape(sv::AVec{Shape})
ShapeGeometry(Any[vertices(s) for s in sv])
end
# create a Compose context given a ShapeGeometry and the xs/ys/sizes
function make_polygon(geom::ShapeGeometry, xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
n = max(length(xs), length(ys), length(rs))
T = @compat(Tuple{Compose.Measure, Compose.Measure})
T = Tuple{Compose.Measure, Compose.Measure}
polys = Array(Vector{T}, n)
for i in 1:n
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 geom.vertices]
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in _cycle(geom.vertices, i)]
end
Gadfly.polygon(polys, geom.tag)
end
# ---------------------------------------------------------------------------------------------
+186
View File
@@ -0,0 +1,186 @@
# https://github.com/JuliaGraphics/Immerse.jl
supported_attrs(::ImmerseBackend) = supported_attrs(GadflyBackend())
supported_types(::ImmerseBackend) = supported_types(GadflyBackend())
supported_styles(::ImmerseBackend) = supported_styles(GadflyBackend())
supported_markers(::ImmerseBackend) = supported_markers(GadflyBackend())
supported_scales(::ImmerseBackend) = supported_scales(GadflyBackend())
is_subplot_supported(::ImmerseBackend) = true
# --------------------------------------------------------------------------------------
function _initialize_backend(::ImmerseBackend; kw...)
@eval begin
import Immerse, Gadfly, Compose, Gtk
export Immerse, Gadfly, Compose, Gtk
include(joinpath(dirname(@__FILE__), "gadfly_shapes.jl"))
end
end
function createImmerseFigure(d::KW)
w,h = d[:size]
figidx = Immerse.figure(; name = d[:window_title], width = w, height = h)
Immerse.Figure(figidx)
end
# ----------------------------------------------------------------
# create a blank Gadfly.Plot object
# function _create_plot(pkg::ImmerseBackend, d::KW)
# # create the underlying Gadfly.Plot object
# gplt = createGadflyPlotObject(d)
#
# # save both the Immerse.Figure and the Gadfly.Plot
# Plot((nothing,gplt), pkg, 0, d, KW[])
# end
function _create_backend_figure(plt::Plot{ImmerseBackend})
(nothing, createGadflyPlotObject(plt.attr))
end
# # plot one data series
# function _series_added(::ImmerseBackend, plt::Plot, d::KW)
# addGadflySeries!(plt, d)
# push!(plt.seriesargs, d)
# plt
# end
function _series_added(plt::Plot{ImmerseBackend}, series::Series)
addGadflySeries!(plt, series.d)
end
function _update_plot_object(plt::Plot{ImmerseBackend}, d::KW)
updateGadflyGuides(plt, d)
updateGadflyPlotTheme(plt, d)
end
# ----------------------------------------------------------------
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
end
# ----------------------------------------------------------------
# accessors for x/y data
function getxy(plt::Plot{ImmerseBackend}, i::Integer)
mapping = getGadflyMappings(plt, i)[1]
mapping[:x], mapping[:y]
end
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
plt
end
# ----------------------------------------------------------------
# function _create_subplot(subplt::Subplot{ImmerseBackend}, isbefore::Bool)
# return false
# # isbefore && return false
# end
#
# function showSubplotObject(subplt::Subplot{ImmerseBackend})
# # create the Gtk window with vertical box vsep
# d = getattr(subplt,1)
# w,h = d[:size]
# vsep = Gtk.GtkBoxLeaf(:v)
# win = Gtk.GtkWindowLeaf(vsep, d[:window_title], w, h)
#
# figindices = []
# row = Gtk.GtkBoxLeaf(:h)
# push!(vsep, row)
# for (i,(r,c)) in enumerate(subplt.layout)
# plt = subplt.plts[i]
#
# # get the components... box is the main plot GtkBox, and canvas is the GtkCanvas where it's plotted
# box, toolbar, canvas = Immerse.createPlotGuiComponents()
#
# # add the plot's box to the row
# push!(row, box)
#
# # create the figure and store the index returned for destruction later
# figidx = Immerse.figure(canvas)
# push!(figindices, figidx)
#
# fig = Immerse.figure(figidx)
# plt.o = (fig, plt.o[2])
#
# # add the row
# if c == ncols(subplt.layout, r)
# row = Gtk.GtkBoxLeaf(:h)
# push!(vsep, row)
# end
#
# end
#
# # destructor... clean up plots
# Gtk.on_signal_destroy((x...) -> ([Immerse.dropfig(Immerse._display,i) for i in figindices]; subplt.o = nothing), win)
#
# subplt.o = win
# true
# end
function _remove_axis(plt::Plot{ImmerseBackend}, isx::Bool)
gplt = getGadflyContext(plt)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "")
end
function _expand_limits(lims, plt::Plot{ImmerseBackend}, isx::Bool)
for l in getGadflyContext(plt).layers
_expand_limits(lims, l.mapping[isx ? :x : :y])
end
end
# ----------------------------------------------------------------
getGadflyContext(plt::Plot{ImmerseBackend}) = plt.o[2]
# getGadflyContext(subplt::Subplot{ImmerseBackend}) = buildGadflySubplotContext(subplt)
function Base.display(::PlotsDisplay, plt::Plot{ImmerseBackend})
fig, gplt = plt.o
if fig == nothing
fig = createImmerseFigure(plt.attr)
Gtk.on_signal_destroy((x...) -> (Immerse.dropfig(Immerse._display, fig.figno); plt.o = (nothing,gplt)), fig.canvas)
plt.o = (fig, gplt)
end
Immerse.figure(fig.figno; displayfig = false)
display(gplt)
end
# function Base.display(::PlotsDisplay, subplt::Subplot{ImmerseBackend})
#
# # if we haven't created the window yet, do it
# if subplt.o == nothing
# showSubplotObject(subplt)
# end
#
# # display the plots by creating a fresh Immerse.Figure object from the GtkCanvas and Gadfly.Plot
# for plt in subplt.plts
# fig, gplt = plt.o
# Immerse.figure(fig.figno; displayfig = false)
# display(gplt)
# end
#
# # o is the window... show it
# showall(subplt.o)
# end
@@ -1,7 +1,35 @@
# https://github.com/tbreloff/Qwt.jl
function _initialize_backend(::QwtPackage; kw...)
supported_attrs(::QwtBackend) = merge_with_base_supported([
:annotations,
:linecolor,
:fillrange,
:fillcolor,
:label,
:legend,
:seriescolor, :seriesalpha,
:linestyle,
:linewidth,
:markershape,
:markercolor,
:markersize,
:bins,
:pos,
:title,
:window_title,
:guide, :lims, :ticks, :scale,
])
supported_types(::QwtBackend) = [:path, :scatter, :hexbin, :bar]
supported_markers(::QwtBackend) = [:none, :auto, :rect, :circle, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :star8, :hexagon]
supported_scales(::QwtBackend) = [:identity, :log10]
is_subplot_supported(::QwtBackend) = true
# --------------------------------------------------------------------------------------
function _initialize_backend(::QwtBackend; kw...)
@eval begin
warn("Qwt is no longer supported... many features will likely be broken.")
import Qwt
@@ -11,8 +39,8 @@ end
# -------------------------------
@compat const _qwtAliases = Dict(
:nbins => :heatmap_n,
const _qwtAliases = KW(
:bins => :heatmap_n,
:fillrange => :fillto,
:linewidth => :width,
:markershape => :marker,
@@ -24,7 +52,7 @@ end
:star8 => :star2,
)
function fixcolors(d::Dict)
function fixcolors(d::KW)
for (k,v) in d
if typeof(v) <: ColorScheme
d[k] = getColor(v)
@@ -38,31 +66,31 @@ function replaceQwtAliases(d, s)
end
end
function adjustQwtKeywords(plt::Plot{QwtPackage}, iscreating::Bool; kw...)
d = Dict(kw)
lt = d[:linetype]
if lt == :scatter
d[:linetype] = :none
function adjustQwtKeywords(plt::Plot{QwtBackend}, iscreating::Bool; kw...)
d = KW(kw)
st = d[:seriestype]
if st == :scatter
d[:seriestype] = :none
if d[:markershape] == :none
d[:markershape] = :ellipse
d[:markershape] = :circle
end
elseif lt in (:hline, :vline)
elseif st in (:hline, :vline)
addLineMarker(plt, d)
d[:linetype] = :none
d[:markershape] = :ellipse
d[:seriestype] = :none
d[:markershape] = :circle
d[:markersize] = 1
if lt == :vline
if st == :vline
d[:x], d[:y] = d[:y], d[:x]
end
elseif !iscreating && lt == :bar
elseif !iscreating && st == :bar
d = barHack(; kw...)
elseif !iscreating && lt == :hist
elseif !iscreating && st == :histogram
d = barHack(; histogramHack(; kw...)...)
end
replaceQwtAliases(d, :linetype)
replaceQwtAliases(d, :seriestype)
replaceQwtAliases(d, :markershape)
for k in keys(d)
@@ -73,38 +101,39 @@ function adjustQwtKeywords(plt::Plot{QwtPackage}, iscreating::Bool; kw...)
d[:x] = collect(d[:x])
d[:y] = collect(d[:y])
d
end
function _create_plot(pkg::QwtPackage; kw...)
d = Dict(kw)
fixcolors(d)
dumpdict(d,"\n\n!!! plot")
o = Qwt.plot(zeros(0,0); d..., show=false)
plt = Plot(o, pkg, 0, d, Dict[])
plt
# function _create_plot(pkg::QwtBackend, d::KW)
function _create_backend_figure(plt::Plot{QwtBackend})
fixcolors(plt.attr)
dumpdict(plt.attr,"\n\n!!! plot")
o = Qwt.plot(zeros(0,0); plt.attr..., show=false)
# plt = Plot(o, pkg, 0, d, KW[])
# plt
end
function _add_series(::QwtPackage, plt::Plot; kw...)
d = adjustQwtKeywords(plt, false; kw...)
# function _series_added(::QwtBackend, plt::Plot, d::KW)
function _series_added(plt::Plot{QwtBackend}, series::Series)
d = adjustQwtKeywords(plt, false; series.d...)
fixcolors(d)
dumpdict(d,"\n\n!!! plot!")
Qwt.oplot(plt.o; d...)
push!(plt.seriesargs, d)
plt
# push!(plt.seriesargs, d)
# plt
end
# ----------------------------------------------------------------
function updateLimsAndTicks(plt::Plot{QwtPackage}, d::Dict, isx::Bool)
function updateLimsAndTicks(plt::Plot{QwtBackend}, d::KW, isx::Bool)
lims = get(d, isx ? :xlims : :ylims, nothing)
ticks = get(d, isx ? :xticks : :yticks, nothing)
w = plt.o.widget
axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft]
if typeof(lims) <: @compat(Union{Tuple,AVec}) && length(lims) == 2
axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft]
if typeof(lims) <: Union{Tuple,AVec} && length(lims) == 2
if isx
plt.o.autoscale_x = false
else
@@ -132,21 +161,21 @@ function updateLimsAndTicks(plt::Plot{QwtPackage}, d::Dict, isx::Bool)
# scaletype == :log && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(e))
# scaletype == :log2 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(2))
scaletype == :log10 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLog10ScaleEngine())
scaletype in supportedScales() || warn("Unsupported scale type: ", scaletype)
scaletype in supported_scales() || warn("Unsupported scale type: ", scaletype)
end
end
function _update_plot(plt::Plot{QwtPackage}, d::Dict)
function _update_plot_object(plt::Plot{QwtBackend}, d::KW)
haskey(d, :title) && Qwt.title(plt.o, d[:title])
haskey(d, :xlabel) && Qwt.xlabel(plt.o, d[:xlabel])
haskey(d, :ylabel) && Qwt.ylabel(plt.o, d[:ylabel])
haskey(d, :xguide) && Qwt.xlabel(plt.o, d[:xguide])
haskey(d, :yguide) && Qwt.ylabel(plt.o, d[:yguide])
updateLimsAndTicks(plt, d, true)
updateLimsAndTicks(plt, d, false)
end
function _update_plot_pos_size(plt::PlottingObject{QwtPackage}, d::Dict)
function _update_plot_pos_size(plt::AbstractPlot{QwtBackend}, d::KW)
haskey(d, :size) && Qwt.resizewidget(plt.o, d[:size]...)
haskey(d, :pos) && Qwt.movewidget(plt.o, d[:pos]...)
end
@@ -155,10 +184,10 @@ end
# ----------------------------------------------------------------
# curve.setPen(Qt.QPen(Qt.QColor(color), linewidth, self.getLineStyle(linestyle)))
function addLineMarker(plt::Plot{QwtPackage}, d::Dict)
function addLineMarker(plt::Plot{QwtBackend}, d::KW)
for yi in d[:y]
marker = Qwt.QWT.QwtPlotMarker()
ishorizontal = (d[:linetype] == :hline)
ishorizontal = (d[:seriestype] == :hline)
marker[:setLineStyle](ishorizontal ? 1 : 2)
marker[ishorizontal ? :setYValue : :setXValue](yi)
qcolor = Qwt.convertRGBToQColor(getColor(d[:linecolor]))
@@ -182,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{QwtPackage}, 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
@@ -199,12 +228,12 @@ end
# accessors for x/y data
function Base.getindex(plt::Plot{QwtPackage}, i::Int)
function getxy(plt::Plot{QwtBackend}, i::Int)
series = plt.o.lines[i]
series.x, series.y
end
function Base.setindex!(plt::Plot{QwtPackage}, xy::Tuple, 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
@@ -213,70 +242,67 @@ end
# -------------------------------
# savepng(::QwtPackage, plt::PlottingObject, fn::@compat(AbstractString), args...) = Qwt.savepng(plt.o, fn)
# -------------------------------
# create the underlying object (each backend will do this differently)
function _create_subplot(subplt::Subplot{QwtPackage}, isbefore::Bool)
isbefore && return false
i = 0
rows = Any[]
row = Any[]
for (i,(r,c)) in enumerate(subplt.layout)
push!(row, subplt.plts[i].o)
if c == ncols(subplt.layout, r)
push!(rows, Qwt.hsplitter(row...))
row = Any[]
end
end
# for rowcnt in subplt.layout.rowcounts
# push!(rows, Qwt.hsplitter([plt.o for plt in subplt.plts[(1:rowcnt) + i]]...))
# i += rowcnt
# end
subplt.o = Qwt.vsplitter(rows...)
# Qwt.resizewidget(subplt.o, getplotargs(subplt,1)[:size]...)
# Qwt.moveToLastScreen(subplt.o) # hack so it goes to my center monitor... sorry
true
end
# # create the underlying object (each backend will do this differently)
# function _create_subplot(subplt::Subplot{QwtBackend}, isbefore::Bool)
# isbefore && return false
# i = 0
# rows = Any[]
# row = Any[]
# for (i,(r,c)) in enumerate(subplt.layout)
# push!(row, subplt.plts[i].o)
# if c == ncols(subplt.layout, r)
# push!(rows, Qwt.hsplitter(row...))
# row = Any[]
# end
# end
# # for rowcnt in subplt.layout.rowcounts
# # push!(rows, Qwt.hsplitter([plt.o for plt in subplt.plts[(1:rowcnt) + i]]...))
# # i += rowcnt
# # end
# subplt.o = Qwt.vsplitter(rows...)
# # Qwt.resizewidget(subplt.o, getattr(subplt,1)[:size]...)
# # Qwt.moveToLastScreen(subplt.o) # hack so it goes to my center monitor... sorry
# true
# end
function _expand_limits(lims, plt::Plot{QwtPackage}, isx::Bool)
function _expand_limits(lims, plt::Plot{QwtBackend}, isx::Bool)
for series in plt.o.lines
_expand_limits(lims, isx ? series.x : series.y)
end
end
function _remove_axis(plt::Plot{QwtPackage}, isx::Bool)
function _remove_axis(plt::Plot{QwtBackend}, isx::Bool)
end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::Plot{QwtPackage})
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{QwtPackage})
for plt in subplt.plts
Qwt.refresh(plt.o)
end
Qwt.savepng(subplt.o, "/tmp/dfskjdhfkh.png")
write(io, readall("/tmp/dfskjdhfkh.png"))
end
# function Base.show(io::IO, ::MIME"image/png", subplt::Subplot{QwtBackend})
# for plt in subplt.plts
# Qwt.refresh(plt.o)
# end
# Qwt.savepng(subplt.o, "/tmp/dfskjdhfkh.png")
# write(io, readall("/tmp/dfskjdhfkh.png"))
# end
function Base.display(::PlotsDisplay, plt::Plot{QwtPackage})
function Base.display(::PlotsDisplay, plt::Plot{QwtBackend})
Qwt.refresh(plt.o)
Qwt.showwidget(plt.o)
end
function Base.display(::PlotsDisplay, subplt::Subplot{QwtPackage})
for plt in subplt.plts
Qwt.refresh(plt.o)
end
Qwt.showwidget(subplt.o)
end
# function Base.display(::PlotsDisplay, subplt::Subplot{QwtBackend})
# for plt in subplt.plts
# Qwt.refresh(plt.o)
# end
# Qwt.showwidget(subplt.o)
# end
@@ -3,7 +3,35 @@
# credit goes to https://github.com/jverzani for contributing to the first draft of this backend implementation
function _initialize_backend(::WinstonPackage; kw...)
supported_attrs(::WinstonBackend) = merge_with_base_supported([
:annotations,
:linecolor,
:fillrange,
:fillcolor,
:label,
:legend,
:seriescolor, :seriesalpha,
:linestyle,
:linewidth,
:markershape,
:markercolor,
:markersize,
:bins,
:title,
:window_title,
:guide, :lims, :scale,
])
supported_types(::WinstonBackend) = [:path, :scatter, :bar]
supported_styles(::WinstonBackend) = [:auto, :solid, :dash, :dot, :dashdot]
supported_markers(::WinstonBackend) = [:none, :auto, :rect, :circle, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5]
supported_scales(::WinstonBackend) = [:identity, :log10]
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.")
@@ -16,15 +44,15 @@ end
## dictionaries for conversion of Plots.jl names to Winston ones.
@compat const winston_linestyle = Dict(:solid=>"solid",
const winston_linestyle = KW(:solid=>"solid",
:dash=>"dash",
:dot=>"dotted",
:dashdot=>"dotdashed"
)
@compat const winston_marker = Dict(:none=>".",
const winston_marker = KW(:none=>".",
:rect => "square",
:ellipse=>"circle",
:circle=>"circle",
:diamond=>"diamond",
:utriangle=>"triangle",
:dtriangle=>"down-triangle",
@@ -33,23 +61,23 @@ end
:star5 => "asterisk"
)
function _before_add_series(plt::Plot{WinstonPackage})
function _before_update(plt::Plot{WinstonBackend})
Winston.ghf(plt.o)
end
# ---------------------------------------------------------------------------
function _create_plot(pkg::WinstonPackage; kw...)
d = Dict(kw)
wplt = Winston.FramedPlot(title = d[:title], xlabel = d[:xlabel], ylabel = d[:ylabel])
Plot(wplt, pkg, 0, d, Dict[])
function _create_backend_figure(plt::Plot{WinstonBackend})
Winston.FramedPlot(
title = plt.attr[:title],
xlabel = plt.attr[:xguide],
ylabel = plt.attr[:yguide]
)
end
copy_remove(d::Dict, s::Symbol) = delete!(copy(d), s)
copy_remove(d::KW, s::Symbol) = delete!(copy(d), s)
function addRegressionLineWinston(d::Dict, wplt)
function addRegressionLineWinston(d::KW, wplt)
xs, ys = regressionXY(d[:x], d[:y])
Winston.add(wplt, Winston.Curve(xs, ys, kind="dotted"))
end
@@ -64,18 +92,17 @@ function getWinstonItems(plt::Plot)
window, canvas, wplt
end
function _add_series(::WinstonPackage, plt::Plot; kw...)
d = Dict(kw)
function _series_added(plt::Plot{WinstonBackend}, series::Series)
d = series.d
window, canvas, wplt = getWinstonItems(plt)
# until we call it normally, do the hack
if d[:linetype] == :bar
if d[:seriestype] == :bar
d = barHack(;d...)
end
e = Dict()
e = KW()
e[:color] = getColor(d[:linecolor])
e[:linewidth] = d[:linewidth]
e[:kind] = winston_linestyle[d[:linestyle]]
@@ -88,11 +115,11 @@ function _add_series(::WinstonPackage, plt::Plot; kw...)
## lintype :path, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hexbin, :hist, :bar
if d[:linetype] == :none
## lintype :path, :step, :stepinverted, :sticks, :dots, :none, :histogram2d, :hexbin, :histogram, :bar
if d[:seriestype] == :none
Winston.add(wplt, Winston.Points(d[:x], d[:y]; copy_remove(e, :kind)..., color=getColor(d[:markercolor])))
elseif d[:linetype] == :path
elseif d[:seriestype] == :path
x, y = d[:x], d[:y]
Winston.add(wplt, Winston.Curve(x, y; e...))
@@ -106,38 +133,38 @@ function _add_series(::WinstonPackage, plt::Plot; kw...)
Winston.add(wplt, Winston.FillBetween(x, y, x, y2, fillcolor=getColor(d[:fillcolor])))
end
elseif d[:linetype] == :scatter
elseif d[:seriestype] == :scatter
if d[:markershape] == :none
d[:markershape] = :ellipse
d[:markershape] = :circle
end
# elseif d[:linetype] == :step
# elseif d[:seriestype] == :step
# fn = Winston.XXX
# elseif d[:linetype] == :stepinverted
# elseif d[:seriestype] == :stepinverted
# fn = Winston.XXX
elseif d[:linetype] == :sticks
elseif d[:seriestype] == :sticks
Winston.add(wplt, Winston.Stems(d[:x], d[:y]; e...))
# elseif d[:linetype] == :dots
# elseif d[:seriestype] == :dots
# fn = Winston.XXX
# elseif d[:linetype] == :heatmap
# elseif d[:seriestype] == :histogram2d
# fn = Winston.XXX
# elseif d[:linetype] == :hexbin
# elseif d[:seriestype] == :hexbin
# fn = Winston.XXX
elseif d[:linetype] == :hist
hst = hist(d[:y], d[:nbins])
Winston.add(wplt, Winston.Histogram(hst...; copy_remove(e, :nbins)...))
elseif d[:seriestype] == :histogram
hst = hist(d[:y], d[:bins])
Winston.add(wplt, Winston.Histogram(hst...; copy_remove(e, :bins)...))
# elseif d[:linetype] == :bar
# elseif d[:seriestype] == :bar
# # fn = Winston.XXX
else
error("linetype $(d[:linetype]) not supported by Winston.")
error("seriestype $(d[:seriestype]) not supported by Winston.")
end
@@ -149,25 +176,25 @@ function _add_series(::WinstonPackage, plt::Plot; kw...)
# optionally add a regression line
d[:smooth] && d[:linetype] != :hist && addRegressionLineWinston(d, wplt)
d[:smooth] && d[:seriestype] != :histogram && addRegressionLineWinston(d, wplt)
push!(plt.seriesargs, d)
plt
# push!(plt.seriesargs, d)
# plt
end
# ----------------------------------------------------------------
@compat const _winstonNames = Dict(
const _winstonNames = KW(
:xlims => :xrange,
:ylims => :yrange,
:xscale => :xlog,
:yscale => :ylog,
)
function _update_plot(plt::Plot{WinstonPackage}, d::Dict)
function _update_plot_object(plt::Plot{WinstonBackend}, d::KW)
window, canvas, wplt = getWinstonItems(plt)
for k in (:xlabel, :ylabel, :title, :xlims, :ylims)
for k in (:xguide, :yguide, :title, :xlims, :ylims)
if haskey(d, k)
Winston.setattr(wplt, string(get(_winstonNames, k, k)), d[k])
end
@@ -186,11 +213,11 @@ end
# ----------------------------------------------------------------
function createWinstonAnnotationObject(plt::Plot{WinstonPackage}, 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{WinstonPackage}, 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
@@ -199,26 +226,26 @@ end
# ----------------------------------------------------------------
function _create_subplot(subplt::Subplot{WinstonPackage}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
end
# function _create_subplot(subplt::Subplot{WinstonBackend}, isbefore::Bool)
# # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
# end
# ----------------------------------------------------------------
function addWinstonLegend(plt::Plot, wplt)
if plt.plotargs[:legend] != :none
if plt.attr[:legend] != :none
Winston.legend(wplt, [sd[:label] for sd in plt.seriesargs])
end
end
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{WinstonPackage})
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
function Base.display(::PlotsDisplay, plt::Plot{WinstonPackage})
function Base.display(::PlotsDisplay, plt::Plot{WinstonBackend})
window, canvas, wplt = getWinstonItems(plt)
@@ -227,9 +254,9 @@ function Base.display(::PlotsDisplay, plt::Plot{WinstonPackage})
error("Gtk is the only supported display for Winston in Plots. Set `output_surface = gtk` in src/Winston.ini")
end
# initialize window
w,h = plt.plotargs[:size]
w,h = plt.attr[:size]
canvas = Gtk.GtkCanvasLeaf()
window = Gtk.GtkWindowLeaf(canvas, plt.plotargs[:windowtitle], w, h)
window = Gtk.GtkWindowLeaf(canvas, plt.attr[:window_title], w, h)
plt.o = (window, canvas, wplt)
end
@@ -240,6 +267,6 @@ function Base.display(::PlotsDisplay, plt::Plot{WinstonPackage})
end
function Base.display(::PlotsDisplay, subplt::Subplot{WinstonPackage})
# TODO: display/show the Subplot object
end
# function Base.display(::PlotsDisplay, subplt::Subplot{WinstonBackend})
# # TODO: display/show the Subplot object
# end
File diff suppressed because it is too large Load Diff
+82 -57
View File
@@ -1,14 +1,42 @@
abstract ColorScheme
abstract type ColorScheme end
Base.getindex(scheme::ColorScheme, i::Integer) = getColor(scheme, i)
export
cgrad
cgrad() = default_gradient()
function cgrad(arg, values = nothing; alpha = nothing, scale = :identity)
colors = ColorGradient(arg, alpha=alpha).colors
values = if values != nothing
values
elseif scale in (:log, :log10)
log10(linspace(1,10,30))
elseif scale == :log2
log2(linspace(1,2,30))
elseif scale == :ln
log(linspace(1,pi,30))
elseif scale in (:exp, :exp10)
(exp10(linspace(0,1,30)) - 1) / 9
else
linspace(0, 1, length(colors))
end
ColorGradient(colors, values)
end
# --------------------------------------------------------------
getColor(scheme::ColorScheme) = getColor(scheme, 1)
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)]'
@@ -18,17 +46,20 @@ colorscheme(c::Colorant; kw...) = ColorWrapper(c; kw...)
# --------------------------------------------------------------
convertColor(c::@compat(Union{AbstractString, Symbol})) = parse(Colorant, string(c))
convertColor(c::AbstractString) = parse(Colorant, c)
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(b::Bool) = b ? RGBA(0,0,0,1) : RGBA(0,0,0,0)
function convertColor(c, α::Real)
c = convertColor(c)
RGBA(RGB(c), α)
RGBA(RGB(getColor(c)), α)
end
convertColor(cs::AVec, α::Real) = map(c -> convertColor(c, α), cs)
convertColor(c, α::@compat(Void)) = convertColor(c)
convertColor(c, α::Void) = convertColor(c)
# backup... try to convert
getColor(c) = convertColor(c)
@@ -48,11 +79,11 @@ end
# --------------------------------------------------------------
const _rainbowColors = [colorant"blue", colorant"purple", colorant"green", colorant"orange", colorant"red"]
const _rainbowColors = [colorant"purple", colorant"blue", colorant"green", colorant"orange", colorant"red"]
const _testColors = [colorant"darkblue", colorant"blueviolet", colorant"darkcyan",colorant"green",
darken(colorant"yellow",0.3), colorant"orange", darken(colorant"red",0.2)]
@compat const _gradients = Dict(
const _gradients = KW(
:blues => [colorant"lightblue", colorant"darkblue"],
:reds => [colorant"lightpink", colorant"darkred"],
:greens => [colorant"lightgreen", colorant"darkgreen"],
@@ -67,19 +98,26 @@ const _testColors = [colorant"darkblue", colorant"blueviolet", colorant"darkcya
:lighttest => map(c -> lighten(c, 0.3), _testColors),
)
function register_gradient_colors(name::Symbol, colors::AVec{C}) where C<:Colorant
_gradients[name] = colors
end
include("color_gradients.jl")
default_gradient() = ColorGradient(:inferno)
# --------------------------------------------------------------
"Continuous gradient between values. Wraps a list of bounding colors and the values they represent."
immutable ColorGradient <: ColorScheme
colors::Vector{Colorant}
values::Vector{Float64}
struct ColorGradient <: ColorScheme
colors::Vector
values::Vector
function ColorGradient{T<:Colorant,S<:Real}(cs::AVec{T}, vals::AVec{S} = linspace(0, 1, length(cs)); alpha = nothing)
function ColorGradient(cs::AVec, vals::AVec{S} = linspace(0, 1, length(cs)); alpha = nothing) where S<:Real
if length(cs) == length(vals)
return new(convertColor(cs,alpha), collect(vals))
end
# # otherwise interpolate evenly between the minval and maxval
# minval, maxval = minimum(vals), maximum(vals)
# vs = Float64[interpolate(minval, maxval, w) for w in linspace(0, 1, length(cs))]
@@ -93,8 +131,14 @@ immutable ColorGradient <: ColorScheme
end
end
Base.getindex(cs::ColorGradient, i::Integer) = getColor(cs, i)
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
@@ -103,8 +147,17 @@ function ColorGradient{T<:Real}(s::Symbol, vals::AVec{T} = 0:0; kw...)
ColorGradient(cs, vals; kw...)
end
function ColorGradient{T<:Real}(cs::AVec{Symbol}, vals::AVec{T} = linspace(0, 1, length(cs)); kw...)
ColorGradient(map(convertColor, cs), vals; kw...)
# function ColorGradient{T<:Real}(cs::AVec, vals::AVec{T} = linspace(0, 1, length(cs)); kw...)
# ColorGradient(map(convertColor, cs), vals; kw...)
# end
function ColorGradient(grad::ColorGradient; alpha = nothing)
ColorGradient(convertColor(grad.colors, alpha), grad.values)
end
# anything else just gets the default gradient
function ColorGradient(cw; alpha=nothing)
ColorGradient(default_gradient(), alpha=alpha)
end
getColor(gradient::ColorGradient, idx::Int) = gradient.colors[mod1(idx, length(gradient.colors))]
@@ -155,7 +208,7 @@ end
# --------------------------------------------------------------
"Wraps a function, taking an index and returning a Colorant"
immutable ColorFunction <: ColorScheme
struct ColorFunction <: ColorScheme
f::Function
end
@@ -164,16 +217,16 @@ 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
getColorZ(scheme::ColorFunction, z::Real) = scheme.f(z)
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
@@ -185,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
@@ -194,6 +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
# --------------------------------------------------------------
@@ -283,7 +337,7 @@ function generate_colorgradient(bgcolor = colorant"white";
gradient_from_list(colors)
end
function get_color_palette(palette, bgcolor::@compat(Union{Colorant,ColorWrapper}), numcolors::Integer)
function get_color_palette(palette, bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer)
grad = if palette == :auto
generate_colorgradient(bgcolor)
else
@@ -293,7 +347,8 @@ function get_color_palette(palette, bgcolor::@compat(Union{Colorant,ColorWrapper
RGBA[getColorZ(grad, z) for z in zrng]
end
function get_color_palette(palette::Vector{RGBA}, bgcolor::@compat(Union{Colorant,ColorWrapper}), numcolors::Integer)
function get_color_palette(palette::Vector{C},
bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer) where C<:Colorant
palette
end
@@ -336,10 +391,10 @@ end
make255(x) = round(Int, 255 * x)
function webcolor(c::Color)
@sprintf("rgb(%d, %d, %d)", [make255(f(c)) for f in [red,green,blue]]...)
@sprintf("rgb(%d, %d, %d)", [make255(f(c)) for f in [red,green,blue]]...)
end
function webcolor(c::TransparentColor)
@sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c))
@sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c))
end
webcolor(cs::ColorScheme) = webcolor(getColor(cs))
webcolor(c) = webcolor(convertColor(c))
@@ -347,42 +402,12 @@ webcolor(c, α) = webcolor(convertColor(getColor(c), α))
# ----------------------------------------------------------------------------------
# TODO: allow the setting of the algorithm, either by passing a symbol (:colordiff, :fixed, etc) or a function?
# function getBackgroundRGBColor(c, d::Dict)
function handlePlotColors(::PlottingPackage, d::Dict)
if :background_color in supportedArgs()
bgcolor = convertColor(d[:background_color])
else
bgcolor = _plotDefaults[:background_color]
if d[:background_color] != _plotDefaults[:background_color]
warn("Cannot set background_color with backend $(backend())")
end
end
d[:color_palette] = get_color_palette(get(d, :color_palette, :auto), bgcolor, 100)
# set the foreground color (text, ticks, gridlines) to be white or black depending
# on how dark the background is.
fgcolor = get(d, :foreground_color, :auto)
fgcolor = if fgcolor == :auto
isdark(bgcolor) ? colorant"white" : colorant"black"
else
convertColor(fgcolor)
end
# bgcolor
d[:background_color] = colorscheme(bgcolor)
d[:foreground_color] = colorscheme(fgcolor)
end
# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically
function getSeriesRGBColor(c, plotargs::Dict, n::Int)
function getSeriesRGBColor(c, sp::Subplot, n::Int)
if c == :auto
c = autopick(plotargs[:color_palette], n)
c = autopick(sp[:color_palette], n)
end
# c should now be a subtype of ColorScheme
+99
View File
@@ -0,0 +1,99 @@
# create a new "build_series_args" which converts all inputs into xs = Any[xitems], ys = Any[yitems].
# Special handling for: no args, xmin/xmax, parametric, dataframes
# Then once inputs have been converted, build the series args, map functions, etc.
# 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
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::Void, 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(v::AVec{T}, d::KW) where {T<:Number} = Any[v], nothing
# string vector
convertToAnyVector(v::AVec{T}, d::KW) where {T<:AbstractString} = Any[v], nothing
function convertToAnyVector(v::AMat, d::KW)
if all3D(d)
Any[Surface(v)]
else
Any[v[:,i] for i in 1:size(v,2)]
end, nothing
end
# function
convertToAnyVector(f::Function, d::KW) = Any[f], nothing
# surface
convertToAnyVector(s::Surface, d::KW) = Any[s], nothing
# # vector of OHLC
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], 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)
if all(x -> typeof(x) <: Number, v)
# all real numbers wrap the whole vector as one item
Any[convert(Vector{Float64}, v)], nothing
else
# something else... treat each element as an item
vcat(Any[convertToAnyVector(vi, d)[1] for vi in v]...), nothing
# Any[vi for vi in v], nothing
end
end
convertToAnyVector(t::Tuple, d::KW) = Any[t], nothing
function convertToAnyVector(args...)
error("In convertToAnyVector, could not handle the argument types: $(map(typeof, args[1:end-1]))")
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::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, 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) = copy(z)
nobigs(v::AVec{BigFloat}) = map(Float64, v)
nobigs(v::AVec{BigInt}) = map(Int64, v)
nobigs(v) = v
@noinline function compute_xyz(x, y, z)
x = compute_x(x,y,z)
y = compute_y(x,y,z)
z = compute_z(x,y,z)
nobigs(x), nobigs(y), nobigs(z)
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!")
# --------------------------------------------------------------------
+480
View File
@@ -0,0 +1,480 @@
"""
Holds all data needed for a documentation example... header, description, and plotting expression (Expr)
"""
mutable struct PlotExample
header::AbstractString
desc::AbstractString
exprs::Vector{Expr}
end
# the _examples we'll run for each
const _examples = PlotExample[
PlotExample("Lines",
"A simple line plot of the columns.",
[:(begin
plot(Plots.fakedata(50,5), w=3)
end)]
),
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.
""",
[:(begin
p = plot([sin,cos], zeros(0), leg=false)
anim = Animation()
for x in linspace(0, 10π, 100)
push!(p, x, Float64[sin(x), cos(x)])
frame(anim)
end
end)]
),
PlotExample("Parametric plots",
"Plot function pair (x(u), y(u)).",
[:(begin
plot(sin, x->sin(2x), 0, 2π, line=4, leg=false, fill=(0,:orange))
end)]
),
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.
""",
[:(begin
y = rand(100)
plot(0:10:100,rand(11,4),lab="lines",w=3,palette=:grays,fill=0, α=0.6)
scatter!(y, zcolor=abs.(y-.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs.(y-0.5)+4,
lab="grad")
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!`
""",
[:(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)
end)]
),
# PlotExample("Two-axis",
# "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 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.
""",
[:(begin
ys = Vector[rand(10), rand(20)]
plot(ys, color=[:black :orange], line=(:dot,4), marker=([:hex :d],12,0.8,stroke(3,:gray)))
end)]
),
PlotExample("Build plot in pieces",
"Start with a base plot...",
[:(begin
plot(rand(100)/3, reg=true, fill=(0,:green))
end)]
),
PlotExample("",
"and add to it later.",
[:(begin
scatter!(rand(100), markersize=6, c=:orange)
end)]
),
PlotExample("Histogram2D",
"",
[:(begin
histogram2d(randn(10000), randn(10000), nbins=20)
end)]
),
PlotExample("Line types",
"",
[:(begin
linetypes = [:path :steppre :steppost :sticks :scatter]
n = length(linetypes)
x = Vector[sort(rand(20)) for i in 1:n]
y = rand(20,n)
plot(x, y, line=(linetypes,3), lab=map(string,linetypes), ms=15)
end)]
),
PlotExample("Line styles",
"",
[:(begin
styles = filter(s -> s in Plots.supported_styles(),
[:solid, :dash, :dot, :dashdot, :dashdotdot])
styles = reshape(styles, 1, length(styles)) # Julia 0.6 unfortunately gives an error when transposing symbol vectors
n = length(styles)
y = cumsum(randn(20,n),1)
plot(y, line = (5, styles), label = map(string,styles), legendtitle = "linestyle")
end)]
),
PlotExample("Marker types",
"",
[:(begin
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(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)]
),
PlotExample("Bar",
"x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
[:(begin
bar(randn(99))
end)]
),
PlotExample("Histogram",
"",
[:(begin
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.
""",
[:(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=: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.
""",
[:(begin
plot(Plots.fakedata(100,10), layout=4, palette=[:grays :blues :heat :lightrainbow],
bg_inside=[:orange :pink :darkblue :black])
end)]
),
PlotExample("",
"",
[:(begin
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.
""",
[:(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)
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.
""",
[:(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)])
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.
""",
[:(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)
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.
""",
[:(begin
x = 1:0.5:20
y = 1:0.5:10
f(x,y) = (3x+y^2)*abs(sin(x)+cos(y))
X = repmat(reshape(x,1,:), length(y), 1)
Y = repmat(y, 1, length(x))
Z = map(f, X, Y)
p1 = contour(x, y, f, fill=true)
p2 = contour(x, y, Z)
plot(p1, p2)
end)]
),
PlotExample("Pie",
"",
[:(begin
x = ["Nerds", "Hackers", "Scientists"]
y = [0.4, 0.35, 0.25]
pie(x, y, title="The Julia Community", l=0.5)
end)]
),
PlotExample("3D",
"",
[:(begin
n = 100
ts = linspace(0,8π,n)
x = ts .* map(cos,ts)
y = 0.1ts .* map(sin,ts)
z = 1:n
plot(x, y, z, zcolor=reverse(z), m=(10,0.8,:blues,stroke(0)), leg=false, cbar=true, w=5)
plot!(zeros(n),zeros(n),1:n, w=10)
end)]
),
PlotExample("DataFrames",
"Plot using DataFrame column symbols.",
[:(begin
import RDatasets
iris = RDatasets.dataset("datasets", "iris")
@df iris scatter(:SepalLength, :SepalWidth, group=:Species,
title = "My awesome plot", xlabel = "Length", ylabel = "Width",
marker = (0.5, [:cross :hex :star7], 12), bg=RGB(.2,.2,.2))
end)]
),
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], linecolor = :match)
end)]
),
PlotExample("Polar Plots",
"",
[:(begin
Θ = linspace(0,1.5π,100)
r = abs.(0.1randn(100)+sin.(3Θ))
plot(Θ, r, proj=:polar, m=2)
end)]
),
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)*reshape(1:10,1,:))
heatmap(xs, ys, z, aspect_ratio=1)
end)]
),
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=10px, xrotation=60)
end)]
),
PlotExample("Boxplot and Violin series recipes",
"",
[:(begin
import RDatasets
singers = RDatasets.dataset("lattice", "singer")
@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 = linspace(1,10π,100)
plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)]))
frame(anim)
end
end)]
),
PlotExample("Spy",
"""
For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat` has
various different nonzero values, a colorbar is added. The colorbar can be disabled with
`legend = nothing`.
""",
[:(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 = linspace(0, 1, 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)]
),
]
# ---------------------------------------------------------------------------------
# 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)")
backend(pkgname)
backend()
map(eval, _examples[idx].exprs)
plt = current()
if disp
gui(plt)
end
plt
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
plts = Dict()
for i in 1:length(_examples)
only != nothing && !(i in only) && continue
i in skip && continue
try
plt = test_examples(pkgname, i, debug=debug, disp=disp)
plts[i] = plt
catch ex
# TODO: put error info into markdown?
warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex")
end
if sleep != nothing
Base.sleep(sleep)
end
end
plts
end
+800
View File
@@ -0,0 +1,800 @@
# NOTE: (0,0) is the top-left !!!
to_pixels(m::AbsoluteLength) = m.value / 0.254
const _cbar_width = 5mm
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(::Type{F}, l::AbsoluteLength) where {F<:AbstractFloat} = convert(F, l.value)
# TODO: these are unintuitive and may cause tricky bugs
# 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))
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
Base.one(::Type{typeof(pct)}) = 1pct
Base.typemin(::typeof(pct)) = 0pct
Base.typemax(::typeof(pct)) = 1pct
const defaultbox = BoundingBox(0mm, 0mm, 0mm, 0mm)
left(bbox::BoundingBox) = bbox.x0[1]
top(bbox::BoundingBox) = bbox.x0[2]
right(bbox::BoundingBox) = left(bbox) + width(bbox)
bottom(bbox::BoundingBox) = top(bbox) + height(bbox)
Base.size(bbox::BoundingBox) = (width(bbox), height(bbox))
# 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
function Base.:+(bb1::BoundingBox, bb2::BoundingBox)
# empty boxes don't change the union
ispositive(width(bb1)) || return bb2
ispositive(height(bb1)) || return bb2
ispositive(width(bb2)) || return bb1
ispositive(height(bb2)) || return bb1
l = min(left(bb1), left(bb2))
t = min(top(bb1), top(bb2))
r = max(right(bb1), right(bb2))
b = max(bottom(bb1), bottom(bb2))
BoundingBox(l, t, r-l, b-t)
end
# this creates a bounding box in the parent's scope, where the child bounding box
# is relative to the parent
function crop(parent::BoundingBox, child::BoundingBox)
l = left(parent) + left(child)
t = top(parent) + top(child)
w = width(child)
h = height(child)
BoundingBox(l, t, w, h)
end
# convert x,y coordinates from absolute coords to percentages...
# returns x_pct, y_pct
function xy_mm_to_pcts(x::AbsoluteLength, y::AbsoluteLength, figw, figh, flipy = true)
xmm, ymm = x.value, y.value
if flipy
ymm = figh.value - ymm # flip y when origin in bottom-left
end
xmm / figw.value, ymm / figh.value
end
# convert a bounding box from absolute coords to percentages...
# returns an array of percentages of figure size: [left, bottom, width, height]
function bbox_to_pcts(bb::BoundingBox, figw, figh, flipy = true)
mms = Float64[f(bb).value for f in (left,bottom,width,height)]
if flipy
mms[2] = figh.value - mms[2] # flip y when origin in bottom-left
end
mms ./ Float64[figw.value, figh.value, figw.value, figh.value]
end
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
Base.show(io::IO, layout::AbstractLayout) = print(io, "$(typeof(layout))$(size(layout))")
make_measure_hor(n::Number) = n * w
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 == :center
orighor = origver = oarg
elseif oarg in (:left, :right, :hcenter)
orighor = oarg
elseif oarg in (:top, :bottom, :vcenter)
origver = oarg
else
warn("Unused origin arg in bbox construction: $oarg")
end
end
bbox(x, y, w, h; h_anchor = orighor, v_anchor = origver)
end
# create a new bbox
function bbox(x, y, width, height; h_anchor = :left, v_anchor = :top)
x = make_measure_hor(x)
y = make_measure_vert(y)
width = make_measure_hor(width)
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
end
top = if v_anchor == :top
y
elseif v_anchor in (:center, :vcenter)
0.5h - 0.5height + y
else
1h - y - height
end
BoundingBox(left, top, width, height)
end
# this is the available area for drawing everything in this layout... as percentages of total canvas
bbox(layout::AbstractLayout) = layout.bbox
bbox!(layout::AbstractLayout, bb::BoundingBox) = (layout.bbox = bb)
# layouts are recursive, tree-like structures, and most will have a parent field
Base.parent(layout::AbstractLayout) = layout.parent
parent_bbox(layout::AbstractLayout) = bbox(parent(layout))
# padding_w(layout::AbstractLayout) = left_padding(layout) + right_padding(layout)
# padding_h(layout::AbstractLayout) = bottom_padding(layout) + top_padding(layout)
# padding(layout::AbstractLayout) = (padding_w(layout), padding_h(layout))
update_position!(layout::AbstractLayout) = nothing
update_child_bboxes!(layout::AbstractLayout, minimum_perimeter = [0mm,0mm,0mm,0mm]) = nothing
left(layout::AbstractLayout) = left(bbox(layout))
top(layout::AbstractLayout) = top(bbox(layout))
right(layout::AbstractLayout) = right(bbox(layout))
bottom(layout::AbstractLayout) = bottom(bbox(layout))
width(layout::AbstractLayout) = width(bbox(layout))
height(layout::AbstractLayout) = height(bbox(layout))
# pass these through to the bbox methods if there's no plotarea
plotarea(layout::AbstractLayout) = bbox(layout)
plotarea!(layout::AbstractLayout, bb::BoundingBox) = bbox!(layout, bb)
attr(layout::AbstractLayout, k::Symbol) = layout.attr[k]
attr(layout::AbstractLayout, k::Symbol, v) = get(layout.attr, k, v)
attr!(layout::AbstractLayout, v, k::Symbol) = (layout.attr[k] = v)
hasattr(layout::AbstractLayout, k::Symbol) = haskey(layout.attr, k)
leftpad(layout::AbstractLayout) = 0mm
toppad(layout::AbstractLayout) = 0mm
rightpad(layout::AbstractLayout) = 0mm
bottompad(layout::AbstractLayout) = 0mm
# -----------------------------------------------------------
# RootLayout
# this is the parent of the top-level layout
struct RootLayout <: AbstractLayout end
Base.parent(::RootLayout) = nothing
parent_bbox(::RootLayout) = defaultbox
bbox(::RootLayout) = defaultbox
# -----------------------------------------------------------
# EmptyLayout
# contains blank space
mutable struct EmptyLayout <: AbstractLayout
parent::AbstractLayout
bbox::BoundingBox
attr::KW # store label, width, and height for initialization
# label # this is the label that the subplot will take (since we create a layout before initialization)
end
EmptyLayout(parent = RootLayout(); kw...) = EmptyLayout(parent, defaultbox, KW(kw))
Base.size(layout::EmptyLayout) = (0,0)
Base.length(layout::EmptyLayout) = 0
Base.getindex(layout::EmptyLayout, r::Int, c::Int) = nothing
_update_min_padding!(layout::EmptyLayout) = nothing
# -----------------------------------------------------------
# GridLayout
# nested, gridded layout with optional size percentages
mutable struct GridLayout <: AbstractLayout
parent::AbstractLayout
minpad::Tuple # leftpad, toppad, rightpad, bottompad
bbox::BoundingBox
grid::Matrix{AbstractLayout} # Nested layouts. Each position is a AbstractLayout, which allows for arbitrary recursion
widths::Vector{Measure}
heights::Vector{Measure}
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...;
parent = RootLayout(),
widths = zeros(dims[2]),
heights = zeros(dims[1]),
kw...)
grid = Matrix{AbstractLayout}(dims...)
layout = GridLayout(
parent,
(20mm, 5mm, 2mm, 10mm),
defaultbox,
grid,
Measure[w*pct for w in widths],
Measure[h*pct for h in heights],
# convert(Vector{Float64}, widths),
# convert(Vector{Float64}, heights),
KW(kw))
for i in eachindex(grid)
grid[i] = EmptyLayout(layout)
end
layout
end
Base.size(layout::GridLayout) = size(layout.grid)
Base.length(layout::GridLayout) = length(layout.grid)
Base.getindex(layout::GridLayout, r::Int, c::Int) = layout.grid[r,c]
function Base.setindex!(layout::GridLayout, v, r::Int, c::Int)
layout.grid[r,c] = v
end
leftpad(layout::GridLayout) = layout.minpad[1]
toppad(layout::GridLayout) = layout.minpad[2]
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
# 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
# recursively pass those borders back down the tree, one side at a time, but ONLY
# to those perimeter children.
# leftpad, toppad, rightpad, bottompad
function _update_min_padding!(layout::GridLayout)
map(_update_min_padding!, layout.grid)
layout.minpad = (
maximum(map(leftpad, layout.grid[:,1])),
maximum(map(toppad, layout.grid[1,:])),
maximum(map(rightpad, layout.grid[:,end])),
maximum(map(bottompad, layout.grid[end,:]))
)
end
function update_position!(layout::GridLayout)
map(update_position!, layout.grid)
end
# some lengths are fixed... we have to split up the free space among the list v
function recompute_lengths(v)
# dump(v)
tot = 0pct
cnt = 0
for vi in v
if vi == 0pct
cnt += 1
else
tot += vi
end
end
leftover = 1.0pct - tot
if cnt > 1 && leftover.value <= 0
error("Not enough length left over in layout! v = $v, cnt = $cnt, leftover = $leftover")
end
# now fill in the blanks
Measure[(vi == 0pct ? leftover / cnt : vi) for vi in v]
end
# recursively compute the bounding boxes for the layout and plotarea (relative to canvas!)
function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0mm,0mm])
nr, nc = size(layout)
# # create a matrix for each minimum padding direction
# _update_min_padding!(layout)
minpad_left = map(leftpad, layout.grid)
minpad_top = map(toppad, layout.grid)
minpad_right = map(rightpad, layout.grid)
minpad_bottom = map(bottompad, layout.grid)
# 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)
# make sure the perimeter match the parent
pad_left[1] = max(pad_left[1], minimum_perimeter[1])
pad_top[1] = max(pad_top[1], minimum_perimeter[2])
pad_right[end] = max(pad_right[end], minimum_perimeter[3])
pad_bottom[end] = max(pad_bottom[end], minimum_perimeter[4])
# 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)
# 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
# recompute widths/heights
layout.widths = recompute_lengths(layout.widths)
layout.heights = recompute_lengths(layout.heights)
# normalize widths/heights so they sum to 1
# denom_w = sum(layout.widths)
# denom_h = sum(layout.heights)
# we have all the data we need... lets compute the plot areas and set the bounding boxes
for r=1:nr, c=1:nc
child = layout[r,c]
# get the top-left corner of this child... the first one is top-left of the parent (i.e. layout)
child_left = (c == 1 ? left(layout.bbox) : right(layout[r, c-1].bbox))
child_top = (r == 1 ? top(layout.bbox) : bottom(layout[r-1, c].bbox))
# compute plot area
plotarea_left = child_left + pad_left[c]
plotarea_top = child_top + pad_top[r]
plotarea_width = total_plotarea_horizontal * layout.widths[c]
plotarea_height = total_plotarea_vertical * layout.heights[r]
plotarea!(child, BoundingBox(plotarea_left, plotarea_top, plotarea_width, plotarea_height))
# compute child bbox
child_width = pad_left[c] + plotarea_width + pad_right[c]
child_height = pad_top[r] + plotarea_height + pad_bottom[r]
bbox!(child, BoundingBox(child_left, child_top, child_width, child_height))
# this is the minimum perimeter as decided by this child's parent, so that
# all children on this border have the same value
min_child_perimeter = [
c == 1 ? layout.minpad[1] : 0mm,
r == 1 ? layout.minpad[2] : 0mm,
c == nc ? layout.minpad[3] : 0mm,
r == nr ? layout.minpad[4] : 0mm
]
# recursively update the child's children
update_child_bboxes!(child, min_child_perimeter)
end
end
# for each inset (floating) subplot, resolve the relative position
# to absolute canvas coordinates, relative to the parent's plotarea
function update_inset_bboxes!(plt::Plot)
for sp in plt.inset_subplots
p_area = Measures.resolve(plotarea(sp.parent), sp[:relative_bbox])
plotarea!(sp, p_area)
bbox!(sp, bbox(
left(p_area) - leftpad(sp),
top(p_area) - toppad(sp),
width(p_area) + leftpad(sp) + rightpad(sp),
height(p_area) + toppad(sp) + bottompad(sp)
))
end
end
# ----------------------------------------------------------------------
calc_num_subplots(layout::AbstractLayout) = 1
function calc_num_subplots(layout::GridLayout)
tot = 0
for l in layout.grid
tot += calc_num_subplots(l)
end
tot
end
function compute_gridsize(numplts::Int, nr::Int, nc::Int)
# figure out how many rows/columns we need
if nr < 1
if nc < 1
nr = round(Int, sqrt(numplts))
nc = ceil(Int, numplts / nr)
else
nr = ceil(Int, numplts / nc)
end
else
nc = ceil(Int, numplts / nr)
end
nr, nc
end
# ----------------------------------------------------------------------
# constructors
# pass the layout arg through
function layout_args(d::KW)
layout_args(get(d, :layout, default(:layout)))
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) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.")
end
layout, n
end
function layout_args(n::Integer)
nr, nc = compute_gridsize(n, -1, -1)
GridLayout(nr, nc), n
end
function layout_args(sztup::NTuple{2,I}) where I<:Integer
nr, nc = sztup
GridLayout(nr, nc), nr*nc
end
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
end
# compute number of subplots
function layout_args(layout::GridLayout)
# recursively get the size of the grid
n = calc_num_subplots(layout)
layout, n
end
layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")
# ----------------------------------------------------------------------
function build_layout(args...)
layout, n = layout_args(args...)
build_layout(layout, n)
end
# # just a single subplot
# function build_layout(sp::Subplot, n::Integer)
# sp, Subplot[sp], SubplotMap(gensym() => sp)
# end
# n is the number of subplots... build a grid and initialize the inner subplots recursively
function build_layout(layout::GridLayout, n::Integer)
nr, nc = size(layout)
subplots = Subplot[]
spmap = SubplotMap()
i = 0
for r=1:nr, c=1:nc
l = layout[r,c]
if isa(l, EmptyLayout) && !get(l.attr, :blank, false)
sp = Subplot(backend(), parent=layout)
layout[r,c] = sp
push!(subplots, sp)
spmap[attr(l,:label,gensym())] = sp
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
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)
i += length(sps)
elseif isa(l, Subplot)
error("Subplot exists. Cannot re-use existing layout. Please make a new one.")
end
i >= n && break # only add n subplots
end
layout, subplots, spmap
end
# build a layout from a list of existing Plot objects
# TODO... much of the logic overlaps with the method above... can we merge?
function build_layout(layout::GridLayout, numsp::Integer, plts::AVec{Plot})
nr, nc = size(layout)
subplots = Subplot[]
spmap = SubplotMap()
i = 0
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
layout[r,c] = plt.layout
append!(subplots, plt.subplots)
merge!(spmap, plt.spmap)
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
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)
i += length(sps)
end
i >= numsp && break # only add n subplots
end
layout, subplots, spmap
end
# ----------------------------------------------------------------------
# @layout macro
function add_layout_pct!(kw::KW, v::Expr, idx::Integer, nidx::Integer)
# dump(v)
# something like {0.2w}?
if v.head == :call && v.args[1] == :*
num = v.args[2]
if length(v.args) == 3 && isa(num, Number)
units = v.args[3]
if units == :h
return kw[:h] = num*pct
elseif units == :w
return kw[:w] = num*pct
elseif units in (:pct, :px, :mm, :cm, :inch)
idx == 1 && (kw[:w] = v)
(idx == 2 || nidx == 1) && (kw[:h] = v)
# return kw[idx == 1 ? :w : :h] = v
end
end
end
error("Couldn't match layout curly (idx=$idx): $v")
end
function add_layout_pct!(kw::KW, v::Number, idx::Integer)
# kw[idx == 1 ? :w : :h] = v*pct
idx == 1 && (kw[:w] = v*pct)
(idx == 2 || nidx == 1) && (kw[:h] = v*pct)
end
isrow(v) = isa(v, Expr) && v.head in (:hcat,:row)
iscol(v) = isa(v, Expr) && v.head == :vcat
rowsize(v) = isrow(v) ? length(v.args) : 1
function create_grid(expr::Expr)
if iscol(expr)
create_grid_vcat(expr)
elseif isrow(expr)
:(let cell = GridLayout(1, $(length(expr.args)))
$([:(cell[1,$i] = $(create_grid(v))) for (i,v) in enumerate(expr.args)]...)
cell
end)
elseif expr.head == :curly
create_grid_curly(expr)
else
# if it's something else, just return that (might be an existing layout?)
esc(expr)
end
end
function create_grid_vcat(expr::Expr)
rowsizes = map(rowsize, expr.args)
rmin, rmax = extrema(rowsizes)
if rmin > 0 && rmin == rmax
# we have a grid... build the whole thing
# note: rmin is the number of columns
nr = length(expr.args)
nc = rmin
body = Expr(:block)
for r=1:nr
arg = expr.args[r]
if isrow(arg)
for (c,item) in enumerate(arg.args)
push!(body.args, :(cell[$r,$c] = $(create_grid(item))))
end
else
push!(body.args, :(cell[$r,1] = $(create_grid(arg))))
end
end
:(let cell = GridLayout($nr, $nc)
$body
cell
end)
else
# otherwise just build one row at a time
:(let cell = GridLayout($(length(expr.args)), 1)
$([:(cell[$i,1] = $(create_grid(v))) for (i,v) in enumerate(expr.args)]...)
cell
end)
end
end
function create_grid_curly(expr::Expr)
kw = KW()
for (i,arg) in enumerate(expr.args[2:end])
add_layout_pct!(kw, arg, i, length(expr.args)-1)
end
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)
:(EmptyLayout(label = $(QuoteNode(s)), blank = $(s == :_)))
end
macro layout(mat::Expr)
create_grid(mat)
end
# -------------------------------------------------------------------------
# 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 = link_subplots(a, axissym)
axes = [sp.attr[axissym] for sp in subplots]
if length(axes) > 0
link_axes!(axes...)
end
end
# don't do anything for most layout types
function link_axes!(l::AbstractLayout, link::Symbol)
end
# process a GridLayout, recursively linking axes according to the link symbol
function link_axes!(layout::GridLayout, link::Symbol)
nr, nc = size(layout)
if link in (:x, :both)
for c=1:nc
link_axes!(layout.grid[:,c], :xaxis)
end
end
if link in (:y, :both)
for r=1:nr
link_axes!(layout.grid[r,:], :yaxis)
end
end
if link == :square
sps = filter(l -> isa(l, Subplot), layout.grid)
if !isempty(sps)
base_axis = sps[1][:xaxis]
for sp in sps
link_axes!(base_axis, sp[:xaxis])
link_axes!(base_axis, sp[:yaxis])
end
end
end
if link == :all
link_axes!(layout.grid, :xaxis)
link_axes!(layout.grid, :yaxis)
end
for l in layout.grid
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])
+275 -33
View File
@@ -1,63 +1,82 @@
defaultOutputFormat(plt::PlottingObject) = "png"
defaultOutputFormat(plt::Plot) = "png"
function png(plt::PlottingObject, fn::@compat(AbstractString))
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::@compat(AbstractString)) = png(current(), fn)
png(fn::AbstractString) = png(current(), fn)
function svg(plt::PlottingObject, fn::@compat(AbstractString))
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::@compat(AbstractString)) = svg(current(), fn)
svg(fn::AbstractString) = svg(current(), fn)
function pdf(plt::PlottingObject, fn::@compat(AbstractString))
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::@compat(AbstractString)) = pdf(current(), fn)
pdf(fn::AbstractString) = pdf(current(), fn)
function ps(plt::PlottingObject, fn::@compat(AbstractString))
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::@compat(AbstractString)) = ps(current(), fn)
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::PlottingObject, fn::@compat(AbstractString))
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::@compat(AbstractString)) = tex(current(), fn)
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::@compat(AbstractString))
function getExtension(fn::AbstractString)
pieces = split(fn, ".")
length(pieces) > 1 || error("Can't extract file extension: ", fn)
ext = pieces[end]
@@ -65,7 +84,7 @@ function getExtension(fn::@compat(AbstractString))
ext
end
function addExtension(fn::@compat(AbstractString), ext::@compat(AbstractString))
function addExtension(fn::AbstractString, ext::AbstractString)
try
oldext = getExtension(fn)
if oldext == ext
@@ -78,8 +97,15 @@ function addExtension(fn::@compat(AbstractString), ext::@compat(AbstractString))
end
end
function savefig(plt::PlottingObject, fn::@compat(AbstractString))
"""
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
local ext
try
@@ -96,24 +122,240 @@ function savefig(plt::PlottingObject, fn::@compat(AbstractString))
end
func(plt, fn)
end
savefig(fn::@compat(AbstractString)) = savefig(current(), fn)
# savepng(args...; kw...) = savepng(current(), args...; kw...)
# savepng(plt::PlottingObject, fn::@compat(AbstractString); kw...) = (io = open(fn, "w"); writemime(io, MIME("image/png"), plt); close(io))
savefig(fn::AbstractString) = savefig(current(), fn)
# ---------------------------------------------------------
"""
gui([plot])
gui(plt::PlottingObject = current()) = display(PlotsDisplay(), plt)
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::PlottingObject) = gui(plt)
Base.display(::Base.REPL.REPLDisplay, ::MIME"text/plain", plt::Plot) = gui(plt)
# a backup for html... passes to svg
function Base.writemime(io::IO, ::MIME"text/html", plt::PlottingObject)
writemime(io, MIME("image/svg+xml"), 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 _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 _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(show, MIME("image/png"), plt), "\" />")
elseif output_type == :svg
# info("writing svg to html output")
show(io, MIME("image/svg+xml"), plt)
elseif output_type == :txt
show(io, MIME("text/plain"), plt)
else
error("only png or svg allowed. got: $(repr(output_type))")
end
end
# delegate mimewritable (showable on julia 0.7) to _show instead
function Base.mimewritable(m::M, plt::P) where {M<:MIME, P<:Plot}
return method_exists(_show, Tuple{IO, M, P})
end
function _display(plt::Plot)
warn("_display is not defined for this backend.")
end
# for writing to io streams... first prepare, then callback
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)
_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 _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends})
fn = tempname()
# first save a pdf file
pdf(plt, fn)
# load that pdf into a FileIO Stream
s = FileIO.load(fn * ".pdf")
# save a png
pngfn = fn * ".png"
FileIO.save(pngfn, s)
# now write from the file
write(io, readstring(open(pngfn)))
end
end
# function html_output_format(fmt)
# if fmt == "png"
# @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.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")
# end
# end
#
# html_output_format("svg")
# ---------------------------------------------------------
# IJulia
# ---------------------------------------------------------
@require IJulia begin
if IJulia.inited
"""
Add extra jupyter mimetypes to display_dict based on the plot backed.
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
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 begin
import Hiccup, Media
if Juno.isactive()
Media.media(Plot, Media.Plot)
function Juno.render(e::Juno.Editor, plt::Plot)
Juno.render(e, nothing)
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)
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
+423
View File
@@ -0,0 +1,423 @@
# ------------------------------------------------------------------
# preprocessing
function command_idx(kw_list::AVec{KW}, kw::KW)
Int(kw[:series_plotindex]) - Int(kw_list[1][:series_plotindex]) + 1
end
function _expand_seriestype_array(d::KW, args)
sts = get(d, :seriestype, :path)
if typeof(sts) <: AbstractArray
delete!(d, :seriestype)
RecipeData[begin
dc = copy(d)
dc[:seriestype] = sts[r:r,:]
RecipeData(dc, args)
end for r=1:size(sts,1)]
else
RecipeData[RecipeData(copy(d), args)]
end
end
function _preprocess_args(d::KW, args, still_to_process::Vector{RecipeData})
# the grouping mechanism is a recipe on a GroupBy object
# we simply add the GroupBy object to the front of the args list to allow
# the recipe to be applied
if haskey(d, :group)
args = (extractGroupArgs(d[:group], args...), args...)
end
# if we were passed a vector/matrix of seriestypes and there's more than one row,
# we want to duplicate the inputs, once for each seriestype row.
if !isempty(args)
append!(still_to_process, _expand_seriestype_array(d, args))
end
# remove subplot and axis args from d... they will be passed through in the kw_list
if !isempty(args)
for (k,v) in d
for defdict in (_subplot_defaults,
_axis_defaults,
_axis_defaults_byletter)
if haskey(defdict, k)
delete!(d, k)
end
end
end
end
args
end
# ------------------------------------------------------------------
# user recipes
function _process_userrecipes(plt::Plot, d::KW, args)
still_to_process = RecipeData[]
args = _preprocess_args(d, args, still_to_process)
# for plotting recipes, swap out the args and update the parameter dictionary
# 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, 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 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 = shift!(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
# don't allow something else to handle it
d[:smooth] = false
kw_list
end
function _process_userrecipe(plt::Plot, kw_list::Vector{KW}, recipedata::RecipeData)
# 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)
# add the plot index
plt.n += 1
kw[:series_plotindex] = plt.n
push!(kw_list, kw)
_add_errorbar_kw(kw_list, kw)
_add_smooth_kw(kw_list, kw)
return
end
function _preprocess_userrecipe(kw::KW)
_add_markershape(kw)
# if there was a grouping, filter the data here
_filter_input_data!(kw)
# map marker_z if it's a Function
if isa(get(kw, :marker_z, nothing), Function)
# TODO: should this take y and/or z as arguments?
kw[:marker_z] = map(kw[:marker_z], kw[:x], kw[:y], kw[:z])
end
# map line_z if it's a Function
if isa(get(kw, :line_z, nothing), Function)
kw[:line_z] = map(kw[:line_z], kw[:x], kw[:y], kw[:z])
end
# convert a ribbon into a fillrange
if get(kw, :ribbon, nothing) != nothing
make_fillrange_from_ribbon(kw)
end
return
end
function _add_errorbar_kw(kw_list::Vector{KW}, kw::KW)
# handle error bars by creating new recipedata data... these will have
# the same recipedata index as the recipedata they are copied from
for esym in (:xerror, :yerror)
if get(kw, esym, nothing) != nothing
# we make a copy of the KW and apply an errorbar recipe
errkw = copy(kw)
errkw[:seriestype] = esym
errkw[:label] = ""
errkw[:primary] = false
push!(kw_list, errkw)
end
end
end
function _add_smooth_kw(kw_list::Vector{KW}, kw::KW)
# handle smoothing by adding a new series
if get(kw, :smooth, false)
x, y = kw[:x], kw[:y]
β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y)
sx = [ignorenan_minimum(x), ignorenan_maximum(x)]
sy = β * sx + α
push!(kw_list, merge(copy(kw), KW(
:seriestype => :path,
:x => sx,
:y => sy,
:fillrange => nothing,
:label => "",
:primary => false,
)))
end
end
# ------------------------------------------------------------------
# plot recipes
# Grab the first in line to be processed and pass it through apply_recipe
# to generate a list of RecipeData objects (data + attributes).
# If we applied a "plot recipe" without error, then add the returned datalist's KWs,
# otherwise we just add the original KW.
function _process_plotrecipe(plt::Plot, kw::KW, kw_list::Vector{KW}, still_to_process::Vector{KW})
if !isa(get(kw, :seriestype, nothing), Symbol)
# seriestype was never set, or it's not a Symbol, so it can't be a plot recipe
push!(kw_list, kw)
return
end
try
st = kw[:seriestype]
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
push!(still_to_process, data.d)
end
catch err
if isa(err, MethodError)
push!(kw_list, kw)
else
rethrow()
end
end
return
end
# ------------------------------------------------------------------
# setup plot and subplot
function _plot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
# merge in anything meant for the Plot
for kw in kw_list, (k,v) in kw
haskey(_plot_defaults, k) && (d[k] = pop!(kw, k))
end
# TODO: init subplots here
_update_plot_args(plt, d)
if !plt.init
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)
for (idx,sp) in enumerate(plt.subplots)
sp.plt = plt
sp.attr[:subplot_index] = idx
end
plt.init = true
end
# handle inset subplots
insets = plt[:inset_subplots]
if insets != nothing
if !(typeof(insets) <: AVec)
insets = [insets]
end
for inset in insets
parent, bb = is_2tuple(inset) ? inset : (nothing, inset)
P = typeof(parent)
if P <: Integer
parent = plt.subplots[parent]
elseif P == Symbol
parent = plt.spmap[parent]
else
parent = plt.layout
end
sp = Subplot(backend(), parent=parent)
sp.plt = plt
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})
# we'll keep a map of subplot to an attribute override dict.
# Subplot/Axis attributes set by a user/series recipe apply only to the
# Subplot object which they belong to.
# TODO: allow matrices to still apply to all subplots
sp_attrs = Dict{Subplot,Any}()
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)))
kw[:subplot] = sp
# extract subplot/axis attributes from kw and add to sp_attr
attr = KW()
for (k,v) in collect(kw)
if haskey(_subplot_defaults, k) || haskey(_axis_defaults_byletter, k)
attr[k] = pop!(kw, k)
end
if haskey(_axis_defaults, k)
v = pop!(kw, k)
for letter in (:x,:y,:z)
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 = 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
# do we need to link any axes together?
link_axes!(plt.layout, plt[:link])
end
# getting ready to add the series... last update to subplot from anything
# that might have been added during series recipes
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)
_update_subplot_args(plt, sp, d, sp_idx, true)
st = _override_seriestype_check(d, st)
# change to a 3d projection for this subplot?
if is3d(st)
sp.attr[:projection] = "3d"
end
# initialize now that we know the first series type
if !haskey(sp.attr, :init)
_initialize_subplot(plt, sp)
sp.attr[:init] = true
end
sp
end
# ------------------------------------------------------------------
# series types
function _override_seriestype_check(d::KW, st::Symbol)
# do we want to override the series type?
if !is3d(st) && !(st in (:contour,:contour3d))
z = d[:z]
if !isa(z, Void) && (size(d[:x]) == size(d[:y]) == size(z))
st = (st == :scatter ? :scatter3d : :path3d)
d[:seriestype] = st
end
end
st
end
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])
# 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
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, 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
# -------------------------------------------------------------------------------
# this method recursively applies series recipes when the seriestype is not supported
# natively by the backend
function _process_seriesrecipe(plt::Plot, d::KW)
# replace seriestype aliases
st = Symbol(d[:seriestype])
st = d[:seriestype] = get(_typeAliases, st, st)
# shapes shouldn't have fillrange set
if d[:seriestype] == :shape
d[:fillrange] = nothing
end
# if it's natively supported, finalize processing and pass along to the backend, otherwise recurse
if is_seriestype_supported(st)
sp = _prepare_subplot(plt, d)
_prepare_annotations(sp, d)
_expand_subplot_extrema(sp, d, st)
_update_series_attributes!(d, plt, sp)
_add_the_series(plt, sp, d)
else
# get a sub list of series for this seriestype
datalist = RecipesBase.apply_recipe(d, Val{st}, d[:x], d[:y], d[:z])
# 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)")
break
end
end
end
nothing
end
+226 -506
View File
@@ -1,18 +1,22 @@
type CurrentPlot
nullableplot::Nullable{PlottingObject}
mutable struct CurrentPlot
nullableplot::Nullable{AbstractPlot}
end
const CURRENT_PLOT = CurrentPlot(Nullable{PlottingObject}())
const CURRENT_PLOT = CurrentPlot(Nullable{AbstractPlot}())
isplotnull() = isnull(CURRENT_PLOT.nullableplot)
"""
current()
Returns the Plot object for the current plot
"""
function current()
if isplotnull()
error("No current plot/subplot")
end
get(CURRENT_PLOT.nullableplot)
if isplotnull()
error("No current plot/subplot")
end
get(CURRENT_PLOT.nullableplot)
end
current(plot::PlottingObject) = (CURRENT_PLOT.nullableplot = Nullable(plot))
current(plot::AbstractPlot) = (CURRENT_PLOT.nullableplot = Nullable(plot))
# ---------------------------------------------------------
@@ -22,553 +26,269 @@ Base.print(io::IO, plt::Plot) = print(io, string(plt))
Base.show(io::IO, plt::Plot) = print(io, string(plt))
getplot(plt::Plot) = plt
getplotargs(plt::Plot, idx::Int = 1) = plt.plotargs
getattr(plt::Plot, idx::Int = 1) = plt.attr
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
plot!(args...; kw...) # adds to the `current`
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
plot(args...; kw...) # creates a new plot window, and sets it to be the current
plot!(args...; kw...) # adds to the `current`
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
```
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...)
pkg = backend()
d = Dict(kw)
preprocessArgs!(d)
dumpdict(d, "After plot preprocessing")
d = KW(kw)
preprocessArgs!(d)
plotargs = merge(d, getPlotArgs(pkg, d, 1))
dumpdict(plotargs, "Plot args")
plt = _create_plot(pkg; plotargs...) # create a new, blank plot
# create an empty Plot then process
plt = Plot()
# plt.user_attr = d
_plot!(plt, d, args)
end
delete!(d, :background_color)
plot!(plt, args...; d...) # add to it
# build a new plot from existing plots
# note: we split into plt1 and plts_tail so we can dispatch correctly
function plot(plt1::Plot, plts_tail::Plot...; kw...)
d = KW(kw)
preprocessArgs!(d)
# build our plot vector from the args
n = length(plts_tail) + 1
plts = Array{Plot}(n)
plts[1] = plt1
for (i,plt) in enumerate(plts_tail)
plts[i+1] = plt
end
# compute the layout
layout = layout_args(d, n)[1]
num_sp = sum([length(p.subplots) for p in plts])
# create a new plot object, with subplot list/map made of existing subplots.
# note: we create a new backend figure for this new plot object
# note: all subplots and series "belong" to this new plot...
plt = Plot()
# TODO: build the user_attr dict by creating "Any matrices" for the args of each subplot
# 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, copy(p.attr))
plt.n += p.n
end
_update_plot_args(plt, d)
# pass new plot to the backend
plt.o = _create_backend_figure(plt)
plt.init = true
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)
if sp in sp.plt.inset_subplots
push!(plt.inset_subplots, sp)
end
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
# first apply any args for the subplots
for (idx,sp) in enumerate(plt.subplots)
_update_subplot_args(plt, sp, d, idx, false)
end
# finish up
current(plt)
_do_plot_show(plt, get(d, :show, default(:show)))
plt
end
# this adds to the current plot, or creates a new plot if none are current
function plot!(args...; kw...)
local plt
try
plt = current()
catch
return plot(args...; kw...)
end
plot!(current(), args...; kw...)
end
# not allowed:
function plot!(subplt::Subplot, args...; kw...)
error("Can't call plot! on a Subplot!")
local plt
try
plt = current()
catch
return plot(args...; kw...)
end
plot!(current(), args...; kw...)
end
# this adds to a specific plot... most plot commands will flow through here
function plot!(plt::Plot, args...; kw...)
d = Dict(kw)
preprocessArgs!(d)
d = KW(kw)
preprocessArgs!(d)
# merge!(plt.user_attr, d)
_plot!(plt, d, args)
end
# for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, args...; kw...)
# -------------------------------------------------------------------------------
dumpdict(d, "After plot! preprocessing")
# this is the core plotting function. recursively apply recipes to build
# 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
warnOnUnsupportedArgs(plt.backend, d)
# grouping
groupargs = get(d, :group, nothing) == nothing ? [] : [extractGroupArgs(d[:group], args...)]
# just in case the backend needs to set up the plot (make it current or something)
_before_add_series(plt)
# get the list of dictionaries, one per series
seriesArgList, xmeta, ymeta = createKWargsList(plt, groupargs..., args...; d...)
# if we were able to extract guide information from the series inputs, then update the plot
# @show xmeta, ymeta
updateDictWithMeta(d, plt.plotargs, xmeta, true)
updateDictWithMeta(d, plt.plotargs, ymeta, false)
# now we can plot the series
for (i,di) in enumerate(seriesArgList)
plt.n += 1
if !stringsSupported()
setTicksFromStringVector(d, di, :x, :xticks)
setTicksFromStringVector(d, di, :y, :yticks)
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
# remove plot args
for k in keys(_plotDefaults)
delete!(di, k)
# --------------------------------
# "USER RECIPES"
# --------------------------------
kw_list = _process_userrecipes(plt, d, args)
# info(1)
# map(DD, kw_list)
# --------------------------------
# "PLOT RECIPES"
# --------------------------------
# "plot recipe", which acts like a series type, and is processed before
# the plot layout is created, which allows for setting layouts and other plot-wide attributes.
# we get inputs which have been fully processed by "user recipes" and "type recipes",
# so we can expect standard vectors, surfaces, etc. No defaults have been set yet.
still_to_process = kw_list
kw_list = KW[]
while !isempty(still_to_process)
next_kw = shift!(still_to_process)
_process_plotrecipe(plt, next_kw, kw_list, still_to_process)
end
dumpdict(di, "Series $i")
# info(2)
# map(DD, kw_list)
_add_series(plt.backend, plt; di...)
end
# --------------------------------
# Plot/Subplot/Layout setup
# --------------------------------
_plot_setup(plt, d, kw_list)
_subplot_setup(plt, d, kw_list)
_add_annotations(plt, d)
# !!! note: At this point, kw_list is fully decomposed into individual series... one KW per series. !!!
# !!! The next step is to recursively apply series recipes until the backend supports that series type !!!
warnOnUnsupportedScales(plt.backend, d)
# --------------------------------
# "SERIES RECIPES"
# --------------------------------
# info(3)
# map(DD, kw_list)
# add title, axis labels, ticks, etc
if !haskey(d, :subplot)
merge!(plt.plotargs, d)
dumpdict(plt.plotargs, "Updating plot items")
_update_plot(plt, plt.plotargs)
end
for kw in kw_list
sp::Subplot = kw[:subplot]
# idx = get_subplot_index(plt, sp)
_update_plot_pos_size(plt, d)
# # we update subplot args in case something like the color palatte is part of the recipe
# _update_subplot_args(plt, sp, kw, idx, true)
current(plt)
# set default values, select from attribute cycles, and generally set the final attributes
_add_defaults!(kw, plt, sp, command_idx(kw_list,kw))
# NOTE: lets ignore the show param and effectively use the semicolon at the end of the REPL statement
# # do we want to show it?
if haskey(d, :show) && d[:show]
gui()
end
plt
end
# --------------------------------------------------------------------
# if x or y are a vector of strings, we should create a list of unique strings,
# and map x/y to be the index of the string... then set the x/y tick labels
function setTicksFromStringVector(d::Dict, di::Dict, sym::Symbol, ticksym::Symbol)
# if the x or y values are strings, set ticks to the unique values, and x/y to the indices of the ticks
v = di[sym]
isa(v, AbstractArray) || return
T = eltype(v)
if T <: @compat(AbstractString) || (!isempty(T.types) && all(x -> x <: @compat(AbstractString), T.types))
ticks = unique(di[sym])
di[sym] = Int[findnext(ticks, v, 1) for v in di[sym]]
if !haskey(d, ticksym) || d[ticksym] == :auto
d[ticksym] = (collect(1:length(ticks)), UTF8String[t for t in ticks])
end
end
end
# --------------------------------------------------------------------
_before_add_series(plt::Plot) = nothing
# --------------------------------------------------------------------
# should we update the x/y label given the meta info during input slicing?
function updateDictWithMeta(d::Dict, plotargs::Dict, meta::Symbol, isx::Bool)
lsym = isx ? :xlabel : :ylabel
if plotargs[lsym] == default(lsym)
d[lsym] = string(meta)
end
end
updateDictWithMeta(d::Dict, plotargs::Dict, meta, isx::Bool) = nothing
# --------------------------------------------------------------------
annotations(::@compat(Void)) = []
annotations{X,Y,V}(v::AVec{@compat(Tuple{X,Y,V})}) = v
annotations{X,Y,V}(t::@compat(Tuple{X,Y,V})) = [t]
annotations(v::AVec{PlotText}) = v
annotations(v::AVec) = map(PlotText, v)
annotations(anns) = error("Expecting a tuple (or vector of tuples) for annotations: ",
"(x, y, annotation)\n got: $(typeof(anns))")
function _add_annotations(plt::Plot, d::Dict)
anns = annotations(get(d, :annotation, nothing))
if !isempty(anns)
# if we just have a list of PlotText objects, then create (x,y,text) tuples
if typeof(anns) <: AVec{PlotText}
x, y = plt[plt.n]
anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
# now we have a fully specified series, with colors chosen. we must recursively handle
# series recipes, which dispatch on seriestype. If a backend does not natively support a seriestype,
# we check for a recipe that will convert that series type into one made up of lower-level components.
# For example, a histogram is just a bar plot with binned data, a bar plot is really a filled step plot,
# and a step plot is really just a path. So any backend that supports drawing a path will implicitly
# be able to support step, bar, and histogram plots (and any recipes that use those components).
_process_seriesrecipe(plt, kw)
end
_add_annotations(plt, anns)
end
end
# --------------------------------
current(plt)
# --------------------------------------------------------------------
function Base.copy(plt::Plot)
backend(plt.backend)
plt2 = plot(; plt.plotargs...)
for sargs in plt.seriesargs
sargs = filter((k,v) -> haskey(_seriesDefaults,k), sargs)
plot!(plt2; sargs...)
end
plt2
end
# --------------------------------------------------------------------
# create a new "createKWargsList" which converts all inputs into xs = Any[xitems], ys = Any[yitems].
# Special handling for: no args, xmin/xmax, parametric, dataframes
# Then once inputs have been converted, build the series args, map functions, etc.
# 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}})
all3D(d::Dict) = trueOrAllTrue(lt -> lt in (:contour, :surface, :wireframe, :image), get(d, :linetype, :none))
# missing
convertToAnyVector(v::@compat(Void), d::Dict) = Any[nothing], nothing
# fixed number of blank series
convertToAnyVector(n::Integer, d::Dict) = Any[zeros(0) for i in 1:n], nothing
# numeric vector
convertToAnyVector{T<:Real}(v::AVec{T}, d::Dict) = Any[v], nothing
# string vector
convertToAnyVector{T<:@compat(AbstractString)}(v::AVec{T}, d::Dict) = Any[v], nothing
# numeric matrix
function convertToAnyVector{T<:Real}(v::AMat{T}, d::Dict)
if all3D(d)
Any[Surface(v)]
else
Any[v[:,i] for i in 1:size(v,2)]
end, nothing
end
# function
convertToAnyVector(f::Function, d::Dict) = Any[f], nothing
# surface
convertToAnyVector(s::Surface, d::Dict) = Any[s], nothing
# vector of OHLC
convertToAnyVector(v::AVec{OHLC}, d::Dict) = Any[v], nothing
# dates
convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}, d::Dict) = Any[dts], nothing
# list of things (maybe other vectors, functions, or something else)
function convertToAnyVector(v::AVec, d::Dict)
if all(x -> typeof(x) <: Real, v)
# all real numbers wrap the whole vector as one item
Any[convert(Vector{Float64}, v)], nothing
else
# something else... treat each element as an item
vcat(Any[convertToAnyVector(vi, d)[1] for vi in v]...), nothing
# Any[vi for vi in v], nothing
end
end
# --------------------------------------------------------------------
# in computeXandY, we take in any of the possible items, convert into proper x/y vectors, then return.
# this is also where all the "set x to 1:length(y)" happens, and also where we assert on lengths.
computeX(x::@compat(Void), y) = 1:size(y,1)
computeX(x, y) = copy(x)
computeY(x, y::Function) = map(y, x)
computeY(x, y) = copy(y)
function computeXandY(x, y)
if x == nothing && isa(y, Function)
error("If you want to plot the function `$y`, you need to define the x values somehow!")
end
x, y = computeX(x,y), computeY(x,y)
# @assert length(x) == length(y)
x, y
end
# --------------------------------------------------------------------
# create n=max(mx,my) series arguments. the shorter list is cycled through
# note: everything should flow through this
function createKWargsList(plt::PlottingObject, x, y; kw...)
kwdict = Dict(kw)
xs, xmeta = convertToAnyVector(x, kwdict)
ys, ymeta = convertToAnyVector(y, kwdict)
mx = length(xs)
my = length(ys)
ret = Any[]
for i in 1:max(mx, my)
# try to set labels using ymeta
d = copy(kwdict)
if !haskey(d, :label) && ymeta != nothing
if isa(ymeta, Symbol)
d[:label] = string(ymeta)
elseif isa(ymeta, AVec{Symbol})
d[:label] = string(ymeta[mod1(i,length(ymeta))])
end
end
# build the series arg dict
numUncounted = get(d, :numUncounted, 0)
n = plt.n + i + numUncounted
dumpdict(d, "before getSeriesArgs")
d = getSeriesArgs(plt.backend, getplotargs(plt, n), d, i + numUncounted, convertSeriesIndex(plt, n), n)
dumpdict(d, "after getSeriesArgs")
d[:x], d[:y] = computeXandY(xs[mod1(i,mx)], ys[mod1(i,my)])
lt = d[:linetype]
if isa(d[:y], Surface)
if lt in (:contour, :surface, :wireframe, :image)
z = d[:y]
d[:y] = 1:size(z,2)
d[lt == :image ? :zcolor : :z] = z
end
end
if haskey(d, :idxfilter)
d[:x] = d[:x][d[:idxfilter]]
d[:y] = d[:y][d[:idxfilter]]
end
# for linetype `line`, need to sort by x values
if lt == :line
# order by x
indices = sortperm(d[:x])
d[:x] = d[:x][indices]
d[:y] = d[:y][indices]
d[:linetype] = :path
end
# map functions to vectors
if isa(d[:zcolor], Function)
d[:zcolor] = map(d[:zcolor], d[:x])
end
if isa(d[:fillrange], Function)
d[:fillrange] = map(d[:fillrange], d[:x])
end
# cleanup those fields that were used only for generating kw args
for k in (:idxfilter, :numUncounted, :dataframe)
delete!(d, k)
end
# add it to our series list
push!(ret, d)
end
ret, xmeta, ymeta
end
# handle grouping
function createKWargsList(plt::PlottingObject, groupby::GroupBy, args...; kw...)
ret = Any[]
for (i,glab) in enumerate(groupby.groupLabels)
# TODO: don't automatically overwrite labels
kwlist, xmeta, ymeta = createKWargsList(plt, args...; kw...,
idxfilter = groupby.groupIds[i],
label = string(glab),
numUncounted = length(ret)) # we count the idx from plt.n + numUncounted + i
append!(ret, kwlist)
end
ret, nothing, nothing # TODO: handle passing meta through
end
# pass it off to the x/y version
function createKWargsList(plt::PlottingObject, y; kw...)
createKWargsList(plt, nothing, y; kw...)
end
# 3d line or scatter
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, zvec::AVec; kw...)
d = Dict(kw)
if !(get(d, :linetype, :none) in _3dTypes)
d[:linetype] = :path3d
end
createKWargsList(plt, x, y; z=zvec, d...)
end
function createKWargsList{T<:Real}(plt::PlottingObject, z::AMat{T}; kw...)
d = Dict(kw)
if all3D(d)
n,m = size(z)
createKWargsList(plt, 1:n, 1:m, z; kw...)
else
createKWargsList(plt, nothing, z; kw...)
end
end
# contours or surfaces... function grid
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, zf::Function; kw...)
# only allow sorted x/y for now
# TODO: auto sort x/y/z properly
@assert x == sort(x)
@assert y == sort(y)
surface = Float64[zf(xi, yi) for xi in x, yi in y]
createKWargsList(plt, x, y, surface; kw...) # passes it to the zmat version
end
# contours or surfaces... matrix grid
function createKWargsList{T<:Real}(plt::PlottingObject, x::AVec, y::AVec, zmat::AMat{T}; kw...)
# only allow sorted x/y for now
# TODO: auto sort x/y/z properly
@assert x == sort(x)
@assert y == sort(y)
@assert size(zmat) == (length(x), length(y))
# surf = Surface(convert(Matrix{Float64}, zmat))
# surf = Array(Any,1,1)
# surf[1,1] = convert(Matrix{Float64}, zmat)
d = Dict(kw)
d[:z] = Surface(convert(Matrix{Float64}, zmat))
if !(get(d, :linetype, :none) in (:contour, :surface, :wireframe))
d[:linetype] = :contour
end
createKWargsList(plt, x, y; d...) #, z = surf)
end
# contours or surfaces... general x, y grid
function createKWargsList{T<:Real}(plt::PlottingObject, x::AMat{T}, y::AMat{T}, zmat::AMat{T}; kw...)
@assert size(zmat) == size(x) == size(y)
surf = Surface(convert(Matrix{Float64}, zmat))
# surf = Array(Any,1,1)
# surf[1,1] = convert(Matrix{Float64}, zmat)
d = Dict(kw)
d[:z] = Surface(convert(Matrix{Float64}, zmat))
if !(get(d, :linetype, :none) in (:contour, :surface, :wireframe))
d[:linetype] = :contour
end
createKWargsList(plt, Any[x], Any[y]; d...) #kw..., z = surf, linetype = :contour)
end
function createKWargsList(plt::PlottingObject, surf::Surface; kw...)
createKWargsList(plt, 1:size(surf.surf,1), 1:size(surf.surf,2), convert(Matrix{Float64}, surf.surf); kw...)
end
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, surf::Surface; kw...)
createKWargsList(plt, x, y, convert(Matrix{Float64}, surf.surf); kw...)
end
function createKWargsList(plt::PlottingObject, f::FuncOrFuncs; kw...)
createKWargsList(plt, f, xmin(plt), xmax(plt); kw...)
end
# list of functions
function createKWargsList(plt::PlottingObject, f::FuncOrFuncs, x; kw...)
@assert !(typeof(x) <: FuncOrFuncs) # otherwise we'd hit infinite recursion here
createKWargsList(plt, x, f; kw...)
end
# special handling... xmin/xmax with function(s)
function createKWargsList(plt::PlottingObject, f::FuncOrFuncs, xmin::Real, xmax::Real; kw...)
width = get(plt.plotargs, :size, (100,))[1]
x = collect(linspace(xmin, xmax, width)) # we don't need more than the width
createKWargsList(plt, x, f; kw...)
end
mapFuncOrFuncs(f::Function, u::AVec) = map(f, u)
mapFuncOrFuncs(fs::AVec{Function}, u::AVec) = [map(f, u) for f in fs]
# special handling... xmin/xmax with parametric function(s)
createKWargsList{T<:Real}(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, u::AVec{T}; kw...) = createKWargsList(plt, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u); kw...)
createKWargsList{T<:Real}(plt::PlottingObject, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs; kw...) = createKWargsList(plt, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u); kw...)
createKWargsList(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Real, umax::Real, numPoints::Int = 1000; kw...) = createKWargsList(plt, fx, fy, linspace(umin, umax, numPoints); kw...)
# special handling... 3D parametric function(s)
createKWargsList{T<:Real}(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, u::AVec{T}; kw...) = createKWargsList(plt, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u); kw...)
createKWargsList{T<:Real}(plt::PlottingObject, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs; kw...) = createKWargsList(plt, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u); kw...)
createKWargsList(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, umin::Real, umax::Real, numPoints::Int = 1000; kw...) = createKWargsList(plt, fx, fy, fz, linspace(umin, umax, numPoints); kw...)
# (x,y) tuples
function createKWargsList{R1<:Real,R2<:Real}(plt::PlottingObject, xy::AVec{Tuple{R1,R2}}; kw...)
createKWargsList(plt, unzip(xy)...; kw...)
end
function createKWargsList{R1<:Real,R2<:Real}(plt::PlottingObject, xy::Tuple{R1,R2}; kw...)
createKWargsList(plt, [xy[1]], [xy[2]]; kw...)
end
# special handling... no args... 1 series
function createKWargsList(plt::PlottingObject; kw...)
d = Dict(kw)
if !haskey(d, :y)
# assume we just want to create an empty plot object which can be added to later
return [], nothing, nothing
# error("Called plot/subplot without args... must set y in the keyword args. Example: plot(; y=rand(10))")
end
if haskey(d, :x)
return createKWargsList(plt, d[:x], d[:y]; kw...)
else
return createKWargsList(plt, d[:y]; kw...)
end
end
# --------------------------------------------------------------------
# @require FixedSizeArrays begin
unzip{T}(x::AVec{FixedSizeArrays.Vec{2,T}}) = T[xi[1] for xi in x], T[xi[2] for xi in x]
unzip{T}(x::FixedSizeArrays.Vec{2,T}) = T[x[1]], T[x[2]]
function createKWargsList{T<:Real}(plt::PlottingObject, xy::AVec{FixedSizeArrays.Vec{2,T}}; kw...)
createKWargsList(plt, unzip(xy)...; kw...)
end
function createKWargsList{T<:Real}(plt::PlottingObject, xy::FixedSizeArrays.Vec{2,T}; kw...)
createKWargsList(plt, [xy[1]], [xy[2]]; kw...)
end
# end
# --------------------------------------------------------------------
# For DataFrame support. Imports DataFrames and defines the necessary methods which support them.
@require DataFrames begin
function createKWargsList(plt::PlottingObject, df::DataFrames.AbstractDataFrame, args...; kw...)
createKWargsList(plt, args...; kw..., dataframe = df)
end
# expecting the column name of a dataframe that was passed in... anything else should error
function extractGroupArgs(s::Symbol, df::DataFrames.AbstractDataFrame, args...)
if haskey(df, s)
return extractGroupArgs(df[s])
else
error("Got a symbol, and expected that to be a key in d[:dataframe]. s=$s d=$d")
end
end
function getDataFrameFromKW(d::Dict)
# for (k,v) in kw
# if k == :dataframe
# return v
# end
# do we want to force display?
# if plt[:show]
# gui(plt)
# end
get(d, :dataframe) do
error("Missing dataframe argument!")
end
end
# the conversion functions for when we pass symbols or vectors of symbols to reference dataframes
# convertToAnyVector(s::Symbol; kw...) = Any[getDataFrameFromKW(;kw...)[s]], s
# convertToAnyVector(v::AVec{Symbol}; kw...) = (df = getDataFrameFromKW(;kw...); Any[df[s] for s in v]), v
convertToAnyVector(s::Symbol, d::Dict) = Any[getDataFrameFromKW(d)[s]], s
convertToAnyVector(v::AVec{Symbol}, d::Dict) = (df = getDataFrameFromKW(d); Any[df[s] for s in v]), v
_do_plot_show(plt, plt[:show])
plt
end
# we're getting ready to display/output. prep for layout calcs, then update
# the plot object after
function prepare_output(plt::Plot)
_before_layout_calcs(plt)
w, h = plt.attr[:size]
plt.layout.bbox = BoundingBox(0mm, 0mm, w*px, h*px)
# One pass down and back up the tree to compute the minimum padding
# of the children on the perimeter. This is an backend callback.
_update_min_padding!(plt.layout)
for sp in plt.inset_subplots
_update_min_padding!(sp)
end
# now another pass down, to update the bounding boxes
update_child_bboxes!(plt.layout)
# update those bounding boxes of inset subplots
update_inset_bboxes!(plt)
# the backend callback, to reposition subplots, etc
_update_plot_object(plt)
end
function backend_object(plt::Plot)
prepare_output(plt)
plt.o
end
# --------------------------------------------------------------------
# plot to a Subplot
function plot(sp::Subplot, args...; kw...)
plt = sp.plt
plot(plt, args...; kw..., subplot = findfirst(plt.subplots, sp))
end
function plot!(sp::Subplot, args...; kw...)
plt = sp.plt
plot!(plt, args...; kw..., subplot = findfirst(plt.subplots, sp))
end
# --------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More