[TIP] Python에서 Animation Plot 만들기

2022. 9. 1. 00:06
728x90

시계열 데이터 혹은 Real-Time 데이터에 대한 전처리 혹은 알고리즘 적용에 따른 변화량을 측정하기 위해 때론 Animation을 활용한 Plot 생성을 활용하기도 한다.

 

특히, 무선 통신의 경우, 필터링의 성능 평가에 대한 Demo로 활용되기도 하며, 해당 글에서는 Kalman filter 적용에 따른 RSSI 성능 분석에 관하여 논해보도록 한다.

 

우선 아래와 같이 matplotlib를 호출하여, import 처리하도록 한다.

from RTLS_Filter import KalmanFilter
from RTLS_Utils import *


import numpy as np
from matplotlib.pylab import *
from matplotlib.animation import FuncAnimation

 

다음으로는 raw 데이터와 실제 필터링 된 값을 처리하기 위해 다음과 같은 변수를 할당한다.

recv_rssi = []
raw_rssi = [0]
filtered_rssi = [0]

path_loss = func_cal_ENV()

# Filter setting
kalman_set = KalmanFilter(0.05, path_loss)

# create empty lists for the x and y data
x = []
raw_data = []
filterd_data = []
total_pt = []

 

다음으로는 Animation 생성을 위한 함수와 figure 생성을 위한 plt 설정을 할당한다.

이때, animate 함수에 존재하는 다양한 random 변수는 target beacon의 움직임과 그에 따른 RSSI 변화량을 모사하기 위해 활용되었다.

# create the figure and axes objects
fig, ax = plt.subplots(figsize = (18, 5))

def animate(i):

    # motivate from the moving target beacon
    if i <= 20:
        pt = np.random.randint(-60,-55)
    elif i > 20 and i <= 45:
        pt = np.random.randint(-55,-45)
    elif i > 45 and i <= 65:
        pt = np.random.randint(-45,-35)
    elif i > 65 and i <= 100:
        pt = np.random.randint(-35,-25)
    elif i > 100 and i <= 125:
        pt = np.random.randint(-45,-35)
    elif i > 125 and i <= 150:
        pt = np.random.randint(-55,-45)
    elif i > 150 and i <= 175:
        pt = np.random.randint(-65,-55)
    elif i > 175 and i <= 200:
        pt = np.random.randint(-70,-55)
    elif i > 200 and i <= 225:
        pt = np.random.randint(-65,-55)
    elif i > 250 and i <= 275:
        pt = np.random.randint(-55,-50)
    elif i > 275 and i <= 300:
        pt = np.random.randint(-50,-45)
    elif i > 300 and i <= 325:
        pt = np.random.randint(-45,-40)
    elif i > 325 and i <= 350:
        pt = np.random.randint(-40,-35)
    elif i > 350 and i <= 375:
        pt = np.random.randint(-35,-30)
    elif i > 370 and i <= 400:
        pt = np.random.randint(-30,-25)
    elif i > 400 and i <= 450:
        pt = np.random.randint(-25,-20)
    else:
        pt = np.random.randint(-45,-35)
        
    total_pt.append(pt)
    for rssi_idx in total_pt:
      raw_rssi.append(rssi_idx)
      filtering = kalman_set.filter(rssi_idx)
    
    x.append(i)
    raw_data.append(rssi_idx)
    filterd_data.append(filtering)
    
    ax.clear()
    ax.plot(x, raw_data, 'b-', label = "raw rssi", linewidth=2)
    ax.plot(x, filterd_data, 'r-', label = 'after kalman', linewidth=2)
    
    ax.set_xlabel("Time")
    ax.set_ylabel("RSSI(dBm)")
    ax.set_title('RSSI RAW vs RSSI Kalman')
    ax.grid(True) 
    ax.set_xlim([0,550])
    ax.set_ylim([-70,-20])
    ax.legend(loc='best', ncol=2)

 

