use super::{Diffractive, Geometric, Model, WavefrontSensor};
use crate::{cu::Single, imaging::NoiseDataSheet, Cu, Mask, Propagation, Source};
pub struct ShackHartmann<S: Model> {
pub _c_: S,
pub n_side_lenslet: i32,
pub n_px_lenslet: i32,
pub d: f64,
pub n_sensor: i32,
pub n_centroids: i32,
pub centroids: Cu<Single>,
pub detector_noise_model: Option<NoiseDataSheet>,
}
impl<M: Model> WavefrontSensor for ShackHartmann<M> {
fn calibrate(&mut self, src: &mut Source, threshold: f64) {
<M as Model>::calibrate(&mut self._c_, src, threshold);
}
fn reset(&mut self) {
<M as Model>::reset(&mut self._c_);
}
fn process(&mut self) {
<M as Model>::process(&mut self._c_);
}
fn data(&mut self) -> Vec<f64> {
<M as Model>::data(&mut self._c_).into()
}
fn readout(&mut self) {
if let Some(noise_model) = self.detector_noise_model {
<M as Model>::readout(
&mut self._c_,
noise_model.exposure_time as f32,
noise_model.rms_read_out_noise as f32,
noise_model.n_background_photon as f32,
noise_model.noise_factor as f32,
);
}
}
fn frame(&self) -> Option<Vec<f32>> {
<M as Model>::frame(&self._c_)
}
fn n_frame(&self) -> usize {
<M as Model>::n_frame(&self._c_)
}
fn valid_lenslet_from(&mut self, wfs: &mut dyn WavefrontSensor) {
<M as Model>::valid_lenslet_from(&mut self._c_, wfs.valid_lenslet())
}
fn valid_lenslet(&mut self) -> &mut crate::mask {
<M as Model>::valid_lenslet(&mut self._c_)
}
fn n_valid_lenslet(&mut self) -> Vec<usize> {
let lenslet_mask: Vec<f32> = self.lenslet_mask().into();
lenslet_mask
.chunks(lenslet_mask.len() / self.n_sensor as usize)
.map(|x| {
x.iter().fold(0usize, |mut a, &x| {
if x > 0f32 {
a += 1;
}
a
})
})
.collect()
}
fn left_multiply(
&self,
_calibration: &crate::wavefrontsensor::Calibration,
) -> Option<Vec<f32>> {
todo!()
}
}
impl<M: Model> ShackHartmann<M> {
pub fn n_valid_lenslet(&mut self) -> usize {
<M as Model>::n_valid_lenslet(&mut self._c_)
}
pub fn lenslet_mask(&mut self) -> Cu<Single> {
<M as Model>::lenslet_mask(&mut self._c_)
}
pub fn lenslet_flux(&mut self) -> Cu<Single> {
<M as Model>::lenslet_flux(&mut self._c_)
}
pub fn set_valid_lenslet(&mut self, lenslet_mask: &[i32]) {
<M as Model>::set_valid_lenslet(&mut self._c_, lenslet_mask);
}
pub fn filter(&mut self, lenslet_mask: &mut Mask) -> Cu<Single> {
<M as Model>::filter(&mut self._c_, lenslet_mask)
}
pub fn set_reference_slopes(&mut self, src: &mut Source) {
<M as Model>::set_reference_slopes(&mut self._c_, src)
}
pub fn as_mut_ptr(&mut self) -> &mut M {
&mut self._c_
}
pub fn guide_star_args(&self) -> (i32, f64, i32) {
(
self.n_sensor,
self.d * self.n_side_lenslet as f64,
self.n_px_lenslet * self.n_side_lenslet + 1,
)
}
pub fn new_guide_stars(&self) -> Source {
Source::new(
self.n_sensor,
self.d * self.n_side_lenslet as f64,
self.n_px_lenslet * self.n_side_lenslet + 1,
)
}
}
impl ShackHartmann<Geometric> {
pub fn fold_into(&mut self, data: &mut Cu<Single>, lenslet_mask: &mut Mask) {
unsafe {
self._c_
.folded_slopes(data.as_mut_ptr(), lenslet_mask.as_mut_prt());
}
}
}
impl<S: Model> Drop for ShackHartmann<S> {
fn drop(&mut self) {
self._c_.drop();
}
}
impl<M: Model> Propagation for ShackHartmann<M> {
fn propagate(&mut self, src: &mut Source) {
<M as Model>::propagate(&mut self._c_, src);
}
fn time_propagate(&mut self, _secs: f64, src: &mut Source) {
self.propagate(src)
}
}
impl ShackHartmann<Diffractive> {
pub fn detector_resolution(&self) -> (usize, usize) {
let res = (self._c_.camera.N_PX_CAMERA * self._c_.camera.N_SIDE_LENSLET) as usize;
(res, res)
}
}
impl From<ShackHartmann<Geometric>> for Source {
fn from(item: ShackHartmann<Geometric>) -> Self {
item.new_guide_stars()
}
}
impl From<ShackHartmann<Diffractive>> for Source {
fn from(item: ShackHartmann<Diffractive>) -> Self {
item.new_guide_stars()
}
}