use std::fmt::Display; use std::ops::Range; use uom::fmt::DisplayStyle::Abbreviation; use uom::num_traits::Zero; use uom::si::energy::joule; use uom::si::{ f64::{Energy, Length}, length::nanometer, }; pub struct Spectrum { start: Length, dlambda: Length, data: Vec<Energy>, } impl Spectrum { pub fn new(range: Range<Length>, resolution: Length) -> Self { Self { start: range.start, dlambda: resolution, data: vec![Energy::zero(); ((range.end-range.start)/resolution).value as usize] } } pub fn set_single_peak(&mut self, wavelength: Length, energy: Energy) { let index=((wavelength-self.start) / self.dlambda).value as usize; self.data[index]=energy; } pub fn total_energy(&self) -> Energy { let mut total_energy=Energy::zero(); for data in self.data.iter() { total_energy+=*data; } total_energy } } impl Display for Spectrum { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let fmt_length = Length::format_args(nanometer, Abbreviation); let fmt_energy = Energy::format_args(joule, Abbreviation); for value in self.data.iter().enumerate() { let wavelength=self.start + value.0 as f64 * self.dlambda; write!( f, "{:7.2} -> {}\n", fmt_length.with(wavelength), fmt_energy.with(*value.1) ).unwrap(); } write!(f, "\nTotal energy: {}",fmt_energy.with(self.total_energy())) } }