pub mod comparison;
pub mod composite;
pub mod correlogram;
pub mod evoked;
pub mod firing;
pub mod isolation;
pub mod rate;
pub mod refractory;
pub use crate::core::template::{UnitQualityLabel, WaveformTemplate, compute_mean_template};
pub use comparison::{
PairwiseTrainMatch, SortingComparison, UnitMatchSummary, compare_sortings,
compare_spike_trains,
};
pub use composite::{composite_score, firing_range, sort_composite_score, CompositeScore, CompositeScoreOptions};
pub use correlogram::{Correlogram, compute_autocorrelogram, compute_crosscorrelogram};
pub use evoked::{
MepMetrics, PsthResult, StimulusTriggeredAverage, compute_psth,
compute_stimulus_triggered_average, quantify_mep,
};
pub use firing::{
IsiMetrics, compute_amplitude_cutoff, compute_amplitude_cutoff_with, compute_isi_violations,
compute_llobet_contamination, compute_presence_ratio, count_refractory_violations, isi_histogram,
};
pub use isolation::{
compute_d_prime, compute_isolation_distance, compute_silhouette_score, compute_snr,
};
pub use refractory::{acg_refractory, ccg_refractory, refractory_stats, RefractoryOptions, RefractoryStats};
pub use rate::{
BurstEpoch, FiringRateCurve, compute_instantaneous_firing_rate, detect_burst_epochs,
};
pub const DEFAULT_ISI_THRESHOLD_MS: f64 = 1.5;
pub const DEFAULT_MIN_ISI_MS: f64 = 0.0;
pub const DEFAULT_PRESENCE_BIN_SEC: f64 = 60.0;
pub const DEFAULT_PRESENCE_MEAN_FR_RATIO: f64 = 0.0;
pub const DEFAULT_CORRELOGRAM_BIN_MS: f32 = 1.0;
pub const DEFAULT_CORRELOGRAM_WINDOW_MS: f32 = 50.0;
pub const DEFAULT_MATCH_DELTA_MS: f64 = 0.4;
pub const DEFAULT_AGREEMENT_THRESHOLD: f32 = 0.5;
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QualityCriteria {
pub refractory_ms: f64,
pub censored_ms: f64,
pub min_spikes: usize,
pub noise_snr_threshold: f32,
pub sua_snr_threshold: f32,
pub max_isi_violation_ratio: f64,
}
impl Default for QualityCriteria {
fn default() -> Self {
Self {
refractory_ms: DEFAULT_ISI_THRESHOLD_MS,
censored_ms: DEFAULT_MIN_ISI_MS,
min_spikes: 3,
noise_snr_threshold: 1.5,
sua_snr_threshold: 3.0,
max_isi_violation_ratio: 0.5,
}
}
}
impl QualityCriteria {
pub const PHY: Self = Self {
refractory_ms: 2.0,
censored_ms: 0.0,
min_spikes: 3,
noise_snr_threshold: 1.5,
sua_snr_threshold: 3.0,
max_isi_violation_ratio: 0.5,
};
pub fn classify(&self, num_spikes: usize, snr: f32, isi_violation_ratio: f64) -> UnitQualityLabel {
if num_spikes < self.min_spikes {
return UnitQualityLabel::Noise;
}
if !snr.is_finite() {
return UnitQualityLabel::Unsorted;
}
if snr < self.noise_snr_threshold {
UnitQualityLabel::Noise
} else if (isi_violation_ratio.is_nan() || isi_violation_ratio < self.max_isi_violation_ratio)
&& snr >= self.sua_snr_threshold
{
UnitQualityLabel::SingleUnit
} else {
UnitQualityLabel::MultiUnit
}
}
}