Change to aspect ratio handling

All,

Motivated in part by an old patch (1233294) submitted to sourceforge by Nikolai Hlubek, I took a look at how aspect ratio is handled in mpl, and concluded it wasn't quite right:

1) The aspect='preserve' kwarg in image caused the image to retain its aspect ratio only with some resize events, not with all. The implementation in the image.py code does not look right to me.

2) The aspect='equal' kwarg in axes.py did not respond to resize events at all.

3) I could not understand why there should be separate "aspect" kwargs for image and for axes.

Therefore I have reworked the aspect-handling code in axes.py, and I think it is working reasonably well. Indeed, I don't see any remaining need for an "aspect" kwarg in image.py, and I would like to take it out unless someone raises an objection.

I have also changed the aspect-related API to make it more flexible and self-explanatory:

     def set_aspect(self, aspect='auto', fixLimits=None,
                             aspect_adjusts='position'):
         """
         aspect:
             'auto' - automatic; fill position rectangle with data
             'normal' - same as 'auto'; deprecated
             'equal' - same scaling from data to plot units for x and y
              A - a circle will be stretched such that the height
                         is A times the width. aspect=1 is the same as
                         aspect='equal'.

         aspect_adjusts:
              'position' - change width or height of bounding rectangle;
                           keep it centered.
              'box_size' - as above, but anchored to lower left
              'datalim' - change xlim or ylim

         fixLimits: deprecated; False is aspect_adjusts='datalim';
                    True is aspect_adjusts='position'

         ACCEPTS: ['auto' | 'equal' | aspect_ratio]
...

     def set_aspect_adjusts(self, aspect_adjusts = 'position'):
         """
         Must be called after set_aspect.

         ACCEPTS: ['position' | 'box_size' | 'datalim']

...

Anticipating that some additional work will need to be done, I have not yet made an entry in the CHANGELOG or API_CHANGES.

In addition to removing the aspect kwarg from image.py, I would like to take fixLimits out of set_aspect (above). No code in mpl or its examples depends on it, but this might break some user code, so for the present I have maintained compatibility.

One question: is there an easy way to automatically trigger a redraw in an interactive backend (e.g. ipython with gtkagg) at the end of the set_aspect() method, for example? The way it works now is that one can make a plot, call the set_aspect() method on the resulting axes object, and the result will appear as soon as the window is manipulated with the mouse; but this manipulation is needed to trigger a redraw.

Eric

Eric Firing wrote:

All,

Motivated in part by an old patch (1233294) submitted to sourceforge by Nikolai Hlubek, I took a look at how aspect ratio is handled in mpl, and concluded it wasn't quite right:

1) The aspect='preserve' kwarg in image caused the image to retain its aspect ratio only with some resize events, not with all. The implementation in the image.py code does not look right to me.

2) The aspect='equal' kwarg in axes.py did not respond to resize events at all.

3) I could not understand why there should be separate "aspect" kwargs for image and for axes.

Therefore I have reworked the aspect-handling code in axes.py, and I think it is working reasonably well. Indeed, I don't see any remaining need for an "aspect" kwarg in image.py, and I would like to take it out unless someone raises an objection.

I have also changed the aspect-related API to make it more flexible and self-explanatory:

    def set_aspect(self, aspect='auto', fixLimits=None,
                            aspect_adjusts='position'):
        """
        aspect:
            'auto' - automatic; fill position rectangle with data
            'normal' - same as 'auto'; deprecated
            'equal' - same scaling from data to plot units for x and y
             A - a circle will be stretched such that the height
                        is A times the width. aspect=1 is the same as
                        aspect='equal'.

        aspect_adjusts:
             'position' - change width or height of bounding rectangle;
                          keep it centered.
             'box_size' - as above, but anchored to lower left
             'datalim' - change xlim or ylim

        fixLimits: deprecated; False is aspect_adjusts='datalim';
                   True is aspect_adjusts='position'

        ACCEPTS: ['auto' | 'equal' | aspect_ratio]
...

    def set_aspect_adjusts(self, aspect_adjusts = 'position'):
        """
        Must be called after set_aspect.

        ACCEPTS: ['position' | 'box_size' | 'datalim']

...

Anticipating that some additional work will need to be done, I have not yet made an entry in the CHANGELOG or API_CHANGES.

In addition to removing the aspect kwarg from image.py, I would like to take fixLimits out of set_aspect (above). No code in mpl or its examples depends on it, but this might break some user code, so for the present I have maintained compatibility.

One question: is there an easy way to automatically trigger a redraw in an interactive backend (e.g. ipython with gtkagg) at the end of the set_aspect() method, for example? The way it works now is that one can make a plot, call the set_aspect() method on the resulting axes object, and the result will appear as soon as the window is manipulated with the mouse; but this manipulation is needed to trigger a redraw.

Eric

Eric: It occurred to me that there are actually 9 possibilities for adjusting the location of the plot in the bounding box after fixing the aspect ratio. Here's a patch to this morning's svn axes.py that adds the other 7 possibilities. Does this make sense to you? If so, I can go ahead and apply it.

-Jeff

axes.patch (4.7 KB)

···

--
Jeffrey S. Whitaker Phone : (303)497-6313
Meteorologist FAX : (303)497-6449
NOAA/OAR/PSD R/PSD1 Email : Jeffrey.S.Whitaker@...236...
325 Broadway Office : Skaggs Research Cntr 1D-124
Boulder, CO, USA 80303-3328 Web : http://tinyurl.com/5telg

Jeff,

Jeff Whitaker wrote:

Eric: It occurred to me that there are actually 9 possibilities for adjusting the location of the plot in the bounding box after fixing the aspect ratio. Here's a patch to this morning's svn axes.py that adds the other 7 possibilities. Does this make sense to you? If so, I can go ahead and apply it.

-Jeff

Thanks, but I think it would be better to hold off.

This possibility did occur to me, but I originally left it out to keep things simple, both in the API and in the code. (My inclination was actually to make centering standard, and not even offer the corner-anchoring.) I think that perhaps this sort of positioning functionality should be factored out. Resizing and repositioning are more generally useful; for example, they are used in the colorbar function. I would like to take a look at this broader question before finalizing the axes aspect ratio handling.

Eric