Skip to main content

dune_core/
solution.rs

1//! Analysis results in the shape of a rawfile plot (D-0008): named
2//! variables with [`VarType`](crate::VarType)s and real or complex
3//! columns ([`Data`](crate::Data), both re-exported from `dune_raw`),
4//! so the oracle, the CLI and the bindings all read the same thing.
5
6use dune_raw::{Data, Plot, VarType, Variable};
7use num_complex::Complex64;
8
9/// One analysis plot: what a rawfile plot holds, with
10/// [`crate::VarType`] and [`crate::Data`] re-exported at the crate
11/// root so callers need not depend on `dune_raw`.
12#[derive(Clone, Debug)]
13pub struct Solution {
14    /// The `Plotname:` (e.g. `Operating Point`).
15    pub plotname: String,
16    /// Variable names and kinds ([`crate::VarType`]), in rawfile
17    /// order.
18    pub variables: Vec<(String, VarType)>,
19    /// One column per variable, all the same length; complex for
20    /// `.ac`, real for everything else ([`crate::Data`]).
21    pub data: Data,
22    /// Index of the abscissa (`time`, `frequency`, `v(v-sweep)`) in
23    /// `variables`; `None` for the operating point.
24    pub scale: Option<usize>,
25}
26
27impl Solution {
28    pub fn num_points(&self) -> usize {
29        self.data.num_points()
30    }
31
32    /// Real column by variable name (case-insensitive, like the 3f5
33    /// front end); `None` when missing or complex.
34    pub fn column(&self, name: &str) -> Option<&[f64]> {
35        let i = self.index(name)?;
36        match &self.data {
37            Data::Real(cols) => Some(&cols[i]),
38            Data::Complex(_) => None,
39        }
40    }
41
42    /// Complex column by variable name.
43    pub fn column_complex(&self, name: &str) -> Option<&[Complex64]> {
44        let i = self.index(name)?;
45        match &self.data {
46            Data::Complex(cols) => Some(&cols[i]),
47            Data::Real(_) => None,
48        }
49    }
50
51    pub(crate) fn index(&self, name: &str) -> Option<usize> {
52        self.variables
53            .iter()
54            .position(|(n, _)| n.eq_ignore_ascii_case(name))
55    }
56
57    /// Package as a rawfile plot (padded).
58    pub fn to_plot(&self, title: &str, date: &str) -> Plot {
59        Plot {
60            title: title.to_string(),
61            date: date.to_string(),
62            name: self.plotname.clone(),
63            padded: true,
64            commands: Vec::new(),
65            options: Vec::new(),
66            dimensions: None,
67            variables: self
68                .variables
69                .iter()
70                .map(|(n, t)| Variable::new(n.clone(), t.clone()))
71                .collect(),
72            data: self.data.clone(),
73        }
74    }
75}