Setting x scale manually, but letting y scale automatic within the current x-axis

Hi

I’ve got a plot, containing a graph.
I would like to look at certain parts of it.
To do this I zoom in on the x-axis using set_xlim()
Then I would like to call autoscale(axis=‘y’) and have matplotlib
autoscale the y axis within the current x-axis.

I’ve tried several ways of doing this, both with autoscale and set_ylim(auto=True)
but non of them have been able to do this, as they only autoscale y on the full graph.
In the end I ended up writing my own code for calculating the new ymin and ymax ans using set_ylim([ymin, ymax]),
but I feel that this should not be necessary.

While googling for the a solution I found an earlier e-mail on the matplotlib list,
http://www.mail-archive.com/matplotlib-users@…1753…forge.net/msg19664.html
which describes the same problem, but was never answered.

Is there any other solution for this that I’ve missed?

Regards

Pål

Actually, the autoscaling is working as it should in your case. By default, automatic limits will encompass all data plotted.

The missing piece of your puzzle is specifying an aspect constraint. ax.set_aspect() will allow for some sort of relationship between the x and y axes to exist. For example, setting it to ‘equal’ means that limits are chosen such that a distance on the x axis is displayed the same way as the same distance in the y-axis. There are some other preset values and I think you can specify a float as well.

This is what I can remember of the top of my head. I hope this helps!

Ben Root

···

On Friday, February 3, 2012, Pål Gunnar Ellingsen <paalge@…287…> wrote:

Hi

I’ve got a plot, containing a graph.
I would like to look at certain parts of it.

To do this I zoom in on the x-axis using set_xlim()
Then I would like to call autoscale(axis=‘y’) and have matplotlib
autoscale the y axis within the current x-axis.

I’ve tried several ways of doing this, both with autoscale and set_ylim(auto=True)

but non of them have been able to do this, as they only autoscale y on the full graph.
In the end I ended up writing my own code for calculating the new ymin and ymax ans using set_ylim([ymin, ymax]),
but I feel that this should not be necessary.

While googling for the a solution I found an earlier e-mail on the matplotlib list,
http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg19664.html

which describes the same problem, but was never answered.

Is there any other solution for this that I’ve missed?

Regards

Pål

Hi

Thank you for trying to help me, though I can’t see how aspect is going
to help me. As I understand of the documentation, it would require me to know the
relationship between x and y, which I don’t.
I can calculate it, but since it varies between each change in xlimits
and different plot, it would be the same as calculating the ylimits.

As for pyplot.xlim(xmin,xmax) (suggested by Ethan Swint), it does the same as ax.set_xlim() for me.

Below is a sample code that will illustrate the problem.

Regards

Pål

####### Start code ############

#!/usr/bin/env python
import matplotlib
matplotlib.use(‘Qt4Agg’) # generate postscript output by default

import matplotlib.pyplot as plt
import numpy as np

Creating a function to plot

x = np.linspace(-10, 10, 200)
p = np.poly1d([2, 3, 1, 4])
y = p(x) * np.sin(x)

plotting the full figure

fig = plt.figure()

ax = fig.add_subplot(111)
ax.plot(x, y)
ax.autoscale(tight=True)
plt.title(‘Full graph. (Press key for next plot)’)
plt.draw()

plt.waitforbuttonpress()

This is how I’m currently doing it

x limits

xmin = 2
xmax = 6

Calculating y limits

ymin = y[np.logical_and(xmin < x, x < xmax)].min()
ymax = y[np.logical_and(xmin < x, x < xmax)].max()

Inserting some room

room = np.maximum(np.abs(ymin * 0.05), np.abs(ymax * 0.05))
ymin = ymin + room * np.sign(ymin)
ymax = ymax + room * np.sign(ymax)

Setting the limits

ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])

plt.title(‘What I want (Press key for next plot)’)
plt.draw()
plt.waitforbuttonpress()

This is what pyplot does by default if I only set the limits

ax.autoscale(tight=True)
ax.set_xlim([2, 6])

plt.title(‘What I get if I only use set_xlim (Press key for exit)’)
plt.draw()
plt.waitforbuttonpress()
plt.close()

####### End code ############

···

On 3 February 2012 15:21, Benjamin Root <ben.root@…1304…> wrote:

On Friday, February 3, 2012, Pål Gunnar Ellingsen <paalge@…287…> wrote:

Hi

I’ve got a plot, containing a graph.
I would like to look at certain parts of it.

To do this I zoom in on the x-axis using set_xlim()
Then I would like to call autoscale(axis=‘y’) and have matplotlib
autoscale the y axis within the current x-axis.

I’ve tried several ways of doing this, both with autoscale and set_ylim(auto=True)

but non of them have been able to do this, as they only autoscale y on the full graph.
In the end I ended up writing my own code for calculating the new ymin and ymax ans using set_ylim([ymin, ymax]),
but I feel that this should not be necessary.

