5252-- Right now there's no easy way to bind to an option other than the last one
5353-- unless you want to pass options in as parameters.
5454--
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
5656-- 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".
5861-----------------------------------------------------------------------------
5962
6063module Graphics.Matplotlib
6164 ( module Graphics.Matplotlib
6265 -- * 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 )
6568where
6669import Data.List
6770import Data.Aeson
@@ -101,20 +104,21 @@ histogram values bins = readData [values] % dataHistogram 0 bins
101104
102105-- | Plot a 2D histogram for the given values with 'bins'
103106histogram2D x y = readData [x,y] %
104- mp # " plot.hist2d(data[0], data[1]" ## " )"
107+ mp # " plot.sci(ax. hist2d(data[0], data[1]" ## " )[-1] )"
105108
106109-- | Plot the given values as a scatter plot
107110scatter :: (ToJSON t1 , ToJSON t ) => t1 -> t -> Matplotlib
108111scatter x y = readData (x, y)
109- % mp # " ax.scatter(data[0], data[1]" ## " )"
112+ % mp # " plot.sci( ax.scatter(data[0], data[1]" ## " ) )"
110113
111114-- | Plot a line
112115line :: (ToJSON t1 , ToJSON t ) => t1 -> t -> Matplotlib
113116line x y = plot x y `def` [o1 " -" ]
114117
115118-- | 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]" ## " )"
118122
119123-- | Plot a line given a function that will be executed for each element of
120124-- given list. The list provides the x values, the function the y values.
@@ -165,12 +169,12 @@ line1 y = line [0..length y] y
165169-- | Plot a matrix
166170matShow :: ToJSON a => a -> Matplotlib
167171matShow d = readData d
168- % (mp # " plot.matshow(data" ## " )" )
172+ % (mp # " plot.sci(ax. matshow(data" ## " ) )" )
169173
170174-- | Plot a matrix
171175pcolor :: ToJSON a => a -> Matplotlib
172176pcolor d = readData d
173- % (mp # " plot.pcolor(np.array(data)" ## " )" )
177+ % (mp # " plot.sci(ax. pcolor(np.array(data)" ## " ) )" )
174178
175179-- | Plot a KDE of the given functions; a good bandwith will be chosen automatically
176180density :: [Double ] -> Maybe (Double , Double ) -> Matplotlib
@@ -197,7 +201,7 @@ setUnicode b = mp # "matplotlib.rcParams['text.latex.unicode'] = " # b
197201
198202-- | Plot the 'a' and 'b' entries of the data object
199203dataPlot :: (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 # " ]" ## " )"
201205
202206-- | Plot the Haskell objects 'x' and 'y' as a line
203207plot :: (ToJSON t , ToJSON t1 ) => t1 -> t -> Matplotlib
@@ -216,7 +220,7 @@ dateLine x y xunit (yearStart, monthStart, dayStart) =
216220
217221-- | Create a histogram for the 'a' entry of the data array
218222dataHistogram :: (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 ## " )"
220224
221225-- | Create a scatter plot accessing the given fields of the data array
222226dataScatter :: (MplotValue val1 , MplotValue val ) => val1 -> val -> Matplotlib
@@ -309,8 +313,14 @@ acorr x = readData x % mp # "ax.acorr(data" ## ")"
309313-- | Plot text at a specified location
310314text x y s = mp # " ax.text(" # x # " ," # y # " ," # raw s ## " )"
311315
316+ figText x y s = mp # " plot.figtext(" # x # " ," # y # " ," # raw s ## " )"
317+
312318-- * Layout, axes, and legends
313319
320+ -- | Square up the aspect ratio of a plot.
321+ setAspect :: Matplotlib
322+ setAspect = mp # " ax.set_aspect(" ## " )"
323+
314324-- | Square up the aspect ratio of a plot.
315325squareAxes :: Matplotlib
316326squareAxes = mp # " ax.set_aspect('equal')"
@@ -353,14 +363,6 @@ legend = mp # "ax.legend(" ## ")"
353363-- TODO This refers to the plot and not an axis. Might cause trouble with subplots
354364colorbar = mp # " plot.colorbar(" ## " )"
355365
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-
364366-- | Add a title
365367title :: String -> Matplotlib
366368title s = mp # " ax.set_title(" # raw s ## " )"
@@ -397,22 +399,70 @@ zLabel label = mp # "ax.set_zlabel(" # raw label ## ")"
397399
398400setSizeInches w h = mp # " fig.set_size_inches(" # w # " ," # h # " , forward=True)"
399401
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+
400445-- * Subplots
401446
447+ setAx = mp # " plot.sca(ax) "
448+
402449-- | 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
404451
405452-- | 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
407454
408455-- | Creates subplots and stores them in an internal variable
409456subplots = mp # " fig, axes = plot.subplots(" ## " )"
457+ % mp # " axes = np.asarray(axes)"
458+ % mp # " axes = axes.flatten()"
459+ % updateAxes % setAx
410460
411461-- | Access a subplot
412- setSubplot s = mp # " ax = axes[" # s # " ]"
462+ setSubplot s = mp # " ax = axes[" # s # " ]" % setAx
413463
414464-- | Add axes to a figure
415- axes = mp # " ax = plot.axes(" ## " )" % updateAxes
465+ axes = mp # " ax = plot.axes(" ## " )" % updateAxes % setAx
416466
417467-- | Creates a new figure with the given id. If the Id is already in use it
418468-- switches to that figure.
0 commit comments