Question

I need to plot a few exponential curves on the same plot - with the constraint that the plot ends at y=1.

For reference, here is the code:

from numpy import arange
from matplotlib import pyplot as plt

T = arange(60,89)
curve1 = 2**(T - 74)
curve2 = 2**(T - 60)
plt.plot(T,curve1 )
plt.plot(T,curve2 )
plt.show()

Here's the result: curves 1 and 2 The second curve is just barely visible, since the values are comparatively so low.

The problem I'm having is that all of these curves blow up to 700000+ fairly rapidly, but I'm only interested in the range being (0,1). How do I plot just these bits, but with nice smooth curves (so that one curve doesn't just stop halfway along)?

Was it helpful?

Solution

As you've found, this is easy to do if you adjust the range (T) for each function you add. However, if you need to change the functions, you'll need to recheck it.

The problem you're dealing with, generically, is calculating the x-range of some functions given their y-range - or, as a mathematician may put it, determining the domain of a function that corresponds to a range of its image. While, for a arbitrary function, this is impossible, it's possible if your function is injective, as is the case.

Let's say we have a function y=f(x), and the yrange is [y1,y2]. The x-range will be [f^(-1)(y1), f^(-1)(y2] (f^-1 being the inverse function of f)

Since we have multiple functions that we need to plot, the x_range is simply the greatest range - of all - the lower portion of the final range is the minimum of the lower portion of all the ranges, and the upper portion is the maximum of the upper portions.

Here's some code that exemplifies all this, by taking as a parameter the number of steps, and calculating the proper T over the x-range:

from numpy import arange
from matplotlib import pyplot as plt
from sympy import sympify, solve

f1= '2**(T - 74)' #note these are strings
f2= '2**(T - 60)'

y_bounds= (0.001, 1) #exponential functions never take 0 value, so we use 0.001
mm= (min, max)
x_bounds= [m(solve(sympify(f+"-"+str(y)))[0] for f in (f1,f2)) for y,m in zip(y_bounds, mm)]
print x_bounds

N_STEPS=100 #distributed over x_bounds
T = arange(x_bounds[0], x_bounds[1]+0.001, (x_bounds[1]-x_bounds[0])/N_STEPS)

curve1 = eval(f1) #this evaluates the function over the range, by evaluating the string as a python expression
curve2 = eval(f2)
plt.plot(T,curve1)
plt.plot(T,curve2)
plt.ylim([0,1])
plt.show()

The code outputs both the x-range (50.03, 74) and this plot: final plot of two curves

OTHER TIPS

This one was really easy: sorry to have wasted time on it.

Just set the y limits to be [0,1] via

plt.ylim([0,1])

and you're done.

In addition to the other answers, it may be worth plotting on a log-scale, since the growth of your functions is essentially exponential. For example:

from numpy import arange
from matplotlib import pyplot as plt

T = arange(60,89)
curve1 = 2**(T - 74)
curve2 = 2**(T - 60)
plt.semilogy(T,curve1 )
plt.semilogy(T,curve2 )
plt.show()

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top