Repository navigation
Store JSON data in zarr SortingAnalyzers as byte arrays instead of object arrays - #4881
Merged
alejoe91 merged 3 commits intoOct 20, 2026
Merged
Conversation
This was referenced Oct 19, 2026
Merged
Member
|
Brillant!!! |
alejoe91
approved these changes
Oct 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is another peel-off from #4260, the first half of the format change (4 in my review there). zarr-python 3 cannot write object arrays, which is how a zarr
SortingAnalyzerstores its recording provenance and the dict extension data. I now store their JSON as bytes in auint8array, which any zarr version can write, and old analyzers still load. The scikit-learn models ofprincipal_componentsstay pickled for now as that is a bigger decision and I think it should go on its own PR (this is mostly for me as I need to think on the two issuses separately).This PR is not a carbon copy of the changes in #4260, as I think there is a small improvement to make. In #4260 the recording
to_dictis stored as an attribute, which makes sense semantically but is less performant than it could be because of how zarr-python works. zarr-python parses the attributes every time a group is opened, and loading an analyzer with its extensions opens the root group 53 times. The sizes tend not to be large (about 1 MB with motion correction and whitening, for example), but it is a cost that we can avoid. As a concrete example I did the following test:I took a 30-minute Neuropixels 1.0 recording (384 channels at 30 kHz, int16) preprocessed with a bandpass filter, phase shift and a global common reference, followed by motion correction with a non-rigid motion shaped like the dredge preset produces (1 s bins and 400 µm windows, so 1800 x 10 values), with and without whitening. I stored its provenance as a root attribute of a zarr analyzer with 17 extensions, as #4260 does, and timed loading the analyzer with all its extensions against the same analyzer with a small provenance.
And in short, we have:
Time to load the zarr SortingAnalyzer and all its extensions, local disk
Time to load the zarr SortingAnalyzer and all its extensions, simulated cloud storage
That is up to 1.5 s locally and 14 s remotely on every load with #4260, growing with the recording duration. Stored as a byte array, the provenance is only read when the recording is loaded, so the analyzer loads as fast as with a small provenance, as it does on main today.
The bigger behavior change, here and in #4260, is that recordings that are not JSON-serializable but used to be pickled into the zarr analyzer are no longer saved. After #4877 these are rare. In spikeinterface, this only affects recordings built on an
NwbRecordingExtractoropened from a file handle (a minority case), on anInjectDriftingTemplatesRecordingwith a saved sorting, or on templates injected into a pickle-only sorting such as the agreement sorting of a multi-sorting comparison, plus third-party extractors that opt out of JSON. Instead, the analyzer warns:V
This also fixes
get_preprocessing_list_from_analyzeron the backward compatibility path, and analyzers in the new format can already be loaded with zarr-python 3.