> From: C M [mailto:cmpyt...@gmail.com] 
> Sent: Friday, February 12, 2010 17:15
>
> I would like to understand your approach better.  So far, I can't get
> your code to produce the "margins" indicated--but I'm probably
> applying it wrongly.  I don't know how to force an autoscale, for
> example.  Your code is tough for me to understand because there are a
> number of things you make use of that I'm not familiar with yet. I
> could ask a number of questions but don't want to burden the list with
> that unless people are up for it.

Okay.  The basic idea is that axes.autoscale_view(tight=False) already has the
capacity to obtain whatever view limits are returned by each axis' major tick
locator, so we don't need to alter the autoscale_view code within matplotlib;
we just implement a locator that yields limits we like.  I based my locator on
MaxNLocator, but you could use a different base.  Only two methods inherited
from MaxNLocator need to be modified -- the __init__ method to store the
margin, and the view_limits method to implement the looser limits.  We attach
an instance of the locator to an axis using the axis' set_major_locator
method, and if we've already plotted and need to autoscale, we invoke
axes.autoscale_view.  To later change the margin (or the parameters handled by
MaxNLocator), we can attach a new instance.

I updated my code for matplotlib 0.99.1, added some comments and examples, and
have attached it below.  I hope it's helpful as an example.

----

import numpy as np
import matplotlib as mpl
import matplotlib.ticker as mticker
import matplotlib.transforms as mtransforms

class LooseMaxNLocator(mticker.MaxNLocator):
    """
    Select no more than N intervals at nice locations with view 
    limits loosely fitted to the data.  Unlike MaxNLocator, the 
    view limits do not necessarily coincide with tick locations.
    """

    def __init__(self, margin = 0.0, **kwargs):
        """
        Keyword arguments:
        *margin*
            Specifies the minimum size of both the lower and upper 
            margins (between the view limits and the data limits) as 
            a fraction of the data range.  Must be non-negative.
        Remaining keyword arguments are passed to MaxNLocator.
        """
        mticker.MaxNLocator.__init__(self, **kwargs)
        if margin < 0:
            raise ValueError('The margin must be non-negative.')
        self._margin = margin

    def view_limits(self, dmin, dmax):
        # begin partial duplication of MaxNLocator.view_limits
        if self._symmetric:
            maxabs = max(abs(dmin), abs(dmax))
            dmin = -maxabs
            dmax = maxabs
        dmin, dmax = mtransforms.nonsingular(dmin, dmax, expander=0.05)
        # end duplication
        margin = self._margin * (dmax - dmin)  # fraction of data range
        vmin = dmin - margin  # expand the view
        vmax = dmax + margin
        bin_boundaries = self.bin_boundaries(vmin, vmax)
            # locate ticks with MaxNLocator
        # Note: If the lines below change vmin or vmax, the bin boundaries
        # later calculated by MaxNLocator.__call__ may differ from those
        # calculated here.
        vmin = min(vmin, max(bin_boundaries[bin_boundaries <= dmin]))
            # expand view to the highest tick below or touching the data
        vmax = max(vmax, min(bin_boundaries[bin_boundaries >= dmax]))
            # expand view to the lowest tick above or touching the data
        return np.array([vmin, vmax])

# Examples

import matplotlib.pyplot as plt

fig1 = plt.figure()
ax1 = fig1.add_subplot(1, 1, 1)
ax1.set_xlabel('default locator')
ax1.set_ylabel('LooseMaxNLocator')
ax1.yaxis.set_major_locator(
    LooseMaxNLocator(nbins=9, steps=[1, 2, 5, 10], margin=0.125))
    # Set our locator before we plot.
ax1.plot([0, 0.95], [0, 0.95])  # Our locator's view limits are used.

fig2 = plt.figure()
ax2 = fig2.add_subplot(1, 1, 1)
ax2.set_xlabel('default locator')
ax2.set_ylabel('LooseMaxNLocator')
ax2.plot([0, 1.05], [0, 1.05])  # The default locator's view limits are used.
ax2.yaxis.set_major_locator(
    LooseMaxNLocator(nbins=9, steps=[1, 2, 5, 10], margin=0.125))
    # Now set our locator.
ax2.autoscale_view()  # Autoscale activates our locator's view limits.


------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to