pub mod center;
pub mod data;
pub mod output;
pub mod run;
pub mod tune;
pub(crate) fn show_image_view_with_value(ui: &mut rsplot::egui::Ui, view: &mut rsplot::ImageView) {
use rsplot::egui;
let value = view.value_changed();
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
value_readout(ui, value);
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
view.show(ui, None, None);
});
});
}
pub(crate) fn value_readout(ui: &mut rsplot::egui::Ui, value: Option<(f64, f64, f64)>) {
let text = match value {
Some((col, row, v)) => format!("value @ ({col:.0}, {row:.0}) = {v:.6}"),
None => "value @ —".to_owned(),
};
ui.label(text);
}
pub(crate) fn load_tiff_f32(path: &std::path::Path) -> anyhow::Result<(u32, u32, Vec<f32>)> {
let file = std::fs::File::open(path)?;
let mut dec = tiff::decoder::Decoder::new(std::io::BufReader::new(file))?;
let (w, h) = dec.dimensions()?;
match dec.read_image()? {
tiff::decoder::DecodingResult::F32(v) => Ok((w, h, v)),
_ => anyhow::bail!("not an f32 tiff"),
}
}
pub(crate) fn autoscale_viridis(data: &[f32]) -> rsplot::Colormap {
let (lo, hi) = robust_range(data);
rsplot::Colormap::viridis(lo, hi)
}
pub(crate) fn robust_range(data: &[f32]) -> (f64, f64) {
let mut finite: Vec<f32> = data.iter().copied().filter(|v| v.is_finite()).collect();
if finite.is_empty() {
return (0.0, 1.0);
}
let last = finite.len() - 1;
let ilo = last / 200; let ihi = last - ilo; let (_, lo, _) = finite.select_nth_unstable_by(ilo, f32::total_cmp);
let lo = *lo as f64;
let (_, hi, _) = finite.select_nth_unstable_by(ihi, f32::total_cmp);
let hi = *hi as f64;
if lo < hi { (lo, hi) } else { (0.0, 1.0) }
}
#[cfg(test)]
mod tests {
use super::robust_range;
#[test]
fn robust_range_clips_outliers() {
let mut data: Vec<f32> = (0..1000).map(|i| i as f32 / 1000.0).collect();
data.push(-1e6);
data.push(1e6);
let (lo, hi) = robust_range(&data);
assert!((0.0..0.05).contains(&lo), "lo = {lo}");
assert!((0.95..1.0).contains(&hi), "hi = {hi}");
}
#[test]
fn robust_range_degenerate_falls_back() {
assert_eq!(robust_range(&[]), (0.0, 1.0));
assert_eq!(robust_range(&[f32::NAN, f32::INFINITY]), (0.0, 1.0));
assert_eq!(robust_range(&[3.0; 16]), (0.0, 1.0));
}
}