Python plotting clearing the graph in for loop - python

I am plotting within a for loop. So that I get a new graph each iteration. Of course I want to clear the graph from the previous iteration. When I use plt.cla() the axis labels and title is also cleared. How can I just remove the graph but keep the axis labels and title?
for n in range(N):
ax.plot(x[n],t) # plot
plt.savefig(f'fig_{n}.png') # save the plot
plt.cla()

Try plt.clf() - clear figure
for n in range(N):
ax.plot(x[n],t) # plot
plt.savefig(f'fig_{n}.png') # save the plot
plt.clf()

Remove lines at the bottom of the loop.
from matplotlib import pyplot as plt
import numpy as np
y = np.arange(10)
fig,ax = plt.subplots()
ax.set_title('foo')
ax.set_ylabel('wye')
ax.set_xlabel('EX')
for n in range(3):
ln, = ax.plot(y*n)
fig.savefig(f'fig{n}')
ln.remove()

Related

Matplotlib: How to recreate `6 petal` polar diagram

For an assignment, I have to recreate the following plot (including all labels and ticks):
This is what I have tried so far with my code
import numpy as np
import matplotlib.pyplot as plt
nmax=101 # choose a high number to "smooth out" lines in plots
x = np.linspace(0,20,nmax) # create an array x
y_br = np.sin(3*x) # y for the bottom right subplot
fig = plt.figure()
ax4 = plt.subplot(224, projection = 'polar')
ax4.plot(x, y_br, 'tab:blue')
But if you were to run this yourself, this does not replicate the plot. What function could be used here and how can tick marks be changed in polar plots? Thanks in advance?

Plot n different graphs on the same plot with different colors in Python

I would like to plot n different graphs on the same plot with different color.
The problem I got is that I get lines between the different plots, and I don't get random color on the graph. I'm an beginner.
My Plot:
My Code:
import matplotlib.pyplot as plt
import random
import numpy
list_y = []
list_x = []
counter = 0
# generate data
for i in range(0,5):
for p in range(0,10):
list_y.append(random.uniform(0.9,1.2))
counter=counter+1
list_x.append(counter)
print(list_y)
print(list_x)
plt.plot(list_x, list_y,c=numpy.random.rand(3,))
counter = 0
# naming the x axis
plt.xlabel('x - axis')
# naming the y axis
plt.ylabel('y - axis')
# giving a title to my graph
plt.title('My first graph!')
# function to show the plot
plt.show()
You just misplaced the initialisations
list_y=[]
list_x=[]
before the line for i in range(0,5): rather than after it, hence finally a plot with the points of all 5 graphs is drawn over the preceding ones.

Plotting a curve in the margin of a figure

I have the plot of a function f, which depends on time in a discontinuous way. More precisely, it has a particular behavior for t1<=t<t2 and another everywhere else, like in the example below
import matplotlib.pyplot as plt
import numpy as np
from pylab import *
l1=1.
l2=5.
t1=20.
t2=50.
tf=120.
def f1(t):
if t<t1:
L = l1
elif t1<=t<t2:
L = l2
else:
L=l1
g=L*t
return g
a=np.linspace(0.,100,1000)
values1=map(f1,a)
fig1=plt.figure(1)
plt.plot(a,values1,color='red')
plt.show()
The plot of the pulse is the following
def f2(t):
if t<t1:
L = l1
elif t1<=t<t2:
L = l2
else:
L=l1
return L
values2=map(f2,a)
fig2=plt.figure(2)
plt.plot(a,values2,color='blue')
plt.show()
I want to make a figure with the red curve as the main plot and a little inset in the top margin of the figure showing the blue curve, without any x axis or y axis, just to make the viewer understand when the change in the parameter L happens.
I think that subplots will do what you want. If you make the top subplot smaller, and take the ticks/labels off it looks like its in the margins. Here's a code snippet that sets up the plot.
f = plt.figure()
# Make 2 subplots arranged vertically with different ratios
(ax, ax2) = f.subplots(2,1, gridspec_kw={'height_ratios':[1,4]})
#remove the labels on your top subplot
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax.plot(a, f2(a))
ax2.plot(a, f1(a), 'r:') #red curve main plt
plt.show()
I used this code to plot a few sinusoids and it came out as follows:
Is this what you're looking for?
Maybe you could use inset_axes from mpl_toolkits.axes_grid1.inset_locator
See for example: https://matplotlib.org/gallery/axes_grid1/inset_locator_demo.html
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
fig, axs = plt.subplots(1, 1)
# Create inset of width 1.3 inches and height 0.9 inches
# at the default upper right location
axins = inset_axes(axs, width='20%', height='20%', loc=2)
And then plot your data in axins:
axins.plot(data)
You can also switch off the ticks and labes using:
axins.axes.get_yaxis().set_visible(False)
axins.axes.get_xaxis().set_visible(False)

