Skip to main content

celestial_pointing/commands/
mvet.rs

1use super::{Command, CommandOutput};
2use crate::error::{Error, Result};
3use crate::session::Session;
4
5pub struct Mvet;
6
7impl Command for Mvet {
8    fn name(&self) -> &str {
9        "MVET"
10    }
11    fn description(&self) -> &str {
12        "Find and optionally remove weak terms"
13    }
14
15    fn execute(&self, session: &mut Session, args: &[&str]) -> Result<CommandOutput> {
16        if args.is_empty() {
17            return Err(Error::Parse(
18                "MVET requires a significance threshold".into(),
19            ));
20        }
21        let threshold: f64 = args[0]
22            .parse()
23            .map_err(|e| Error::Parse(format!("invalid threshold: {}", e)))?;
24        let remove = args.get(1).is_some_and(|a| a.eq_ignore_ascii_case("R"));
25
26        let fit = session
27            .last_fit
28            .as_ref()
29            .ok_or_else(|| Error::Fit("no fit results available (run FIT first)".into()))?;
30
31        let mut weak: Vec<(String, f64, f64, f64)> = Vec::new();
32        for (i, name) in fit.term_names.iter().enumerate() {
33            let coeff = fit.coefficients[i];
34            let sigma = fit.sigma[i];
35            if sigma > 0.0 {
36                let significance = (coeff / sigma).abs();
37                if significance < threshold {
38                    weak.push((name.clone(), coeff, sigma, significance));
39                }
40            }
41        }
42
43        if weak.is_empty() {
44            return Ok(CommandOutput::Text(format!(
45                "No weak terms (all significance >= {:.1})",
46                threshold
47            )));
48        }
49
50        let mut output = format!("Weak terms (significance < {:.1}):\n", threshold);
51        for (name, coeff, sigma, sig) in &weak {
52            output += &format!(
53                "  {}:  coeff={:.1}  sigma={:.1}  sig={:.2}\n",
54                name, coeff, sigma, sig
55            );
56        }
57
58        if remove {
59            for (name, _, _, _) in &weak {
60                session.model.remove_term(name);
61            }
62            session.last_fit = None;
63            output += &format!("\nRemoved {} terms", weak.len());
64        } else {
65            output += &format!("\nUse MVET {:.1} R to remove", threshold);
66        }
67
68        Ok(CommandOutput::Text(output))
69    }
70}