psfparser/analysis/
ac.rs

1use num::complex::Complex64;
2use std::collections::HashMap;
3
4use crate::ascii::ast::{PsfAst, Trace, Values};
5use crate::bin_search_before;
6
7pub struct AcData {
8    pub signals: HashMap<String, Vec<Complex64>>,
9    pub freq: Vec<f64>,
10}
11
12impl AcData {
13    pub fn from_ascii(ast: &PsfAst) -> Self {
14        // Assume all groups have count = 1
15        // group name -> signal name
16        let mut groups = HashMap::<&str, &str>::new();
17        let mut i = 0;
18        while i < ast.traces.len() {
19            match ast.traces[i] {
20                Trace::Group { name: group, count } => {
21                    debug_assert!(count >= 0);
22                    let count = count as usize;
23                    for j in 1..=count {
24                        if let Trace::Signal { name, .. } = ast.traces[i + j] {
25                            groups.insert(group, name);
26                        } else {
27                            panic!("Expected signal; found group");
28                        }
29                    }
30                    i += count + 1;
31                }
32                Trace::Signal { name, .. } => {
33                    groups.insert(name, name);
34                    i += 1;
35                }
36            }
37        }
38
39        let mut signals = HashMap::<String, Vec<Complex64>>::new();
40        let mut freq = Vec::<f64>::new();
41        for v in ast.values.iter() {
42            if v.signal == "freq" {
43                if let Values::Real(values) = &v.values {
44                    debug_assert_eq!(values.len(), 1);
45                    freq.push(values[0]);
46                } else {
47                    panic!("Expected real signal values; found complex");
48                }
49            } else if let Values::Complex(values) = &v.values {
50                debug_assert_eq!(values.len(), 1);
51                if let Some(lst) = signals.get_mut(groups[v.signal]) {
52                    lst.push(values[0]);
53                } else {
54                    signals.insert(groups[v.signal].to_string(), vec![values[0]]);
55                }
56            } else {
57                panic!("Expected complex signal values; found real");
58            }
59        }
60
61        Self { signals, freq }
62    }
63
64    pub fn from_binary(mut ast: crate::binary::ast::PsfAst) -> Self {
65        let mut signals = HashMap::<String, Vec<Complex64>>::new();
66        for group in ast.traces.iter() {
67            for sig in group.signals() {
68                let v = ast
69                    .values
70                    .values
71                    .remove(&sig.id)
72                    .expect("missing values for trace");
73                signals.insert(sig.name.to_string(), v.unwrap_complex());
74            }
75        }
76
77        assert_eq!(
78            ast.sweeps[0].name, "freq",
79            "ac analysis expects to sweep frequency"
80        );
81        let freq = ast
82            .values
83            .values
84            .remove(&ast.sweeps[0].id)
85            .unwrap()
86            .unwrap_real();
87
88        Self { signals, freq }
89    }
90
91    /// Gets the index into the data arrays
92    /// corresponding to the largest frequency less than or equal to `f`.
93    pub fn idx_before_freq(&self, f: f64) -> Option<usize> {
94        bin_search_before(&self.freq, f)
95    }
96
97    #[inline]
98    pub fn signal(&self, name: &str) -> Option<&Vec<Complex64>> {
99        self.signals.get(name)
100    }
101}