Multiple plots on same chart - Matplotlib - python

I'm plotting real-time data using parsed data from a file that is being repeatedly opened. I'm deriving and plotting two different values on the same chart. The Y axis scales up and down according the values of each. The "snr" (green) value is plotting fine but the "data_rate"(red) value seems to be static. See screenshot.
import matplotlib.pyplot as plt
import csv
import datetime
from matplotlib.animation import FuncAnimation
import numpy as np
x = []
y = []
z = []
rssi_val = []
def animate(i):
with open('stats.txt', 'r') as searchfile:
time = (searchfile.read(8))
for line in searchfile:
if 'agrCtlRSSI:' in line:
rssi_val = line[16:20]
rssi_val=int(rssi_val)
if 'agrCtlNoise:' in line:
noise_val = (line[16:20])
noise_val=int(noise_val)
if 'maxRate:' in line:
data_rate = (line[16:20])
data_rate=int(data_rate)
snr = ((noise_val - rssi_val) * -1)
#begin test
y.append(snr)
x.append(time)
z.append(data_rate)
#end test
#begin test
plt.cla()
#Verify values are not empty
print("SNR = ", snr)
print("DR = ", data_rate)
plt.plot(snr,label='Signal')
plt.plot(data_rate,label='Data Rate')
plt.legend(loc='upper right')
plt.plot(x,y,z)
ax=plt.gca()
ax.tick_params('x',labelrotation=60)
#end test
ani = FuncAnimation(plt.gcf(), animate, interval=1000)
plt.show()

The simplest way is to call plot twice.
plt.plot(x,y)
plt.plot(x,z)
See "Plotting multiple sets of data" here for more options.

Related

How to only show the last 20 results from an updating/real time graph

I've got this script running to update every time a new value is added to my csv file (it's a manual log taking in values from a machine):
from itertools import count
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
plt.style.use('fivethirtyeight')
x_vals = []
y_vals = []
counter=0
index = count()
def animate(i):
data = pd.read_csv('C:/Users/Owner/Downloads/Manual-Log-27Nov2020-150846.csv')
data=data.dropna()
data['Date And Time']=data['Date']+' '+data['Time']
Date = data['Date And Time']
Temp = data['Temperature']
Pressure = data['Pressure']
pH = data['pH']
plt.cla()
plt.plot(Date, Temp, label='Temperature')
plt.plot(Date, Pressure, label='Pressure')
plt.plot(Date, pH, label='pH')
plt.legend(loc='upper left')
plt.xlabel('Date and Time')
plt.ylabel('Y Values')
plt.xticks(rotation=90)
plt.tight_layout()
ani = FuncAnimation(plt.gcf(), animate, interval=30000)
plt.tight_layout()
plt.show()
Since it's such a large file (20k lines or so) the resulting graph is huge and you can't really read the data properly. Is there a way I could only get it to show the 20 most recent readings?
you can slice it or get first n records. you can apply the following after your code line : data=data.dropna()
df=pd.DataFrame({'Count':[2,33,4,6,8,9],'apha':['A','B','C','D','E','F']})
df_sorted=sorted_df = df.sort_values(by=['Count'], ascending=True) # in case needed
df_limited=df_sorted.head(3) # this is one you are looking for

plot in the same figure multiple lines from different data files with python

