Matplotlib: using a curly object to initialize a chart

I am creating a plot tool class for a specific experiment. I currently have two construction methods, a static plot using imshow () and a movie format. using imshow ().

Both methods and any future methods get parameters that are the same for any particular construction method that I could write. I have all these parameters in the config object while using the plot class.

I do not want to rewrite the code in every build method. I would like to initialize an object (AxesImage, I think) that will have these arguments: vmin, vmax, extent_dim, Xlocs, Xlabels, Ylocs, Ylabels.

Then I just pass this object to various methods that do some other specific things. I do not understand how to do this ...

import matplotlib.pyplot as plt data = data_dict[type] # could be real part of a complex number, phase, or the mag... v_min, v_max = self.get_data_type_scale(data_dict, Type) freq = data_dict['freq'] # essentially sets the aspect of the plot since the x and y resolutions could be different extent_dim = self._get_extent(2) # gets the labels for physical dimensions of the experiment Xlocs,Xlabels,Ylocs,Ylabels = self._get_ticks(5,5,extent_dim) # in the guts of a plot method, the basic idea is the call below. plt.imshow(data[0,:,:],cmap='jet',vmin=v_min,... vmax=v_max,origin='lower', extent = extent_dim) plt.title('Type: %s Freq: %.3e Hz' %(Type,data_dict['freq'][0]) ) plt.xticks(Xlocs, Xlabels) plt.yticks(Ylocs,Ylabels) 
+4
source share
2 answers

First you need to understand a bit of matplotlib architecture (see here for a long article by the founder and current lead developer). At the bottom of the backend layer, which refers to rendering and talking to equipment. At the top of this layer there are artists who know how to draw themselves, telling the backend what to do. At the top of this layer is the pyplot state machine interface, which mimics MATLAB .

Everything that you see in the picture is represented inside as Artist , and artists may contain other artists. For example, an Axes object tracks its children artists , which are axes, ticks, ticks, labels, your lines or images, etc., and Axes objects are children of Figure . When you tell a figure to draw itself (via fig.canvas.draw() ), all child artists are drawn recursively.

One of the reverse ways of this project is that this instance of Artist can be on the same figure (and moving them between the figures is difficult), so you cannot create an AxesImage object and then reuse it.

This design also separates information about what artists know. Axes objects are aware of things such as location and cue marks and display range (what he does when he knows about the Axis object, but it gets even bigger in the weeds). Things like vmin and vmax are encapsulated in Normalize ( doc ) objects that AxesImage tracks. This means that you will need to make out how you deal with everything on your list.

I would suggest either using a factory-like pattern here or a curry-like pattern

Factory - like:

 def set_up_axes(some, arguements): ''' Factory to make configured axes ( ''' fig, ax = plt.subplots(1, 1) # or what ever layout you want ax.set_*(...) return fig, ax my_norm = matplotlib.colors.Normalize(vmin, mmax) # or write a factory to do fancier stuff fig, ax = set_up_axes(...) ax.imshow(..., norm=my_norm) fig2, ax2 = set_up_axes(...) ax2.imshow(..., norm=mynorm) 

You can complete the entire set of kwargs to easily use them as such:

 my_imshow_args = {'extent':[...], 'interpolation':'nearest', 'norm': my_norm, ...} ax2.imshow(..., **my_imshow_args) 

Curry like:

 def my_imshow(im, ax=None, *args, **kwargs): if ax is None: ax = plt.gca() # do all of your axes set up ax.set_xlim(..) # set default vmin and vmax # you can drop some of these conditionals if you don't want to be # able to explicitly override the defaults if 'norm' not in kwargs: vmin = kwargs.pop('vmin', None) vmax = kwargs.pop('vmax', None) if vmin is None: vmin = default_vmin # or what ever if vmax is None: vmax = default_vmax my_norm = matplotlib.colors.Normalize(vmin, mmax) kwargs['norm'] = norm # add a similar block for `extent` # or any other kwargs you want to change the default of ax.figure.canvas.draw() # if you want to force a re-draw return ax.imshow(im, *args, **kwargs) 

If you want to be super smart, you can plt.imshow monkey patch with your version

 plt.imshow = my_imshow 

There is also an rcParams interface that allows you to change the default values โ€‹โ€‹for a lot of bits and parts of matplotlib in a global path.

And another way to accomplish (via partial )

+10
source

To show the graph, you want to use fig.canvas.draw() , where fig is an instance of the Figure class. fig.canvas.draw() is a version of the interactive shell API (read: pylab ) draw()

If you need to get Axes or Figure from an AxesImage object, you can call either im.get_axes() or im.get_figure() , respectively.

As for writing โ€œgoodโ€ object-oriented code for UI examples , this may be a good place to start.

+2
source

Source: https://habr.com/ru/post/1497529/


All Articles