Files
plot_channels/plots.py
T
2024-06-07 00:24:30 +02:00

126 lines
3.3 KiB
Python

from abc import ABC, abstractmethod
import plotext as plt
import plotly.express as px
from plotly.subplots import make_subplots
from nicegui import ui, context
class AbstractPlot(ABC):
def __init__(
self,
channels,
in_subplots=False,
) -> None:
pass
@abstractmethod
def setup_plot(self):
"""Set up the plot."""
pass
@abstractmethod
def update_plot(self, channels, start_time=0, **kwargs):
"""Update the plot with new data from the given channels."""
pass
class PlotlyPlot(AbstractPlot):
def __init__(
self,
channels,
start_time=0,
in_subplots=False,
) -> None:
self.channels = channels
self.start_time = start_time
self.in_subplots = in_subplots
self.plot, self.fig = self.setup_plot()
def setup_plot(self):
num_traces = len(self.channels)
labels = [channel.name for channel in self.channels.values()]
context.client.content.classes("h-[100vh]") # full height and width of the container
colors = px.colors.qualitative.D3
fig = make_subplots(rows=num_traces, cols=1, shared_xaxes=True, vertical_spacing=0.05)
subfigures = [
px.line(
markers=True,
)
for _ in range(num_traces)
]
for i, subfig in enumerate(subfigures):
trace = subfig["data"][0]
subfig["data"][0]["showlegend"] = True
subfig["data"][0]["name"] = f"{labels[i]}"
subfig["data"][0]["line"]["color"] = colors[i % len(colors)]
fig.add_trace(trace, row=i + 1, col=1)
fig.update_layout(
autosize=True,
margin=dict(l=10, r=10, b=10, t=10, pad=5),
# paper_bgcolor="LightSteelBlue",
)
# set xaxis title for last subplot at the bottom
fig["layout"][f"xaxis{num_traces}"]["title"] = "time (s)"
plot = ui.plotly(fig).classes("w-full h-full") # full height and width inside the container
return plot, fig
def update_plot(self, channels, start_time=0, **kwargs) -> None:
for i, channel in enumerate(channels.values()):
self.fig["data"][i]["x"] = channel.x - start_time
self.fig["data"][i]["y"] = channel.y
self.plot.update_figure(self.fig)
class ConsolePlot(AbstractPlot):
def __init__(self, channels, start_time=0, in_subplots=False, marker="hd"):
self.channels = channels
self.start_time = start_time
self.in_subplots = in_subplots
self.marker = marker
self.setup_plot()
def setup_plot(self):
"""Set up the plot."""
plt.clf()
plt.limit_size(False, False)
plt.theme("pro")
plt.xlabel("Timestamp")
plt.ylabel("Value")
def update_plot(self, channels, start_time=0, in_subplots=False, marker="hd"):
"""Plots channels on the console."""
num_channels = len(channels)
if in_subplots:
plt.subplots(num_channels, 1)
plt.main().plot_size(plt.tw(), plt.th() - 1)
plt.clear_data()
for i, channel in enumerate(channels.values()):
if in_subplots:
plt.subplot(i + 1, 1)
plt.plot(channel.x - start_time, channel.y, label=channel.name, marker=marker)
plt.show()