meas: finish porting to a concrete type.
this will in future let me more easily test each individual measurement type
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::geom::{Meters, Region, Torus, WorldRegion};
|
||||
use crate::real::{Real as _, ToFloat as _};
|
||||
use crate::cross::vec::Vec3;
|
||||
use crate::cross::vec::{Vec3, Vec3u};
|
||||
use crate::sim::AbstractSim;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
@@ -15,11 +15,11 @@ pub fn as_dyn_measurements<S, M: AbstractMeasurement<S>>(meas: &[M]) -> Vec<&dyn
|
||||
|
||||
|
||||
/// combine several measurements
|
||||
pub fn eval_multiple_kv<S>(state: &S, meas: &[&dyn AbstractMeasurement<S>]) -> Vec<Measurement>
|
||||
pub fn eval_multiple_kv<S>(state: &S, meas: &[&dyn AbstractMeasurement<S>]) -> Vec<Measurement> {
|
||||
meas.into_iter().flat_map(|m| m.key_value(state).into_iter()).collect()
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum MeasurementValue {
|
||||
Field(Vec3<f32>),
|
||||
Float(f32),
|
||||
@@ -48,7 +48,7 @@ impl From<Vec3u> for MeasurementValue {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Measurement {
|
||||
name: String,
|
||||
value: MeasurementValue,
|
||||
@@ -59,7 +59,7 @@ pub struct Measurement {
|
||||
impl Measurement {
|
||||
fn new<T: Into<MeasurementValue>>(name: &str, value: T, unit: &str) -> Self {
|
||||
Self {
|
||||
name.to_owned(),
|
||||
name: name.to_owned(),
|
||||
value: value.into(),
|
||||
unit: unit.to_owned(),
|
||||
}
|
||||
@@ -67,6 +67,30 @@ impl Measurement {
|
||||
fn new_unitless<T: Into<MeasurementValue>>(name: &str, value: T) -> Self {
|
||||
Self::new(name, value, "")
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn str_value(&self) -> String {
|
||||
use MeasurementValue::*;
|
||||
let val = match self.value {
|
||||
Field(v) => v.to_string(),
|
||||
Float(f) => f.to_string(),
|
||||
Int(u) => u.to_string(),
|
||||
Dim(v) => format!("{}x{}x{}", v.x(), v.y(), v.z()),
|
||||
};
|
||||
format!("{}{}", val, self.unit)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> AbstractMeasurement<S> for Measurement {
|
||||
fn eval(&self, _state: &S) -> String {
|
||||
format!("{}: {}", self.name, self.str_value())
|
||||
}
|
||||
fn key_value(&self, _state: &S) -> Vec<Measurement> {
|
||||
vec![self.clone()]
|
||||
}
|
||||
}
|
||||
|
||||
enum SiScale {
|
||||
@@ -149,7 +173,7 @@ impl<S: AbstractSim> AbstractMeasurement<S> for Time {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
format!("{} (step {})", SiScale::format_short(state.time(), "s"), state.step_no())
|
||||
}
|
||||
fn key_value(&self, state: &S) -> Vec<Measurement>
|
||||
fn key_value(&self, state: &S) -> Vec<Measurement> {
|
||||
vec![
|
||||
Measurement::new_unitless("step", state.step_no()),
|
||||
Measurement::new("time", state.time(), "s"),
|
||||
@@ -166,7 +190,7 @@ impl<S: AbstractSim> AbstractMeasurement<S> for Meta {
|
||||
}
|
||||
fn key_value(&self, state: &S) -> Vec<Measurement> {
|
||||
vec![
|
||||
Measurement::new_unitless("dim", state.dim()),
|
||||
Measurement::new_unitless("dim", state.size().0),
|
||||
Measurement::new("feature_size", state.feature_size(), "m"),
|
||||
]
|
||||
}
|
||||
@@ -202,7 +226,7 @@ impl<S: AbstractSim> AbstractMeasurement<S> for Volume {
|
||||
}
|
||||
fn key_value(&self, state: &S) -> Vec<Measurement> {
|
||||
vec![
|
||||
Measurement::new(&format!("Vol({})", self.name), self.data(), "um^3"),
|
||||
Measurement::new(&format!("Vol({})", self.name), self.data(state), "um^3"),
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -416,9 +440,9 @@ impl<S: AbstractSim> AbstractMeasurement<S> for MagneticLoop {
|
||||
fn key_value(&self, state: &S) -> Vec<Measurement> {
|
||||
let (mean_directed_m, mean_directed_b, mean_directed_h) = self.data(state);
|
||||
vec![
|
||||
Measurement::new_unitless(&format!("M({})", self.name), mean_directed_current_m),
|
||||
Beasurement::new_unitless(&format!("B({})", self.name), mean_directed_current_b),
|
||||
Beasurement::new_unitless(&format!("H({})", self.name), mean_directed_current_h),
|
||||
Measurement::new_unitless(&format!("M({})", self.name), mean_directed_m),
|
||||
Measurement::new_unitless(&format!("B({})", self.name), mean_directed_b),
|
||||
Measurement::new_unitless(&format!("H({})", self.name), mean_directed_h),
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -520,7 +544,7 @@ impl<S: AbstractSim> AbstractMeasurement<S> for MagnetizationAt {
|
||||
fn key_value(&self, state: &S) -> Vec<Measurement> {
|
||||
let m = state.sample(self.0).m();
|
||||
vec![
|
||||
Measurement::new_unitless(&format!("M{}", loc(self.0)), m)
|
||||
Measurement::new_unitless(&format!("M{}", loc(self.0)), m.cast())
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -538,7 +562,7 @@ impl<S: AbstractSim> AbstractMeasurement<S> for MagneticFluxAt {
|
||||
let b = state.sample(self.0).b();
|
||||
vec![
|
||||
Measurement::new_unitless(
|
||||
&format!("B{}", loc(self.0)), b
|
||||
&format!("B{}", loc(self.0)), b.cast()
|
||||
)
|
||||
]
|
||||
}
|
||||
@@ -557,7 +581,7 @@ impl<S: AbstractSim> AbstractMeasurement<S> for MagneticStrengthAt {
|
||||
let h = state.sample(self.0).h();
|
||||
vec![
|
||||
Measurement::new_unitless(
|
||||
&format!("H{}", loc(self.0)), h
|
||||
&format!("H{}", loc(self.0)), h.cast()
|
||||
)
|
||||
]
|
||||
}
|
||||
@@ -575,7 +599,7 @@ impl<S: AbstractSim> AbstractMeasurement<S> for ElectricField {
|
||||
let e = state.sample(self.0).e();
|
||||
vec![
|
||||
Measurement::new_unitless(
|
||||
&format!("E{}", loc(self.0)), e
|
||||
&format!("E{}", loc(self.0)), e.cast()
|
||||
)
|
||||
]
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ use crate::geom::Index;
|
||||
use crate::real::ToFloat as _;
|
||||
use crate::cross::vec::{Vec2, Vec3};
|
||||
use crate::sim::{AbstractSim, GenericSim, Sample};
|
||||
use crate::meas::{self, AbstractMeasurement};
|
||||
use crate::meas::{self, AbstractMeasurement, Measurement};
|
||||
use crossterm::{cursor, QueueableCommand as _};
|
||||
use crossterm::style::{style, Color, PrintStyledContent, Stylize as _};
|
||||
use font8x8::{BASIC_FONTS, GREEK_FONTS, UnicodeFonts as _};
|
||||
@@ -592,7 +592,7 @@ pub struct SerializedFrame<S> {
|
||||
pub state: S,
|
||||
/// although not generally necessary to load the sim, saving the measurements is beneficial for
|
||||
/// post-processing.
|
||||
pub measurements: Vec<meas::Evaluated>,
|
||||
pub measurements: Vec<Measurement>,
|
||||
}
|
||||
|
||||
impl<S: AbstractSim> SerializedFrame<S> {
|
||||
@@ -633,7 +633,7 @@ impl SerializerRenderer {
|
||||
}
|
||||
|
||||
impl SerializerRenderer {
|
||||
fn serialize<S: AbstractSim + Serialize>(&self, state: &S, measurements: Vec<meas::Evaluated>) {
|
||||
fn serialize<S: AbstractSim + Serialize>(&self, state: &S, measurements: Vec<Measurement>) {
|
||||
let frame = SerializedFrame {
|
||||
state,
|
||||
measurements,
|
||||
@@ -656,9 +656,9 @@ impl<S: AbstractSim + Serialize> Renderer<S> for SerializerRenderer {
|
||||
}
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement<S>], _config: RenderConfig) {
|
||||
if self.prefer_generic {
|
||||
self.serialize(&state.to_generic(), meas::eval_to_vec(state, measurements));
|
||||
self.serialize(&state.to_generic(), meas::eval_multiple_kv(state, measurements));
|
||||
} else {
|
||||
self.serialize(state, meas::eval_to_vec(state, measurements));
|
||||
self.serialize(state, meas::eval_multiple_kv(state, measurements));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -732,13 +732,13 @@ impl<S: AbstractSim> Renderer<S> for CsvRenderer {
|
||||
file.set_len(0).unwrap();
|
||||
let mut writer = csv::Writer::from_writer(BufWriter::new(file));
|
||||
// write the header
|
||||
writer.write_record(row.keys()).unwrap();
|
||||
writer.write_record(row.iter().map(|m| m.name())).unwrap();
|
||||
writer
|
||||
}
|
||||
},
|
||||
CsvState::Writing(writer) => writer,
|
||||
};
|
||||
writer.write_record(row.values()).unwrap();
|
||||
writer.write_record(row.iter().map(|m| m.str_value())).unwrap();
|
||||
writer.flush().unwrap();
|
||||
*lock = Some(CsvState::Writing(writer));
|
||||
}
|
||||
|
@@ -15,13 +15,13 @@ fn main() {
|
||||
|
||||
let mut frame = cache.load_first();
|
||||
for meas in frame.measurements() {
|
||||
print!("\"{}\",", meas.key());
|
||||
print!("\"{}\",", meas.name());
|
||||
}
|
||||
println!("");
|
||||
|
||||
loop {
|
||||
for meas in frame.measurements() {
|
||||
print!("\"{}\",", meas.value());
|
||||
print!("\"{}\",", meas.str_value());
|
||||
}
|
||||
println!("");
|
||||
|
||||
|
@@ -36,7 +36,7 @@ pub struct Frame {
|
||||
}
|
||||
|
||||
impl Frame {
|
||||
pub fn measurements(&self) -> &[meas::Evaluated] {
|
||||
pub fn measurements(&self) -> &[meas::Measurement] {
|
||||
&*self.data.measurements
|
||||
}
|
||||
pub fn sim(&self) -> &GenericSim<f32> {
|
||||
|
Reference in New Issue
Block a user