Step by step showing 2D/3D add/remove points - python

I'm writing some python functions that deals with manipulating sets of 2D/3D coordinates, mostly 2D.
The issue is debugging such code is made difficult just by looking at the points. So I'm looking for some software that could display the points and showing which points have been added/removed after each step. Basically, I'm looking for a turn my algorithm into an animation.
I've seen a few applets online that do things similar what I was looking for, but I lack the graphics/GUI programming skills to write something similar at this point, and I'm not sure it's wise to email the authors of things whose last modified timestamps reads several years ago. I should note I'm not against learning some graphics/GUI programming in the process, but I'd rather not spend more than 1-3 days if it can't be helped, although such links are still appreciated. In this sense, linking to a how-to site for writing such a step-by-step program might be acceptable.

With the matplotlib library it is very easy to get working animations up. Below is a minimal example to work with. The function generate_data can be adapted to your needs:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def generate_data():
X = np.arange(25)
Y = X**2 * np.random.rand(25)
return X,Y
def update(data):
mat[0].set_xdata(data[0])
mat[0].set_ydata(data[1])
return mat
def data_gen():
while True:
yield generate_data()
fig, ax = plt.subplots()
X,Y = generate_data()
mat = ax.plot(X,Y,'o')
ani = animation.FuncAnimation(fig, update, data_gen, interval=500,
save_count=10)
ani.save('animation.mp4')
plt.show()
This example was adapted from a previous answer and modified to show a line plot instead of a colormap.

Related

PyTest Matplotlib Figure Appears on Show

I have a complicated method called plotter() which processes some data and produces a matplotlib plot with several components. Due to its complexity I simply want to test that the plot appears. This will confirm that all of the data is processed reasonably and that something gets shown without any errors being thrown. I am not looking to run an image comparison as that's not currently possible for this project.
My function is too complicated to show here, so the following example could be considered instead.
import matplotlib.pyplot as plt
import numpy as np
def plotter():
x = np.arange(0,10)
y = 2*x
fig = plt.plot(x, y)
plotter()
plt.show()
Is there a way to use PyTest to simply assert that a figure appears? If not then solutions using other test frameworks would also be greatly appreciated.
(For context I am using Python 3.)

plotting an iv-curve with python

So I am trying to plot an IV-curve using python, but all I'm getting is a straight, linear line. This may seem like a trivial code, but I just started self teaching myself literally a week a go, so bear with me as I am still learning :)
Here's my code:
import matplotlib.pyplot as plt
xdata = [20,27] # voltage data
ydata = [0.4,0.9] # current data
plt.plot(xdata, ydata)
plt.title(r'IV-curve')
plt.xlabel('Voltage(V)')
plt.ylabel('Current(I)')
plt.show()
A picture of it is shown here: http://imgur.com/a/lxPPo
Probably you can try something like below (change equation to set 'y' based on your requirements):

Live plotting on bloch sphere

