I have for quite some time noticed that some of the spirograph images were plotted smaller than I expected. They would be towards the bottom of the figure with a lot of empty background above them. I figured that somehow Matplotlib was not handling the calls to autoscale() correctly. And, the axes somehow kept the plot limits from the previous image. Or some such thing.

I figured if I wanted to save one of these kinds of image that when I recreated it with my repeat route that the image would be displayed as I expected it to be—filling out the plot area.

Putting That to the Test

I recently had just such an image I wished to save. So I finally had the chance to test my hypothesis.

Here’s what it looked like when I first generated the image.

spirograph image with the curve smaller than expected
Example of Small Curve in Larger Image

So I set up the data in the repeats module. Then I made sure that this was the first image I plotted after starting the development server. To my surprise, no change.

So I decided to do the repeat but without plotting any background on the image.

same curve but no longer shrunk in bottom half of iamge
Same Curve Now Displaying as Expected

Now that’s what I expect the curve to look like. Nicely filling out the area available in the plot’s axes.

Background Image Issue?

Would appear the problem is somehow caused by the way I add the background.

The function called to generate the background is as follows.

def set_bg(axb):
  abg = None
  baxt = None
  if g.use_bb2:
    if not g.do_rpt or not g.abg:
      baxt, abg = blotch_bg_2(axb, extent=(0, 1, 0, 1), dim=g.bb2_dim,
        cmap=g.bg_cmap, alpha=g.bg_lpha, transform=axb.transAxes, zorder=1, aspect='auto')
    else:
      baxt, abg = blotch_bg_2(axb, extent=(0, 1, 0, 1), abg=g.abg, dim=g.bb2_dim,
        cmap=g.bg_cmap, alpha=g.bg_lpha, transform=axb.transAxes, zorder=1, aspect='auto')

  return baxt, abg

I figured by using the transAxes transform with the extent parameter set as shown, that I was setting the background to cover the whole of the axes’ area. I assumed the transform would convert the extent provided to the appropriate data coordinates for imshow() to use. I am now guessing that is not the case.

For reference, here’s the blotch_bg_2 function.

def blotch_bg_2(axb, extent, abg=None, dim=5, **kwargs):
  if abg is not None:
    A = abg
  else:
    # A = np.random.rand(dim, dim)
    A = rng.random((dim, dim))
  c = axb.imshow(A, extent=extent, interpolation='bilinear', **kwargs)
  axb.autoscale()
  
  return c, A

I tried a variety of things but nothing really worked. After re-reading the imshow documentation, I finally decided to get the x and y limits for the axes and pass those in the function call.

def set_bg(axb):
  abg = None
  baxt = None
  if g.use_bb2:
    axb.autoscale()
    bxmin, bxmax = axb.get_xlim()
    bymin, bymax = axb.get_ylim()

    if not g.do_rpt or not g.abg:
      baxt, abg = blotch_bg_2(axb, extent=(bxmin, bxmax, bymin, bymax), dim=g.bb2_dim,
        cmap=g.bg_cmap, alpha=g.bg_lpha, zorder=1, aspect='auto')
    else:
      baxt, abg = blotch_bg_2(axb, extent=(bxmin, bxmax, bymin, bymax), abg=g.abg,
        dim=g.bb2_dim, cmap=g.bg_cmap, alpha=g.bg_lpha, zorder=1, aspect='auto')
      axb.autoscale()

  return baxt, abg
same curve but no longer shrunk in bottom half of iamge
Curve Now Displaying as Expected With Background

And, bingo!

Happily, Done

I don’t really understand why the use of the transform parameter failed to work. Likely imshow() ignored it as I can’t find any reference for its use in the documentation. So it simply treated the extent as data coordinates and plotted the background accordingly.

Given the plot limits for the above curve before adding the background were: -1.5930286154874118, 1.5933027977633585, -0.387623702605103, 0.3876237026051031. Then by specifying the extent as (0, 1, 0, 1) the upper y-axis limit was moved to 1.0, shrinking the curve into the bottom half of the figure.

I had mentally been trying to sort this issue every time a shrunken curve was generated. With this refactoring I am no longer getting any such images produced by the app. So, a rather short post; but one I am extremely happy to have finally been able to write.

Resources