Skip to main content

run_liveplot

Function run_liveplot 

Source
pub fn run_liveplot(
    rx: Receiver<PlotCommand>,
    cfg: LivePlotConfig,
) -> Result<()>
Expand description

Launch the LivePlot application in a native window.

This is the main entry point for standalone use. It:

  1. Constructs a LivePlotApp with the given command channel and any controllers extracted from cfg.
  2. Applies the configuration (axis units, hotkeys, responsive thresholds, …).
  3. Opens a native window and enters the eframe event loop.

The call blocks until the window is closed.

Examples found in repository?
examples/sine.rs (line 42)
16fn main() -> eframe::Result<()> {
17    // Create multi-trace plot channel (we use a single trace labeled "signal")
18    let (sink, rx) = channel_plot();
19    let trace = sink.create_trace("signal", Some("Test Sine"));
20
21    // Producer: 1 kHz sample rate, 3 Hz sine
22    std::thread::spawn(move || {
23        const FS_HZ: f64 = 1000.0; // 1 kHz sampling rate
24        const F_HZ: f64 = 3.0; // 3 Hz sine wave
25        let dt = Duration::from_millis(1);
26        let mut n: u64 = 0;
27        loop {
28            let t = n as f64 / FS_HZ;
29            let val = (2.0 * std::f64::consts::PI * F_HZ * t).sin();
30            let t_s = SystemTime::now()
31                .duration_since(UNIX_EPOCH)
32                .map(|d| d.as_secs_f64())
33                .unwrap_or(0.0);
34            // Ignore error if the UI closed (receiver dropped)
35            let _ = sink.send_point(&trace, PlotPoint { x: t_s, y: val });
36            n = n.wrapping_add(1);
37            std::thread::sleep(dt);
38        }
39    });
40
41    // Run the UI until closed
42    run_liveplot(rx, LivePlotConfig::default())
43}
More examples
Hide additional examples
examples/fixed_data.rs (line 69)
41fn main() -> eframe::Result<()> {
42    // Create the plot channel: we will create traces and push their data via `PlotSink`.
43    let (sink, rx) = channel_plot();
44
45    // Prepare fixed waves and convert to PlotPoint vectors
46    let (sine_v, cosine_v) = make_fixed_waves();
47    let sine_points: Vec<PlotPoint> = sine_v
48        .into_iter()
49        .map(|p| PlotPoint { x: p[0], y: p[1] })
50        .collect();
51    let cosine_points: Vec<PlotPoint> = cosine_v
52        .into_iter()
53        .map(|p| PlotPoint { x: p[0], y: p[1] })
54        .collect();
55
56    // Register traces and set full data via sink
57    let sine_t = sink.create_trace("sine", Some("Sine"));
58    let cos_t = sink.create_trace("cosine", Some("Cosine"));
59    let _ = sink.set_data(&sine_t, sine_points);
60    let _ = sink.set_data(&cos_t, cosine_points);
61
62    // Build configuration via LivePlotConfig instead of mutating the internal app fields
63    let mut cfg = LivePlotConfig::default();
64    cfg.time_window_secs = 10.0;
65    cfg.max_points = 10_000;
66    cfg.features.legend = true;
67
68    // Show the UI using the channel receiver and the config
69    run_liveplot(rx, cfg)
70}
examples/sine_cosine.rs (line 45)
16fn main() -> eframe::Result<()> {
17    // Create multi-trace plot channel
18    let (sink, rx) = channel_plot();
19    let tr_sine = sink.create_trace("sine", None);
20    let tr_cos = sink.create_trace("cosine", None);
21
22    // Producer: 1 kHz sample rate, 3 Hz sine and cosine
23    std::thread::spawn(move || {
24        const FS_HZ: f64 = 1000.0; // 1 kHz sampling rate
25        const F_HZ: f64 = 3.0; // 3 Hz
26        let dt = Duration::from_millis(1);
27        let mut n: u64 = 0;
28        loop {
29            let t = n as f64 / FS_HZ;
30            let s_val = (2.0 * std::f64::consts::PI * F_HZ * t).sin();
31            let c_val = (2.0 * std::f64::consts::PI * F_HZ * t).cos();
32            let t_s = SystemTime::now()
33                .duration_since(UNIX_EPOCH)
34                .map(|d| d.as_secs_f64())
35                .unwrap_or(0.0);
36            // Ignore error if the UI closed (receiver dropped)
37            let _ = sink.send_point(&tr_sine, PlotPoint { x: t_s, y: s_val });
38            let _ = sink.send_point(&tr_cos, PlotPoint { x: t_s, y: c_val });
39            n = n.wrapping_add(1);
40            std::thread::sleep(dt);
41        }
42    });
43
44    // Run the UI until closed (default: FFT hidden). Uses the unified multi-trace engine.
45    run_liveplot(rx, LivePlotConfig::default())
46}
examples/set_toggle.rs (line 75)
33fn main() {
34    // channel for PlotCommand messages
35    let (tx, rx) = mpsc::channel::<PlotCommand>();
36
37    // Producer thread: send commands while UI runs on the main thread
38    let producer = thread::spawn(move || {
39        // register trace id 1
40        let _ = tx.send(PlotCommand::RegisterTrace {
41            id: 1,
42            name: "toggle".into(),
43            info: Some("sine/cosine toggle".into()),
44        });
45
46        let _start = Instant::now();
47        let mut t0 = 0.0_f64;
48        // pre-generate one period of samples at 100 Hz
49        let n = 200usize;
50        let dt = 0.01_f64;
51        let mut is_sine = true;
52
53        loop {
54            // Build waveform and use SetData to overwrite the trace
55            let pts = make_wave(is_sine, t0, n, dt);
56            if mpsc::Sender::send(
57                &tx,
58                PlotCommand::SetData {
59                    trace_id: 1,
60                    points: pts,
61                },
62            )
63            .is_err()
64            {
65                break; // UI likely closed
66            }
67            // toggle every 2 seconds
68            thread::sleep(Duration::from_secs(2));
69            t0 += 2.0;
70            is_sine = !is_sine;
71        }
72    });
73
74    // Run UI on the main thread (required by winit/eframe)
75    if let Err(e) = run_liveplot(rx, LivePlotConfig::default()) {
76        eprintln!("UI error: {e}");
77    }
78
79    // Ensure producer exits
80    let _ = producer.join();
81}
examples/events_simple.rs (line 62)
19fn main() -> eframe::Result<()> {
20    // Create the event controller and subscribe to click-related events.
21    let event_ctrl = EventController::new();
22    let rx = event_ctrl.subscribe(EventFilter::only(
23        EventKind::CLICK | EventKind::DOUBLE_CLICK,
24    ));
25
26    // Print received events on a background thread.
27    std::thread::spawn(move || {
28        while let Ok(evt) = rx.recv() {
29            println!("[event] kind={}", evt.kinds);
30            if let Some(click) = &evt.click {
31                if let Some(pp) = &click.plot_pos {
32                    println!("  plot position: ({:.4}, {:.4})", pp.x, pp.y);
33                }
34                if let Some(sp) = &click.screen_pos {
35                    println!("  screen position: ({:.1}, {:.1})", sp.x, sp.y);
36                }
37            }
38        }
39        println!("[event] channel closed");
40    });
41
42    // Set up a simple sine trace so there is something to click on.
43    let (sink, data_rx) = channel_plot();
44    let trace = sink.create_trace("sine", Some("Sine Wave"));
45
46    std::thread::spawn(move || {
47        let dt = Duration::from_millis(1);
48        loop {
49            let t_s = SystemTime::now()
50                .duration_since(UNIX_EPOCH)
51                .map(|d| d.as_secs_f64())
52                .unwrap_or(0.0);
53            let val = (2.0 * std::f64::consts::PI * 2.0 * t_s).sin();
54            let _ = sink.send_point(&trace, PlotPoint { x: t_s, y: val });
55            std::thread::sleep(dt);
56        }
57    });
58
59    let mut cfg = LivePlotConfig::default();
60    cfg.controllers.event = Some(event_ctrl);
61
62    run_liveplot(data_rx, cfg)
63}
examples/thresholds_sine.rs (line 75)
20fn main() -> eframe::Result<()> {
21    let (sink, rx) = channel_plot();
22    let trace = sink.create_trace("signal", None);
23
24    // Producer: 1 kHz sample rate, 3 Hz sine
25    std::thread::spawn(move || {
26        const FS_HZ: f64 = 1000.0; // 1 kHz sampling rate
27        const F_HZ: f64 = 3.0; // 3 Hz sine wave
28        let dt = Duration::from_millis(1);
29        let mut n: u64 = 0;
30        loop {
31            let t = n as f64 / FS_HZ;
32            let val = (2.0 * std::f64::consts::PI * F_HZ * t).sin();
33            let t_s = SystemTime::now()
34                .duration_since(UNIX_EPOCH)
35                .map(|d| d.as_secs_f64())
36                .unwrap_or(0.0);
37            let _ = sink.send_point(&trace, PlotPoint { x: t_s, y: val });
38            n = n.wrapping_add(1);
39            std::thread::sleep(dt);
40        }
41    });
42
43    // Build a threshold controller and pre-configure a "> 0.8" threshold on "signal".
44    let thr_ctrl = ThresholdController::new();
45    {
46        // Subscribe to events and print them
47        let rx_evt = thr_ctrl.subscribe();
48        std::thread::spawn(move || {
49            while let Ok(evt) = rx_evt.recv() {
50                eprintln!(
51                    "[threshold] {}: {} from {:.3}s for {:.3} ms, area={:.4}",
52                    evt.threshold,
53                    evt.trace,
54                    evt.start_t,
55                    evt.duration * 1000.0,
56                    evt.area
57                );
58            }
59        });
60    }
61    thr_ctrl.request_add_threshold(ThresholdDef {
62        name: "gt_0_8".into(),
63        target: TraceRef("signal".into()),
64        kind: ThresholdKind::GreaterThan { value: 0.8 },
65        min_duration_s: 0.002,
66        max_events: 100,
67        ..Default::default()
68    });
69
70    // Run the UI with the controller attached via config
71    let mut cfg = LivePlotConfig::default();
72    cfg.title = "LivePlot (thresholds)".into();
73    cfg.native_options = Some(eframe::NativeOptions::default());
74    cfg.controllers.threshold = Some(thr_ctrl);
75    run_liveplot(rx, cfg)
76}