cleanup, relative time fix

This commit is contained in:
2024-06-07 00:24:30 +02:00
parent 653eeafd2c
commit 2a3085ec14
3 changed files with 72 additions and 44 deletions
+41 -27
View File
@@ -4,24 +4,25 @@ from typing import Tuple, Optional
from itertools import cycle, islice
import re
import time
import asyncio
import random
from collections import deque
import click
import asyncio
import click
import numpy as np
from bsread import dispatcher, source
import epics
try:
from nicegui import ui, app, context, run
from nicegui import ui, app
from plots import PlotlyPlot
except ImportError as e:
print("nicegui not available, falling back to console plot.")
print("Nicegui not available, falling back to console plot.")
print(e)
from plots import ConsolePlot, PlotlyPlot
from plots import ConsolePlot
def clean_name(fname):
@@ -79,7 +80,7 @@ class ChannelData:
Append a new data point to the channel.
Args:
x: The x value.
x: The x value (timestamp).
y: The y value.
"""
@@ -137,7 +138,9 @@ def yield_bs_data(channel_names: list[str]):
# message.data.data['SINSB0-'].timestamp # timestamp of the IOC
# message.data.data['SINSB0-'].timestamp_offset # timestamp offset (ns) of the IOC
timestamp = message.data.global_timestamp + message.data.global_timestamp_offset / 1000_000_000
timestamp = (
message.data.global_timestamp + message.data.global_timestamp_offset / 1000_000_000
)
channel_data = {"pulse_id": {"value": message.data.pulse_id, "timestamp": timestamp}}
for key, value in message.data.data.items():
@@ -165,18 +168,17 @@ def yield_pv_data(channel_names: list[str]):
def yield_test_data(channel_names: list[str]):
"""Yields test data from the given channels with timestamp."""
import random
import time
while True:
channel_data = {
channel: {"value": random.random(), "timestamp": time.time()} for channel in channel_names
channel: {"value": random.random(), "timestamp": time.time()}
for channel in channel_names
}
yield channel_data
def roundrobin(*iterables):
"Visit input iterables in a cycle until each is exhausted."
"""Visit input iterables in a cycle until each is exhausted."""
# roundrobin('ABC', 'D', 'EF') → A D E B F C
# Algorithm credited to George Sakkis, posted as recipe in itertools
iterators = map(iter, iterables)
@@ -212,7 +214,9 @@ def yield_data(channel_names: list, only_pv=False):
def collect_data(channels: dict):
"""Collects data from the given channels and yields the updated data dictionary."""
"""Collects data from the given channels and respective sources
and yields the updated data dictionary.
"""
# typical channel_data:
# {'pulse_id': {'value': 21289615168, 'timestamp': 1717427820.5366151},
@@ -227,11 +231,9 @@ def collect_data(channels: dict):
yield channels
async def runner(
channels: dict,
plot_interface,
plot_interface: ConsolePlot | PlotlyPlot,
acquire_interval=0.1,
plot_interval=1,
in_subplots=False,
@@ -279,13 +281,20 @@ async def runner(
@click.command()
@click.argument("channel_names", nargs=-1)
@click.argument("channel_names", nargs=-1, type=str, required=True)
@click.option("--acquire-interval", default=0.1, help="Interval in seconds for data collection.")
@click.option("--plot-interval", default=1, help="Interval in seconds for plot update.")
@click.option("--save-prefix", default=None, help="Prefix for the save filenames.")
@click.option("--in-subplots", default=False, type=bool, help="Whether to plot in subplots.")
@click.option("--in-subplots", is_flag=True, default=False, type=bool, help="Enable plotting each channel in a subplot.")
@click.option(
"--web", is_flag=True, default=False, type=bool, help="Whether to use the local web interface as a GUI."
"--relative-time", default=True, is_flag=True, type=bool, help="Use relative time since start of acquisition."
)
@click.option(
"--web",
is_flag=True,
default=False,
type=bool,
help="Whether to use the local web interface as a GUI.",
)
def main(
channel_names: Tuple[str, ...],
@@ -293,15 +302,18 @@ def main(
plot_interval=1,
save_prefix: Optional[str] = None,
in_subplots=False,
relative_time=True,
web=False,
):
"""Plot channels from BS (beam synchronous) or PV (EPICS) sources."""
channels = {channel: ChannelData(channel, save_file_prefix=save_prefix) for channel in channel_names}
"""Plot channel data from BS (beam synchronous) or PV (EPICS) sources.
Use TEST_CHANNEL for test data.
"""
channels = {
channel: ChannelData(channel, save_file_prefix=save_prefix) for channel in channel_names
}
start_time = time.time()
if not web: # console plot version
plot = ConsolePlot(channels, start_time=start_time, in_subplots=in_subplots)
if not web: # console plot interface
plot = ConsolePlot(channels, in_subplots=in_subplots)
asyncio.run(
runner(
channels,
@@ -309,11 +321,12 @@ def main(
acquire_interval=float(acquire_interval),
plot_interval=plot_interval,
in_subplots=in_subplots,
relative_time=relative_time,
)
)
else: # nicegui version
plot = PlotlyPlot(channels, start_time=start_time, in_subplots=in_subplots)
else: # nicegui plotly interface
plot = PlotlyPlot(channels, in_subplots=in_subplots)
async def run_async():
await runner(
@@ -322,6 +335,7 @@ def main(
acquire_interval=float(acquire_interval),
plot_interval=plot_interval,
in_subplots=in_subplots,
relative_time=relative_time,
)
app.on_startup(run_async)