use liveplot::{
channel_plot, run_liveplot, LivePlotConfig, PlotPoint, ThresholdController, ThresholdDef,
ThresholdKind, TraceRef,
};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
fn main() -> eframe::Result<()> {
let (sink, rx) = channel_plot();
let trace = sink.create_trace("signal", None);
std::thread::spawn(move || {
const FS_HZ: f64 = 1000.0; const F_HZ: f64 = 3.0; let dt = Duration::from_millis(1);
let mut n: u64 = 0;
loop {
let t = n as f64 / FS_HZ;
let val = (2.0 * std::f64::consts::PI * F_HZ * t).sin();
let t_s = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs_f64())
.unwrap_or(0.0);
let _ = sink.send_point(&trace, PlotPoint { x: t_s, y: val });
n = n.wrapping_add(1);
std::thread::sleep(dt);
}
});
let thr_ctrl = ThresholdController::new();
{
let rx_evt = thr_ctrl.subscribe();
std::thread::spawn(move || {
while let Ok(evt) = rx_evt.recv() {
eprintln!(
"[threshold] {}: {} from {:.3}s for {:.3} ms, area={:.4}",
evt.threshold,
evt.trace,
evt.start_t,
evt.duration * 1000.0,
evt.area
);
}
});
}
thr_ctrl.add_threshold(ThresholdDef {
name: "gt_0_8".into(),
target: TraceRef("signal".into()),
kind: ThresholdKind::GreaterThan { value: 0.8 },
min_duration_s: 0.002,
max_events: 100,
..Default::default()
});
let mut cfg = LivePlotConfig::default();
cfg.title = "LivePlot (thresholds)".into();
cfg.native_options = Some(eframe::NativeOptions::default());
cfg.threshold_controller = Some(thr_ctrl);
run_liveplot(rx, cfg)
}