You need to understand a bit of architecture of matplotlib
first (see here for a long article by the founder and current lead developer). At the bottom of the backend
layer which deals with rendering and talking to the hardware. On top of that layer are artists
which know how to draw them selves by tell the backend
object what to do. On top of that layer is the pyplot
state machine interface which mimics MATLAB
.
Everything you see in a figure is represented internally as an Artist
and artists can contain other artists. 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. When you tell a figure to draw itself (via fig.canvas.draw()
) all the children artists are drawn recursively.
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.
This design also separates what Artists
know about. 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). Things like vmin
and vmax
are encapsulated in Normalize
(doc) objects which the AxesImage
keeps track of. 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:
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 = 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.
And yet another way to accomplish this (through partial
)