While googling for the a solution I found an earlier e-mail on the matplotlib list,
http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg19664.html

which describes the same problem, but was never answered.

Is there any other solution for this that I’ve missed?

Regards

Pål

Actually, the autoscaling is working as it should in your case. By default, automatic limits will encompass all data plotted.

The missing piece of your puzzle is specifying an aspect constraint. ax.set_aspect() will allow for some sort of relationship between the x and y axes to exist. For example, setting it to ‘equal’ means that limits are chosen such that a distance on the x axis is displayed the same way as the same distance in the y-axis. There are some other preset values and I think you can specify a float as well.

This is what I can remember of the top of my head. I hope this helps!

Ben Root

Ok, I see what you want. You want the y-limits to automatically change to fit only the data that is displayed for the x-domain you have chosen.

I have tried some tricks, and I am not sure that it is currently possible. There might even be some sort of bug at play here because the function ax.update_datalim() does not appear to update the internal data used for autoscaling. We might have to look into this further.

Ben Root

···

On Fri, Feb 3, 2012 at 9:15 AM, Pål Gunnar Ellingsen <paalge@…287…> wrote:

Hi

Thank you for trying to help me, though I can’t see how aspect is going
to help me. As I understand of the documentation, it would require me to know the
relationship between x and y, which I don’t.

I can calculate it, but since it varies between each change in xlimits
and different plot, it would be the same as calculating the ylimits.

As for pyplot.xlim(xmin,xmax) (suggested by Ethan Swint), it does the same as ax.set_xlim() for me.

Below is a sample code that will illustrate the problem.

Regards

Pål

####### Start code ############

#!/usr/bin/env python
import matplotlib
matplotlib.use(‘Qt4Agg’) # generate postscript output by default

import matplotlib.pyplot as plt
import numpy as np

Creating a function to plot

x = np.linspace(-10, 10, 200)
p = np.poly1d([2, 3, 1, 4])
y = p(x) * np.sin(x)

plotting the full figure

fig = plt.figure()

ax = fig.add_subplot(111)
ax.plot(x, y)
ax.autoscale(tight=True)
plt.title(‘Full graph. (Press key for next plot)’)
plt.draw()

plt.waitforbuttonpress()

This is how I’m currently doing it

x limits

xmin = 2
xmax = 6

Calculating y limits

ymin = y[np.logical_and(xmin < x, x < xmax)].min()
ymax = y[np.logical_and(xmin < x, x < xmax)].max()

Inserting some room

room = np.maximum(np.abs(ymin * 0.05), np.abs(ymax * 0.05))

ymin = ymin + room * np.sign(ymin)
ymax = ymax + room * np.sign(ymax)

Setting the limits

ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])

plt.title(‘What I want (Press key for next plot)’)

plt.draw()
plt.waitforbuttonpress()

This is what pyplot does by default if I only set the limits

ax.autoscale(tight=True)
ax.set_xlim([2, 6])

plt.title(‘What I get if I only use set_xlim (Press key for exit)’)

plt.draw()
plt.waitforbuttonpress()
plt.close()

####### End code ############

Hi

Yes you’ve understood my problem correctly.

Let me know if there is anything I can do to help solve this issue.

Regards

Pål

···

On 3 February 2012 17:07, Benjamin Root <ben.root@…1304…> wrote:

On Fri, Feb 3, 2012 at 9:15 AM, Pål Gunnar Ellingsen <paalge@…120…287…> wrote:

Hi

Thank you for trying to help me, though I can’t see how aspect is going
to help me. As I understand of the documentation, it would require me to know the
relationship between x and y, which I don’t.

I can calculate it, but since it varies between each change in xlimits
and different plot, it would be the same as calculating the ylimits.

As for pyplot.xlim(xmin,xmax) (suggested by Ethan Swint), it does the same as ax.set_xlim() for me.

Below is a sample code that will illustrate the problem.

Regards

Pål

####### Start code ############

#!/usr/bin/env python
import matplotlib
matplotlib.use(‘Qt4Agg’) # generate postscript output by default

import matplotlib.pyplot as plt
import numpy as np

Creating a function to plot

x = np.linspace(-10, 10, 200)
p = np.poly1d([2, 3, 1, 4])
y = p(x) * np.sin(x)

plotting the full figure

fig = plt.figure()

ax = fig.add_subplot(111)
ax.plot(x, y)
ax.autoscale(tight=True)
plt.title(‘Full graph. (Press key for next plot)’)
plt.draw()

plt.waitforbuttonpress()

This is how I’m currently doing it

x limits

xmin = 2
xmax = 6

Calculating y limits

ymin = y[np.logical_and(xmin < x, x < xmax)].min()
ymax = y[np.logical_and(xmin < x, x < xmax)].max()

