SpikeInterface 0.105.0 release notes
Sept 21st 2026
Main changes:
Added
dartsort[Boussard2023] as an external sorter, run withrun_sorter("dartsort")(#2125)Generalized the chunking machinery: the recording-specific chunking code is now a reusable
TimeSeriesbase class, plusTimeSeriesChunkExecutor, so that any object chunkable along the time axis reuses the same parallelization and time handling (#4472, #4533)main_channel_indicesand themain_channel_idsorting property replacepeak_signacross postprocessing and metrics. The main channel is now set once on the analyzer, and sorters such as Kilosort anddartsortset it directly (#4624, #4672, #4733, #4725)SortingAnalyzergained alazymode, which keeps the spike vector and extension data as memmaps / Zarr arrays and defers loading until first access, and an independentread_onlymode (#4623, #4709, #4713) (see: Core module)Node pipelines can gather results straight to disk with
GatherToZarr, so pipeline node extension data no longer has to fit in memory (#4703)Reworked probe handling around
ProbeGroup:set_probeandset_probegroupnow act in place, while the newselect_channels_with_probeandselect_channels_with_probegroupreturn a new recording (#4465)Added the
detect_and_remove_artifactspreprocessor, with"envelope"and"saturation"detection, a separaterecording_to_detect, and"zeros"/"noise"/"apodization"silencing modes (#4539)Added antialiased decimation (
decimate(..., antialias=True)) and support for non-integer resampling rates (#4621)Added
SortingAnalyzer.split_by()to split an aggregated analyzer into per-group analyzers (#4660), andread_kilosort4_motionto build aMotionobject from a Kilosort4 output folder (#4518)Significant speedups in multi-segment synchrony metrics (#4770), duplicated spike removal (#4614), amplitude scalings (#4764, #4759, #4786), PCA over all spikes (#4488), NWB sorting loading (#4662), spike vector handling (#4618, #4695, #4581), and import time (#4641, #4644, #4650, #4651)
API and breaking changes:
Despite this long list of breaking changes, we have worked hard to try and preserve backwards compatibility for any objects saved using older versions of SpikeInterface. If you cannot load an object saved with an older version of SpikeInterface, please raise an issue.
Probe handling is reworked around
ProbeGroup, and the internal"contact_vector"property is gone (#4465). Previously saved objects and folders still load.
set_probe()andset_probegroup()always act in place and returnNone. Useselect_channels_with_probe()/select_channels_with_probegroup()to obtain a new recording (see: Core module)
set_probe()accepts a singleProbeonly; pass aProbeGrouptoset_probegroup()
reset_probe()–>remove_probe()
has_3d_locations()–>is_probe_3d(), andhas_channel_location()is now equivalent tohas_probe()
get_channel_locations()raises when no probe is attached, instead of falling back to a bare"location"propertyThe main channel of each unit is fixed when the analyzer is created and stored as the
main_channel_idsorting property.peak_signis also decided when the analyzer is created, and so is removed from the API (#4624)
get_template_extremum_channel()–>SortingAnalyzer.get_main_channels(),get_template_extremum_channel_peak_shift()–>get_template_peak_shift_on_main_channel(),get_template_extremum_amplitude()–>get_template_amplitude_on_main_channel(). The old names are deprecated shims
peak_signis no longer a valid parameter ofcompute_quality_metrics,compute_template_metrics,compute_spike_amplitudes,compute_spike_locationsandcompute_unit_locations. It is removed from the saved params of older analyzers on load
compute_snrs(sorting_analyzer, unit_ids, peak_sign, peak_mode, ...)–>compute_snrs(sorting_analyzer, unit_ids, method), and thesnrmetric paramspeak_sign/peak_mode–>method
get_template_amplitudes(..., mode=...)–>peak_mode=...
compute_sparsity()and theChannelSparsity.from_*constructors takepeak_sign=None/amplitude_mode=Noneby default. With an analyzer they must stayNone; with aTemplatesobject they are now mandatory.amplitude_modealso moved earlier in the positional order ofcompute_sparsity()
estimate_sparsity()now defaults topeak_sign="both"instead of"neg", which changes results silently
peak_signis removed fromremove_redundant_units(),export_report()andplot_unit_depths()
sorting_to_peaks(sorting, extremum_channel_inds, dtype)–>sorting_to_peaks(sorting, main_channel_indices, dtype), taking an array rather than a dict, andSpikeRetrievernow requires the sorting to carrymain_channel_id
BaseSorting.to_spike_vector()gainedmain_channel_indicesas its third positional parameterThe chunking and node pipeline machinery is generalized to any time series (#4472, #4533)
ChunkRecordingExecutor–>TimeSeriesChunkExecutor, whose first argument istime_seriesrather thanrecording, and whoserun(recording_slices=...)–>run(slices=...)
PipelineNode.get_trace_margin()–>get_margin(),PipelineNode.compute(traces, ...)–>compute(chunk, ...), andPipelineNodetakestime_seriesrather thanrecording
run_node_pipeline(recording, ..., recording_slices=...)–>run_node_pipeline(time_series, ..., slices=...), andcheck_for_peak_sourcenow defaults toFalse
divide_recording_into_chunks–>divide_time_series_into_chunks,write_binary_recording_file_handle–>write_binary_file_handle,get_random_recording_slices–>get_random_sample_slices
BaseRecordingSegmentnow derives fromTimeSeriesSegment, whose time attributes are private (#4701): useget_times_kwargs(),get_start_time(),set_times()andshift_times()instead ofsegment.t_start,segment.time_vectorandsegment.sampling_frequencySaving and serialization are unified on the concrete classes (#4671, #4661, #4664)
BaseExtractor.save()is abstract, andBaseExtractor._save()is removed, so third-party extractors overriding_saveno longer take part insave(). UseRecording.save(),Sorting.save()andSnippets.save()
folder_metadatais removed fromto_dict(),dump(),dump_to_json()anddump_to_pickle(), andload_metadata_from_folder()/save_metadata_to_folder()are removed.to_dict()also gainedinclude_extra_metadatain its third positional slot
check_if_memory_serializable(),check_if_json_serializable()andcheck_if_pickle_serializable()–>check_serializability(type)
BaseExtractor.load_from_folder()is removed; usesi.load()
ZarrRecordingExtractor.write_recording(recording, zarr_path=...)–>folder_path=..., andadd_traces_to_zarr()is removed
_get_t_starts()–>get_segment_t_starts()
si.load()forwards unknown keyword arguments instead of dropping them, so a bad argument now raises (#4709)
PreprocessingPipelinetakes a list of{"name": ..., "params": ...}steps instead of a dictionary (#4755) (see: Preprocessing module)
PreprocessingPipeline.preprocessor_dict–>.preprocessor_list
get_preprocessing_dict_from_analyzer/get_preprocessing_dict_from_file–>get_preprocessing_list_from_analyzer/get_preprocessing_list_from_file
apply_preprocessing_pipeline(recording, pipeline_or_dict, ...)–>apply_preprocessing_pipeline(recording_or_dict, pipeline, ...). Passing a dictionary still works, but is deprecatedOther signature and naming changes
parent_recording–>recordinginChannelSliceRecording,FrameSliceRecording,depth_order,detect_and_remove_bad_channelsandaverage_across_direction(#4779)
AnalyzerExtension._select_extension_data()–>_select_units_extension_data(), with a new_select_channels_extension_data(). This breaks customAnalyzerExtensionsubclasses (#4648)
create_sorting_analyzer()gained several parameters betweenfolderandsparse, sosparseandsparsitymust now be passed by keyword (#4624, #4623)
NoiseGeneratorRecordingandnoise_generator_recordingmoved fromspikeinterface.coretospikeinterface.generation(#4520). The lightweightMockRecordingreplaces the old core class for testing
resample():margin_msnow defaults toNonerather than100.0, andskip_checksandcheck_nyquist()are removed (#4621, #4499)
read_kilosort_as_analyzer()gainedrecordingas its second positional parameter (#4529), andmodel_based_label_units()gainedunit_idsas its second positional parameter (#4716)
run_sorterraises an error when channel locations are not unique, suggestingrun_sorter_by_propertyinsteadPython packaging:
numpy>=2.0is required on all supported Python versions, the minimumneoandprobeinterfaceversions are raised to0.14.5and0.4.0(#4593), thetest,test_core,test_extractorsandtest_preprocessingextras are replaced by PEP 735 dependency groups,sonpyis dropped, and thepandas<3(#4691) andscikit-learn<1.8(#4780) pins are relaxedChanged results and defaults
sliding_rp_violationvalues change: the metric now reusescompute_correlogramsand derives refractory-period bins from the actual correlogram bins (#4324), the expected-violations formula is corrected to the [Llobet] formulation, which previously overestimated it, and the tested contamination range now includes 35% (#4682)Multi-segment
synchrony_metricswere incorrectly grouping equal sample indices across segments, and are now computed per segment (#4770)
estimate_sparsity()defaults topeak_sign="both"(#4624)
amplitude_cutoffnow prefersamplitude_scalingsoverspike_amplitudes(#4513)
num_depth_binsfor MEDiCINe motion estimation uses MEDiCINe’s own recommended default (#4686)Preprocessed traces are rounded, rather than truncated, before being cast to integer dtypes (#4653)
Amplitudes are scaled to uV using channel offsets in addition to gains (#4765)
get_metrics_extension_data()drops duplicated columns when two extensions provide a metric of the same name (#4609)Template metrics no longer raise on 3D channel locations; they warn and use the first two dimensions (#4572)
decimateemits aFutureWarningwhenantialiasis not set explicitly: the default will becomeTruein a future release (#4621)Removal of previously deprecated features
curation.auto_label_units()–>model_based_label_units()(#4716)the
load_sync_channelargument ofOpenEphysBinaryRecordingExtractor–>stream_name/stream_id(#4466)the
num_chanargument ofBinaryRecordingExtractor–>num_channels(#4666)New deprecations, which will be removed in 0.106.0, and which now raise
FutureWarningrather thanDeprecationWarningso that they are visible by default (#4667, #4676):
BaseSnippetsthe
in_placeargument ofset_probe, as well as its return value
set_channel_locations()andclear_channel_locations()
get_template_extremum_channel()–>analyzer.get_main_channels()
get_template_extremum_channel_peak_shift()–>get_template_peak_shift_on_main_channel()
get_template_extremum_amplitude()–>get_template_amplitude_on_main_channel()
save_to_memory(),save_to_folder()andsave_to_zarr()–>save(format=...)the
"npz_folder"save format andNpzFolderSorting.write_sorting()–>"numpy_folder"(readingnpz_folderis still supported)the
extremum_channel_indsargument ofSpikeRetriever–>main_channel_idsfrom the sortingpassing sparsity and job arguments as loose keyword arguments to
create_sorting_analyzer–>sparsity_kwargsandjob_kwargsdictionariesthe
input_dataargument ofmodel_based_label_units–>metrics
split_non_somatic_good_muaandlabel_non_somaticin Bombcell curation –>split_non_somaticcomputing
amplitude_cutoffwithout theamplitude_scalingsextension (#4513)Passing a dictionary to
apply_preprocessing_pipelineis deprecated and will be removed in 0.107.0 (#4755)Items deprecated during the 0.104 cycle, such as
return_scaled, thespikeinterface.qualitymetricsandspikeinterface.postprocessing.template_metricsmodules,CurationModel,get_potential_auto_merge(),get_default_qm_params,get_default_tm_params, thesortingandsorting_analyzerarguments of several widgets, are removed.
core:
Add
GatherToZarrand save pipeline node extension data to disk (#4703)Respect requested unit order for templates and sparsity in SortingAnalyzer.select_units (#4791)
Fix main_channel_id donor selection when merged units disagree (#4773)
Keep spikeinterface importable when zarr-python v3 is installed (#4751)
Run the kwargs backward compatibility hook regardless of the saved version (#4749)
Propagate shared annotations in aggregate_channels (#4731)
Support a SortingAnalyzer with no unit in the core extensions (#4729)
Fix
n_jobs=-1oversubscribing cores under CPU affinity restrictions (#4724)fix: preserve caller-owned inputs (#4721)
Fix
is_merged/is_splitproperties for different strategies (#4718)SortingAnalyzer: addread_onlymode (different thanlazy) (#4713)Fix channel order bug and make
select_channelsprivate (#4712)Fix cache spike vector in base sorting (#4710)
Propagate
lazyarg to fromsi.load()(#4709)Fixes a couple of minor warnings (#4707)
Create SortingAnalyzer object directly during create_sorting_analyzer (#4705)
Make time attributes private in
TimeSeriesSegment(#4701)Fix and speed up to_reordered_spike_vector (#4695)
Clean up code around create_sorting_analyzer and create/load_* functions in sortinganalyzer.py (#4680)
Add backwards compatibility when passing sparsity kwargs to create_sorting_analyzer (#4677)
Move the
Base.savetoSorting.save()andRecording.save()(#4671)Add copy_sorting option to SortingAnalyzer.create_memory (#4668)
Remove
load_from_folderfrom base (#4664)Cleanup Serializability checking in
base.py(#4661)Add
SortingAnalyzer.split()function for aggregated analyzers (#4660)Fix template estimate sparsity (#4657)
Parameter pass through for class -> function wrapper (#4656)
Improve sparsity estimation for aggregated analyzers (#4649)
Add
SortingAnalyzer.select_channels()function (#4648)Remove
peak_signin favour ofmain_channel_indices(#4624)Lazy-mode for loading
Sortinganalyzer(#4623)write_binary:Nonedtype should be replaced by actual dtype (#4622)Avoid materializing entire time vector from zarr for time_to_sample_index (#4620)
Remove some full lexsort of spikes when not necesary. (#4618)
Remove deduplicated columns in
get_metrics_extension_data(#4609)Use np.load(…, mmap_mode=”r”) for time_vector in
BaseRecording._extra_metadata_from_folder(#4608)Fix file size calculation in
write_binary()(#4607)SortingAnalyzer: intepret any remote path as zarr (#4583)Faster unit selection sorting. (#4581)
Handle failure in dumping sorting provenance to Zarr (#4577)
Add SelectSegmentEvent (#4575)
Improve backward compatibility for dartsort after the chunkable PR (#4559)
Add
shift_timestoBaseSorting(#4551)Improvements over chuking refactoring (#4533)
Add
num_channelstoBaseRecordingSegment(#4526)Add
get_start_time,get_end_time, andget_last_spike_frametoBaseSorting(#4525)Add
t_startsparameter togenerate_recordingandgenerate_sorting(#4523)Add regression test for GH-4508 (deprecated metric names in legacy WE folders) (#4514)
Improve
get_timesfunction to slice timestamps (#4512)Delete a failed SortingAnalyzer extension (#4511)
Replace int() truncation with shared ms_to_samples() (#4484)
Implement
TimeSeriesclass (#4472)Add
zarr_class_infoattribute to zarr files for unambiguous and extendible zarr read (#4467)Use
ProbeGroupobject instead ofcontact_vectorproperty andset_probe/probegroupfromselect_channels_with_probe/probegroup(#4465)Centralize
add_segmentandsegmentstoBaseExtractor(#4462)
extractors:
Add
main_channel_idwhen running Kilosort (#4725)Add
ZarrArrayExtractorto read “plain” Zarr arrays (#4760)Let
get_streamswork from the path alone on Neuralynx, Biocam and Blackrock (#4727)Add option to export spike waveforms subset to phy (mimic phy extract-waveforms) (#4699)
Fix backward compatibility for binary recording/openephys/spikeglx (#4666)
Build the
NwbSortingExtractorspike vector with a single bulk read (#4662)Read the ragged index before the data when loading NWB table properties (#4655)
Map NWB sorting spikes to samples via the ElectricalSeries timestamps (#4654)
Fix NwbSortingExtractor unit-property loading for DynamicTableRegion columns (#4647)
Infer
sampling_frequencyfromUnits.resolutioninNwbSortingExtractor(#4646)Separate NWB reading from extractor construction (#4630)
Materialize electrode-table columns before indexing in the NWB recording extractor (#4627)
Fix
read_mclustreturning zero units for.tfiles (#4626)Use probeinterface’s renamed Neuropixels readers and new probe detectors (#4593)
Implement cache spike vector for phy sorting reader (#4579)
Fix the IBL Cbin extractor so that it works with 4 split shanks as well (#4567)
preprocessing:
Accept recording= consistently in detect_and_remove_bad_channels, depth_order and average_across_direction (#4779)
Extend preprocessing pipeline by defining a
BasePipeline(#4755)Parallelize coherence-based bad channel detection (#4750)
Handle empty annulus in local common reference (#4728)
Cast not_enough_channels as str before ‘join’ (#4690)
Fix remove_artifacts sparsity handling for median/average modes (#3290) (#4685)
Fix
test_pipeline_equiv_to_step(#4675)Fix double setting of
operatorinself(#4659)Round before casting preprocessed traces to integer dtypes (#4653)
Add antialiased decimation and allow non-integer resampling rates (#4621)
Add per-group ref_channel_ids to common_reference (#4601)
Extend artifact detection:
DetectAndRemoveArtifactspreprocessor and signed saturation (#4539)Fix false-positive margin warning in forkserver workers (#4506)
Fix resampling of gapped recordings. (#4499)
Allow overwrite argument when saving motion object (#4464)
Refactor artifacts detection + add saturation detection (#4297)
sorters:
Save recording_attributes before run_sorter() (#4795)
Only use nonempty main channel indices when making an analyzer from templates (#4763)
Fix encoding error in shellscript on Windows (#4720)
Add
read_kilosort4_motionfunction (#4518)Initial dartsort wrapper implementation. (#2125)
postprocessing:
Speed up collision-aware amplitude scaling (#4786)
Fix ComputeACG3D soft merge indexing bug that swaps kept units’ data (#4776)
Materialize templates array before amp scalings computation for lazy mode (#4769)
BUG: preserve correlogram unit axes across segments (#4767)
Use channel offsets, not gains, when scaling amplitudes to uV (#4765)
perf(postprocessing): compute only the amplitude scaling coefficients (#4764)
Scale only the waveforms amplitude_scalings reads (#4759)
Remove unused full-chunk scaling in spike_amplitudes (#4758)
Fix PCA metric recomputation when “soft” merging (#4748)
Expose seed for spike_locations (grid) (#4717)
Remove
peak_signin favour ofmain_channel_indices(#4624)“Allow” for 3D channel locations for compute unit locs and template metrics (#4572)
Vectorize per-channel PCA transform in
run_for_all_spikes(#4488)
metrics:
Correct and speed up multi-segment synchrony metrics (#4770)
Fix PCA metric recomputation when “soft” merging (#4748)
Add
template_operatorto template metrics backwards compatibility (#4714)Deepcopy of metric params (#4688)
Fix Llobet expected-violations formula in sliding RP metric (#4682)
QualityMetrics: store
use_valid_periodsparam (#4596)Amplitude cutoff should favor amplitude_scalings extension (#4513)
Harmonization of the way we are computing sliding_rp_violations (#4324)
curation:
Fix mismatch in vairable name in mergeunitssorting.py (#4743)
Fix
is_merged/is_splitproperties for different strategies (#4718)Model_based_curation + unitrefine prediction: add
unit_idsinput (#4716)Vectorize _find_duplicated_spikes_keep_first/last_iterative kernels. (#4614)
Bombcell extension (#4494)
Change to using upset-bombcell package (#4493)
Make sure default automerge params reflect their type (#4483)
widgets:
Fix unit presence time_range (#4571)
Add
sort_by_depthkwargs toRasterWidget(#4544)
generators:
Fix amplitude being ignored for static hybrid recordings (#4674)
Add
interpolation_kwargstointerpolate_templates(#4665)Small change to add amplitude jitter in drifting_generator (#4592)
Use mock instead of generate in tests (#4587)
Generate recording with probe from library (#4568)
generate: Add power decay spatial profile (#4489)
sortingcomponents:
Only use nonempty main channel indices when making an analyzer from templates (#4763)
Enhance single channel denoiser and
WaveformNode(#4673)Add
thin_plateinterpolation tointerpolate_templates(#4640)Add install check for components sorters (#4574)
Small fix in nodepipeline that prevent tdc peeler in drift-aware mode (#4557)
Patch to improve the nearest peeler. (#4516)
motion correction:
Allow Dredge AP to use online motion resolution method (#4746)
Use MEDiCINe’s own recommended default for num_depth_bins (#4686)
documentation:
Update copyright in
conf.py(#4642)Update release dates and add 0.104.4 (#4613)
Fix doc typo on home page (#4492)
continuous integration:
Use a single dataset cache for all the runner OSes (#4772)
Skip pruning of macOS uv cache (#4678)
Add cross-version serialization tests (#4636)
Update actions versions (#4585)
Modularize CI test and runtime dependencies per module (#4541)
Fix numpy and scipy failures on the CI (#4534)
Loosen import-time gate on Windows and unpin pytest (#4532)
Use uv and caching in CI (#4515)
packaging:
Relax
scikit-learn<1.8pin (#4780)Dev version should be 0.105.0 (#4696)
Relax pandas<3 pin (#4691)
Fix imports in sortingview (#4652)
Cleanup importing spikeinterface rather than inspecting it during curation (#4651)
Update checking for editable mode of spikeinterface (#4650)
Another round of import edits to reduce memory burden and increase speed of startup (#4644)
Updating Imports (details in comment) (#4641)
Use probeinterface and neo source when using spikeinterface source (#4615)
Use legacy numpy versions for ks 4.1.1-4.1.6 tests (#4591)
Add install check for components sorters (#4574)
Fix module level test groups (#4573)
Modularize CI test and runtime dependencies per module (#4541)
testing:
Fix failing tests: decimate in chunks and skops (#4792)
Use a single dataset cache for all the runner OSes (#4772)
Fix interpolate tests after probeinterface to_numpy change (#4637)
Fix curation tests for missing kachery dependency (#4599)
Use legacy numpy versions for ks 4.1.1-4.1.6 tests (#4591)
Fix module level test groups (#4573)
Modularize CI test and runtime dependencies per module (#4541)
Speed up
test_sorting_s3_nwb_zarr(again) (#4538)Fix tests paths (#4490)
deprecations:
Accept recording= consistently in detect_and_remove_bad_channels, depth_order and average_across_direction (#4779)
Deprecation -> Future (#4667)
Fix backward compatibility for binary recording/openephys/spikeglx (#4666)
Segment backward compatibility (#4542)
Contributors:
@4iar
@Antorhythms
@AtomicGlance
@CodeBlackwell
@JESUSROYETH
@Julie-Fabre
@Leonard013
@RobertoDF
@SZNRR
@adityasingh2400
@alejoe91
@chrishalcrow
@cwindolf
@ecobost
@galenlynch
@grahamfindlay
@h-mayorquin
@hayleybounds
@lochhh
@nwatters01
@oliche
@rai-pranav
@samuelgarcia
@stanbot8
@tayheau
@yger
@zm711