Newer
Older
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import time
# Different exceptions can be thrown while plotting, depending on the backend.
# We catch them all locally and raise our own exception instead
class PlottingError(Exception):
"Raised when plotting fails"
pass
Michael Pawelzik
committed
def __init__(self, title='', env_cond_sensors ='', legend_loc = 'upper left',\
legend_bbox_to_anchor = (1.09, 1)):
# set python for opening an separate plot window when starting from anaconda, Michael
if 'ipykernel' in sys.modules:
from IPython import get_ipython
get_ipython().run_line_magic('matplotlib', 'qt')
Michael Pawelzik
committed
self.env_cond_sensors = env_cond_sensors
Michael Pawelzik
committed
# parameter for legend of subplots
self.legend_loc = legend_loc
self.legend_bbox_to_anchor = legend_bbox_to_anchor
# Third, Fourth and Fifth plot for additional external sensors, Michael
self.fig, self.ax1 = plt.subplots(5, figsize=(25, 20))
Michael Pawelzik
committed
self.fig.subplots_adjust(bottom= 0.1, right=0.8, hspace = 0.4)
self.fig.suptitle("Measurement "+title, color="red")
Michael Pawelzik
committed
# First plot: Phase and magnitude, Michael
self.path_collection_phase = self.ax1[0].scatter([], [], c='red', marker='<', label='DUT Phase')
self.path_collection_fit = self.ax1[0].scatter([], [], c='green', marker='.', label = ' ')
self.magnitude_axis = self.ax1[0].twinx()
# in entry of legend for phase and magnitude the word DUT is added in front, Michael
self.path_collection_mag = self.magnitude_axis.scatter([], [], c='#3120E0', marker='4', label='DUT Magnitude')
self.equi_axis0 = self.ax1[0].twinx()
self.equi_axis0.spines['right'].set_position(('outward', 75))
self.path_collection_equi0 = self.equi_axis0.scatter([], [], c='black', marker=".", label='Equilibrium_Indicator')
# units added to y-axes of subplot 1, Michael
self.ax1[0].set_xlabel("TIMESTAMP")
self.ax1[0].set_ylabel("PHASE [°]", color='red')
self.magnitude_axis.set_ylabel("MAGNITUDE [dB]", color='#3120E0')
# label of y-axis for equilibrium indicator is changed to Indiccator Value because it's shorter, Michael
self.equi_axis0.set_ylabel("INDICATOR VALUE", color='black')
# fix range to 0..31 with some extra margin for plotting
self.equi_axis0.set_ylim(-1, 32)
self.ax1[0].grid(True, linestyle=":")
all_path_collections = [self.path_collection_phase, self.path_collection_mag, \
self.path_collection_equi0, self.path_collection_fit]
labels = [pc.get_label() for pc in all_path_collections]
self.phase_legend = self.ax1[0].legend(all_path_collections, labels, loc=self.legend_loc, bbox_to_anchor = \
Michael Pawelzik
committed
self.legend_bbox_to_anchor)
ax = self.fig.axes
# plot delta values for phase and magnitude at left position outside the plot, Michael
self.annotation = ax[0].annotate('' ,xy=(0,1), \
xycoords='axes fraction', xytext=(-0.16,1), \
textcoords='axes fraction',fontsize = '16', \
horizontalalignment='left',verticalalignment='bottom')
# Second plot: Humidity and temperature of climate chamber requested from internal sensors of chamber
self.path_collection_temp = self.ax1[1].scatter([], [], c='blue', marker='p', label="Chamber Temperature")
self.humidity_axis = self.ax1[1].twinx()
self.path_collection_hum = self.humidity_axis.scatter([], [], c='green', marker="*", label="Chamber Humidity")
self.equi_axis1 = self.ax1[1].twinx()
self.equi_axis1.spines['right'].set_position(('outward', 75))
self.path_collection_equi1 = self.equi_axis1.scatter([], [], c='black', marker=".", label="Equilibrium_Indicator")
# units added to y-axes of subplot 2, Michael
self.ax1[1].set_xlabel("TIMESTAMP")
self.ax1[1].set_ylabel("TEMPERATURE [°C] ", color='blue')
self.humidity_axis.set_ylabel("HUMIDITY [%RH]", color='green')
# label of y-axis for equilibrium indicator is changed to Indiccator Value because it's shorter, Michael
self.equi_axis1.set_ylabel("INDICATOR VALUE", color='black')
self.equi_axis1.set_ylim(-1, 32)
self.ax1[1].grid(True, linestyle=":")
all_path_collections = [self.path_collection_temp, self.path_collection_hum, self.path_collection_equi1]
labels = [pc.get_label() for pc in all_path_collections]
Michael Pawelzik
committed
self.ax1[1].legend(all_path_collections, labels, loc=self.legend_loc, bbox_to_anchor = \
self.legend_bbox_to_anchor)
# Third plot: parameter of external sensors
# DUT temperature, DUT humidity, Michael
# configuration of used sensor port in ext_sens_data.json, Michael
Michael Pawelzik
committed
self.path_collection_temp_dut = self.ax1[2].scatter([],[], c='red', marker='p', \
label='DUT temperature')
self.ext_sens_hum_axis = self.ax1[2].twinx()
Michael Pawelzik
committed
self.path_collection_hum_dut = self.ext_sens_hum_axis.scatter([],[], c='purple', \
marker='*', label='DUT humidity')
self.ax1[2].set_xlabel("TIMESTAMP")
self.ax1[2].set_ylabel("TEMPERATURE [°C]", color='red')
self.ext_sens_hum_axis.set_ylabel("HUMIDITY [%RH]", color = 'purple')
self.ax1[2].grid(True, linestyle=":")
all_path_collections = [self.path_collection_temp_dut, self.path_collection_hum_dut]
labels = [pc.get_label() for pc in all_path_collections]
Michael Pawelzik
committed
self.ax1[2].legend(all_path_collections, labels, loc=self.legend_loc, bbox_to_anchor = \
self.legend_bbox_to_anchor)
# Forth plot: parameter of external sensors
# room temperature, room humidity , air pressure room, Michael
# configuration of used sensor port in ext_sens_data.json, Michael
self.path_collection_temp_room = self.ax1[3].scatter([],[], c='green', marker='*', label='room temperature')
self.sec_ext_hum_sens_axis = self.ax1[3].twinx()
self.path_collection_hum_room = self.sec_ext_hum_sens_axis.scatter([],[], c='orange', marker='>', label='room humidity')
self.press_axis = self.ax1[3].twinx()
Michael Pawelzik
committed
self.press_axis.spines['right'].set_position(('outward', 60))
self.path_collection_air_press_room = self.press_axis.scatter([],[], c='grey', marker='4', label='air pressure room')
self.ax1[3].set_xlabel("TIMESTAMP")
self.ax1[3].set_ylabel("TEMPERATURE [°C]", color='green')
self.sec_ext_hum_sens_axis.set_ylabel("HUMIDITY [%RH]", color = 'orange')
self.press_axis.set_ylabel("AIR PRESSURE [mb]", color ='grey')
self.ax1[3].grid(True, linestyle=":")
all_path_collections = [self.path_collection_temp_room, self.path_collection_hum_room, \
self.path_collection_air_press_room]
labels = [pc.get_label() for pc in all_path_collections]
Michael Pawelzik
committed
self.ax1[3].legend(all_path_collections, labels, loc=self.legend_loc, bbox_to_anchor = \
self.legend_bbox_to_anchor)
# Fifth plot: parameter of external sensors
# meas instruments temperature, meas instruments humidity, Michael
# configuration of used sensor port in ext_sens_data.json, Michael
Michael Pawelzik
committed
subplot_dict = self.config_fith_subplot()
Michael Pawelzik
committed
self.path_collection_trace_1 = self.ax1[4].scatter([], [], c='black', \
marker='p', label = subplot_dict.get('label_trace_1'))
Michael Pawelzik
committed
self.sec_plot_param_axis = self.ax1[4].twinx()
self.path_collection_trace_2 = self.sec_plot_param_axis.scatter([], [], c='brown', \
marker="*",label = subplot_dict.get('label_trace_2'))
Michael Pawelzik
committed
# # units added to y-axes of subplot 5, Michael
self.ax1[4].set_xlabel("TIMESTAMP")
self.ax1[4].set_ylabel(subplot_dict.get('y_axis'), color='black')
self.sec_plot_param_axis.set_ylabel(subplot_dict.get('sec_y_axis'), color='brown')
Michael Pawelzik
committed
self.ax1[4].grid(True, linestyle=":")
all_path_collections = [self.path_collection_trace_1, \
self.path_collection_trace_2]
labels = [pc.get_label() for pc in all_path_collections]
self.ax1[4].legend(all_path_collections, labels, loc=self.legend_loc, bbox_to_anchor = \
self.legend_bbox_to_anchor)
Michael Pawelzik
committed
# sclae fontsize of all plot window elements to size 16, Michael
plt.rcParams.update({'font.size':16})
def draw(self, data_frame, pdf_name=''):
timestamps = data_frame.TIMESTAMP
minimum, maximum = self.get_extended_min_max(timestamps)
self.ax1[0].set_xlim(minimum, maximum)
self.ax1[1].set_xlim(minimum, maximum)
# because subplots where increase x-axis limits has to be set equal to first and second plot, Michael
self.ax1[2].set_xlim(minimum, maximum)
self.ax1[3].set_xlim(minimum, maximum)
self.ax1[4].set_xlim(minimum, maximum)
# refresh data for phase in subplot for phase and magnitude
phases = data_frame.S21_PHASE
minimum, maximum = self.get_extended_min_max(phases)
self.ax1[0].set_ylim(minimum, maximum)
self.path_collection_phase.set_offsets(np.c_[timestamps, phases])
self.path_collection_fit.set_offsets(np.c_[[], []])
# refresh data for magnitude in subplot for phase and magnitude
magnitudes = data_frame.S21_MAGNITUDE
minimum, maximum = self.get_extended_min_max(magnitudes)
self.magnitude_axis.set_ylim(minimum, maximum)
self.path_collection_mag.set_offsets(np.c_[timestamps, magnitudes])
# refresh data for chamber temperature in subplot for chamber temperature and humidity
temperatures = data_frame.READBACK_TEMPERATURE
minimum, maximum = self.get_extended_min_max(temperatures)
self.ax1[1].set_ylim(minimum, maximum)
self.path_collection_temp.set_offsets(np.c_[timestamps, temperatures])
# refresh data for chamber humidity in subplot for chamber temperature and humidity
humidities = data_frame.READBACK_HUMIDITY
minimum, maximum = self.get_extended_min_max(humidities)
self.humidity_axis.set_ylim(minimum, maximum)
self.path_collection_hum.set_offsets(np.c_[timestamps, humidities])
# refresh temperatures for used external sensors in subplots, Michael
temp_dut = data_frame.TEMP_DUT
temp_room = data_frame.TEMP_ROOM
minimum, maximum = self.get_extended_min_max(temp_dut)
self.ax1[2].set_ylim(minimum, maximum)
self.path_collection_temp_dut.set_offsets(np.c_[timestamps, temp_dut])
minimum, maximum = self.get_extended_min_max(temp_room)
self.ax1[3].set_ylim(minimum, maximum)
self.path_collection_temp_room.set_offsets(np.c_[timestamps, temp_room])
Michael Pawelzik
committed
# refresh humidities external sensors in subplots for DUT humidity and room humidity
# humidity, Michael
hum_dut = data_frame.HUM_DUT
hum_room = data_frame.HUM_ROOM
minimum, maximum = self.get_extended_min_max(hum_dut)
self.ext_sens_hum_axis.set_ylim(minimum, maximum)
minimum, maximum = self.get_extended_min_max(hum_room)
self.sec_ext_hum_sens_axis.set_ylim(minimum, maximum)
self.path_collection_hum_dut.set_offsets(np.c_[timestamps, hum_dut])
self.path_collection_hum_room.set_offsets(np.c_[timestamps, hum_room])
# refresh air pressure of external sensor in subplot for air pressure room, Michael
air_press_room = data_frame.AIR_PRESS_ROOM
minimum, maximum = self.get_extended_min_max(air_press_room)
self.press_axis.set_ylim(minimum, maximum)
self.path_collection_air_press_room.set_offsets(np.c_[timestamps, air_press_room])
# refresh temperature and humidity of external sensor in subplot for measurement
# for instrument temperature and measurement instrument humidity, Michael
Michael Pawelzik
committed
val_trace_1, val_trace_2 = self.refresh_param_fith_subplot(data_frame)
Michael Pawelzik
committed
minimum, maximum = self.get_extended_min_max(val_trace_1)
self.ax1[4].set_ylim(minimum, maximum)
minimum, maximum = self.get_extended_min_max(val_trace_2)
self.sec_plot_param_axis.set_ylim(minimum, maximum)
self.path_collection_trace_1.set_offsets(np.c_[timestamps, val_trace_1])
self.path_collection_trace_2.set_offsets(np.c_[timestamps, val_trace_2])
self.path_collection_equi0.set_offsets(np.c_[timestamps, data_frame.EQUILIBRIUM_INDICATOR])
self.path_collection_equi1.set_offsets(np.c_[timestamps, data_frame.EQUILIBRIUM_INDICATOR])
if not pdf_name == '':
self.fig.savefig(pdf_name)
plt.show()
if plt.isinteractive():
try:
self.fig.canvas.draw()
self.fig.canvas.flush_events()
except Exception as e:
raise PlottingError from e
Michael Pawelzik
committed
def config_fith_subplot(self):
# key names for config parameter fith subplot
keys = ["label_trace_1", "label_trace_2", "y_axis", "sec_y_axis"]
if self.env_cond_sensors == 'ext':
# values for plotting evironmental conditions in measurement instrument chamber
values = ["temp sensor\nmeas instruments", "hum sensor\nmeas instruments", \
"TEMPERATURE [°C]", "HUMIDITY [%RH]"]
elif self.env_cond_sensors == 'int':
# values for plotting evironmental conditions in measurement instrument chamber
values = ["chamber temperature\nmeas instruments", "chamber humidity\nmeas instruments", \
"TEMPERATURE [°C]", "HUMIDITY [%RH]"]
else:
# values for plotting heater activity in fith subplot
values = ["Temp Heater", "Temp Heater", \
"ACTIVITY [%]","ACTIVITY [%]"]
Michael Pawelzik
committed
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# generate dictionary from selection
config_subplot_dict = dict(zip(keys, values))
return config_subplot_dict
def refresh_param_fith_subplot(self, data_frame):
if self.env_cond_sensors == 'ext':
# chose sensor values for refreshing fith subplot
val_trace_1 = data_frame.TEMP_MEAS_INSTR
val_trace_2 = data_frame.HUM_MEAS_INSTR
elif self.env_cond_sensors == 'int':
val_trace_1 = data_frame.READBACK_TEMP_MEAS_INSTR
val_trace_2 = data_frame.READBACK_HUM_MEAS_INSTR
else:
# chose heater values for refreshing fift plot
val_trace_1 = data_frame.TEMP_HEATER
val_trace_2 = data_frame.HUM_HEATER
return val_trace_1, val_trace_2
# add 5 % of the distance between min and max to the range
@staticmethod
def get_extended_min_max(array):
distance = array.max() - array.min()
if distance == 0.:
return array.min()-0.05*distance, array.max()+0.05*distance
# test procedure for measurement plot procedure
if __name__ == '__main__':
Michael Pawelzik
committed
m = MeasurementPlot(env_cond_sensors = "int")
plt.ion()
measurements = []
for i in range(20):
measurement = {
'TIMESTAMP': i,
'READBACK_TEMPERATURE': 25 - i,
'READBACK_HUMIDITY': 10 + 0.1*i,
'EQUILIBRIUM_INDICATOR': i % 4,
'S21_PHASE': 20 - 2*i,
Michael Pawelzik
committed
#acivity temp heater and hum heater, Michael
'TEMP_HEATER': 10,
# activity humidity heater, Michael, Michael
'HUM_HEATER': 3,
# DUT Temperature of external temp sensor added, Michael
'TEMP_DUT': i,
# room temperature of external temp sensor added, Michael
'TEMP_ROOM': 25-i,
# DUT Humidity of external hum sensor added, Michael
'HUM_DUT': 40,
# room humidity of external hum sensor added, Michael
'HUM_ROOM': 45,
# Air pressure of external sensor added, Michael
'AIR_PRESS_ROOM': 1000+10*i,
# measurement instrument temperature of external temp sensor added, Michael
'TEMP_MEAS_INSTR': 40-1.5*i,
# measurement instrument humidity of external hum sensor added, Michael
Michael Pawelzik
committed
'HUM_MEAS_INSTR': 55,
'READBACK_TEMP_MEAS_INSTR': 50-2*i,
# measurement instrument humidity of external hum sensor added, Michael
'READBACK_HUM_MEAS_INSTR': 39
measurements.append(measurement)
data_frame = pd.DataFrame(measurements)
# plot of data frame with test data for actual step
m.draw(data_frame)
print(str(i))
time.sleep(0.3)
print('I am done. ')
plt.ioff()
m.draw(data_frame, 'the.pdf')