use crate::{
errors::Error,
headers::{File, RecordType},
parsers::ptu,
tttr_tools::colored_circular_buffer::CCircularBuffer,
{Click, TTTRFile, TTTRStream},
};
use std::fmt::Debug;
use ndarray::Array2;
const MAX_BUFFER_SIZE: usize = 4096;
struct G3<P: TTTRStream + Iterator> {
pub click_stream: P,
pub params: G3Params,
}
pub struct G3Result {
pub t: Vec<f64>,
pub hist: Array2<u64>,
}
#[derive(Debug, Copy, Clone)]
pub struct G3Params {
pub channel_1: i32,
pub channel_2: i32,
pub channel_3: i32,
pub correlation_window: f64,
pub resolution: f64,
pub start_record: Option<usize>,
pub stop_record: Option<usize>,
}
impl<P: TTTRStream + Iterator> G3<P> {
fn compute(self) -> G3Result
where
<P as Iterator>::Item: Debug + Click,
{
let real_resolution = self.params.resolution.clone();
let n_bins = (self.params.correlation_window / self.params.resolution) as u64;
let correlation_window =
self.params.correlation_window / (self.click_stream.time_resolution());
let resolution = (correlation_window / (n_bins as f64)) as u64;
let correlation_window = n_bins * resolution;
let n_bins = n_bins * 2;
let central_bin = n_bins / 2;
let mut histogram = Array2::<u64>::zeros((n_bins as usize, n_bins as usize));
let mut click_buffer = CCircularBuffer::new(MAX_BUFFER_SIZE);
let relevant_channels: Vec<i32> = vec![
self.params.channel_1,
self.params.channel_2,
self.params.channel_3,
];
for click_1 in self.click_stream.into_iter() {
let (&tof1, &chn1) = (click_1.tof(), click_1.channel());
if !relevant_channels.contains(&chn1) {
continue;
}
for click_2 in click_buffer.iter() {
let &(tof2, chn2) = click_2;
let delta12 = tof1 - tof2;
if delta12 > correlation_window {
break;
}
for click_3 in click_buffer.iter() {
let &(tof3, chn3) = click_3;
if tof3 >= tof2 {
continue;
}
let delta23 = tof2 - tof3;
let delta13 = tof1 - tof3;
if chn1 == self.params.channel_1 {
if chn2 == self.params.channel_2 {
if chn3 == self.params.channel_3 {
let tau1 = delta12;
let tau2 = delta13;
if tau1 < correlation_window && tau2 < correlation_window {
let idx1 = central_bin - tau1 / resolution - 1;
let idx2 = central_bin - tau2 / resolution - 1;
histogram[[idx1 as usize, idx2 as usize]] += 1;
} else {
break;
}
}
} else if chn2 == self.params.channel_3 {
if chn3 == self.params.channel_2 {
let tau1 = delta13;
let tau2 = delta12;
if tau1 < correlation_window && tau2 < correlation_window {
let idx1 = central_bin - tau1 / resolution - 1;
let idx2 = central_bin - tau2 / resolution - 1;
histogram[[idx1 as usize, idx2 as usize]] += 1;
} else {
break;
}
}
}
} else if chn1 == self.params.channel_2 {
if chn2 == self.params.channel_1 {
if chn3 == self.params.channel_3 {
let tau1 = delta12;
let tau2 = delta23;
if tau1 < correlation_window && tau2 < correlation_window {
let idx1 = central_bin + tau1 / resolution;
let idx2 = central_bin - tau2 / resolution - 1;
histogram[[idx1 as usize, idx2 as usize]] += 1;
} else {
break;
}
}
} else if chn2 == self.params.channel_3 {
if chn3 == self.params.channel_1 {
let tau1 = delta13;
let tau2 = delta23;
if tau1 < correlation_window && tau2 < correlation_window {
let idx1 = central_bin + tau1 / resolution;
let idx2 = central_bin + tau2 / resolution;
histogram[[idx1 as usize, idx2 as usize]] += 1;
} else {
break;
}
}
}
} else if chn1 == self.params.channel_3 {
if chn2 == self.params.channel_1 {
if chn3 == self.params.channel_2 {
let tau1 = delta23;
let tau2 = delta12;
if tau1 < correlation_window && tau2 < correlation_window {
let idx1 = central_bin - tau1 / resolution - 1;
let idx2 = central_bin + tau2 / resolution;
histogram[[idx1 as usize, idx2 as usize]] += 1;
} else {
break;
}
}
} else if chn2 == self.params.channel_2 {
if chn3 == self.params.channel_1 {
let tau1 = delta23;
let tau2 = delta13;
if tau1 < correlation_window && tau2 < correlation_window {
let idx1 = central_bin + tau1 / resolution;
let idx2 = central_bin + tau2 / resolution;
histogram[[idx1 as usize, idx2 as usize]] += 1;
} else {
break;
}
}
}
}
}
}
click_buffer.push(tof1, chn1);
}
let t = (0..n_bins)
.map(|i| ((i as f64) - (central_bin as f64)) * real_resolution)
.collect::<Vec<f64>>();
G3Result {
t: t,
hist: histogram,
}
}
}
pub fn g3(f: &File, params: &G3Params) -> Result<G3Result, Error> {
let start_record = params.start_record;
let stop_record = params.stop_record;
match f {
File::PTU(x) => match x.record_type().unwrap() {
RecordType::PHT2 => {
let stream = ptu::streamers::PHT2Stream::new(x, start_record, stop_record)?;
let tt = G3 {
click_stream: stream,
params: *params,
};
Ok(tt.compute())
}
RecordType::HHT2_HH1 => {
let stream = ptu::streamers::HHT2_HH1Stream::new(x, start_record, stop_record)?;
let tt = G3 {
click_stream: stream,
params: *params,
};
Ok(tt.compute())
}
RecordType::HHT2_HH2 => {
let stream = ptu::streamers::HHT2_HH2Stream::new(x, start_record, stop_record)?;
let tt = G3 {
click_stream: stream,
params: *params,
};
Ok(tt.compute())
}
RecordType::HHT3_HH2 => {
let stream = ptu::streamers::HHT3_HH2Stream::new(x, start_record, stop_record)?;
let tt = G3 {
click_stream: stream,
params: *params,
};
Ok(tt.compute())
}
RecordType::NotImplemented => panic! {"Record type not implemented"},
},
}
}