1use serde::{Deserialize, Serialize};
2
3pub use nanonis_rs::motor::{
5 Amplitude, Frequency, MotorAxis, MotorDirection, MotorDisplacement, MotorGroup,
6 MotorMovement, MovementMode, Position3D, StepCount,
7};
8pub use nanonis_rs::oscilloscope::{
9 OsciData, OsciTriggerMode, OscilloscopeIndex, OversamplingIndex, SampleCount, SignalStats,
10 TimebaseIndex, TriggerConfig, TriggerLevel, TriggerMode, TriggerSlope,
11};
12pub use nanonis_rs::Position;
13pub use nanonis_rs::bias::PulseMode;
14pub use nanonis_rs::scan::{ScanAction, ScanConfig, ScanDirection, ScanFrame};
15pub use nanonis_rs::signals::SignalFrame;
16pub use nanonis_rs::tcplog::{TCPLogStatus, TCPLoggerData};
17pub use nanonis_rs::z_ctrl::ZControllerHold;
18use std::time::{Duration, Instant};
21
22#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Default)]
24pub enum TipShape {
25 #[default]
26 Blunt,
27 Sharp,
28 Stable,
29}
30
31#[derive(Debug, Clone)]
33pub struct SessionMetadata {
34 pub session_id: String,
35 pub signal_names: Vec<String>, pub active_indices: Vec<usize>, pub primary_signal_index: usize, pub session_start: f64, }
40
41#[derive(Debug, Clone, Copy, PartialEq)]
43pub enum DataToGet {
44 Current,
45 NextTrigger,
46 Wait2Triggers,
47 Stable { readings: u32, timeout: Duration },
48}
49
50#[derive(Debug, Clone)]
52pub struct TimestampedSignalFrame {
53 pub signal_frame: SignalFrame,
55 pub timestamp: Instant,
57 pub relative_time: Duration,
59}
60
61impl TimestampedSignalFrame {
62 pub fn new(signal_frame: SignalFrame, start_time: Instant) -> Self {
65 let timestamp = Instant::now();
66 Self {
67 signal_frame,
68 timestamp,
69 relative_time: timestamp.duration_since(start_time),
70 }
71 }
72}
73
74#[derive(Debug)]
79pub struct ExperimentData {
80 pub action_result: crate::actions::ActionResult,
82 pub signal_frames: Vec<TimestampedSignalFrame>,
84 pub tcp_config: crate::action_driver::TCPReaderConfig,
86 pub action_start: Instant,
88 pub action_end: Instant,
90 pub total_duration: Duration,
92}
93
94#[derive(Debug)]
96pub struct ChainExperimentData {
97 pub action_results: Vec<crate::actions::ActionResult>,
99 pub signal_frames: Vec<TimestampedSignalFrame>,
101 pub tcp_config: crate::action_driver::TCPReaderConfig,
103 pub action_timings: Vec<(Instant, Instant)>,
105 pub chain_start: Instant,
107 pub chain_end: Instant,
109 pub total_duration: Duration,
111}
112
113impl ExperimentData {
114 pub fn data_during_action(&self) -> Vec<&TimestampedSignalFrame> {
116 self.signal_frames
117 .iter()
118 .filter(|frame| {
119 frame.timestamp >= self.action_start && frame.timestamp <= self.action_end
120 })
121 .collect()
122 }
123
124 pub fn data_before_action(&self, duration: Duration) -> Vec<&TimestampedSignalFrame> {
126 let cutoff = self.action_start - duration;
127 self.signal_frames
128 .iter()
129 .filter(|frame| frame.timestamp >= cutoff && frame.timestamp < self.action_start)
130 .collect()
131 }
132
133 pub fn data_after_action(&self, duration: Duration) -> Vec<&TimestampedSignalFrame> {
135 let cutoff = self.action_end + duration;
136 self.signal_frames
137 .iter()
138 .filter(|frame| frame.timestamp > self.action_end && frame.timestamp <= cutoff)
139 .collect()
140 }
141
142 pub fn get_tcp_logger_data(&self) -> Vec<TCPLoggerData> {
145 self.signal_frames
146 .iter()
147 .map(|frame| TCPLoggerData {
148 num_channels: self.tcp_config.channels.len() as u32,
149 oversampling: self.tcp_config.oversampling as f32,
150 counter: frame.signal_frame.counter,
151 state: TCPLogStatus::Running,
152 data: frame.signal_frame.data.clone(),
153 })
154 .collect()
155 }
156}
157
158impl ChainExperimentData {
159 pub fn data_during_action(&self, action_index: usize) -> Vec<&TimestampedSignalFrame> {
167 if let Some((start, end)) = self.action_timings.get(action_index) {
168 self.signal_frames
169 .iter()
170 .filter(|frame| frame.timestamp >= *start && frame.timestamp <= *end)
171 .collect()
172 } else {
173 Vec::new()
174 }
175 }
176
177 pub fn data_between_actions(
186 &self,
187 action1_index: usize,
188 action2_index: usize,
189 ) -> Vec<&TimestampedSignalFrame> {
190 if let (Some((_, end1)), Some((start2, _))) = (
191 self.action_timings.get(action1_index),
192 self.action_timings.get(action2_index),
193 ) {
194 self.signal_frames
195 .iter()
196 .filter(|frame| frame.timestamp > *end1 && frame.timestamp < *start2)
197 .collect()
198 } else {
199 Vec::new()
200 }
201 }
202
203 pub fn data_before_chain(&self, duration: Duration) -> Vec<&TimestampedSignalFrame> {
211 let cutoff = self.chain_start - duration;
212 self.signal_frames
213 .iter()
214 .filter(|frame| frame.timestamp >= cutoff && frame.timestamp < self.chain_start)
215 .collect()
216 }
217
218 pub fn data_after_chain(&self, duration: Duration) -> Vec<&TimestampedSignalFrame> {
226 let cutoff = self.chain_end + duration;
227 self.signal_frames
228 .iter()
229 .filter(|frame| frame.timestamp > self.chain_end && frame.timestamp <= cutoff)
230 .collect()
231 }
232
233 pub fn data_for_entire_chain(&self) -> Vec<&TimestampedSignalFrame> {
238 self.signal_frames
239 .iter()
240 .filter(|frame| {
241 frame.timestamp >= self.chain_start && frame.timestamp <= self.chain_end
242 })
243 .collect()
244 }
245
246 pub fn action_timing(&self, action_index: usize) -> Option<(Instant, Instant, Duration)> {
254 self.action_timings
255 .get(action_index)
256 .map(|(start, end)| (*start, *end, end.duration_since(*start)))
257 }
258
259 pub fn chain_summary(&self) -> (usize, usize, usize, Duration) {
264 let total_actions = self.action_results.len();
265 let successful_actions = self
266 .action_results
267 .iter()
268 .filter(|result| matches!(result, crate::actions::ActionResult::Success))
269 .count();
270 let total_frames = self.signal_frames.len();
271
272 (
273 total_actions,
274 successful_actions,
275 total_frames,
276 self.total_duration,
277 )
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq)]
283pub enum AutoApproachResult {
284 Success,
286 Timeout,
288 Failed(String),
290 AlreadyRunning,
292 Cancelled,
294}
295
296impl AutoApproachResult {
297 pub fn is_success(&self) -> bool {
299 matches!(self, AutoApproachResult::Success)
300 }
301
302 pub fn is_failure(&self) -> bool {
304 matches!(
305 self,
306 AutoApproachResult::Failed(_) | AutoApproachResult::Timeout
307 )
308 }
309
310 pub fn error_message(&self) -> Option<&str> {
312 match self {
313 AutoApproachResult::Failed(msg) => Some(msg),
314 AutoApproachResult::Timeout => Some("Auto-approach timed out"),
315 AutoApproachResult::AlreadyRunning => Some("Auto-approach already running"),
316 AutoApproachResult::Cancelled => Some("Auto-approach was cancelled"),
317 AutoApproachResult::Success => None,
318 }
319 }
320}
321
322#[derive(Debug, Clone, PartialEq, Eq)]
324pub enum AutoApproachStatus {
325 Idle,
327 Running,
329 Unknown,
331}
332