photoreflectance/update_funcs.py
2025-05-02 15:48:36 +02:00

84 lines
2.9 KiB
Python

import matplotlib.pyplot as plt
import numpy as np
class Monitor:
"""
Monitor v and i data in a matplotlib window
"""
def __init__(self, xlabel: str, datas: list[dict], max_points_shown=None, use_print=False):
self.max_points_shown = max_points_shown
self.use_print = use_print
self.index = []
self.xdata = []
self.options = [{"ax": 0, "ylabel": None, "lim": None, "color": "orange", "grid": True, "label": None} | datas[i] for i in range(len(datas))]
self.ydatas = [[] for _ in range(len(datas))]
self.lines = []
n_ax = max(self.options, key=lambda v: v["ax"])["ax"] + 1
plt.ion()
self.fig1, self.ax = plt.subplots(n_ax, 1, figsize=(7, 8), sharex=True)
for i in range(len(self.ydatas)):
opt = self.options[i]
ax = self.ax[opt["ax"]]
self.lines.append(ax.plot(self.xdata, self.ydatas[i], color=opt["color"], label=opt["label"])[0])
if opt["label"]:
ax.legend()
if opt["grid"]:
ax.grid(True)
if opt["lim"]:
ax.set_ylim(opt["lim"][0], opt["lim"][1])
if opt["ylabel"]:
ax.set_ylabel(opt["ylabel"])
def override(self, xval, *yvals):
idx = self.xdata.index(xval)
for i, y in enumerate(yvals):
if y is None: continue
self.ydatas[i][idx] = y
self.lines[i].set_ydata(self.ydatas[i])
self._post_update()
def update(self, xval, *yvals):
n = len(self.xdata)
if self.use_print:
s = f"n = {n}"
for i, y in enumerate(yvals):
s += f", {self.options[i]['label']} = {y}"
print(s + " "*10, end='\r')
self.xdata.append(xval)
for i, y in enumerate(yvals):
if y is None: y = np.nan
self.ydatas[i].append(y)
self.lines[i].set_xdata(self.xdata)
self.lines[i].set_ydata(self.ydatas[i])
self._post_update()
def update_array(self, xdata, *ydatas):
self.xdata.extend(xdata)
for i, y in enumerate(ydatas):
self.ydatas[i].extend(y)
self.lines[i].set_xdata(self.xdata)
self.lines[i].set_ydata(self.ydatas[i])
self._post_update()
def _post_update(self):
n = len(self.xdata)
if self.max_points_shown and n > self.max_points_shown:
# recalculate limits and set them for the view
for ax in self.ax:
self.ax[-1].set_xlim(self.xdata[n - self.max_points_shown], self.xdata[n])
for ax in self.ax:
ax.relim() # required for autoscale_view to work
ax.autoscale_view()
self.ax[-1].autoscale_view()
# update plot
self.fig1.canvas.draw()
self.fig1.canvas.flush_events()
def __del__(self):
plt.close(self.fig1)