Skip to main content

fpm_rs/callbacks/
context.rs

1use crate::{
2    Result,
3    diagnostics::{DiagnosticRequest, Diagnostics, ReconstructionHistory},
4    model::ImagePlaneModel,
5    reconstruction::{ReconstructionResult, ReconstructionState},
6};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum CallbackAction {
10    Continue,
11    Stop,
12}
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub enum CallbackHook {
16    Start,
17    FrameEnd,
18    IterationEnd,
19    Finish,
20}
21
22pub struct StepContext<'a> {
23    pub iteration: usize,
24    pub frame_index: Option<usize>,
25    pub batch_index: Option<usize>,
26    pub state: &'a ReconstructionState,
27    pub diagnostics: &'a Diagnostics,
28    pub history: &'a ReconstructionHistory,
29    pub model: &'a ImagePlaneModel,
30    pub problem_name: Option<&'a str>,
31}
32
33pub trait Callback: Send {
34    fn requires(&self) -> Vec<DiagnosticRequest> {
35        Vec::new()
36    }
37
38    /// Requests diagnostics for a specific hook. Built-in periodic callbacks
39    /// override this to avoid computing snapshots on inactive iterations.
40    fn requires_for(&self, _hook: CallbackHook, _iteration: usize) -> Vec<DiagnosticRequest> {
41        self.requires()
42    }
43
44    fn on_start(&mut self, _context: &StepContext<'_>) -> Result<CallbackAction> {
45        Ok(CallbackAction::Continue)
46    }
47
48    /// Runs once for every completed frame when frame callbacks are enabled.
49    /// For multi-frame algorithms, all frames in a batch observe the same
50    /// post-batch state while `frame_index` and natural loss remain per-frame.
51    fn on_frame_end(&mut self, _context: &StepContext<'_>) -> Result<CallbackAction> {
52        Ok(CallbackAction::Continue)
53    }
54
55    fn on_iteration_end(&mut self, _context: &StepContext<'_>) -> Result<CallbackAction> {
56        Ok(CallbackAction::Continue)
57    }
58
59    fn on_finish(&mut self, _result: &ReconstructionResult) -> Result<()> {
60        Ok(())
61    }
62}