Skip to main content

dspk_synapse/
lib.rs

1//! Neural spike detection, spatial deduplication, waveform alignment, feature extraction,
2//! localization, drift estimation, kriging, clustering, template matching, correlograms,
3//! Allen/IBL quality metrics, sorter comparison, and neural frequency bands.
4//!
5//! Recording and sorting file formats (NWB, SpikeGLX, mtscomp, Phy, `.sorting.zarr`) and probe
6//! geometry (layouts, presets, nearest-site queries) are in [`io`].
7//!
8//! # Where things are
9//!
10//! | Step | Module | Start with |
11//! |---|---|---|
12//! | Find spikes | [`detection`] | [`detect_spikes_threshold`], [`deduplicate_spikes_spatial`] |
13//! | Whole recordings, bounded memory | [`streaming`] | [`streaming::StreamingDetector`] |
14//! | Cut waveforms | [`extraction`] | [`extract_snippets`] |
15//! | Features | [`features`] | [`PcaFeatureEmbedder`] |
16//! | Positions and drift | [`spatial`] | [`PeakLocalizer`] implementations |
17//! | Cluster into units | [`sorting`] | k-means, GMM, HDBSCAN, bipartite modularity |
18//! | Quality and comparison | [`metrics`] | ISI violations, presence, amplitude cutoff; sorter agreement |
19//! | Results on disk | [`storage`] | [`SortingOutput`] (Phy, Zarr, NWB) |
20//! | Recordings, probes, sorting files | [`io`] | [`io::open`], [`io::probe`] |
21//!
22//! Complete sorters are separate crates, one per upstream project, each under its upstream's
23//! licence: `dspk-sorter-kilosort` (Kilosort4, EMUsort), `dspk-sorter-ms5` (MountainSort 5),
24//! `dspk-sorter-si` (SpyKING CIRCUS 2, Tridesclous 2). Pretrained models: `dspk-synapse-ml`.
25//!
26//! # Example
27//!
28//! Detect threshold crossings, then keep one spike per event: a spike seen on neighbouring
29//! channels is one spike, assigned to the channel where it is largest.
30//!
31//! ```
32//! use dspk_synapse::io::probe::{Position3D, SensorLayout, SensorSite};
33//! use dspk_synapse::{deduplicate_spikes_spatial, detect_spikes_threshold, SpikePolarity, ThresholdSpikeDetector};
34//!
35//! // 4 channels on a line, 20 µm apart
36//! let sites = (0..4).map(|c| SensorSite::new(c, Position3D::new(0.0, 20.0 * c as f32, 0.0), 0)).collect();
37//! let layout = SensorLayout::new("linear", sites);
38//!
39//! // Small noise, and one spike at sample 500: −80 µV on channel 1, −40 µV on its neighbour
40//! let (channels, samples) = (4, 1_000);
41//! let mut x: Vec<f32> = (0..channels * samples).map(|i| ((i * 7_919) % 200) as f32 / 100.0 - 1.0).collect();
42//! x[samples + 500] = -80.0;
43//! x[2 * samples + 500] = -40.0;
44//!
45//! // Troughs below −5 σ (σ per channel, from the median absolute deviation), ≥ 1 ms apart at 30 kHz
46//! let settings = ThresholdSpikeDetector::new(5.0, 1.0, SpikePolarity::Negative);
47//! let crossings = detect_spikes_threshold(&x, channels, samples, 30_000.0, &settings);
48//! assert_eq!(crossings.len(), 2); // the same spike, on two channels
49//!
50//! // Crossings within 50 µm and 10 samples of a larger one belong to it
51//! let spikes = deduplicate_spikes_spatial(&crossings, &layout, 50.0, 10);
52//! assert_eq!(spikes.len(), 1);
53//! assert_eq!(spikes[0].primary_channel, 1);
54//! assert_eq!(spikes[0].participating_channels, vec![1, 2]);
55//! ```
56
57pub mod core;
58pub mod detection;
59pub mod extraction;
60pub mod features;
61pub mod io;
62pub mod metrics;
63pub mod provenance;
64pub mod sorter;
65pub mod sorting;
66pub mod spatial;
67pub mod storage;
68pub mod streaming;
69
70pub use core::{
71    DeduplicatedSpike, FeatureEmbedder, MatchedSpike, NeuralBand, PeakLocalizer, RecordingMeta,
72    SnippetBatch, SortedUnit, SortingOutput, SpikeDetector, SpikeEvent, SpikeMatcher,
73    UnitQualityLabel, WaveformDenoiser, WaveformSnippet, WaveformTemplate, compute_mean_template,
74    dense_waveform, pack_templates, unpack_template,
75};
76pub use detection::{
77    AdaptiveThresholdDetector, DistanceRule, MatchedFilterSpikeDetector, NeoSpikeDetector,
78    SpikePolarity, SpikeSpacing, ThresholdSpikeDetector, canonical_biphasic_prototype,
79    DedupNeighbours, compute_neo_energy, deduplicate_spikes_spatial, deduplicate_spikes_spatial_device,
80    detect_spikes_matched_filter, detect_spikes_threshold, detect_spikes_neo,
81    detect_spikes_threshold_with_sigma, detection_heights, estimate_noise_std, execute_detect_spikes_in_vram,
82};
83pub use extraction::{
84    execute_extract_sinc_in_vram, extract_snippet_batch,
85    extract_snippets, extract_snippets_single_channel, read_snippets,
86};
87pub use features::{
88    ConductionVelocityEstimate, PcaFeatureEmbedder, PpcaFeatureEmbedder, SpikeMorphology,
89    WaveletFeatureEmbedder, compute_morphology, estimate_hdemg_conduction_velocity,
90    extract_waveform_pca, compute_haar_dwt,
91};
92pub use metrics::{
93    BurstEpoch, Correlogram, FiringRateCurve, IsiMetrics, MepMetrics, PairwiseTrainMatch,
94    PsthResult, QualityCriteria, SortingComparison, StimulusTriggeredAverage, UnitMatchSummary,
95    compare_sortings, compare_spike_trains, compute_amplitude_cutoff,
96    AmplitudeCutoffOptions, compute_autocorrelogram, compute_crosscorrelogram,
97    compute_d_prime, compute_instantaneous_firing_rate, compute_isi_violations,
98    compute_isolation_distance, compute_llobet_contamination, compute_presence_ratio,
99    compute_psth, compute_silhouette_score, compute_snr, compute_stimulus_triggered_average,
100    count_refractory_violations, detect_burst_epochs, compute_isi_histogram, quantify_mep,
101};
102pub use sorting::{
103    ConvolutiveBssDecomposer, DensityPeaksResult, GmmClusterer, GmmCovarianceKind, GmmResult,
104    KdeMergeResult, MotorUnitPulseTrain, MatchingPursuitMatcher, cluster_density_peaks,
105    DensityPeaksOptions, KdeMergeOptions, cluster_gmm_bic, cluster_kde_merge,
106    compute_template_similarity_matrix, match_spikes_matching_pursuit,
107    suggest_template_merges, template_max_cosine_similarity,
108};
109pub use spatial::{
110    CenterOfMassLocalizer, DipoleEstimate, DipoleLocalizer, DriftEstimate, GridConvolutionLocalizer,
111    KRIGING_REGULARIZATION, MonopolarTriangulator, NonRigidDriftEstimate, TraceKriging,
112    compute_kriging_weight_matrix,
113    correct_snippet_batch_drift_kriging, correct_traces_drift_kriging, estimate_nonrigid_drift,
114    estimate_rigid_drift, localize_spike_center_of_mass, localize_spike_dipole,
115    localize_spike_grid_convolution, localize_spike_monopolar,
116};
117pub use streaming::{
118    BatchTemplateStats, SINC_RESAMPLE_MARGIN, StreamingDetectionConfig, StreamingDetectionResult,
119    StreamingDetector, TemplateAccumulator, execute_reduce_templates_in_vram,
120};
121pub use provenance::{ArtifactSource, Attributed, Paper, Provenance, ProvenanceKind, UpstreamCode};
122pub use storage::{
123    fill_similarity, load_nwb_units, load_phy_folder, load_sorting,
124    load_sorting_zarr, load_spikes, save_nwb_units, save_phy_folder, save_sorting,
125    save_sorting_zarr,
126};