bubbles 4.2.0

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

pub struct FrameParams {
    pub monitor: f64,
    pub transmission: f64,
    pub photo: f64,
}

impl ops::AddAssign<&FrameParams> for FrameParams {
    fn add_assign(&mut self, rhs: &FrameParams) {
        self.monitor += rhs.monitor;
        self.transmission += rhs.transmission;
        self.photo += rhs.photo;
    }
}

impl ops::DivAssign<f64> for FrameParams {
    fn div_assign(&mut self, rhs: f64) {
        self.monitor /= rhs;
        self.transmission /= rhs;
        self.photo /= rhs;
    }
}

#[derive(Frame)]
pub struct AverageFrame {
    pub array: Array,
    pub fp: FrameParams,
    pub done: usize,
    pub header: Header,
}

impl AverageFrame {
    pub fn new(frame: &mut Box<dyn Frame>, fp: FrameParams) -> AverageFrame {
        AverageFrame {
            array: frame.take_array(),
            fp,
            done: 1,
            header: Header::new(),
        }
    }

    pub fn append(&mut self, frame: &Box<dyn Frame>, fp: &FrameParams) -> FrameResult<()> {
        let mut array = &mut self.array;
        if array != frame.array() {
            return Err(FrameError::FormatError(
                "inconsistent array dimensions".into(),
            ));
        }
        array += frame.array();
        self.fp += fp;
        self.done += 1;
        Ok(())
    }

    pub fn average(&mut self, coefficient: f64) {
        let done = self.done as f64;
        let mut array = &mut self.array;
        array *= coefficient / done;
        self.fp /= done;
        self.header.insert(
            cbf::KEY_FLUX.to_string(),
            HeaderEntry::Float(self.fp.monitor),
        );
        self.header.insert(
            KEY_DUBBLE_MONITOR.to_string(),
            HeaderEntry::Float(self.fp.monitor),
        );
        self.header.insert(
            KEY_DUBBLE_PHOTO.to_string(),
            HeaderEntry::Float(self.fp.photo),
        );
    }
}