Inserting some room

room = np.maximum(np.abs(ymin * 0.05), np.abs(ymax * 0.05))

ymin = ymin + room * np.sign(ymin)
ymax = ymax + room * np.sign(ymax)

Setting the limits

ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])

plt.title(‘What I want (Press key for next plot)’)

plt.draw()
plt.waitforbuttonpress()

This is what pyplot does by default if I only set the limits

ax.autoscale(tight=True)
ax.set_xlim([2, 6])

plt.title(‘What I get if I only use set_xlim (Press key for exit)’)

plt.draw()
plt.waitforbuttonpress()
plt.close()

####### End code ############

Ok, I see what you want. You want the y-limits to automatically change to fit only the data that is displayed for the x-domain you have chosen.

I have tried some tricks, and I am not sure that it is currently possible. There might even be some sort of bug at play here because the function ax.update_datalim() does not appear to update the internal data used for autoscaling. We might have to look into this further.

Ben Root

    Hi

    Thank you for trying to help me, though I can't see how aspect is going
    to help me. As I understand of the documentation, it would require
    me to know the
    relationship between x and y, which I don't.
    I can calculate it, but since it varies between each change in xlimits
    and different plot, it would be the same as calculating the ylimits.

    As for pyplot.xlim(xmin,xmax) (suggested by Ethan Swint), it does
    the same as ax.set_xlim() for me.

    Below is a sample code that will illustrate the problem.

    Regards

    Pål

    ####### Start code ############

    #!/usr/bin/env python
    import matplotlib
    matplotlib.use('Qt4Agg') # generate postscript output by default

    import matplotlib.pyplot as plt
    import numpy as np

    # Creating a function to plot
    x = np.linspace(-10, 10, 200)
    p = np.poly1d([2, 3, 1, 4])
    y = p(x) * np.sin(x)

    # plotting the full figure
    fig = plt.figure()

    ax = fig.add_subplot(111)
    ax.plot(x, y)
    ax.autoscale(tight=True)
    plt.title('Full graph. (Press key for next plot)')
    plt.draw()

    plt.waitforbuttonpress()

    # This is how I'm currently doing it
    # x limits
    xmin = 2
    xmax = 6

    # Calculating y limits
    ymin = y[np.logical_and(xmin < x, x < xmax)].min()
    ymax = y[np.logical_and(xmin < x, x < xmax)].max()

    # Inserting some room
    room = np.maximum(np.abs(ymin * 0.05), np.abs(ymax * 0.05))
    ymin = ymin + room * np.sign(ymin)
    ymax = ymax + room * np.sign(ymax)

    # Setting the limits
    ax.set_xlim([xmin, xmax])
    ax.set_ylim([ymin, ymax])

    plt.title('What I want (Press key for next plot)')
    plt.draw()
    plt.waitforbuttonpress()

    # This is what pyplot does by default if I only set the limits
    ax.autoscale(tight=True)
    ax.set_xlim([2, 6])

    plt.title('What I get if I only use set_xlim (Press key for exit)')
    plt.draw()
    plt.waitforbuttonpress()
    plt.close()

    ####### End code ############

Ok, I see what you want. You want the y-limits to automatically change
to fit only the data that is displayed for the x-domain you have chosen.

This has never been supported; it would have to be a new option. I suspect it would be quite difficult to get this right in general, even though the concept seems simple enough.

Eric

···

On 02/03/2012 06:07 AM, Benjamin Root wrote:

On Fri, Feb 3, 2012 at 9:15 AM, Pål Gunnar Ellingsen <paalge@…287… > <mailto:paalge@…287…>> wrote:

I have tried some tricks, and I am not sure that it is currently
possible. There might even be some sort of bug at play here because the
function ax.update_datalim() does not appear to update the internal data
used for autoscaling. We might have to look into this further.

Ben Root

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Hi

I understand that it would be hard to implement, as it requires that all the points are checked, which for a arbitrary plot is not easy.
Though is this not what is already done for the normal autoscale, or have I misunderstood how the normal autoscale is done?

I would like to have this as a new feature, as it would prove useful for analysing graphs, especially in scientific research.

Kind regards

Pål

···

On 3 February 2012 19:56, Eric Firing <efiring@…202…> wrote:

On 02/03/2012 06:07 AM, Benjamin Root wrote:

On Fri, Feb 3, 2012 at 9:15 AM, Pål Gunnar Ellingsen <paalge@…287… > > mailto:paalge@...287...> wrote:

