bubbles 3.1.1

Bubble integration server for powder diffraction
use crate::utils::{KEY_DUBBLE_MONITOR, KEY_DUBBLE_PHOTO};
use cryiorust::cbf;
use cryiorust::frame::{Array, Frame, Header, HeaderEntry};

pub struct FrameToAverage<'a> {
    pub frame: Box<dyn Frame>,
    pub name: &'a str,
    pub transmission: f64,
    pub monitor: f64,
    pub photo: f64,
}

impl<'a> FrameToAverage<'a> {
    pub fn new(frame: Box<dyn Frame>, name: &'a str) -> FrameToAverage<'a> {
        FrameToAverage {
            frame,
            name,
            transmission: 0.0,
            monitor: 0.0,
            photo: 0.0,
        }
    }
}

pub struct AveragedFrame {
    pub array: Array,
    pub monitor: f64,
    pub transmission: f64,
    pub photo: f64,
    pub done: usize,
    pub errors: Vec<String>,
    pub header: Header,
}

impl AveragedFrame {
    pub fn new(frames: &[FrameToAverage], coefficient: f64) -> AveragedFrame {
        let (dim1, dim2) = frames[0].frame.array().dims();
        let mut af = AveragedFrame {
            array: Array::with_data(dim1, dim2, vec![0.; dim1 * dim2]),
            monitor: 0.0,
            transmission: 0.0,
            photo: 0.0,
            done: 0,
            errors: vec![],
            header: Header::new(),
        };
        let mut array = &mut af.array;
        for frame in frames {
            if frame.frame.array() != array {
                af.errors
                    .push(format!("File {} has different dimensions", frame.name));
                continue;
            }
            array += frame.frame.array();
            af.transmission += frame.transmission;
            af.monitor += frame.monitor;
            af.photo += frame.photo;
            af.done += 1;
        }
        if af.done > 0 {
            let done = af.done as f64;
            array *= coefficient / done;
            af.transmission /= done;
            af.monitor /= done;
            af.photo /= done;
        }
        af.header
            .insert(cbf::KEY_FLUX.to_string(), HeaderEntry::Float(af.monitor));
        af.header.insert(
            KEY_DUBBLE_MONITOR.to_string(),
            HeaderEntry::Float(af.monitor),
        );
        af.header
            .insert(KEY_DUBBLE_PHOTO.to_string(), HeaderEntry::Float(af.photo));
        af
    }

    pub fn set_array(&mut self, array: Array) {
        self.array = array;
    }
}

impl Frame for AveragedFrame {
    fn array(&self) -> &Array {
        &self.array
    }

    fn header(&self) -> &Header {
        &self.header
    }

    fn header_mut(&mut self) -> &mut Header {
        &mut self.header
    }

    fn array_mut(&mut self) -> &mut Array {
        &mut self.array
    }

    fn set_array(&mut self, array: Array) {
        self.set_array(array);
    }
}