I am new into the field of plotting in the same figure multiple lines from different data files with matplotlib in python. Currently I have the following script which is to plot column 1 and 2 from file 'statistics_paa_f0_vs_N.dat'. I want to be able also to plot in the same figure column 1 and 2 from file 'statistics_paa_f1_vs_N.dat'
#--- Import the necessary packages and modules
import matplotlib.pyplot as plt
import numpy as np
#--- initiate the list of coordinates for x and y lists
x,y = [],[]
#--- iterate over each line of the file and store it as a string
for line in open('statistics_paa_f0_vs_N.dat','r'):
values = [float(s) for s in line.split()]
x.append(values[0])
y.append(values[1])
#--- plot the data
plt.plot(x,y,color='r',label='line1') # r - red colour
plt.xlabel('time (s)',fontsize=12)
plt.ylabel('Density (kg/m3)',fontsize=12)
plt.title('hi',fontsize=20,fontweight='bold')
plt.legend(loc='upper right')
plt.grid(False)
plt.axis(True)
#--- show and save the plot
plt.savefig('png_files-matplotlib/test.png')
plt.show()
The simplest way to do this (without the usage of any external package) is to write a simple class that reads the file. Then, call class multiple times.
import matplotlib.pyplot as plt
import numpy as np
class ReadFile():
def __init__(self,filename : str):
self.x = []
self.y = []
with open(filename,'r') as f:
lines = f.readlines()
for line in lines:
val = [float(s) for s in line.split() ]
self.x.append(val[0])
self.y.append(val[1])
self.x = np.array(self.x,dtype=np.double)
self.y = np.array(self.y,dtype=np.double)
def getData(self):
return self.x, self.y
file1 = ReadFile("./test")
file2 = ReadFile("./test1")
plt.plot(*file1.getData(), linewidth = 3.0, label = "test ")
plt.plot(*file2.getData(), linewidth = 3.0, label = "test1")
plt.xlabel('time (s)',fontsize=12)
plt.ylabel('Density (kg/m3)',fontsize=12)
plt.title('hi',fontsize=20,fontweight='bold')
plt.legend(loc='upper right')
plt.show()
although it is an unorthodox approach, one way of doing it is as such:
#--- Import the necessary packages and modules
import matplotlib.pyplot as plt
import numpy as np
#--- initiate the list of coordinates for x and y lists
x,y,z,e,l,m = [],[],[],[],[],[]
#--- iterate over each line of the file and store it as a string
for line in open('statistics_paa_f0_vs_N.dat','r'):
values = [float(s) for s in line.split()]
x.append(values[0])
y.append(values[1])
for line in open('statistics_paa_f1_vs_N.dat','r'):
values = [float(s) for s in line.split()]
e.append(values[0])
z.append(values[1])
for line in open('statistics_paa_f5_vs_N.dat','r'):
values = [float(s) for s in line.split()]
l.append(values[0])
m.append(values[1])
#--- plot the data
plt.plot(x,y,'rs:',label='f=0')
plt.plot(e,z,'gs:',label='f=1')
plt.plot(l,m,'bs:',label='f=0.5')
#plt.plot(x,y,x,z,color='r',label='line1') # r - red colour
plt.xlabel('N (mer)',fontsize=12)
plt.ylabel('Density (kg/m3)',fontsize=12)
plt.title('hi',fontsize=20,fontweight='bold')
plt.legend(loc='upper right')
plt.grid(False)
plt.axis(True)
#--- show and save the plot
plt.savefig('png_files-matplotlib/test.png')
plt.show()

How to prevent i from incrementing until there is an applicible value in the csv file in my Python program?

This Python program plots lines dynamically from data in a csv file. When the program first starts it dynamically draws points that already exist in the file. This part works as expected. I'd like for any new points added to the file to be subsequently drawn. The problem is that i continues to increment so by the time a new item is added to my csv file the value of i is usually much higher than the index from the csv so it never gets plotted. How can I prevent the count of i continuing on until there is an applicable value in the csv file?
import numpy as np
from itertools import count
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
plt.style.use('fivethirtyeight')
data = pd.read_csv('csv_data.csv')
x_vals = []
y_vals1 = []
y_vals2 = []
index = count()
def animate(i):
x = data['x_value']
y1 = data['total_1']
y2 = data['total_2']
x_vals.append(x[i])
y_vals1.append(y1[i])
y_vals2.append(y2[i])
plt.cla()
plt.plot(x_vals, y_vals1, label='Channel 1')
plt.plot(x_vals, y_vals2, label='Channel 2')
plt.legend(loc='upper left')
plt.tight_layout()
ani = FuncAnimation(plt.gcf(), animate, interval=100)
plt.show()