Preserve content of fig after show() in matplotlib?

I'm creating a violinplot of some data and afterwards I render a scatterplot with individual data points (red points in example) to three subplots.
Since the generation of the violinplot is relatively time consuming, I'm generating the violinplot only once, then add the scatterplot for one data row, write the result file, remove the scatterplots from the axes and add the scatterplots for the next row.
Everything works, but I would like to add the option, to show() each plot prior to saving it.
If I'm using plt.show(), the figure is shown correctly, but afterwards the figure seems to be cleared and in the next iteration I'm getting the plot without the violin plots.
Is there any way to preserve the content of the figure after plt.show()?
In short, my code is
fig = generate_plot(ws, show=False) #returns the fig instance of the violin plot
#if I do plt.show() here (or in "generate_plot()"), the violin plots are gone.
ax1, ax3, ax2 = fig.get_axes()
scatter1 = ax1.scatter(...) #draw scatter plot for first axes
[...] #same vor every axis
plt.savefig(...)
scatter1.remove()
I was thinking that a possible option is to use the event loop to advance through the plots. The following would define an updating function, which changes only the scatter points, draws the image and saves it. We can manage this via a class with a callback on the key_press - such then when you hit Space the next image is shown; upon pressing Space on the last image, the plot is closed.
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
import numpy as np
class NextPlotter(object):
def __init__(self, fig, func, n):
self.__dict__.update(locals())
self.i = 0
self.cid = self.fig.canvas.mpl_connect("key_press_event", self.adv)
def adv(self, evt):
if evt.key == " " and self.i < self.n:
self.func(self.i)
self.i+=1
elif self.i >= self.n:
plt.close("all")
#Start of code:
# Create data
pos = [1, 2, 4, 5, 7, 8]
data = [np.random.normal(0, std, size=100) for std in pos]
data2 = [np.random.rayleigh(std, size=100) for std in pos]
scatterdata = np.random.normal(0, 5, size=(10,len(pos)))
#Create plot
fig, axes = plt.subplots(ncols=2)
axes[0].violinplot(data, pos, points=40, widths=0.9,
showmeans=True, showextrema=True, showmedians=True)
axes[1].violinplot(data2, pos, points=40, widths=0.9,
showmeans=True, showextrema=True, showmedians=True)
scatter = axes[0].scatter(pos, scatterdata[0,:], c="crimson", s=60)
scatter2 = axes[1].scatter(pos, scatterdata[1,:], c="crimson", s=60)
# define updating function
def update(i):
scatter.set_offsets(np.c_[pos,scatterdata[2*i,:]])
scatter2.set_offsets(np.c_[pos,scatterdata[2*i+1,:]])
fig.canvas.draw()
plt.savefig("plot{i}.png".format(i=i))
# instantiate NextPlotter; press <space> to advance to the next image
c = NextPlotter(fig, update, len(scatterdata)//2)
plt.show()
A workaround could be to not remove the scatterplot.
Why not keep the scatter plot axis, and just update the data for that set of axis?
You will most likely need a plt.draw() after update of scatter plot data to force a new rendering.
I found a way to draw figures interactively here. plt.ion() and block the process with input() seems to be important.
import matplotlib.pyplot as plt
plt.ion()
fig = plt.figure()
ax = plt.subplot(1,1,1)
ax.set_xlim([-1, 5])
ax.set_ylim([-1, 5])
ax.grid('on')
for i in range(5):
lineObject = ax.plot(i,i,'ro')
fig.savefig('%02d.png'%i)
# plt.draw() # not necessary?
input()
lineObject[0].remove()
I also tried to block the process with time.sleep(1), but it does not work at all.

How to undo all what is done by a colorbar() call (which is known to call the make_axes function)?

How does one restore a Matplotlib figure in its initial state before a colorbar creation ?
I want to use a single subplot that displays lines, curves, images, contours,etc, in a dynamical way depending on the actions of a user. So it can happen that at some point this subplot contains 3 images, then later no images, and then even later 2 images again, and so on. Each time a first image is added, a colorbar is created, whereas each time the last image is deleted, the colorbar is deleted and the subplot resized to its original size.
Here is a simple piece of code that tries to create the colorbar and then delete it and resize the plot several times. (for simplicity here, I don't play with the content of the 1st subplot) :
import matplotlib.pyplot as plt
import matplotlib.colorbar as cb
import numpy as np
import time
##
fig= plt.figure()
ax = fig.add_subplot(111)
arr= np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
im = ax.imshow(arr,interpolation='Nearest',origin='lower')
initialPosition=ax.get_position()
plt.show()
for i in range(5):
cb = plt.colorbar(im) # here is the problem for i>1. ax is too small.
fig.canvas.draw()
time.sleep(2)
# Try now to delete the colorbar and restore the initial size of ax
fig.delaxes(fig.axes[1]) # first delete the colobar axes => OK
ax.set_position(initialPosition) # then restore the size => OK
fig.canvas.draw()
The behavior is strange: each time a new colorbar is created, the first subplot is smaller and smaller... I guess it has to do with the behavior of the make_axes() function called by colorbar(), which does not simply modify the position of the first subplot ax but also other properties of ax and/or fig.
Now another question, may be more important: Where a programmer is supposed to find this piece of information in the matplotlib official documentation?
Thanks for your help.
Denis
I don't understand why you want to do this, but you can try this:
import matplotlib.pyplot as plt
import numpy as np
#
fig= plt.figure()
ax = fig.add_subplot(111)
arr= np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
im = ax.imshow(arr,interpolation='Nearest',origin='lower')
fig.canvas.draw() # draw the axis so we can get the right position
pos = ax.get_position() # backup the position before draw colorbar
cb= plt.colorbar(im)
fig.canvas.draw()
fig.delaxes(fig.axes[1]) # first delete the colobar axes
ax.set_position(pos) #restore the position
plt.show()
EDIT
To restore colorbar, we need save the position of ax and cb.ax when the colorbar is visible:
import matplotlib.pyplot as plt
import matplotlib.colorbar as cb
import numpy as np
import time
##
fig= plt.figure()
ax = fig.add_subplot(111)
arr= np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
im = ax.imshow(arr,interpolation='Nearest',origin='lower')
fig.canvas.draw()
init_pos=ax.get_position()
cb = plt.colorbar(im)
fig.canvas.draw()
cb_pos = cb.ax.get_position()
ax_pos = ax.get_position()
fig.delaxes(fig.axes[1])
fig.canvas.draw()
plt.show()
for i in range(5):
cb = plt.colorbar(im) # here is the problem for i>1. ax is too small.
cb.ax.set_position(cb_pos)
ax.set_position(ax_pos)
fig.canvas.draw()
time.sleep(2)
# Try now to delete the colorbar and restore the initial size of ax
fig.delaxes(fig.axes[1]) # first delete the colobar axes => OK
ax.set_position(init_pos) # then restore the size => OK
fig.canvas.draw()
time.sleep(2)

Categories