autoscaling

A while back, I put some effort into rendering an offset ticklabel, which
allowed the user to do something like

plot(linspace(100000100, 100000200, 100))

and the plot would look like a plot from 0 to 100, with a "+100000100"
rendered in a new label near the far end of the axis. This doesnt work quite
as well as it used to, because the axes autoscaling is setting the plot range
to something like the average plus and minus 6%. I have tried tracing the
source of this change, but I can't find it. It might be buried in the
_transforms extension code, and I've never been able to wrap my head around
mpl's transforms.

Does anyone know why autoscaling is defaulting to this +-6% range? Does it
have to be this way? I'm trying to improve the scalar formatter (supporting
engineering notation, cleaning up the code).

Thanks,
Darren

I don't know anything about it what happened to the code, but I will
say that +- 6% autoscaling is better than tight bounds for many kinds
of plots. Like a scatter plot. It doesn't look good if some of your
points are right on the axes, with their marker cut in half by the
border. It's always bugged me with Matlab that there was no easy way
to get slightly enlarged bounds on plots, so I'm glad to hear mpl has
added something like that. I'm not sure it should be the default, or
only option though. Some plots are better with tight bounds.

--bb

···

On 8/28/06, Darren Dale <dd55@...143...> wrote:

A while back, I put some effort into rendering an offset ticklabel, which
allowed the user to do something like

plot(linspace(100000100, 100000200, 100))

and the plot would look like a plot from 0 to 100, with a "+100000100"
rendered in a new label near the far end of the axis. This doesnt work quite
as well as it used to, because the axes autoscaling is setting the plot range
to something like the average plus and minus 6%. I have tried tracing the
source of this change, but I can't find it. It might be buried in the
_transforms extension code, and I've never been able to wrap my head around
mpl's transforms.

Does anyone know why autoscaling is defaulting to this +-6% range?

Darren Dale wrote:

A while back, I put some effort into rendering an offset ticklabel, which allowed the user to do something like

plot(linspace(100000100, 100000200, 100))

and the plot would look like a plot from 0 to 100, with a "+100000100" rendered in a new label near the far end of the axis. This doesnt work quite as well as it used to, because the axes autoscaling is setting the plot range to something like the average plus and minus 6%. I have tried tracing the source of this change, but I can't find it. It might be buried in the _transforms extension code, and I've never been able to wrap my head around mpl's transforms.

Does anyone know why autoscaling is defaulting to this +-6% range? Does it have to be this way? I'm trying to improve the scalar formatter (supporting engineering notation, cleaning up the code).

Yes. It is not a +-6% range in general, rather it is an adjustment that is made if the range is very small. The relevant method in Locator is:

     def nonsingular(self, vmin, vmax, expander=0.001, tiny=1e-6):
         if vmax < vmin:
             vmin, vmax = vmax, vmin
         if vmax - vmin <= max(abs(vmin), abs(vmax)) * tiny:
             if vmin==0.0:
                 vmin -= 1
                 vmax += 1
             else:
                 vmin -= expander*abs(vmin)
                 vmax += expander*abs(vmax)
         return vmin, vmax

I know I did it this way for a reason, but I don't remember exactly what it was--whether it was because of problems with zooming when the zoom range gets too small (this was definitely a big problem), or because of problems with the rest of the locator code, or because it seemed to me to be roughly the desired behavior in most cases. Maybe it was all of the above. Certainly, something like this is needed--I think you will find that things go bad rapidly if vmin gets too close to vmax. I put in the "expander" and "tiny" kwargs in case of future need, but only expander is non-default (e.g., 0.05) in other parts of ticker.py, and neither kwarg is presently exposed to the user. That could be changed.

Eric

Bill Baxter wrote:

I don't know anything about it what happened to the code, but I will
say that +- 6% autoscaling is better than tight bounds for many kinds
of plots. Like a scatter plot. It doesn't look good if some of your
points are right on the axes, with their marker cut in half by the
border. It's always bugged me with Matlab that there was no easy way
to get slightly enlarged bounds on plots, so I'm glad to hear mpl has
added something like that. I'm not sure it should be the default, or
only option though. Some plots are better with tight bounds.

Presently it kicks in only in the unusual case of a very small range, but it has also occurred to me that it would be nice to be able to tell the autoscaling to add a margin in any case. I just haven't gotten around to doing it.

Eric

+1 for that. I've just recently been fixing my limits by hand in this
way precisely to avoid the half-cut markers problem that Bill
describes.

Cheers,

f

···

On 8/27/06, Eric Firing <efiring@...229...> wrote:

Bill Baxter wrote:

>
> I don't know anything about it what happened to the code, but I will
> say that +- 6% autoscaling is better than tight bounds for many kinds
> of plots. Like a scatter plot. It doesn't look good if some of your
> points are right on the axes, with their marker cut in half by the
> border. It's always bugged me with Matlab that there was no easy way
> to get slightly enlarged bounds on plots, so I'm glad to hear mpl has
> added something like that. I'm not sure it should be the default, or
> only option though. Some plots are better with tight bounds.

Presently it kicks in only in the unusual case of a very small range,
but it has also occurred to me that it would be nice to be able to tell
the autoscaling to add a margin in any case. I just haven't gotten
around to doing it.

