ECG Graph not showing on Pi - python

I am using an AD 8232 ECG sensor with ADC MCP3008. I have connected the ADC to Raspberry according to the instructions here (see hardware SPI) https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/mcp3008.
Then I have connected Ground of my sensor to Grnd, Vin to 3.3v and Output to A0 of ADC. other three ports of AD 8232 are not connected. After that I am using this code to read data from ADC and show it in a grap on Pi. But nothing is showing. Is there a problem in code or may be in wiring?
# program to read ECG through SPI and display an updating graph
import board
import time
import Adafruit_MCP3008
from matplotlib import pyplot as plt
from matplotlib import animation
Nsamp = 1250
def get_data_from_MCP(T, filename):
#fs = 250
#i = 0
# Nsamp = T*fs
#milestones = []
SPI_PORT = 0
SPI_DEVICE = 0
#for x in range(1, 11): # List to store Nsamp/multiples of 10 for %age calc
#milestones.append(int(x * (Nsamp / 10)))
mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))
values = []
percentage = 10
fig = plt.figure(figsize=(10, 5))
ax = plt.axes(xlim=(0, Nsamp), ylim=(280, 420))
# ax.get_xaxis().set_visible(False)
plt.title("ECG Real-Time Data")
plt.xlabel("Time [" + str(Nsamp / 250) + " second window]")
plt.ylabel("Amplitude")
ax.grid(True)
(graph,) = ax.plot([], [], "b")
t = list(range(0, Nsamp))
dat = []
for i in range(0, Nsamp):
dat.append(0)
def init():
graph.set_data([], [])
return (graph,)
# continuously update pyplot
def animate(i):
global t, dat
dat.append(float(spi.readline().decode("utf-8")))
dat.pop(0)
graph.set_data(t, dat)
return (graph,)
anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()
I tried to run the code and the graph window appears but there is no ECG plot showing.

Related

Animated points leaving trail of annotations behind

I am trying to make a virtual flight tracker with Python and API data, and I have managed so far to draw the points, update their location every 10 seconds and annotate them. Unfortunately, they are being annotated for each position they are drawn in when in fact I want them to only be shown in the spot where the point is at that time, or else there is a constant trail of labels.
The code is below:
import requests
import json
import time
import cartopy.crs as ccrs
import cartopy
import matplotlib.pyplot as plt
from cartopy.io.img_tiles import GoogleTiles
from matplotlib import animation
#SET AXES
fig, ax = plt.subplots()
ax=plt.axes(projection=ccrs.PlateCarree())
'''
ax.set_ylim(48,61.5)
ax.set_xlim(-12.5, 3.3)
'''
#ADD OSM BASEMAP
osm_tiles=GoogleTiles(style='satellite')
ax.add_image(osm_tiles,8)
ax.stock_img()
ax.set_extent([-12.5, 3.3, 48, 61.55])
ax.add_feature(cartopy.feature.BORDERS)
#mplcursors.cursor(hover=True)
#PLOT TRACK
track, = ax.plot([], [], 'wo')
# RELOAD API EVERY 15"
def update (self):
vapi = requests.get("https://data.vatsim.net/v3/vatsim-data.json")
# LOAD DATA AS JSON
data = vapi.text
parse_json = json.loads(data)
# LOAD PILOTS
pilots = parse_json['pilots']
no_pilots = len(pilots)
# GET INFO FOR EACH AIRCRAFT
x = 0
callsigns, lat, lon, alt, head, gspeed = [], [], [], [], [], []
while x < no_pilots:
xcall = pilots[x]['callsign']
xlat = pilots[x]['latitude']
xlon = pilots[x]['longitude']
xgspeed = pilots[x]['groundspeed']
xalt = pilots[x]['altitude']
xhead = pilots[x]['heading']
callsigns.append(xcall)
lat.append(xlat)
lon.append(xlon)
alt.append(xalt)
head.append(xhead)
gspeed.append(xgspeed)
x += 1
for i, txt in enumerate(callsigns):
ax.annotate(txt, (lon[i], lat[i]))
track.set_data(lon,lat)
return track, callsigns,
anim = animation.FuncAnimation(fig, update,interval=10000, blit=False)
plt.show()
It leaves a trail of annotations like this

