From 30cd80d03b0064e632505a76e9593a23552b9b4d Mon Sep 17 00:00:00 2001 From: jess Date: Thu, 2 Apr 2026 18:13:44 -0700 Subject: [PATCH] wire peak markers into VoltammogramPlot with color-coded rendering and labels --- cue/src/plot.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cue/src/plot.rs b/cue/src/plot.rs index 0023fb2..7d3de74 100644 --- a/cue/src/plot.rs +++ b/cue/src/plot.rs @@ -3,6 +3,7 @@ use iced::{Color, Point, Rectangle, Renderer, Theme}; use iced::mouse; use crate::app::Message; +use crate::lsv_analysis::{LsvPeak, PeakKind}; use crate::protocol::{AmpPoint, ClPoint, EisPoint, LsvPoint}; const MARGIN_L: f32 = 55.0; @@ -823,6 +824,7 @@ pub struct VoltammogramState { pub struct VoltammogramPlot<'a> { pub points: &'a [LsvPoint], pub reference: Option<&'a [LsvPoint]>, + pub peaks: &'a [LsvPeak], } impl VoltammogramPlot<'_> { @@ -983,6 +985,24 @@ impl<'a> canvas::Program for VoltammogramPlot<'a> { draw_polyline(&mut frame, &pts, COL_LSV, 2.0); draw_dots(&mut frame, &pts, COL_LSV, 2.5); + for peak in self.peaks { + let px = lerp(peak.v_mv, xv.lo, xv.hi, xl, xr); + let py = lerp(peak.i_ua, yv.hi, yv.lo, yt, yb); + if !px.is_finite() || !py.is_finite() { continue; } + let col = match peak.kind { + PeakKind::FreeCl => COL_CL_FREE, + PeakKind::TotalCl => COL_CL_TOTAL, + PeakKind::Crossover => COL_FIT_PT, + }; + frame.fill(&Path::circle(Point::new(px, py), 5.0), col); + let label = match peak.kind { + PeakKind::FreeCl => format!("Free {:.0}mV {:.2}uA", peak.v_mv, peak.i_ua), + PeakKind::TotalCl => format!("Total {:.0}mV {:.2}uA", peak.v_mv, peak.i_ua), + PeakKind::Crossover => format!("X-over {:.0}mV", peak.v_mv), + }; + dt(&mut frame, Point::new(px - 20.0, py + 8.0), &label, col, 10.0); + } + if let Some(pos) = cursor.position_in(bounds) { if pos.x >= xl && pos.x <= xr && pos.y >= yt && pos.y <= yb { let v = lerp(pos.x, xl, xr, xv.lo, xv.hi);