This question already has answers here:
How to draw vertical lines on a given plot
(6 answers)
Closed 12 months ago.
I would like to draw a vertical line with Matpotlib and I'm using axvline, but it doesn't work.
import sys
import matplotlib
matplotlib.use('Qt4Agg')
from ui_courbe import *
from PyQt4 import QtGui
from matplotlib import pyplot as plt
class Window(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.setupUi(self)
self.boutonDessiner.clicked.connect(self.generatePlot)
def generatePlot(self):
# generate the plot
ax = self.graphicsView.canvas.fig.add_subplot(111)
ax.plot([1,3,5,7],[2,5,1,-2])
plt.axvline(x=4)
self.graphicsView.canvas.draw()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
I can see my plot, but no vertical line. Why?
Your example is not self contained, but I think you need to replace:
plt.axvline(x=4)
with:
ax.axvline(x=4)
You are adding the line to an axis that you are not displaying. Using plt. is the pyplot interface which you probably want to avoid for a GUI. So all your plotting has to go on an axis like ax.
matplotlib.pyplot.vlines
The difference is that you can pass multiple locations for x as a list, while matplotlib.pyplot.axvline only permits one location.
Single location: x=37
Multiple locations: x=[37, 38, 39]
If you're plotting a figure with something like fig, ax = plt.subplots(), then replace plt.vlines or plt.axvline with ax.vlines or ax.axvline, respectively.
import numpy as np
import matplotlib.pyplot as plt
xs = np.linspace(1, 21, 200)
plt.vlines(x=[37, 38, 39], ymin=0, ymax=len(xs), colors='purple', ls='--', lw=2, label='vline_multiple')
plt.vlines(x=40, ymin=0, ymax=len(xs), colors='green', ls=':', lw=2, label='vline_single')
plt.axvline(x=36, color='b', label='avline')
plt.legend()
plt.show()
Related
I am using matplotlib with tikzplotlib to plot (PGF/TikZ) figures.
I do not want a grid to be plotted, however the grid is always activated in the TeX output.
How can I get around this?
I don't want to edit the .tex
if possible.
Bonus question: Is there also a way to get the legend title?
Example:
import numpy as np
import matplotlib.pyplot as plt
import tikzplotlib as tikz
x = np.arange(0, 5, 1)
y = x
fig, ax = plt.subplots()
ax.plot(x, y, label='asdf')
ax.grid(False)
ax.legend(title='asdf')
ax.set(xlabel='x',
ylabel='y')
plt.show()
tikz.clean_figure()
tikz.save("asdf.tex", figure=fig)
matplotlib plot (without grid)
tikzplotlib plot (grid activated)
I found an example that can run normally on my laptop, but there is a problem. When the drawing is finished, a repeated result graph will be drawn again. I want to know how to not display the last repeated image.
import numpy as np
import matplotlib
%matplotlib inline
import matplotlib.pyplot as plt
# set up matplotlib
is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython:
from IPython import display
plt.ion()
def plot_durations(y):
plt.figure(2)
plt.clf()
plt.subplot(211)
plt.plot(y[:,0])
plt.subplot(212)
plt.plot(y[:,1])
if is_ipython:
display.clear_output(wait=True)
display.display(plt.gcf())
x = np.linspace(-10,10,10)
y = []
for i in range(len(x)):
y1 = np.cos(i/(3*3.14))
y2 = np.sin(i/(3*3.14))
y.append(np.array([y1,y2]))
plot_durations(np.array(y))
plt.ioff()
plt.show()
Replacing plt.show() with plt.close() at the end of your code will prevent jupyter notebook from displaying the final plot twice. An explanation is included here.
I create a heatmap with the following snippet:
import numpy as np
import matplotlib.pyplot as plt
d = np.random.normal(.4,2,(10,10))
plt.imshow(d,cmap=plt.cm.RdBu)
plt.colorbar()
plt.show()
The result is plot below:
Now, since the middle point of the data is not 0, the cells in which the colormap has value 0 are not white, but rather a little reddish.
How do I force the colormap so that max=blue, min=red and 0=white?
Use a DivergingNorm.
Note: From matplotlib 3.2 onwards DivergingNorm is renamed to TwoSlopeNorm.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
d = np.random.normal(.4,2,(10,10))
norm = mcolors.DivergingNorm(vmin=d.min(), vmax = d.max(), vcenter=0)
plt.imshow(d, cmap=plt.cm.RdBu, norm=norm)
plt.colorbar()
plt.show()
A previous SO post (Change colorbar gradient in matplotlib) wanted a solution for a more complicated situation, but one of the answers talked about the MidpointNormalize subclass in the matplotlib documentation. With that, the solution becomes:
import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt
class MidpointNormalize(mpl.colors.Normalize):
## class from the mpl docs:
# https://matplotlib.org/users/colormapnorms.html
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
self.midpoint = midpoint
super().__init__(vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
d = np.random.normal(.4,2,(10,10))
plt.imshow(d,cmap=plt.cm.RdBu,norm=MidpointNormalize(midpoint=0))
plt.colorbar()
plt.show()
Kudos to Joe Kington for writing the subclass, and to Rutger Kassies for pointing out the answer.
I am trying to generate an interactive plot that depends on widgets.
The problem I have is that when I change parameters using the slider, a new plot is done after the previous one, instead I would expect only one plot changing according to the parameters.
Example:
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
def plot_func(freq):
x = np.linspace(0, 2*np.pi)
y = np.sin(x * freq)
plt.plot(x, y)
interact(plot_func, freq = widgets.FloatSlider(value=7.5,
min=1,
max=5.0,
step=0.5))
After moving the slider to 4.0, I have:
while I just want one figure to change as I move the slider.
How can I achieve this?
(I am using Python 2.7, matplotlib 2.0 and I have just updated notebook and jupyter to the latest version. let me know if further info is needed.)
As you want to change the figure, instead of creating a new one, may I suggest the following way:
Use an interactive backend; %matplotlib notebook
Update the line in the plot, instead of drawing new ones.
So the code could look something like this:
%matplotlib notebook
from ipywidgets import *
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
line, = ax.plot(x, np.sin(x))
def update(w = 1.0):
line.set_ydata(np.sin(w * x))
fig.canvas.draw_idle()
interact(update);
Alternatively you may use plt.show() as in this answer.
This is an issue (?) introduced in the last version of jupyter and/or ipywidgets. One workaround I found was to add the line plt.show() at the end of plot_func.
For completion, here is an answer that makes use of more than one slider bar and sets the default parameters as well as the interval lengths.
%matplotlib notebook
from ipywidgets import *
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 10,100)
def f(x, A, B, C):
return A*x**2 + B*x + C
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
line, = ax.plot(x, f(x, A=1, B=1, C=1))
def update(A = 1, B = 0, C = 0):
line.set_ydata(f(x,A,B,C))
fig.canvas.draw_idle()
interact(update, A = (-4,4,0.1), B = (-4,4,0.1), C = (-4,4,0.1));
I'm trying to graph features of a data-set one by one by, via iteration.
So I want the graph to continuously update as I proceed through the loop.
I refered to this thread,real-time plotting in while loop with matplotlib but the answers are all over the place, and despite incorporating some of their suggestions as shown below, I still can't seem to get the code working. I'm using Jupyter Notebook.
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
colors = ["darkblue", "darkgreen"]
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True, sharex = True)
for i in range(X.shape[-1]-1):
idx = np.where(y == 1)[0]
ax1.scatter(X[idx, i], X[idx, i+1], color=colors[0], label=1)
idx = np.where(y == 0)[0]
ax2.scatter(X[idx, i], X[idx, i+1], color=colors[1], label=0)
plt.draw()
plt.pause(0.0001)
Any suggestions?
Thank you.
This is an example for real-time plotting in a Jupyter Notebook
%matplotlib inline
%load_ext autoreload #Reload all modules every time before executing the Python code typed.
%autoreload 2
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
import time
colors = ["darkblue", "darkgreen"]
# initialise the graph and settings
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = fig.add_subplot(211)
plt.ion() # interactive mode
fig.show()
fig.canvas.draw() # matplotlib canvas drawing
# plotting loop
for i in range(X.shape[-1]-1):
ax1.clear()
ax2.clear()
idx = np.where(y == 1)[0]
ax1.scatter(X[idx, i], X[idx, i+1], color=colors[0], label=1)
idx = np.where(y == 0)[0]
ax2.scatter(X[idx, i], X[idx, i+1], color=colors[1], label=0)
fig.canvas.draw() # draw
time.sleep(0.5) # sleep
For an animation you need an interactive backend. %matplotlib inline is no interactive backend (it essentially shows a printed version of the figure).
You may decide not to run you code in jupyter but as a script. In this case you would need to put plt.ion() to put interactive mode on.
Another option would be to use a FuncAnimation, as e.g in this example. To run such a FuncAnimation in Jupyter you will still need some interactive backend, either %matplotlib tk or %matplotlib notebook.
From matplotlib 2.1 on, we can also create an animation using JavaScript.
from IPython.display import HTML
HTML(ani.to_jshtml())
Some complete example:
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
ax.axis([0,2*np.pi,-1,1])
l, = ax.plot([],[])
def animate(i):
l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_jshtml())