I am trying to plot live data on a bloch sphere using Qutip's function bloch().
So far, the code always interrupts, when I have a b.show() in there.
I found a lot of solutions online to similar problems, but most of them make use of direct matplotlib commands like matplotlib.draw() which doesn't seem to work with the bloch class.
Then, there are other solutions which make use of for example Tk or GTKagg (e.g. https://stackoverflow.com/a/15742183/3276735 or real-time plotting in while loop with matplotlib)
Can somebody please help me how to deal with the same problem in the bloch class?
Edit:
Here's a minimal example:
Basically, I want to update my plot with one point at a time, preferably in a loop. My goal is to display live data in the plot that has to be read from a file.
import qutip as qt
import numpy as np
b = qt.Bloch()
theta = np.arange(0,np.pi,0.1)
for ii in range(len(theta)):
b.add_points([np.sin(theta[ii]),0,np.cos(theta[ii])])
b.show()
I think you are breaking your plot because you are calling show for every point. Try calling show outside the loop (in the end).
import qutip as qt
import numpy as np
b = qt.Bloch()
theta = np.arange(0,np.pi,0.1)
for ii in range(len(theta)):
b.add_points([np.sin(theta[ii]),0,np.cos(theta[ii])])
b.show() # Changed here
EDIT: Animated plot
Consider show as an absolute command to call the plot into view. It's not a draw command (or redraw). If you do want to show an image every "n" seconds or so you'll need to clear the plot before calling it again. You may try this:
import qutip as qt
import numpy as np
b = qt.Bloch()
theta = np.arange(0,np.pi,0.1)
for ii in range(len(theta)):
b.clear()
b.add_points([np.sin(theta[ii]),0,np.cos(theta[ii])])
b.show()
# wait time step and load new value from file.
, I don't have QuTip in my current distribution so I can't really test it but I'm betting its heavily based in matplotlib. My best advise however is for you to use the formulation give for animation in the QuTiP docs. By following this recipe:
from pylab import *
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D
fig = figure()
ax = Axes3D(fig,azim=-40,elev=30)
sphere=Bloch(axes=ax)
def animate(i):
sphere.clear()
sphere.add_vectors([sin(theta),0,cos(theta)])
sphere.add_points([sx[:i+1],sy[:i+1],sz[:i+1]])
sphere.make_sphere()
return ax
def init():
sphere.vector_color = ['r']
return ax
ani = animation.FuncAnimation(fig, animate, np.arange(len(sx)),
init_func=init, blit=True, repeat=False)
ani.save('bloch_sphere.mp4', fps=20, clear_temp=True)
, you should be able to modify the animate function to perform all operations you need.

Real-time plot in matplotlib - python

I'm trying to get real-time spectrum analyzer type plot in matplotlib. I've got some code working (with help from other posts on StackOverflow) as follows:
import time
import numpy as np
import matplotlib.pyplot as plt
plt.axis([0, 1000, 0, 1])
plt.ion()
plt.show()
i=0
np.zeros([1,500],'float')
lines=plt.plot(y[0])
while 1:
i=i+1
lines.pop(0).remove()
y = np.random.rand(1,100)
lines=plt.plot(y[0])
plt.draw()
The code works and I'm getting what I want, but there is a serious problem. The plot window would freeze after some time. I know the program is still running by inspecting the i variable (I'm running the code in Anaconda/Spyder so I can see the variables). However the plot window would show "Non responding" and if I terminate the python program in Spyder by ctrl+c, the plot window comes back to life and show the latest plot.
I'm out of wits here as how to further debug the issue. Anyone to help?
Thanks
I am not sure that adding plt.pause will entirely solve your issue. It may just take longer before the application crash. The memory used by your application seems to constantly increase over time (even after adding plt.pause). Below are two suggestions that may help you with your current issue:
Instead of removing/recreating the lines artists with each iteration with remove and plot, I would use the same artist throughout the whole animation and simply update its ydata.
I'll use explicit handlers for the axe and figure and call show and draw explicitly on the figure manager and canvas instead of going with implicit calls through pyplot, following the advices given in a post by tcaswell.
Following the above, the code would look something like this:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.axis([0, 100, 0, 1])
y = np.random.rand(100)
lines = ax.plot(y)
fig.canvas.manager.show()
i=0
while 1:
i=i+1
y = np.random.rand(100)
lines[0].set_ydata(y)
fig.canvas.draw()
fig.canvas.flush_events()
I've run the above code for a good 10 minutes and the memory used by the application remained stable the whole time, while the memory used by your current code (without plt.pause) increased by about 30MiB over the same period.
To answer myself, I solved the issue by adding
plt.pause(0.01)
after the
plt.draw()
This probably allows the GUI to finish the drawing and clear the buffer somewhere (my guess) before the new data comes in.
I know I'm late to answer this question, but for your issue you could look into the "joystick" package. It is based on the line.set_data() and canvas.draw() methods, with optional axes re-scaling, hence most probably faster than removing a line and adding a new one. It also allows for interactive text logging or image plotting (in addition to graph plotting).
No need to do your own loops in a separate thread, the package takes care of it, just give the update frequency you wish. Plus the terminal remains available for more monitoring commands while live plotting, which is not possible with a "while True" loop.
See http://www.github.com/ceyzeriat/joystick/ or https://pypi.python.org/pypi/joystick (use pip install joystick to install)
try:
import joystick as jk
import numpy as np
import time
class test(jk.Joystick):
# initialize the infinite loop decorator
_infinite_loop = jk.deco_infinite_loop()
def _init(self, *args, **kwargs):
"""
Function called at initialization, see the doc
"""
self._t0 = time.time() # initialize time
self.xdata = np.array([self._t0]) # time x-axis
self.ydata = np.array([0.0]) # fake data y-axis
# create a graph frame
self.mygraph = self.add_frame(jk.Graph(name="test", size=(500, 500), pos=(50, 50), fmt="go-", xnpts=100, xnptsmax=1000, xylim=(None, None, 0, 1)))
#_infinite_loop(wait_time=0.2)
def _generate_data(self): # function looped every 0.2 second to read or produce data
"""
Loop starting with the simulation start, getting data and
pushing it to the graph every 0.2 seconds
"""
# concatenate data on the time x-axis
self.xdata = jk.core.add_datapoint(self.xdata, time.time(), xnptsmax=self.mygraph.xnptsmax)
# concatenate data on the fake data y-axis
self.ydata = jk.core.add_datapoint(self.ydata, np.random.random(), xnptsmax=self.mygraph.xnptsmax)
self.mygraph.set_xydata(t, self.ydata)
t = test()
t.start()
t.stop()

Matplotlib Quiver memory leak

I have created quite a nice visualization program using Qt as the interface layer and matplotlib to draw much of the content. I use contour and countourf as well as text and lines and never run into problems with releasing objects.
As soon as I start calling Axes.quiver I get leaks. With the size of the dataset it adds up quickly. The following code demonstrates the problem:
from pylab import *
from numpy import ma
import time
X,Y = meshgrid( arange(0,2*pi,.04),arange(0,2*pi,.04) )
U = cos(X)
V = sin(Y)
fig = figure()
ax = fig.add_axes([0.1,0.1,0.8,0.8])
for i in range(90):
Q = ax.quiver( U, V)
time.sleep(0.2)
Q.remove()
I know this simple snippet isnt drawing to screen (leak becomes worse then).
Q has a sys.getrefcount of 4 so nothing I am able to do seems to get rid of it. Calls to fig and ax clear only reduce the refcount to 2. Quiver draws the image i want, but I am completely out of ideas.
My code is much more complex than this. I have tried completely replacing the axes objects but that doesnt help. I really am not free to replace the Figure instance.

Categories

Resources