Changing the time scale of a matplotlib graph in a real-time fashion

I'm making a real-time application that graphs
sensor data in a real-time fashion.
The data is saved to a .csv file and graphed using matplotlib in the following fashion:
class Scope:
def __init__(self, ax, ax2, f, maxt=2000, dt=0.02):
self.ax = ax
self.ax2 = ax2
self.maxt = maxt
self.f = f
self.tdata = []
self.ydata = []
self.humdata = []
self.tempdata = []
self.TVOCdata = []
self.ax.set_ylim(0, 1023)
self.ax.set_xlim(0, self.maxt)
self.ax2.set_ylim(0, 100)
self.ax2.set_xlim(0, self.maxt)
self.line, = ax.plot(self.tdata, self.ydata)
self.line2, = ax2.plot(self.tdata, self.humdata)
self.line3, = ax2.plot(self.tdata, self.tempdata, 'g-')
self.line4, = ax.plot(self.tdata, self.TVOCdata)
def animate(self, y):
if path.exists(self.f):
data = pd.read_csv(self.f)
self.tdata.append(data['dur'].iloc[-1])
self.ydata.append(data['CO2'].iloc[-1])
self.line.set_data(self.tdata, self.ydata)
self.line.set_label('CO2')
I'd like to change the representation of the time axis from seconds to hours since the measurements that i'm doing might last for days at a time. Is there a handy way of doing this? Truly thankful for any kind of help.
Found a solution to this problem. The key is to use the ticker FuncFormatter-subclass to customize the ticks in the x-axis in the following way:
formatter = matplotlib.ticker.FuncFormatter(lambda s, x: time.strftime('%H:%M',time.gmtime(s // 60)))
self.ax.xaxis.set_major_formatter(mticker.FuncFormatter(formatter))

keep getting MatplotlibDeprecationWarning error when running code,

When I run this code I get this error: ax = plt.subplot("311")
MatplotlibDeprecationWarning: Passing non-integers as three-element position specification is deprecated since 3.3 and will be removed two minor releases later. I made those changes that was suggested now I get errors in other parts of the code.
I have provided a small snippet of the code
Any suggestions on how I can fix this
import socket, traceback
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter,iirfilter,savgol_filter
import math
import pylab
from pylab import *
import time
import numpy as np
host = ''
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((host, port))
# lists for plotting
Ax = [0.0] * 50
Ay = [0.0] * 50
Az = [0.0] * 50
G = [0.0] * 50
x = [i for i in range(len(Ax))]
#used for debugging
fig = plt.figure(figsize=(16,10))
# raw data
ax = plt.subplot(311)
ax.set_xlim(0, 50)
ax.set_ylim(-2, 2)
ax.set_title("Raw acceleration data")
ax.set_ylabel("g$/m^2$",fontsize=18)
line = ax.plot(Ax,label='Acc x')[0]
line2 = ax.plot(Ay,label='Acc y')[0]
line3 = ax.plot(Az,label='Acc z')[0]
# filtered data
ax2 = plt.subplot(312)
ax2.set_xlim(0, 50)
ax2.set_ylim(-2, 2)
ax2.set_title(" acceleration data")
ax2.set_ylabel("g$/m^2$",fontsize=18)
f_line = ax2.plot(Ax,label='Acc x')[0]
f_line2 = ax2.plot(Ay,label='Acc y')[0]
f_line3 = ax2.plot(Az,label='Acc z')[0]
# tilt angle plot
ax3 = plt.subplot(313)
ax3.set_ylim([-180,180])
ax3.set_title("Tilt Angles")
ax3.set_ylabel("degrees",fontsize=18)
t_line = ax3.plot(G)[0]
fig.suptitle('Three-axis accelerometer streamed from Sensorstream',fontsize=18)
plt.show(False)
plt.draw()
# cache the background
background = fig.canvas.copy_from_bbox(fig.bbox)
count = 0
print("Success binding")
while 1:
# time it
tstart = time.time()
message, address = s.recvfrom(8192)
messageString = message.decode("utf-8")
Acc = messageString.split(',')[2:5]
Acc = [float(Acc[i])/10.0 for i in range(3)]
# appending and deleting is order 10e-5 sec
Ax.append(Acc[0])
del Ax[0]
Ay.append(Acc[1])
del Ay[0]
Az.append(Acc[2])
del Az[0]
G.append(np.sqrt(Ax[-1]**2 + Ay[-1]**2 + Az[-1]**2))
del G[0]
# filter
acc_x_savgol = savgol_filter(Ax, window_length=5, polyorder=3)
acc_y_savgol = savgol_filter(Ay, window_length=5, polyorder=3)
acc_z_savgol = savgol_filter(Az, window_length=5, polyorder=3)
tilt_angles = []
for i,val in enumerate(G):
angle = math.atan2(Ax[i], -1*Ay[i]) * (180 / math.pi)
if (math.isnan(angle)):
tilt_angles.append(0)
else:
tilt_angles.append(angle)
print(Ax[0],Ay[1],Az[2])
line.set_xdata(x)
line.set_ydata(Ax)
line2.set_xdata(x)
line2.set_ydata(Ay)
line3.set_xdata(x)
line3.set_ydata(Az)
ax.set_xlim(count, count+50)
f_line.set_xdata(x)
f_line.set_ydata(acc_x_savgol)
f_line2.set_xdata(x)
f_line2.set_ydata(acc_y_savgol)
f_line3.set_xdata(x)
f_line3.set_ydata(acc_z_savgol)
ax2.set_xlim(count, count+50)
t_line.set_xdata(x)
t_line.set_ydata(tilt_angles)
ax3.set_xlim(count, count+50)
# restore background
fig.canvas.restore_region(background)
# redraw just the points
ax.draw_artist(line)
ax.draw_artist(line2)
ax.draw_artist(line3)
ax2.draw_artist(f_line)
ax2.draw_artist(f_line2)
ax2.draw_artist(f_line3)
ax3.draw_artist(t_line)
# fill in the axes rectangle
fig.canvas.blit(fig.bbox)
count+=1
x = np.arange(count,count+50,1)
# tops out at about 25 fps :|
print ("Total time for 1 plot is: ",(time.time() - tstart))
The following code executes without warnings on my laptop.
ax = plt.subplot(311)
ax.set_xlim(0, 50)
ax.set_ylim(-2, 2)
ax.set_title("Raw acceleration data")
ax.set_ylabel("g$/m^2$",fontsize=18)
I removed ax.hold(True) and changed "311" to 311.

How to allow python code to continue after a matplotlib graph is executed so that a loop can feed realtime data into the matplotlib graph

Hello i'm making an application that allows you to effectively create a youtube poll by counting certain responses and then displaying the results realtime in a graph. My current problem is that my code won't start to loop through youtube chat until i've closed the graph, and if i have the graph appear after the loop then there is no information for the graph to update in real-time as the loop will have stopped. how do i get the graph to appear and then for the loop to go through youtube chat, or is there a more elegant way of achieving the same objective?
def animate(i):
x.append(next(index))
y1.append(numprompt1)
y2.append(numprompt2)
plt.cla()
plt.plot(x, numprompt1, label ='prompt 1')
plt.plot(x, numprompt2, label ='prompt 2')
plt.legend(loc='upper left')
FuncAnimation(plt.gcf(), animate, interval=1000)
#livechat code
while livechat.is_alive():
try:
chatdata = livechat.get()
for c in chatdata.items:
print(f"{c.datetime} [{c.author.name}]- {c.message}")
message = str({c.message})
if prompt1 in message:
numprompt1 += 1
print (prompt1, "has been said", numprompt1, "times")
elif prompt2 in message:
numprompt2 += 1
print (prompt2, "has been said", numprompt2, "times")
chatdata.tick()
except KeyboardInterrupt:
livechat.terminate()
break
You can try this example:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
y1 = []
y2 = []
numprompt1 = 0
numprompt2 = 0
fig=plt.figure()
ax = fig.add_subplot(1,1,1)
def animate(i):
global y1
global y2
global numprompt1
global numprompt2
a = ax.clear()
numprompt1 += 1.1
numprompt2 += 1.2
y1.append(numprompt1)
y2.append(numprompt2)
x = np.arange(len(y1))
a = ax.plot(x, y1, color = 'green', label = 'prompt 1')
a = ax.plot(x, y2, color = 'red', label = 'prompt 2')
a = ax.legend()
ani = animation.FuncAnimation(fig, animate, interval=1000)
a = plt.show()

frames overlap in python3 matplotlib animation

I'm getting confused with the FuncAnimation method. I was trying to show real-time sensor data on my raspberry pi using GPIOs. I set the x range to 100. When my data frames are over 100, I will only pick the recent 100 frames to show. At the beginning when the number of frames is less than 100, the pic shows correctly. The problem is that when frames are over 100, the later pic will overlap with the former pic and the graph just mess up. Here's the beginning graph and the overlap graph.
enter image description here
enter image description here
I checked the matplotlib API and I changed the param "blit" from True to False.
The overlap disappears but the frame rate is becoming too low.
Since I also used FuncAnimation with blit set True in another code and the overlap didn't appear, I guess there something else wrong.
The overlap code is below:
max_limit = 20
fig, ax = plt.subplots(light_num, 1)
data = []
lines = []
for i in range(light_num):
data.append([])
ln_one_light, = ax[i].plot([], [], 'r-')
lines.append(ln_one_light)
def init():
for i in range(light_num):
ax[i].set_xlim(0, max_limit)
ax[i].set_ylim(lower_bound, upper_bound)
return lines
def update(frame):
# print(frame)
global data
for i in range(light_num):
data[i].append(frame[i])
if len(data[i]) > max_limit:
data[i] = data[i][1:]
time_axis = np.arange(len(data[i]))
for i in range(light_num):
# print(time_axis, data[i])
lines[i].set_data(time_axis, data[i])
return lines
def gen_function():
res_array = []
output_string = ''
for i in range(light_num):
val = GPIO.input(light_io_array[i])
res_array.append(val)
output_string = output_string + str(val) + ' '
# print(res_array)
lights_data_writer.update_data(output_string)
yield res_array
ani = FuncAnimation(fig, update, frames=gen_function, interval = 500, repeat = True,
init_func=init, blit=True)
plt.show()
The code that I used with blit set as True, but no overlap happens:
fig, ax = plt.subplots(3, 1)
data_x, data_y, data_z = [], [], []
ln_x, = ax[0].plot([], [], 'r-')
ln_y, = ax[1].plot([], [], 'r-')
ln_z, = ax[2].plot([], [], 'r-')
def init():
for i in range(3):
ax[i].set_xlim(0, 100)
ax[i].set_ylim(-5, 5)
return (ln_x, ln_y, ln_z)
def update(frame):
(x, y, z) = frame
global data_x, data_y, data_z
data_x.append(x)
data_y.append(y)
data_z.append(z)
if len(data_x) > 100:
data_x = data_x[1:]
data_y = data_y[1:]
data_z = data_z[1:]
time_xyz = np.arange(len(data_x))
# print(time_xyz, data_x)
ln_x.set_data(time_xyz, data_x)
ln_y.set_data(time_xyz, data_y)
ln_z.set_data(time_xyz, data_z)
return (ln_x, ln_y, ln_z)
def gen_function():
while True:
(x, y, z) = adxl345.getAxes()
output_string = 'acc '+str(x)+' '+str(y)+' '+str(z)
imu_data_writer.update_data(output_string)
yield (x, y, z)
ani = FuncAnimation(fig, update, frames=gen_function, interval = 100,
init_func=init, blit=True)
plt.show()
Thank you for anyone who can have a look and check out what I have done wrong.

Categories