How do i add a text on matplotlib FuncAnimation - python-3.x

i am having difficulty adding a text to a static position using axes coordinate and not the data coordinate while running matplotlib funcanimation . Would you mind helping me out a bit?
import matplotlib.pyplot as plt
import random
from itertools import count
from matplotlib.animation import FuncAnimation
from datetime import datetime
import mplfinance as mpf
%matplotlib notebook
#creats subplots
fig = plt.figure(figsize=(8,4)) [enter image description here][1]
fig.patch.set_facecolor('#121416')
ax1=plt.subplot2grid((9,18), (0,0),colspan=12, rowspan=7 )
ax2=plt.subplot2grid((9,18), (0,12),colspan=6, rowspan=3)
ax3=plt.subplot2grid((9,18), (3,12),colspan=6, rowspan=3)
ax4=plt.subplot2grid((9,18), (6,12),colspan=6, rowspan=3)
ax5=plt.subplot2grid((9,18), (7,0),colspan=12, rowspan=3)
#values
x_vals=[]
y1_vals=[]
y2_vals=[]
y3_vals=[]
y4_vals=[]
y5_vals=[]
index = count()
def animate(i):
#generate and append data
x_vals.append(next(index))
y1_vals.append(random.randint(0,4))
y2_vals.append(random.randint(0,3))
y3_vals.append(random.randint(0,2))
y4_vals.append(random.randint(0,3))
y5_vals.append(random.randint(0,4))
#plot graph
ax1.plot(x_vals, y1_vals, color='green')
ax2.plot(x_vals, y2_vals, color='white')
ax3.plot(x_vals, y3_vals, color='green')
ax4.plot(x_vals, y4_vals, color='white')
ax5.plot(x_vals, y5_vals, color='green')
#add text and title
**ax1.text(y=3, x=0.05, s='position 1', transform=ax.transAxes, color='white' )**
ax1.set_title(label='graph 1', loc='center', fontsize=15, color='white' )
#funcanimation
anim = FuncAnimation(fig, animate, interval=1000)
plt.show()
desired image

I see a few things that may be wrong:
ax1.text(y=3, x=0.05, s='position 1', transform=ax.transAxes, color='white' )
ax.transAxes should be ax1.transAxes
ax1 has a white background, so you won't see color='white' text. Try black: color='k'
Axes coordinates go from 0.0 to 1.0 (fraction of the Axes object).
Therefore y=3 will not work. Try y=0.9
When I made the above changes, it worked for me.

Related

How to update scatter with plot?

I am updating the graph, but can't join to it the scatter, could someone help me, please? I don't understand, how to realize it.
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure()
ax = fig.add_subplot()
line = ax.plot([],[])[0]
x = []
y = []
scat = ax.scatter(x,y,c='Red')
def animate(i):
x.append(i)
y.append((-1)**i)
line.set_data(x, y)
ax.relim()
ax.autoscale_view()
return [line]
anim = FuncAnimation(fig, animate, frames=200, interval=100, blit=True)
plt.show()
I want to add dotes and their coordinates change only in X, Y should be 0.
Several problems have to be addressed here. You have to update the scatter plot, which is a PathCollection that is updated via .set_offsets(). This is in turn requires the x-y data to be in an array of the form (N, 2). We could combine the two lists x, y in every animation loop to such an array but this would be time-consuming. Instead, we declare the numpy array in advance and update it in the loop.
As for axes labels, you might have noticed that they are not updated in your animation. The reason for this is that you use blitting, which suppresses redrawing all artists that are considered unchanged. So, if you don't want to take care manually of the axis limits, you have to turn off blitting.
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
fig, ax = plt.subplots()
line, = ax.plot([],[])
scat = ax.scatter([], [], c='Red')
n=200
#prepare array for data storage
pos = np.zeros((n, 2))
def animate(i):
#calculate new x- and y-values
pos[i, 0] = i
pos[i, 1] = (-1)**i
#update line data
line.set_data(pos[:i, 0], pos[:i, 1])
#update scatter plot data
scat.set_offsets(pos[:i, :])
#update axis view - works only if blit is False
ax.relim()
ax.autoscale_view()
return scat, line
anim = FuncAnimation(fig, animate, frames=n, interval=100, blit=False)
plt.show()
Sample output:

