Skip to main content

fpm_rs/tabular/tables/
mod.rs

1mod algorithm_metrics;
2mod benchmark;
3mod calibration;
4mod diagnostics;
5mod evaluation;
6mod history;
7mod summary;
8
9use polars::prelude::DataFrame;
10
11pub use algorithm_metrics::algorithm_metrics_dataframe;
12pub use benchmark::{
13    benchmark_artifacts_dataframe, benchmark_frames_dataframe, benchmark_metadata_dataframe,
14    benchmark_runs_dataframe,
15};
16pub use calibration::{frame_calibration_dataframe, illumination_calibration_dataframe};
17pub use diagnostics::{
18    frame_diagnostics_dataframe, iteration_diagnostics_dataframe, metadata_dataframe,
19    raw_frame_statistics_dataframe, scalar_diagnostics_dataframe,
20};
21pub use evaluation::frame_evaluation_dataframe;
22pub use history::history_dataframe;
23pub use summary::{COMMON_RUN_COLUMNS, summary_dataframe};
24
25use crate::{
26    Result, diagnostics::ReconstructionDiagnostics, evaluation::ReconstructionEvaluation,
27    reconstruction::ReconstructionResult,
28};
29
30/// All stable reconstruction tables materialized together on explicit request.
31pub struct ReconstructionTables {
32    /// Required one-row run summary.
33    pub summary: DataFrame,
34    /// Required one-row-per-completed-iteration trace.
35    pub history: DataFrame,
36    /// Optional algorithm-specific scalar metrics.
37    pub algorithm_metrics: Option<DataFrame>,
38    /// Optional convergence diagnostics by iteration.
39    pub iteration_diagnostics: Option<DataFrame>,
40    /// Optional comparison metrics by frame and iteration.
41    pub frame_diagnostics: Option<DataFrame>,
42    /// Optional raw measured-intensity statistics by frame.
43    pub raw_frame_statistics: Option<DataFrame>,
44    /// Optional predicted-versus-measured evaluation by frame.
45    pub frame_evaluation: Option<DataFrame>,
46    /// Optional per-source Fourier-grid calibration corrections.
47    pub illumination_calibration: Option<DataFrame>,
48    /// Optional acquisition-frame gains and backgrounds.
49    pub frame_calibration: Option<DataFrame>,
50    /// Optional key/value scalar diagnostics.
51    pub scalar_diagnostics: Option<DataFrame>,
52    /// Optional key/value string metadata.
53    pub metadata: Option<DataFrame>,
54}
55
56/// Materializes all required and non-empty optional tables for one result and run ID.
57pub fn reconstruction_tables(
58    run_id: &str,
59    result: &ReconstructionResult,
60    diagnostics: Option<&ReconstructionDiagnostics>,
61    evaluation: Option<&ReconstructionEvaluation>,
62) -> Result<ReconstructionTables> {
63    Ok(ReconstructionTables {
64        summary: summary_dataframe(run_id, result)?,
65        history: history_dataframe(run_id, &result.trace)?,
66        algorithm_metrics: (!result.trace.algorithm_metrics.is_empty())
67            .then(|| algorithm_metrics_dataframe(run_id, &result.trace))
68            .transpose()?,
69        iteration_diagnostics: diagnostics
70            .filter(|value| !value.iteration_diagnostics.is_empty())
71            .map(|value| iteration_diagnostics_dataframe(run_id, value))
72            .transpose()?,
73        frame_diagnostics: diagnostics
74            .filter(|value| !value.frame_diagnostics.is_empty())
75            .map(|value| frame_diagnostics_dataframe(run_id, value))
76            .transpose()?,
77        raw_frame_statistics: diagnostics
78            .filter(|value| !value.raw_frame_statistics.is_empty())
79            .map(|value| raw_frame_statistics_dataframe(run_id, value))
80            .transpose()?,
81        frame_evaluation: evaluation
82            .and_then(|value| value.intensity.as_ref())
83            .filter(|value| !value.per_frame.is_empty())
84            .map(|value| frame_evaluation_dataframe(run_id, value))
85            .transpose()?,
86        illumination_calibration: result
87            .calibrated_illumination
88            .as_ref()
89            .map(|_| illumination_calibration_dataframe(run_id, result))
90            .transpose()?,
91        frame_calibration: (result.recovered_frame_gains.is_some()
92            || result.recovered_background.is_some())
93        .then(|| frame_calibration_dataframe(run_id, result))
94        .transpose()?,
95        scalar_diagnostics: (!result.scalar_diagnostics.is_empty())
96            .then(|| scalar_diagnostics_dataframe(run_id, &result.scalar_diagnostics))
97            .transpose()?,
98        metadata: (!result.metadata.is_empty())
99            .then(|| metadata_dataframe(run_id, &result.metadata))
100            .transpose()?,
101    })
102}