I have created subplots that contain measurements taken from an oscilloscope. N is a parameter that determines the number of subplots. The issue is that when there's 1 plot, it has no title or y label. When there are more than one plot, only the last one is affected
##Plots a time trend of the active measurements on a MSO4/5/6
##Pierre Dupont - Tek - 2020
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import visa
import sys
rm = visa.ResourceManager()
scope = rm.open_resource('TCPIP::192.168.1.34::INSTR')
##determines number of active measurements
def active_measurements():
meas_list=scope.query('MEASUrement:LIST?')
N=meas_list.count(",")+1
if "NONE" in meas_list:
scope.close()
sys.exit("No measurement found, exiting...")
return(N)
N=active_measurements()
plots_set={} ##dictionary that will contain the subplots. One per active measurement.
ydata_set={} ##dictionary that will contain the array of logged data
fig=plt.figure()
IDN=scope.query('*idn?')
fig.suptitle('Measurement data logger / connected to: '+IDN,fontsize=10,color='purple')
plt.style.use('ggplot')
##definition of the subplots in the dictionary + subplots titles and axis legend
for i in range (1,N+1):
plots_set["ax"+str(i)]=fig.add_subplot(N,1,i)
meas_type=scope.query('MEASUrement:MEAS{}:TYPe?'.format(i))
plots_set["ax"+str(i)].set_title(meas_type,fontsize='small')
meas_unit=scope.query('MEASUrement:MEAS{}:YUNIT?'.format(i))
plots_set["ax"+str(i)].set_ylabel(meas_unit.replace('"',''))
print(i,meas_type,meas_unit)
ydata_set["y"+str(i)]=[]
index=0
x=[]
## function that runs at every data log. Appends the arrays of measurement
## data and updates the subplots
def animate(i):
global index
index+=1
x.append(index)
t=1
for k,k2 in zip(ydata_set,plots_set):
scope.query('*OPC?')
M=float(scope.query('MEASUrement:MEAS{}:RESUlts:CURRentacq:MEAN?'.format(t)))
t+=1
plt.cla()
ydata_set[k].append(M)
plots_set[k2].plot(x,ydata_set[k],marker="X",linewidth=0.5,color='blue')
##frames parameter = number of logs // interval parameter = time between 2 logs (in ms)
ani=FuncAnimation(plt.gcf(), animate, frames=1000, interval=500, repeat=False)
plt.tight_layout()
plt.show()
scope.close()
OUTPUT:
1 RISETIME
"s"
2 POVERSHOOT
"%"
3 MAXIMUM
"V"
Many thanks for your inputs. Sorry for any lack of clarity that's my first post.
Calling plt.cla()
clears the current, in this case most recently created, axes. This will clear all lines, labels, title, etc. If you want to use plt.cla()
in your animate function you will need to reset those each time, e.g.
def animate(i):
# ...
plt.cla()
plt.set_title("title")
plt.set_ylabel("label")
# etc
An alternative would be to use set_data
to update your plots, i.e.
lines = [subplot.plot(x, ydata, marker="X", linewidth=0.5, color='blue')[0]
for subplot, ydata in zip(plots_set, ydata)]
def animate(i):
global index
index+=1
x.append(index)
t=1
for ydata, line in zip(ydata_set, lines):
scope.query('*OPC?')
M=float(scope.query('MEASUrement:MEAS{}:RESUlts:CURRentacq:MEAN?'.format(t)))
t+=1
ydata.append(M)
line.set_data(x, ydata)
This will not require the entire subplot to be cleared each time new data comes in.