52
52
-- Right now there's no easy way to bind to an option other than the last one
53
53
-- unless you want to pass options in as parameters.
54
54
--
55
- -- TODO The generated Python code should follow some invariants. It must maintain the
55
+ -- The generated Python code should follow some invariants. It must maintain the
56
56
-- current figure in "fig", all available axes in "axes", and the current axis
57
- -- in "ax".
57
+ -- in "ax". Plotting commands should use the current axis, never the plot
58
+ -- itself; the two APIs are almost identical. When creating low-level bindings
59
+ -- one must remember to call "plot.sci" to set the current image when plotting a
60
+ -- graph. The current spine of the axes that's being manipulated is in "spine".
58
61
-----------------------------------------------------------------------------
59
62
60
63
module Graphics.Matplotlib
61
64
( module Graphics.Matplotlib
62
65
-- * Creating custom plots and applying options
63
- , Matplotlib (), Option (),(@@) , (%) , o1 , o2 , (##) , (#) , mp , def , readData ,
64
- str , raw , lit , updateAxes , updateFigure )
66
+ , Matplotlib (), Option (),(@@) , (%) , o1 , o2 , (##) , (#) , mp , def , readData
67
+ , str , raw , lit , updateAxes , updateFigure , mapLinear )
65
68
where
66
69
import Data.List
67
70
import Data.Aeson
@@ -101,20 +104,21 @@ histogram values bins = readData [values] % dataHistogram 0 bins
101
104
102
105
-- | Plot a 2D histogram for the given values with 'bins'
103
106
histogram2D x y = readData [x,y] %
104
- mp # " plot.hist2d(data[0], data[1]" ## " )"
107
+ mp # " plot.sci(ax. hist2d(data[0], data[1]" ## " )[-1] )"
105
108
106
109
-- | Plot the given values as a scatter plot
107
110
scatter :: (ToJSON t1 , ToJSON t ) => t1 -> t -> Matplotlib
108
111
scatter x y = readData (x, y)
109
- % mp # " ax.scatter(data[0], data[1]" ## " )"
112
+ % mp # " plot.sci( ax.scatter(data[0], data[1]" ## " ) )"
110
113
111
114
-- | Plot a line
112
115
line :: (ToJSON t1 , ToJSON t ) => t1 -> t -> Matplotlib
113
116
line x y = plot x y `def` [o1 " -" ]
114
117
115
118
-- | Like 'plot' but takes an error bar value per point
116
- errorbar xs ys errs = readData (xs, ys, errs)
117
- % mp # " ax.errorbar(data[0], data[1], yerr=data[2]" ## " )"
119
+ -- errorbar :: (ToJSON x, ToJSON y, ToJSON xs, ToJSON ys) => x -> y -> Maybe xs -> Maybe ys -> Matplotlib
120
+ errorbar xs ys xerrs yerrs = readData (xs, ys, xerrs, yerrs)
121
+ % mp # " ax.errorbar(data[0], data[1], xerr=data[2], yerr=data[3]" ## " )"
118
122
119
123
-- | Plot a line given a function that will be executed for each element of
120
124
-- given list. The list provides the x values, the function the y values.
@@ -165,12 +169,12 @@ line1 y = line [0..length y] y
165
169
-- | Plot a matrix
166
170
matShow :: ToJSON a => a -> Matplotlib
167
171
matShow d = readData d
168
- % (mp # " plot.matshow(data" ## " )" )
172
+ % (mp # " plot.sci(ax. matshow(data" ## " ) )" )
169
173
170
174
-- | Plot a matrix
171
175
pcolor :: ToJSON a => a -> Matplotlib
172
176
pcolor d = readData d
173
- % (mp # " plot.pcolor(np.array(data)" ## " )" )
177
+ % (mp # " plot.sci(ax. pcolor(np.array(data)" ## " ) )" )
174
178
175
179
-- | Plot a KDE of the given functions; a good bandwith will be chosen automatically
176
180
density :: [Double ] -> Maybe (Double , Double ) -> Matplotlib
@@ -197,7 +201,7 @@ setUnicode b = mp # "matplotlib.rcParams['text.latex.unicode'] = " # b
197
201
198
202
-- | Plot the 'a' and 'b' entries of the data object
199
203
dataPlot :: (MplotValue val , MplotValue val1 ) => val1 -> val -> Matplotlib
200
- dataPlot a b = mp # " p = plot .plot(data[" # a # " ], data[" # b # " ]" ## " )"
204
+ dataPlot a b = mp # " p = ax .plot(data[" # a # " ], data[" # b # " ]" ## " )"
201
205
202
206
-- | Plot the Haskell objects 'x' and 'y' as a line
203
207
plot :: (ToJSON t , ToJSON t1 ) => t1 -> t -> Matplotlib
@@ -216,7 +220,7 @@ dateLine x y xunit (yearStart, monthStart, dayStart) =
216
220
217
221
-- | Create a histogram for the 'a' entry of the data array
218
222
dataHistogram :: (MplotValue val1 , MplotValue val ) => val1 -> val -> Matplotlib
219
- dataHistogram a bins = mp # " plot .hist(data[" # a # " ]," # bins ## " )"
223
+ dataHistogram a bins = mp # " ax .hist(data[" # a # " ]," # bins ## " )"
220
224
221
225
-- | Create a scatter plot accessing the given fields of the data array
222
226
dataScatter :: (MplotValue val1 , MplotValue val ) => val1 -> val -> Matplotlib
@@ -309,8 +313,14 @@ acorr x = readData x % mp # "ax.acorr(data" ## ")"
309
313
-- | Plot text at a specified location
310
314
text x y s = mp # " ax.text(" # x # " ," # y # " ," # raw s ## " )"
311
315
316
+ figText x y s = mp # " plot.figtext(" # x # " ," # y # " ," # raw s ## " )"
317
+
312
318
-- * Layout, axes, and legends
313
319
320
+ -- | Square up the aspect ratio of a plot.
321
+ setAspect :: Matplotlib
322
+ setAspect = mp # " ax.set_aspect(" ## " )"
323
+
314
324
-- | Square up the aspect ratio of a plot.
315
325
squareAxes :: Matplotlib
316
326
squareAxes = mp # " ax.set_aspect('equal')"
@@ -353,14 +363,6 @@ legend = mp # "ax.legend(" ## ")"
353
363
-- TODO This refers to the plot and not an axis. Might cause trouble with subplots
354
364
colorbar = mp # " plot.colorbar(" ## " )"
355
365
356
- -- | Set the spacing of ticks on the x axis
357
- axisXTickSpacing :: (MplotValue val1 , MplotValue val ) => val1 -> val -> Matplotlib
358
- axisXTickSpacing nr width = mp # " ax.set_xticks(np.arange(" # nr # " )+" # width ## " )"
359
-
360
- -- | Set the labels on the x axis
361
- axisXTickLabels :: MplotValue val => val -> Matplotlib
362
- axisXTickLabels labels = mp # " ax.set_xticklabels( (" # labels # " ) " ## " )"
363
-
364
366
-- | Add a title
365
367
title :: String -> Matplotlib
366
368
title s = mp # " ax.set_title(" # raw s ## " )"
@@ -397,22 +399,70 @@ zLabel label = mp # "ax.set_zlabel(" # raw label ## ")"
397
399
398
400
setSizeInches w h = mp # " fig.set_size_inches(" # w # " ," # h # " , forward=True)"
399
401
402
+ tightLayout = mp # " fig.tight_layout()"
403
+
404
+ xkcd = mp # " plot.xkcd()"
405
+
406
+ -- * Ticks
407
+
408
+ xticks l = mp # " ax.set_xticks(" # l # " )"
409
+ yticks l = mp # " ax.set_yticks(" # l # " )"
410
+ zticks l = mp # " ax.set_zticks(" # l # " )"
411
+
412
+ xtickLabels l = mp # " ax.set_xticklabels(" # l # " )"
413
+ ytickLabels l = mp # " ax.set_yticklabels(" # l # " )"
414
+ ztickLabels l = mp # " ax.set_zticklabels(" # l # " )"
415
+
416
+ -- | Set the spacing of ticks on the x axis
417
+ axisXTickSpacing :: (MplotValue val1 , MplotValue val ) => val1 -> val -> Matplotlib
418
+ axisXTickSpacing nr width = mp # " ax.set_xticks(np.arange(" # nr # " )+" # width ## " )"
419
+
420
+ -- | Set the labels on the x axis
421
+ axisXTickLabels :: MplotValue val => val -> Matplotlib
422
+ axisXTickLabels labels = mp # " ax.set_xticklabels( (" # labels # " ) " ## " )"
423
+
424
+ -- | Set the spacing of ticks on the y axis
425
+ axisYTickSpacing :: (MplotValue val1 , MplotValue val ) => val1 -> val -> Matplotlib
426
+ axisYTickSpacing nr width = mp # " ax.set_yticks(np.arange(" # nr # " )+" # width ## " )"
427
+
428
+ -- | Set the labels on the y axis
429
+ axisYTickLabels :: MplotValue val => val -> Matplotlib
430
+ axisYTickLabels labels = mp # " ax.set_yticklabels( (" # labels # " ) " ## " )"
431
+
432
+ axisXTicksPosition p = mp # " ax.xaxis.set_ticks_position('" # p # " ')"
433
+ axisYTicksPosition p = mp # " ax.yaxis.set_ticks_position('" # p # " ')"
434
+
435
+ -- * Spines
436
+
437
+ spine s = mp # " spine = ax.spines['" # s # " ']"
438
+
439
+ spineSetBounds l h = mp # " spine.set_bounds(" # l # " ," # h # " )"
440
+
441
+ spineSetVisible b = mp # " spine.set_visible(" # b # " )"
442
+
443
+ spineSetPosition s n = mp # " spine.set_position((" # s # " ," # n # " ))"
444
+
400
445
-- * Subplots
401
446
447
+ setAx = mp # " plot.sca(ax) "
448
+
402
449
-- | Create a subplot with the coordinates (r,c,f)
403
- addSubplot r c f = mp # " ax = plot.gcf().add_subplot(" # r # c # f ## " )" % updateAxes
450
+ addSubplot r c f = mp # " ax = plot.gcf().add_subplot(" # r # c # f ## " )" % updateAxes % setAx
404
451
405
452
-- | Access a subplot with the coordinates (r,c,f)
406
- getSubplot r c f = mp # " ax = plot.subplot(" # r # " ," # c # " ," # f ## " )" % updateAxes
453
+ getSubplot r c f = mp # " ax = plot.subplot(" # r # " ," # c # " ," # f ## " )" % updateAxes % setAx
407
454
408
455
-- | Creates subplots and stores them in an internal variable
409
456
subplots = mp # " fig, axes = plot.subplots(" ## " )"
457
+ % mp # " axes = np.asarray(axes)"
458
+ % mp # " axes = axes.flatten()"
459
+ % updateAxes % setAx
410
460
411
461
-- | Access a subplot
412
- setSubplot s = mp # " ax = axes[" # s # " ]"
462
+ setSubplot s = mp # " ax = axes[" # s # " ]" % setAx
413
463
414
464
-- | Add axes to a figure
415
- axes = mp # " ax = plot.axes(" ## " )" % updateAxes
465
+ axes = mp # " ax = plot.axes(" ## " )" % updateAxes % setAx
416
466
417
467
-- | Creates a new figure with the given id. If the Id is already in use it
418
468
-- switches to that figure.
0 commit comments