[英]Matplotlib: using a figure object to initialize a plot
I am building a class of plot tools for a specific experiment. 我正在为特定的实验构建一类绘图工具。 I currently have two plot methods, a static plot using imshow(), and a "movie" format also using imshow() .
我目前有两种绘图方法,一种是使用imshow()的静态绘图,另一种是使用imshow()的“movie”格式。
Both methods and any future methods, get parameters that are the same for any specific plotting method that I might write. 这两种方法和任何将来的方法都可以获得与我可能编写的任何特定绘图方法相同的参数。 I have all those parameters in a config object at the time the plot class is used.
我在使用plot类时在config对象中拥有所有这些参数。
I don't want to rewrite code in every plot method. 我不想在每个绘图方法中重写代码。 I would like to initialize an object (AxesImage I think) that will have these args set: vmin, vmax, extent_dim, Xlocs, Xlabels, Ylocs, Ylabels.
我想初始化一个对象(AxesImage,我认为)将设置这些args:vmin,vmax,extent_dim,Xlocs,Xlabels,Ylocs,Ylabels。
Then I just pass that object to various methods that do some other specific thing. 然后我将该对象传递给执行其他特定操作的各种方法。 I don't 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)
You need to understand a bit of architecture of matplotlib
first (see here for a long article by the founder and current lead developer). 您需要首先了解
matplotlib
的一些架构(请参阅此处以获取创始人和当前首席开发人员的长篇文章)。 At the bottom of the backend
layer which deals with rendering and talking to the hardware. 在
backend
层的底部,处理渲染和与硬件交谈。 On top of that layer are artists
which know how to draw them selves by tell the backend
object what to do. 在该层之上是
artists
,他们知道如何通过告诉backend
对象做什么来绘制自己。 On top of that layer is the pyplot
state machine interface which mimics MATLAB
. 在该层之上是模拟
MATLAB
的pyplot
状态机接口。
Everything you see in a figure is represented internally as an Artist
and artists can contain other artists. 您在图中看到的所有内容都在内部表示为
Artist
,艺术家可以包含其他艺术家。 For example, the Axes
object keeps track of it's children Artists
which are the axes spines, tickes, labels, your lines or images etc and Axes
objects are children of Figure
objects. 例如,
Axes
对象跟踪它的子项Artists
,它们是轴刺,标记,标签,线或图像等, Axes
对象是Figure
对象的子对象。 When you tell a figure to draw itself (via fig.canvas.draw()
) all the children artists are drawn recursively. 当你告诉一个人物画自己时(通过
fig.canvas.draw()
),所有的儿童艺术家都是递归绘制的。
One draw back of this design is that a given instantiation of an Artist
can be in exactly one figure (and moving them between figures is hard) so you can't make a AxesImage
object and then keep reusing it. 这个设计的一个
AxesImage
是, Artist
的给定实例可以只是一个图形(并且在图形之间移动它们很难),因此您不能创建AxesImage
对象然后继续重复使用它。
This design also separates what Artists
know about. 这种设计也将
Artists
了解的内容分开。 Axes
objects know about things like tick location and labels and the display range (which it does by knowing about Axis
object, but that is getting even more into the weeds). Axes
对象知道诸如刻度位置和标签之类的事情以及显示范围(通过了解Axis
对象来做到这一点,但这会更多地进入杂草)。 Things like vmin
and vmax
are encapsulated in Normalize
( doc ) objects which the AxesImage
keeps track of. 像
vmin
和vmax
这样的东西被封装在AxesImage
跟踪的Normalize
( doc )对象中。 This means that you will need to separate 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 wrap up a whole set of kwargs to easily re-use them as such: 您可以将一整套kwargs包装起来,以便轻松地重复使用它们:
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 clever, you can monkey-patch plt.imshow
with your version 如果你想变得非常聪明,你可以用你的版本修补
plt.imshow
plt.imshow = my_imshow
There is also the rcParams interface which will allow you to change the default values of many bits and pieces of matplotlib
in a global way. 还有rcParams接口,它允许您以全局方式更改
matplotlib
的许多位和默认值。
And yet another way to accomplish this (through partial
) 而另一种方法来实现这一目标(通过
partial
)
To show a plot you'll want to use fig.canvas.draw()
where fig
is an instance of the Figure
class. 要显示一个图,你需要使用
fig.canvas.draw()
,其中fig
是Figure
类的一个实例。 fig.canvas.draw()
is the API version of the interactive shell (read: pylab
) function draw()
fig.canvas.draw()
是交互式shell的API版本(读取: pylab
)函数draw()
If you need to get the Axes
or Figure
from an AxesImage
object you can call either im.get_axes()
or im.get_figure()
, respectively. 如果需要从
AxesImage
对象获取Axes
或Figure
,则可以分别调用im.get_axes()
或im.get_figure()
。
As far as writing "good" object-oriented code the user interface examples might be good place to start. 就编写“好的”面向对象代码而言,用户界面示例可能是开始的好地方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.