Why is the grid turned on only on the last subplot?

I am using subplots in a function which is using a slider widget inputs to calculate some stuff and plotting results.
I want to turn on the grid for all subplots of ax1. But somehow jupternotebooks only turns it on only on the last plot...
import numpy as np
from matplotlib import pyplot as plt
import ipywidgets as widgets
from IPython.html.widgets import interact
%matplotlib inline
## Plot
fig, ax1 = plt.subplots(6,2)
plt.subplots_adjust(right = 2, top = 8 )
# Show the major grid lines with dark grey lines
plt.grid(b=True, which='major', color='#666666', linestyle='-')
# Show the minor grid lines with very faint and almost transparent grey lines
plt.minorticks_on()
plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2)
## Giergeschwindigkeit über v und ay
ax1[0,0].plot(v_ms, omega)
ax1[0,0].set_ylabel('Giergeschwindigkeit [rad/s]')
ax1[0,0].set_xlabel('Geschwindigkeit [m/s]')
ax1[0,0].set_title('Giergeschwindigkeit über Geschwindigkeit')
# ... more subplots
plt.show()
It looks like this:
And can you explain to me why in my case
ax1.grid()
throws an error?
AttributeError: 'numpy.ndarray' object has no attribute 'grid'
This is because plt will only operate on the last-created axes object.
And the reason you're getting that error is that ax1 is a numpy n-dimensional array, not an axes object.
You can do this to iterate over the numpy n-dimensional array to create the grids:
for row in axes:
for ax in row:
ax.grid(b=True, which='major', color='#666666', linestyle='-')
ax.minorticks_on()
ax.grid(b=True, which='minor', color='#999999', linestyle='-',alpha=0.2)
Result (without plt.subplots_adjust()):
You can set grid for every ax object, so in your case you should set like this:
ax1[0,0].grid()
ax1[0,1].grid()

displaying a map in the background with matplotlib animation

I want to show a map in the background when a vehicle is moving. I am using matplotlib animate function. The movement looks fine. But I tried the following while loading the map. The map is not loading. Only a black patch is visible. I tried to specify the zorder as well. but nothing works.
ani = animation.FuncAnimation(fig, animate, len(x11),interval=150,
blit=True, init_func=init, repeat=False)
img = cbook.get_sample_data('..\\maps.png')
image = plt.imread(img)
plt.imshow(image)
plt.show()
You can read background image with scipy.misc import imread and use plt.imshow to render in the background of your animation.
Below example generates a circle (we'll assume its your car), puts "usa_map.jpg" in the background and then moves circle over map.
Bonus, you can save the animation using encoders such as ffmpeg as a movie in mp4 format using anim.save('the_movie.mp4', writer = 'ffmpeg', fps=30)
Source Code
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from scipy.misc import imread
img = imread("usa_map.jpg")
fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(7, 6.5)
ax = plt.axes(xlim=(0, 20), ylim=(0, 20))
patch = plt.Circle((5, -5), 0.75, fc='y')
def init():
patch.center = (20, 20)
ax.add_patch(patch)
return patch,
def animate(i):
x = 10 + 3 * np.sin(np.radians(i))
y = 10 + 3 * np.cos(np.radians(i))
patch.center = (x, y)
return patch,
anim = animation.FuncAnimation(fig, animate,
init_func=init,
frames=360,
interval=20,
blit=True)
plt.imshow(img,zorder=0, extent=[0.1, 20.0, 0.1, 20.0])
anim.save('the_movie.mp4', writer = 'ffmpeg', fps=30)
plt.show()
Above code will generate animaton with a circle moving around USA map. It will also be saved as 'the_movie.mp4' , which I cant upload here.
Result Image

Unable to plot 4 histograms of iris dataset features using matplotlib

using the iris dataset
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib
from sklearn import datasets
iris= datasets.load_iris()
x_index = 3
colors = ['blue', 'red', 'green']
for label, color in zip(range(len(iris.target_names)), colors):
plt.hist(iris.data[iris.target==label, x_index],
label=iris.target_names[label],
color=color)
plt.xlabel(iris.feature_names[x_index])
plt.legend(loc='upper right')
plt.show()
enter image description here
This code is plotting only one histogram with sepal length (image attached) as the x-axis.
To plot other features of iris dataset in a similar manner, I have to change the x_index to 1,2 and 3 (manually) and run this bit of code again.
To plot all four histograms simultaneously, I tried the following code:
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib
from sklearn import datasets
iris= datasets.load_iris()
fig, axes = plt.subplots(nrows= 2, ncols=2)
colors= ['blue', 'red', 'green', 'black']
x_index= 0
for ax in axes.flat:
for label, color in zip(range(len(iris.target_names)), colors):
ax= plt.hist(iris.data[iris.target==label, x_index], label=
iris.target_names[label], color=color)
plt.xlabel(iris.feature_names[x_index])
plt.legend(loc='upper right')
x_index+=1
plt.show()
This code gives me the following error:
IndexError: index 4 is out of bounds for axis 1 with size 4
Any advice?
Two issues:
ax is the name of the current axes in the loop. You should not redefine but instead use it as this is the axes you want to plot to. Replace ax = plt.hist by ax.hist.
x_index+=1 needs to be in the outer loop, not in the inner loop. Otherwise it will increment up to 11 instead of 3. Better get rid of it entirely and use a normal loop variable.
Complete code:
import matplotlib.pyplot as plt
from sklearn import datasets
iris= datasets.load_iris()
fig, axes = plt.subplots(nrows= 2, ncols=2)
colors= ['blue', 'red', 'green']
for i, ax in enumerate(axes.flat):
for label, color in zip(range(len(iris.target_names)), colors):
ax.hist(iris.data[iris.target==label, i], label=
iris.target_names[label], color=color)
ax.set_xlabel(iris.feature_names[i])
ax.legend(loc='upper right')
plt.show()

Display Matplotlib spines in Tkinter

I know how to display spines in Matplotlib. I know how to display a Matplotlib subplot in Tkinter too. But I would like to know how to put the spines in this subplot in Tkinter.
Here is the code to display a subplot in Tkinter :
import matplotlib
matplotlib.use('TkAgg')
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
def destroy(e): sys.exit()
root = Tk.Tk()
root.wm_title("Embedding in TK")
f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
t = arange(0.0,3.0,0.01)
s = sin(2*pi*t)
a.plot(t,s)
a.set_title('Tk embedding')
a.set_xlabel('X axis label')
a.set_ylabel('Y label')
# a tk.DrawingArea
canvas = FigureCanvasTkAgg(f, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
#toolbar = NavigationToolbar2TkAgg( canvas, root )
#toolbar.update()
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
button = Tk.Button(master=root, text='Quit', command=sys.exit)
button.pack(side=Tk.BOTTOM)
Tk.mainloop()`
Here is the code to display spines in Matplotlib :
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
image = np.random.uniform(size=(10, 10))
ax.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
ax.set_title('dropped spines')
# Move left and bottom spines outward by 10 points
ax.spines['left'].set_position(('outward', 10))
ax.spines['bottom'].set_position(('outward', 10))
# Hide the right and top spines
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
# Only show ticks on the left and bottom spines
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')
plt.show()
Where you use ax.set_title('...') in your second code block, you use a.set_title('...') in your first block. This pretty much gives away that the methods you can call on ax, you can also call on a.
Simply use the same code as in the second block, but replace ax with a, and it should work fine.
According to the docs, ax and a are not exactly the same objects. Figure.add_subplot() returns an Axes instance, and pyplot.subplots() returns an Axis object as second output parameter. However, since
The Axes contains most of the figure elements: Axis...
you can edit the spines in the same way from both.

Resources