Ask Your Question
2

Add plots with different ymin, ymax parameters?

asked 2012-03-17 19:38:30 +0100

Greg Marks gravatar image

updated 2012-03-17 19:51:18 +0100

I would like to combine graphs of single-variable functions with different vertical ranges specified for each.  As a test, I tried:

p=plot(x^3, x, -2, 2, ymin=-1, ymax=1)
q=plot(exp(x), x, -2, 2, ymin=0, ymax=4)
(p+q).show()

hoping to display the two graphs with the appropriate vertical ranges, but this does not give the desired result: the second ymin/ymax specification apparently overrides the first.  Various similar attempts also failed.  Is there a syntax that makes this work? 

(Obviously, in this test case, one could simply change the horizontal range in each plot to produce the desired vertical range, but this would be tedious if one were adding a larger number of plots involving more complicated functions.)

edit retag flag offensive close merge delete

2 Answers

Sort by » oldest newest most voted
1

answered 2012-03-17 21:54:48 +0100

kcrisman gravatar image

updated 2012-03-19 23:28:48 +0100

Good question.

The reason for this behavior is that ymax and friends are not in fact parameters for plot, but for show; we just pass those parameters on to show(). Presumably we overwrite them - you can verify this by looking at the output of this.

sage: p+q 
sage: q+p

I don't see an obvious way to fix this without rewriting the code substantially. However, this may work as a workaround for you.

sage: p1 = line([(a,b) for a,b in zip(p[0].xdata,p[0].ydata) if (b>=-1 and b<=1)])
sage: q1 = line([(a,b) for a,b in zip(q[0].xdata,q[0].ydata) if (b>=0 and b<=4)])
sage: p1+q1

image description

We're using the fact that a Graphics object has various subobjects, and for a basic plot there is one of them which we access as the "zeroth" one, and its xdata and ydata are hopefully self-explanatory. Then we use a Python list comprehension and create a line from that data, which after all is what a plot of a function turns out to be.

Good luck!

edit flag offensive delete link more

Comments

Thank you for your helpful answer, which solves my problem. The fact that ymin and ymax can be used as arguments in plot() gives them the illusion of being local variables, although, as you explain, and as my example illustrates, this is not the case. Of course, the fact that ymin and ymax don't appear in the documentation of "plot" as plot options is an indication of the true situation.

Greg Marks gravatar imageGreg Marks ( 2012-03-25 19:52:16 +0100 )edit

True. The true situation is that anyone who ever starts overhauling one aspect of this will be tempted to rewrite the entire plot documentation, and that is naturally a big enough job that it then doesn't get done, since there is cool new functionality to implement instead.

kcrisman gravatar imagekcrisman ( 2012-03-26 23:22:23 +0100 )edit
0

answered 2012-03-17 22:48:28 +0100

Shashank gravatar image

updated 2012-03-17 22:49:05 +0100

You can use parasites. This is a notebook I had on my machine. I has three plots with three different y axes.

from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import matplotlib.pyplot as plt

host = host_subplot(111, axes_class=AA.Axes)
plt.subplots_adjust(right=0.75)

par1 = host.twinx()
par2 = host.twinx()

offset = 60
new_fixed_axis = par2.get_grid_helper().new_fixed_axis
par2.axis["right"] = new_fixed_axis(loc="right",
                                        axes=par2,
                                        offset=(offset, 0))

par2.axis["right"].toggle(all=True)



host.set_xlim(0, 2)
host.set_ylim(0, 4)

host.set_xlabel("Distance")
host.set_ylabel("Density")
par1.set_ylabel("Temperature")
par2.set_ylabel("Velocity")

p1, = host.plot([0, 1, 2], [0, 1, 4], label="Density")
p2, = par1.plot([2, 4, 7], label="Temperature")
p3, = par2.plot([5, 8, 9], label="Velocity")

par1.set_ylim(0, 40)
par2.set_ylim(1, 65)

host.axis["left"].label.set_color(p1.get_color())
par1.axis["right"].label.set_color(p2.get_color())
par2.axis["right"].label.set_color(p3.get_color())

plt.draw()
plt.savefig('test.png')

image description

edit flag offensive delete link more

Comments

Of course, this is pretty much pure matplotlib :) in which case you can do whatever you want. But after your answer I'm now not sure what the poster was asking for - concurrent plots like this, or ones like mine?

kcrisman gravatar imagekcrisman ( 2012-03-19 23:26:27 +0100 )edit

I think your solution and mine is the same. I just added additional ytics to make it clear. I am not sure whether it is against asksage etiquette to answer a sage question with a matplotlib answer. Matplotlib offers a lot of flexibility as you mention and I tend to do all my plotting in matplotlib.

Shashank gravatar imageShashank ( 2012-03-20 09:15:38 +0100 )edit

No, your solution is answering a different question! And it's a good one. But the images should show what I mean by different questions. You have several different vertical axes all in the same place; mine has just one vertical axis, with the various functions.

kcrisman gravatar imagekcrisman ( 2012-03-20 11:33:47 +0100 )edit

As for the mpl issue, certainly that's a legitimate answer, it's just a lot more complicated than some users (including myself) could really implement in general. However, for this user it may be just fine, so you should definitely put it up - the more resources, the better.

kcrisman gravatar imagekcrisman ( 2012-03-20 11:34:36 +0100 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2012-03-17 19:38:30 +0100

Seen: 2,649 times

Last updated: Mar 19 '12