Hi
Thank you for trying to help me, though I can't see how aspect is going
to help me. As I understand of the documentation, it would require
me to know the
relationship between x and y, which I don't.
I can calculate it, but since it varies between each change in xlimits
and different plot, it would be the same as calculating the ylimits.
As for pyplot.xlim(xmin,xmax) (suggested by Ethan Swint), it does
the same as ax.set_xlim() for me.
Below is a sample code that will illustrate the problem.
Regards
Pål
####### Start code ############
#!/usr/bin/env python
import matplotlib
matplotlib.use('Qt4Agg')   # generate postscript output by default
import matplotlib.pyplot as plt
import numpy as np
# Creating a function to plot
x = np.linspace(-10, 10, 200)
p = np.poly1d([2, 3, 1, 4])
y = p(x) * np.sin(x)
# plotting the full figure
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.autoscale(tight=True)
plt.title('Full graph. (Press key for next plot)')
plt.draw()
plt.waitforbuttonpress()
# This is how I'm currently doing it
# x limits
xmin = 2
xmax = 6
# Calculating y limits
ymin = y[np.logical_and(xmin < x, x < xmax)].min()
ymax = y[np.logical_and(xmin < x, x < xmax)].max()
# Inserting some room
room = np.maximum(np.abs(ymin * 0.05), np.abs(ymax * 0.05))
ymin = ymin + room * np.sign(ymin)
ymax = ymax + room * np.sign(ymax)
# Setting the limits
ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])
plt.title('What I want (Press key for next plot)')
plt.draw()
plt.waitforbuttonpress()
# This is what pyplot does by default if I only set the limits
ax.autoscale(tight=True)
ax.set_xlim([2, 6])
plt.title('What I get if I only use set_xlim (Press key for exit)')
plt.draw()
plt.waitforbuttonpress()
plt.close()
####### End code ############

Ok, I see what you want. You want the y-limits to automatically change

to fit only the data that is displayed for the x-domain you have chosen.

This has never been supported; it would have to be a new option. I

suspect it would be quite difficult to get this right in general, even

though the concept seems simple enough.

Eric

I have tried some tricks, and I am not sure that it is currently

possible. There might even be some sort of bug at play here because the

function ax.update_datalim() does not appear to update the internal data

used for autoscaling. We might have to look into this further.

Ben Root


Try before you buy = See our experts in action!

The most comprehensive online learning library for Microsoft developers

is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,

Metro Style Apps, more. Free future releases when you subscribe now!

http://p.sf.net/sfu/learndevnow-dev2


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


Try before you buy = See our experts in action!

The most comprehensive online learning library for Microsoft developers

is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,

Metro Style Apps, more. Free future releases when you subscribe now!

http://p.sf.net/sfu/learndevnow-dev2


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Pal,

Normal autoscaling (when aspect is None, which is default) means to display all the data that has been plotted. This is possible because the plotting functions (which were given the data as input) updates the limits of the “known data bounding box” for the axes. This data is not stored except within each artist object, in their own form. It becomes difficult to then “re-query” that data in the general case. It isn’t to say that it isn’t possible to do, just that the architecture isn’t set up to query subsets of collections.

I hope this is clearer,
Ben Root

···

On Mon, Feb 6, 2012 at 4:47 AM, Pål Gunnar Ellingsen <paalge@…287…> wrote:

Hi

I understand that it would be hard to implement, as it requires that all the points are checked, which for a arbitrary plot is not easy.
Though is this not what is already done for the normal autoscale, or have I misunderstood how the normal autoscale is done?

I would like to have this as a new feature, as it would prove useful for analysing graphs, especially in scientific research.

Kind regards

Pål

Hi

That was a very nice explanation of how autoscale works, thank you very much :smiley:
After now understanding how the function autoscale function works, I see that this would be a major change in the code, as it would require the axes to know all of the bounding boxes, and not only one of them.
As it, at least in my code, is easy to calculate the new limits on the unset axis, I would not put this up as something that should be a feature.
Though I think the documentation for autoscale, section axis could be a bit clearer and state that autoscaling only one axis autoscales that axis with respect to everything plotted, even though xlim/ylim has been set.

Regards

Pål

···

On 6 February 2012 18:02, Benjamin Root <ben.root@…1304…> wrote:

On Mon, Feb 6, 2012 at 4:47 AM, Pål Gunnar Ellingsen <paalge@…287…> wrote:

Hi

I understand that it would be hard to implement, as it requires that all the points are checked, which for a arbitrary plot is not easy.
Though is this not what is already done for the normal autoscale, or have I misunderstood how the normal autoscale is done?

I would like to have this as a new feature, as it would prove useful for analysing graphs, especially in scientific research.

Kind regards

Pål

Pal,

Normal autoscaling (when aspect is None, which is default) means to display all the data that has been plotted. This is possible because the plotting functions (which were given the data as input) updates the limits of the “known data bounding box” for the axes. This data is not stored except within each artist object, in their own form. It becomes difficult to then “re-query” that data in the general case. It isn’t to say that it isn’t possible to do, just that the architecture isn’t set up to query subsets of collections.

I hope this is clearer,
Ben Root