I don't understand, I spent a lot of time making the scalarformatter work with
precisely this scenario (zooming in on extremely small ranges), and it was
working very well. I don't know of any circumstance where there was a
problem, maybe you could be more specific about the big problems you
encountered.

Darren

···

On Sunday 27 August 2006 22:09, Eric Firing wrote:

Darren Dale wrote:
> A while back, I put some effort into rendering an offset ticklabel, which
> allowed the user to do something like
>
> plot(linspace(100000100, 100000200, 100))
>
> and the plot would look like a plot from 0 to 100, with a "+100000100"
> rendered in a new label near the far end of the axis. This doesnt work
> quite as well as it used to, because the axes autoscaling is setting the
> plot range to something like the average plus and minus 6%. I have tried
> tracing the source of this change, but I can't find it. It might be
> buried in the _transforms extension code, and I've never been able to
> wrap my head around mpl's transforms.
>
> Does anyone know why autoscaling is defaulting to this +-6% range? Does
> it have to be this way? I'm trying to improve the scalar formatter
> (supporting engineering notation, cleaning up the code).

Yes. It is not a +-6% range in general, rather it is an adjustment that
is made if the range is very small. The relevant method in Locator is:

     def nonsingular(self, vmin, vmax, expander=0.001, tiny=1e-6):
         if vmax < vmin:
             vmin, vmax = vmax, vmin
         if vmax - vmin <= max(abs(vmin), abs(vmax)) * tiny:
             if vmin==0.0:
                 vmin -= 1
                 vmax += 1
             else:
                 vmin -= expander*abs(vmin)
                 vmax += expander*abs(vmax)
         return vmin, vmax

I know I did it this way for a reason, but I don't remember exactly what
it was--whether it was because of problems with zooming when the zoom
range gets too small (this was definitely a big problem), or because of
problems with the rest of the locator code, or because it seemed to me
to be roughly the desired behavior in most cases. Maybe it was all of
the above. Certainly, something like this is needed--I think you will
find that things go bad rapidly if vmin gets too close to vmax. I put
in the "expander" and "tiny" kwargs in case of future need, but only
expander is non-default (e.g., 0.05) in other parts of ticker.py, and
neither kwarg is presently exposed to the user. That could be changed.

Darren Dale wrote:

Darren Dale wrote:

A while back, I put some effort into rendering an offset ticklabel, which
allowed the user to do something like

plot(linspace(100000100, 100000200, 100))

and the plot would look like a plot from 0 to 100, with a "+100000100"
rendered in a new label near the far end of the axis. This doesnt work
quite as well as it used to, because the axes autoscaling is setting the
plot range to something like the average plus and minus 6%. I have tried
tracing the source of this change, but I can't find it. It might be
buried in the _transforms extension code, and I've never been able to
wrap my head around mpl's transforms.

Does anyone know why autoscaling is defaulting to this +-6% range? Does
it have to be this way? I'm trying to improve the scalar formatter
(supporting engineering notation, cleaning up the code).

Yes. It is not a +-6% range in general, rather it is an adjustment that
is made if the range is very small. The relevant method in Locator is:

     def nonsingular(self, vmin, vmax, expander=0.001, tiny=1e-6):
         if vmax < vmin:
             vmin, vmax = vmax, vmin
         if vmax - vmin <= max(abs(vmin), abs(vmax)) * tiny:
             if vmin==0.0:
                 vmin -= 1
                 vmax += 1
             else:
                 vmin -= expander*abs(vmin)
                 vmax += expander*abs(vmax)
         return vmin, vmax

I know I did it this way for a reason, but I don't remember exactly what
it was--whether it was because of problems with zooming when the zoom
range gets too small (this was definitely a big problem), or because of
problems with the rest of the locator code, or because it seemed to me
to be roughly the desired behavior in most cases. Maybe it was all of
the above. Certainly, something like this is needed--I think you will
find that things go bad rapidly if vmin gets too close to vmax. I put
in the "expander" and "tiny" kwargs in case of future need, but only
expander is non-default (e.g., 0.05) in other parts of ticker.py, and
neither kwarg is presently exposed to the user. That could be changed.

I don't understand, I spent a lot of time making the scalarformatter work with precisely this scenario (zooming in on extremely small ranges), and it was working very well. I don't know of any circumstance where there was a problem, maybe you could be more specific about the big problems you encountered.

Darren,

I'm sorry, but I probably can't be much more specific. I don't remember the details of the whole lengthy process involved in getting MaxNLocator and aspect ratio handling working with pan and zoom, but the present version of nonsingular was part of it. It looks like the change you don't like was revision 2149 on March 16, when the "tiny" kwarg was added. Now, I think that the point of adding it was that checking for vmin == vmax turned out to be not good enough; given floating point math, having vmin too close to vmax could still cause trouble, maybe not in your formatter, but elsewhere. At one point "elsewhere" included the transforms module, but I am not sure whether the bug I fixed in revision 2149 involved an error from the transforms module.

For experimental purposes, you can get the old behavior by setting tiny=0.0.

Eric

···

On Sunday 27 August 2006 22:09, Eric Firing wrote: