Home > Enterprise >  animation matplotlib with dates is not working?
animation matplotlib with dates is not working?

Time:05-26

I'm trying to add to an animated plot of a random variable the dates in the x axes. I've tried different things but the code is working just with a static x-axes array..

I made a small function to update the dates array T and random var array y the I called shift().

  • To see how the basic code (no dates) is behaving you need to uncomment every line that is followed by "# uncomment 1". Viceversa uncomment every line that has "# uncomment 0".

I don't know why I can't plot the dates in the x-axes.

This below is the code:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import pandas as pd
import time
import datetime


plt.rcParams.update({'axes.facecolor':'lightgray'})
plt.rcParams.update({'figure.facecolor':'gray'})
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
# ax = plt.axes()
ax = plt.axes(xlim=(0, 2), ylim=(-8, 8))
line, = ax.plot([], [], lw=2)


def shift(y_arr,y_i,cont_cascata):
    print("cont_cascata:",cont_cascata)
    if type(y_arr)==list:
        y_arr.pop(0)
        y_arr = y_arr [y_i]
    if type(y_arr) is np.ndarray:
        print("np.array..")
        y_arr = np.delete(y_arr, 0)  # togliamo primo
        y_arr = np.append(y_arr, y_i)  # aggiungiamo ultimo
    return y_arr

# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    return line,

# animation function.  This is called sequentially
# pd._libs.tslibs.timestamps.Timestamp
def ts_array(n):
    t0 = pd.Timestamp(2018,1,1,12,30)
    T = []
    for i in range(n):
        t_i = t0 pd.Timedelta(minutes=i)
        T = T [t_i]
    return T

# tarr = ts_array(n=100)


def animate(i):
    global y,x,T
    n = 100
    if i==0:
        y = np.round(np.random.normal(loc=0, scale=2, size=n), decimals=2)
        x = np.linspace(0, 2, n)  # uncomment 0
        T = ts_array(n)   # uncomment 1

    y_i = np.round(np.random.normal(loc=0,scale=2),decimals=2)
    t_i = T[-1] pd.Timedelta(minutes=1)   # uncomment1

    y = shift(y_arr=y,y_i=y_i, cont_cascata=i)
    T = shift(y_arr=T,y_i=t_i,cont_cascata=i)  # uncomment 1
    T = pd.DatetimeIndex(T)   # uncomment 1
    T = T.to_pydatetime()    # uncomment 1

    # line.set_data(x, y)  # uncomment 0
    line.set_data(T,y)   # uncomment 1
    time.sleep(0.5)
    return line,

print("animate")

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=20, blit=True)

plt.show()

What should I do to make this code work properly? Thanks

CodePudding user response:

You need to adjust the xlim of the axes to account for date time. Inside animate, just after line.set_data(T,y), try adding this:

ax.set_xlim(T.min(), T.max())

CodePudding user response:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import matplotlib.dates as mdates
import pandas as pd
import time
import datetime

plt.rcParams.update({'axes.facecolor': 'lightgray'})
plt.rcParams.update({'figure.facecolor': 'gray'})
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()  # include

ax = plt.axes()  # include
# ax = plt.axes(xlim=(0, 2), ylim=(-8, 8))
line, = ax.plot([], [], lw=2)

## tilt dates
plt.setp(ax.xaxis.get_majorticklabels(), rotation=35)


def shift(y_arr, y_i, cont_cascata):
    # print("cont_cascata:",cont_cascata)
    if type(y_arr) == list:
        y_arr.pop(0)
        y_arr = y_arr   [y_i]
    if type(y_arr) is np.ndarray:
        # print("np.array..")
        y_arr = np.delete(y_arr, 0)  # togliamo primo
        y_arr = np.append(y_arr, y_i)  # aggiungiamo ultimo
    return y_arr


# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    line.axes.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M"))  # "%Y-%m-%d %H:%M:%S"
    return line,


# animation function.  This is called sequentially
# pd._libs.tslibs.timestamps.Timestamp
def ts_array(n):
    t0 = pd.Timestamp(2018, 1, 1, 12, 00)
    T = []
    for i in range(n):
        t_i = t0   pd.Timedelta(minutes=i)
        T = T   [t_i]
    return T




def animate(i):
    global y, x, T
    print("i:", i)
    n = 10

    if i == 0:
        y = np.round(np.random.normal(loc=0, scale=2, size=n), decimals=2)
        x = np.linspace(6, 2, n)  # uncomment 0
        T = ts_array(n)  # uncomment 1

    y_i = np.round(np.random.normal(loc=6, scale=2), decimals=2)
    t_i = T[-1]   pd.Timedelta(minutes=1)  # uncomment1

    y = shift(y_arr=y, y_i=y_i, cont_cascata=i)
    T = shift(y_arr=T, y_i=t_i, cont_cascata=i)  # uncomment 1
    T = pd.DatetimeIndex(T)  # uncomment 1
    T = T.to_pydatetime()    # uncomment 1

    # line.set_data(x, y)  # uncomment 0

    line.set_data(T, y)  # uncomment 1
    ax.relim(visible_only=True)
    ax.autoscale()
    # ax.autoscale_view(True,True,True)

    # time.sleep(0.5)
    return line,


print("animate")

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=500)  # blit = True

plt.show()
  • Related