마지막으로 animation 효과와 plot 결과를 출력하기 위해 다음과 같이 마무리될 수 있다.

# run the animation
ani = FuncAnimation(fig, animate, frames=550, interval=1, repeat=False)

plt.show()

 

실제 완성된 소스 코드와 결과물은 아래와 같이 나타난다.

OBS를 이용하여, 노트북에 영상을 저장하였지만, 사양이 좋지 않아 이미지로 대체한다.

from RTLS_Filter import KalmanFilter
from RTLS_Utils import *


import numpy as np
from matplotlib.pylab import *
from matplotlib.animation import FuncAnimation

recv_rssi = []
raw_rssi = [0]
filtered_rssi = [0]

path_loss = func_cal_ENV()

# Filter setting
kalman_set = KalmanFilter(0.05, path_loss)

# create empty lists for the x and y data
x = []
raw_data = []
filterd_data = []
total_pt = []

# create the figure and axes objects
fig, ax = plt.subplots(figsize = (18, 5))

def animate(i):

    # motivate from the moving target beacon
    if i <= 20:
        pt = np.random.randint(-60,-55)
    elif i > 20 and i <= 45:
        pt = np.random.randint(-55,-45)
    elif i > 45 and i <= 65:
        pt = np.random.randint(-45,-35)
    elif i > 65 and i <= 100:
        pt = np.random.randint(-35,-25)
    elif i > 100 and i <= 125:
        pt = np.random.randint(-45,-35)
    elif i > 125 and i <= 150:
        pt = np.random.randint(-55,-45)
    elif i > 150 and i <= 175:
        pt = np.random.randint(-65,-55)
    elif i > 175 and i <= 200:
        pt = np.random.randint(-70,-55)
    elif i > 200 and i <= 225:
        pt = np.random.randint(-65,-55)
    elif i > 250 and i <= 275:
        pt = np.random.randint(-55,-50)
    elif i > 275 and i <= 300:
        pt = np.random.randint(-50,-45)
    elif i > 300 and i <= 325:
        pt = np.random.randint(-45,-40)
    elif i > 325 and i <= 350:
        pt = np.random.randint(-40,-35)
    elif i > 350 and i <= 375:
        pt = np.random.randint(-35,-30)
    elif i > 370 and i <= 400:
        pt = np.random.randint(-30,-25)
    elif i > 400 and i <= 450:
        pt = np.random.randint(-25,-20)
    else:
        pt = np.random.randint(-45,-35)
        
    total_pt.append(pt)
    for rssi_idx in total_pt:
      raw_rssi.append(rssi_idx)
      filtering = kalman_set.filter(rssi_idx)
    
    x.append(i)
    raw_data.append(rssi_idx)
    filterd_data.append(filtering)
    
    ax.clear()
    ax.plot(x, raw_data, 'b-', label = "raw rssi", linewidth=2)
    ax.plot(x, filterd_data, 'r-', label = 'after kalman', linewidth=2)
    
    ax.set_xlabel("Time")
    ax.set_ylabel("RSSI(dBm)")
    ax.set_title('RSSI RAW vs RSSI Kalman')
    ax.grid(True) 
    ax.set_xlim([0,550])
    ax.set_ylim([-70,-20])
    ax.legend(loc='best', ncol=2)
    
# run the animation
ani = FuncAnimation(fig, animate, frames=550, interval=1, repeat=False)

plt.show()

 

더욱 정밀한 설정 등은 아래 홈페이지 상세히 설명되어 있으니, 참조!

 

How to make animated plots with Matplotlib and Python

Python and Matplotlib can be used to create static 2D plots. But it Matplotlib can also be used to create dynamic auto-updating animated plots. In this post, you learn how to create a live auto-updating animated plot using Python and Matplotlib. Table of c

pythonforundergradengineers.com

 

728x90

BELATED ARTICLES

more