Dynamially modify & update plot in matplotlib - python

Claim 1: no precomputed array
Claim 2: no set_ydata
I have read answer from Dynamically updating plot in matplotlib and How to update a plot in matplotlib? and their scenarios are different.
Case 0, you are iteratively solving large linear algebra problem, how can you monitor convergence of the solution at real time -- so you can stop the calculation once the solution shows signs of explosion and save waiting time?
Case 1, you have a two dimensional array and you are changing value at random (i, j), you can think of this as ising model or percolation model or whatever model you are familar with. How to show the evolution of the array?
Case 2, you have a triangular mesh and you are doing depth-first search of the nodes and you want to mark the path, or you are doing something simpler: tracing the mesh boundaries using half-edge data structure. A visualization at real time is of massive help for checking correctness of the algorithm implementation.
Enough background, the 0th one can be solved by the set_ydata method if your number of iterations is not large (or you don't care about memory), but case 1 and 2? I have no hint. Currently my 'solution' is to save hundreds of figures on disk. I've tried to just plot one figure and update it, but matplotlib seems prefer waiting for everything is done and plot everything at once. Can anybody tell me how to dynamically update a figure? Thank you very much!
Test code is below (currently it only plots once in the end):
from numpy import *
import matplotlib.pyplot as plt
from time import sleep
M = zeros((5,5))
fig = plt.figure(1)
for n in range(10):
i = random.randint(5)
j = random.randint(5)
print 'open site at ', i, j
M[i, j] = 1
plt.imshow(M, 'gray', interpolation = 'nearest')
plt.plot(j, i, 'ro') # also mark open site (I have reason to do this)
fig.canvas.draw()
sleep(0.3)
plt.show()

I just found the answer after finding this question: Matplotlib ion() function fails to be interactive
The code above can be made 'real-time' just by replacing the sleep(0.3) with plt.pause(0.3), no other change is necessary. This is quite unexpected and I never used plt.pause() function before, but it simply works.

Related

matplotlib legend performance issue

I am using Jupyter-notebook with python 3.6.2 and matplotlib to plot some data.
When I plot my data, I want to add a legend to the plot (basically to know which line is which)
However calling plt.legend takes a lot of time (almost as much as the plot itself, which to my understanding should just be instant).
Minimal toy problem that reproduces the issue:
import numpy as np
import matplotlib.pyplot as plt
# Toy useless data (one milion x 4)
my_data = np.random.rand(1000000,4)
plt.plot(my_data)
#plt.legend(['A','C','G','T'])
plt.show()
The data here is just random and useless, but it reproduces my problem:
If I uncomment the plt.legend line, the run takes almost double the time
Why? Shouldn't the legend just look at the plot, see that 4 plots have been made, and draw a box assigning each color to the corresponding string?
Why is a simple legend taking so much time?
Am I missing something?
Replicating the answer by #bnaecker, such that this question is answered:
By default, the legend will be placed in the "best" location, which requires computing how many points from each line are inside a potential legend box. If there are many points, this can take a while. Drawing is much faster when specifying a location other than "best", e.g. plt.legend(loc=3).

Python: define color curve section

I am trying to replicate the following figure:
The color gradient goes from blue to red and indicates the state of a material. I can currently plot each curve. Each line is defined by two points, and is then simply plotted using pyplot (matplotlib library). I also have a clear idea on how to compute the associated value.
However, it can be noticed, for example for point 9 or 22 on the first figure, that the value is different at the overlapping area. I have currently no clue on how to do that effectively.
The only idea I have comes from this solution. Basically, I have to turn each curve section into a polygon. But it looks very heavy, and prehaps not the best solution in this case.
I am mainly asking for leads that could help me to achieve this, or just a smarter way to look at the problem !
The code that produced this figure:
import shelve
import matplotlib.pyplot as plt
import os
path = "C:/Users/***/Desktop/Python/PyHugo/"
d = shelve.open(os.path.join(path, 'output.db'))
pointMat = d ['curve']
d.close()
fig=plt.figure()
ax=fig.add_subplot(111)
for matID in pointMat.keys():
for couple in range(len(pointMat[matID])-1):
plt.plot([pointMat[matID][couple][0][0],pointMat[matID][couple][1][0]],[pointMat[matID][couple][0][1],pointMat[matID][couple][1][1]])
plt.show()
Points are stored in the pointMat dictionnary. Each area has a set of points. An area is a specific material. It is represented on figure one by le black line (around 540). So in the current example there are 2 materials.
The, the first set of points is given by:
print matPoint[0][0]
results : [[20, 20], [0, 40]]. We asked for the first couple of point in the first material.
Edit 1: code added, off-topic question removed
EDIT 2: Instead of plotting the curves, I am mapping the values over a grid (discretisation of the phenomena). The problem has too many variations, and this seemed a better idea. Thank you for the time spend trying to help me !
You need to make your lines semi-transparent using the alpha parameter:
plt.plot([pointMat[matID][couple][0][0],
[pointMat[matID][couple][1][0]],
[pointMat[matID][couple][0][1],
[pointMat[matID][couple][1][1]],
alpha=0.7)
as an example.

Nice ways to collect pyplot graphs into a single page/document/etc?

I'm currently working on a program that plots many graphs. I'm using Jupyter. It works okay so far, but it is printing each graph to its own window. This is less than ideal because there are hundreds of graphs.
What are some ways to condense the output? I am hoping for a way to have the many graphs sent to a single document/window.
Also, I am iterating over a dictionary and only plotting graphs when the program encounters something of interest, so the frequency is not very predictable. It is something like this:
while still_true:
if my_condition is True:
a = np.arange(20) // not actually a range, but a dynamic np array
plt.plot(a)
plt.ylabel("some numbers")
plt.show()

Plot looping really slow

I am writing a code to fit a gaussian over a function and if I don't plot the result (it is a datacube of ~60x60 spectra, so I am using a loop) the code works really fast.
But when I say the code to plot every graph it gets really slow, something like 2 graphs a second (when I don't plot it does like 40).
Ok, I understand it can be right to slow a lot down, but there is a code in IDL that does the exact same thing and the code runs 8~10 plots per second.
Is there a way to improve it? Or python is really slower than IDL?
Here is the plot code:
plt.plot(wavelengthset, data_datacube[minpixel:maxpixel+1, j, i], 'k-',
wavelengthset, gaussian(fit[0], wavelengthset), 'r-')
plt.draw()
plt.clf()
I recommend looking into removing plt.draw() and using blit. If that's insufficient, please let me know a little more about your data and the purpose of the plots.
See this answer for more info: why is plotting with Matplotlib so slow?
As the answer at the above link mentions, matplotlib is designed for quality, customizable, interactive plots. Matplotlib may be slower than the data processing tools you're familiar with in IDL, but that's not to say that another, speed-conscious Python toolkit won't be just as fast/helpful.
Good luck!

graphing a relationship matrix in python

i have a python interface using wxpython which allows the user to fill in a matrix (0/1) and then graphs it for them. The program creates a numpy matrix, then makes a networkx graph out of that matrix, and then uses matplotlib.pylab to display the graph.
numpy is a must, because the program also does other things like get the transitive, reflexive, and symmetric closures... as for networkx i can use something else if u recommend something else better for graphing matrices, and as for matplotlib, i hate it, please if u know of any other way to display a graph please advice.
matplotlib is the source of my problem, when the users clicks the graph button, my programs reads the matrix, makes a graphs and matplotlib displays it in a new window (by default). Now if the users goes back to the original window and graphs a different matrix without first closing the matplotlib window, the program crashes.
also the way the relationship "arrows" are drawn is, in my opinion, unattractive.
i need a better way to graph my matrix, or at the very least as a way to force close the myplotlib window, i tried plt.close() but that didnt work, the window would remain open, and both windows will say (Not Responding) and i have to end process.
this is the part of the code in question:
import numpy as np
import networkx as nx
import matplotlib.pylab as plt
...
...
...
def graph(values)
plt.close() #with or without this it does not work
matrix = np.matrix(values)
graph = nx.DiGraph(matrix)
nx.draw(graph)
plt.show()
return
It seems to me like your main complaint is in the way that wx handles the matplotlib windows. It is possible to embed the Matplotlib figure in your wx window. Here's an example:
http://wiki.scipy.org/Matplotlib_figure_in_a_wx_panel (updated)
It gets a bit complicated. Basically, you should copy the code and replace the "DemoPlotPanel.draw()" method. You'll need to modify your code to specify the axis to draw on. It's buried in the networkx documentation here:
http://networkx.lanl.gov/reference/drawing.html
I am just using an example of the Networkx documentation:
try:
import matplotlib.pyplot as plt
except:
raise
import networkx as nx
G=nx.star_graph(20)
pos=nx.spring_layout(G)
nx.draw(G,pos)
plt.show() # display
So your plt.close() statement at the start does not make sense, you should remove it.You should also calculate the coordinates for your nodes, the sentence pos=nx.spring_layout(G) does this. You call a specific layout algorithm and supply your graph G, you get a dictionary in return with for each node the x and y coordinates.
Have a close look at the examples at: http://networkx.lanl.gov/gallery.html

Categories