I want to plot a simple function, but i can't figured out how to do it.
this code works fine
using PyPlot
x = linspace(0,10,1000); y = log(x);
plot(x, y, color="blue", linewidth=2.0, linestyle="-")
but the next code do not work
using PyPlot
x = linspace(0,10,1000); y = x^2;
plot(x, y, color="blue", linewidth=2.0, linestyle="-")
i can't figure out how to multiply x by x.
You need to use an elementwise exponentiation: x.^2.
using PyPlot
x = linspace(0,10,1000); y = x.^2;
plot(x, y, color="blue", linewidth=2.0, linestyle="-")
In Julia v0.5 and later, you should also use the elementwise version of log: y = log.(x). The old automatically-broadcasted functions like sin, log, etc. are scheduled for deprecation in the v0.6 release cycle.
Plots.jl allows a different approach, where you just specify the function to plot and the bounds to plot it in:
using Plots
plot(x->x^2, -3, 3)
Here, x->x^2 is an anonymous function. Alternatively, you can define a standard Julia function:
f(x) = x^2
plot(f, -3, 3)
Related
Using Matplotlib I am trying to shade the region y > N, with N some number.
The problem is that I am not able to have the shaded region going to the end of the frame.
Here is a simple example.
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1)
x = [i for i in range(0,100,10)]
ax.plot(x,x,'-o')
N=110
ylim = max(ax.get_ylim())
ax.axhspan(N,ylim,alpha=.5)
plt.show()
The result is this:
How to have the shaded region not stopping, but arriving up to the end of the frame?
ax.autoscale() can come in handy here. Default, matplotlib automatically adapts the limits of the axes every time something is added. Normally also some padding is added to leave some free space above and below (and left and right).
Calling ax.autoscale(enable=True, axis='y', tight=True) changes this behavior for the y-axis, forcing "tight" limits, so without padding.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x = [i for i in range(0, 100, 10)]
ax.plot(x, x, '-o')
N = 110
ylim1 = max(ax.get_ylim())
ax.autoscale(enable=True, axis='y', tight=True)
ax.axhspan(N, ylim1, alpha=.5)
plt.show()
Alternatively, you could collect the limits before calling axhspan and setting them manually afterwards:
ax.plot(x, x, '-o')
N = 110
ylim0, ylim1 = ax.get_ylim()
ax.axhspan(N, ylim1, alpha=.5)
ax.set_ylim(ylim0, max(N, ylim1))
I would like to draw a surface and some of its iso-z contours, using the plot_surface and contour3D functions of mplot3D. Here is an example (I would like to use it to illustrate Lagrange points in physics) :
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
epsilon, r1 = 0.3, 1
r2 = epsilon*r1
Omega2 = 1/(r1*pow(r1+r2, 2))
u = np.linspace(-2, 2, 100)
x , y = np.meshgrid(u, u)
z = -epsilon/np.sqrt(np.power(x-r1, 2)+ np.power(y, 2)) - 1/np.sqrt(np.power(x+r2, 2)+ np.power(y, 2)) - 0.5*Omega2*(np.power(x, 2) + np.power(y, 2))
z = np.clip(z, -3, 0)
ax.plot_surface(x, y, z, rstride=1, cstride=1, antialiased=True, color="whitesmoke")
ax.contour3D(x, y, z+0.01, levels=np.arange(-2, -1, 0.1))
plt.show()
In the resulting plot, the contours do not show properly :
Image obtained by the code
and as the figure is interactively rotated, they randomly appear and disappear, with a wrong estimation of what part should be hidden by the surface :
Example of figure obtained by interactive rotation
This had been noticed before 4 years ago but no solution had been suggested. Hence my questions :
is it still, 4 years after, considered as a limitation of the plotting capabilities of matplolib ? And is there an alternative way, using some other graphical library ?
I'm having issues with redrawing the figure here. I allow the user to specify the units in the time scale (x-axis) and then I recalculate and call this function plots(). I want the plot to simply update, not append another plot to the figure.
def plots():
global vlgaBuffSorted
cntr()
result = collections.defaultdict(list)
for d in vlgaBuffSorted:
result[d['event']].append(d)
result_list = result.values()
f = Figure()
graph1 = f.add_subplot(211)
graph2 = f.add_subplot(212,sharex=graph1)
for item in result_list:
tL = []
vgsL = []
vdsL = []
isubL = []
for dict in item:
tL.append(dict['time'])
vgsL.append(dict['vgs'])
vdsL.append(dict['vds'])
isubL.append(dict['isub'])
graph1.plot(tL,vdsL,'bo',label='a')
graph1.plot(tL,vgsL,'rp',label='b')
graph2.plot(tL,isubL,'b-',label='c')
plotCanvas = FigureCanvasTkAgg(f, pltFrame)
toolbar = NavigationToolbar2TkAgg(plotCanvas, pltFrame)
toolbar.pack(side=BOTTOM)
plotCanvas.get_tk_widget().pack(side=TOP)
You essentially have two options:
Do exactly what you're currently doing, but call graph1.clear() and graph2.clear() before replotting the data. This is the slowest, but most simplest and most robust option.
Instead of replotting, you can just update the data of the plot objects. You'll need to make some changes in your code, but this should be much, much faster than replotting things every time. However, the shape of the data that you're plotting can't change, and if the range of your data is changing, you'll need to manually reset the x and y axis limits.
To give an example of the second option:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 6*np.pi, 100)
y = np.sin(x)
# You probably won't need this if you're embedding things in a tkinter plot...
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma
for phase in np.linspace(0, 10*np.pi, 500):
line1.set_ydata(np.sin(x + phase))
fig.canvas.draw()
fig.canvas.flush_events()
You can also do like the following:
This will draw a 10x1 random matrix data on the plot for 50 cycles of the for loop.
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
for i in range(50):
y = np.random.random([10,1])
plt.plot(y)
plt.draw()
plt.pause(0.0001)
plt.clf()
This worked for me. Repeatedly calls a function updating the graph every time.
import matplotlib.pyplot as plt
import matplotlib.animation as anim
def plot_cont(fun, xmax):
y = []
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
def update(i):
yi = fun()
y.append(yi)
x = range(len(y))
ax.clear()
ax.plot(x, y)
print i, ': ', yi
a = anim.FuncAnimation(fig, update, frames=xmax, repeat=False)
plt.show()
"fun" is a function that returns an integer.
FuncAnimation will repeatedly call "update", it will do that "xmax" times.
This worked for me:
from matplotlib import pyplot as plt
from IPython.display import clear_output
import numpy as np
for i in range(50):
clear_output(wait=True)
y = np.random.random([10,1])
plt.plot(y)
plt.show()
I have released a package called python-drawnow that provides functionality to let a figure update, typically called within a for loop, similar to Matlab's drawnow.
An example usage:
from pylab import figure, plot, ion, linspace, arange, sin, pi
def draw_fig():
# can be arbitrarily complex; just to draw a figure
#figure() # don't call!
plot(t, x)
#show() # don't call!
N = 1e3
figure() # call here instead!
ion() # enable interactivity
t = linspace(0, 2*pi, num=N)
for i in arange(100):
x = sin(2 * pi * i**2 * t / 100.0)
drawnow(draw_fig)
This package works with any matplotlib figure and provides options to wait after each figure update or drop into the debugger.
In case anyone comes across this article looking for what I was looking for, I found examples at
How to visualize scalar 2D data with Matplotlib?
and
http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop
(on web.archive.org)
then modified them to use imshow with an input stack of frames, instead of generating and using contours on the fly.
Starting with a 3D array of images of shape (nBins, nBins, nBins), called frames.
def animate_frames(frames):
nBins = frames.shape[0]
frame = frames[0]
tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
for k in range(nBins):
frame = frames[k]
tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
del tempCS1
fig.canvas.draw()
#time.sleep(1e-2) #unnecessary, but useful
fig.clf()
fig = plt.figure()
ax = fig.add_subplot(111)
win = fig.canvas.manager.window
fig.canvas.manager.window.after(100, animate_frames, frames)
I also found a much simpler way to go about this whole process, albeit less robust:
fig = plt.figure()
for k in range(nBins):
plt.clf()
plt.imshow(frames[k],cmap=plt.cm.gray)
fig.canvas.draw()
time.sleep(1e-6) #unnecessary, but useful
Note that both of these only seem to work with ipython --pylab=tk, a.k.a.backend = TkAgg
Thank you for the help with everything.
All of the above might be true, however for me "online-updating" of figures only works with some backends, specifically wx. You just might try to change to this, e.g. by starting ipython/pylab by ipython --pylab=wx! Good luck!
Based on the other answers, I wrapped the figure's update in a python decorator to separate the plot's update mechanism from the actual plot. This way, it is much easier to update any plot.
def plotlive(func):
plt.ion()
#functools.wraps(func)
def new_func(*args, **kwargs):
# Clear all axes in the current figure.
axes = plt.gcf().get_axes()
for axis in axes:
axis.cla()
# Call func to plot something
result = func(*args, **kwargs)
# Draw the plot
plt.draw()
plt.pause(0.01)
return result
return new_func
Usage example
And then you can use it like any other decorator.
#plotlive
def plot_something_live(ax, x, y):
ax.plot(x, y)
ax.set_ylim([0, 100])
The only constraint is that you have to create the figure before the loop:
fig, ax = plt.subplots()
for i in range(100):
x = np.arange(100)
y = np.full([100], fill_value=i)
plot_something_live(ax, x, y)
I ploted streamlines using the u and v. How do i determine whether divergence or convergence was occurring and plot those shapes in same figure with matplotlib?
streamline test, red is divergence and blue is convergence.
You can colour streamlines in any way you want, so get whatever form of divergence you want and use that,
import numpy as np
import matplotlib.pyplot as plt
Y, X = np.mgrid[-3:3:100j, -3:3:100j]
U = -1 - X**2 + Y
V = 1 + X - Y**2
divUV = reduce(np.add,np.gradient(U)) + reduce(np.add,np.gradient(V))
fig, ax = plt.subplots()
strm = ax.streamplot(X, Y, U, V, color=divUV, cmap=plt.cm.RdBu)
fig.colorbar(strm.lines)
plt.show()
Not sure the divergence looks right here but you get the idea. Alternatively, you could overlay a colormesh with transparency,
cm = ax.pcolormesh(X, Y, divU, cmap=plt.cm.RdBu, alpha=0.4)
fig.colorbar(cm)
Imshow and meshgrid are not working the way I thought. I have some function defined for a given (x,y) point in 2D that returns a scalar f(x,y). I want to visualize the function f using imshow.
x = np.linspace(0,4)
y = np.linspace(0,1)
X,Y = np.meshgrid(x,y)
Z = np.zeros((50,50))
for i in range(50):
for j in range(50):
Z[i,j] = f(X[i,j],Y[i,j])
fig = plt.figure()
plt.imshow(Z,extent=[0,4,1,0])
plt.show()
This works as expected except in the extent I think it should be [0,4,0,1]... Am I defining the Z[i,j] to each (x,y) pair incorrectly? An explanation for how this works would be great! Thanks!
As far as I am aware, the imshow is normally used to display an image. The extent is then used to define how large it should be, say you might want to give an image as the background of the plot.
Instead I think you will find it more intuitive to use pcolor, a demo can be found here. It works much the same as imshow so you can just supply Z. However, you can also give it the X and Y arrays. This way you can really check if your supplying the values correctly:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0,4)
y = np.linspace(0,1)
def f(x, y):
return y * np.sin(x)
X, Y = np.meshgrid(x,y)
Z = np.zeros((50,50))
for i in range(50):
for j in range(50):
Z[i,j] = f(X[i,j],Y[i,j])
plt.pcolor(X, Y, Z)
plt.show()
I have added a function to show it works. Note that if your function is able to handle numpy arrays you can replace the initialisation of Z and the nested for loops with
X, Y = np.meshgrid(x,y)
Z = f(X, Y)
This is cleaner and will be faster to compute.