Python using Matplotlib for real-time plotting

I’m going to preface this by saying that I am still learning Python so please be kind and patient. My code goes as follows:
Client on the network sends a text file (stats.txt) every ~5 seconds to an SCP server. Python code sits on the server.
Code below begins:
import matplotlib.pyplot as plt
import csv
import datetime
x = []
y = []
rssi_val = []
def animate(i):
with open('stats.txt', 'r') as searchfile:
time = (searchfile.read(5))
for line in searchfile:
if 'agrCtlRSSI:' in line:
rssi_val = line[16:20]
y = [rssi_val]
x = [time for i in range(len(y))]
plt.xlabel('Time')
plt.ylabel('RSSI')
plt.title('Real time signal strength seen by client X')
#plt.legend()
plt.plot(x,y)
ani = FuncAnimation(plt.gcf(), animate, interval=5000)
plt.tight_layout()
#plt.gcf().autofmt_xdate()
plt.show()
SCP server opens the file every 5 seconds and plots the values that are parsed from the file. Time gets plotted on the X axis and the RSSI value gets plotted on the Y axis.
I understand that the code and methods used are not efficient at this point and will be modified in the future. For now I simply want the the plot values to show up and the chart to be animated with the plot (line) every 5 or so seconds.
Running it produces nothing.
You need to have the line
ani = FuncAnimation(plt.gcf(), animate, interval=5000)
Outside of the function animate, then assuming the data are received and read in properly you should see the plot updating. You may also need to put plt.show() after the FuncAnimation() line depending on how you are executing the script.
Edit
You may want to try something like this instead
import matplotlib.pyplot as plt
import csv
import datetime
x = []
y = []
rssi_val = []
def animate(i):
with open('stats.txt', 'r') as searchfile:
time = (searchfile.read(5))
for line in searchfile:
if 'agrCtlRSSI:' in line:
rssi_val = line[16:20]
y.append(rssi_val)
x.append(time)
plt.cla()
plt.plot(x,y)
plt.xlabel('Time')
plt.ylabel('RSSI')
plt.title('Real time signal strength seen by client X')
plt.tight_layout()
ani = FuncAnimation(plt.gcf(), animate, interval=5000)
plt.show()

Matplotlib live updating bar chart from CSV

New to python so any guidance would be appreciated!
I have a CSV that has names. I'm trying to count everybody with the name "Adam" and plot it in a bar chart. When the CSV gets updated I want the bar chart to update as well. Below is my code.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
import csv
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
myCount = 0
otherCount = 0
def animate(i):
with open('test2.csv') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
if row['fName'] == 'Adam':
myCount +=1
else:
otherCount = +=1
x = ["Adam","Not Adam"]
y = [myCount, otherCount]
ax1.clear()
ax1.bar(x,y)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
Right now it shows me the outline of the graph but doesn't display anything.
Also, I got the animate function from another source. Is there a more efficient way to do this?
Ok So I've updated the code:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
import csv
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
myCount = 0
otherCount = 0
with open('testcsv.csv') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
if row['fName'] == 'Adam':
myCount +=1
else:
otherCount +=1
x = ["Adam","Not Adam"]
y = [myCount, otherCount]
ax1.clear()
ax1.bar(x,y)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
I know through testing that it's correctly grabbing the CSV and reading the data, but it's still not plotting it. The data looks like this:
fname,lname
Adam,Smith
Adam,Sandler
Adam,Smith
Adam,Sandler
Bruce,Willis
Adam,Smith
James,Harden
Bruce,Wayne
There seem to be three main problems with the code. The first two have to do with the counters in use. The last with the naming of the data.
otherCount = +=1 is not valid python.
Incrementing a variable locally, does not change it globally. It would hence make sense to define myCount = 0; otherCount = 0 inside the animating function, in case you do not want to show cumulative counts.
The data column seems to be named fname, but the indexing uses row['fName'].

Categories

Resources