Skip to content

SortingAnalyzer: add read_only mode (different than lazy) - #4713

Open
alejoe91 wants to merge 10 commits into
SpikeInterface:mainfrom
alejoe91:lazy-versus-read-only
Open

SortingAnalyzer: add read_only mode (different than lazy)#4713
alejoe91 wants to merge 10 commits into
SpikeInterface:mainfrom
alejoe91:lazy-versus-read-only

Conversation

@alejoe91

Copy link
Copy Markdown
Member

In #4623 (and #4709) we added a lazy mode for loading the SortingAnalyzer. This kept extension data and spike vector unmaterialized to avoid loading large arrays in memory. The lazy mode though did not allow any computation.
However, lazy mode could be used also to compute extensions for large datasets (see #4703) to minimize the overall memory footprint of computations.

To make these 2 use cases separate, this PR adds a read_only flag for loading SortingAnalyzer (e.g., when loading for the GUI), which prevents any saving of extensions). The lazy mode has been extended for creating analyzers, computing, and svaing/merging/splitting.

For very large datasets, one could now use this (especially in conjunction with #4703), to avoid loading large arrays in memory:

analyzer = si.create_sorting_analyzer(sorting, recording, format="zarr"/"binary_folder", folder="my-folder", lazy=True)

The PR also propagates the lazy argument to the parallel computation of PCA metrics.

@alejoe91 alejoe91 added core Changes to core module performance Performance issues/improvements labels Jul 24, 2026
@alejoe91 alejoe91 changed the title SortingAnalyzer: add read_only mode (different than lazy`) SortingAnalyzer: add read_only mode (different than lazy) Jul 24, 2026
@alejoe91 alejoe91 added this to the 0.105.0 milestone Jul 24, 2026
Comment thread src/spikeinterface/core/core_tools.py
Comment thread src/spikeinterface/postprocessing/correlograms.py Outdated

def _split_extension_data(self, split_units, new_unit_ids, new_sorting_analyzer, verbose=False, **job_kwargs):
# splitting only affects random spikes, not waveforms
new_data = dict(waveforms=self.data["waveforms"].copy())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets discuss a bit this copy( that disappear everywhere.
For the lazy it makes sens but for i memory there is drwback no ?
and also what if the source array disapear in between the futur save ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added materialize_array for all returned extension data from select/split/merge. This is particularly relevant for sequential curations.

@chrishalcrow we can handle more efficient ways to apply curations later

tmp_path / "analyzer_lazy", format="auto", lazy=True, read_only=True
)
sorting_analyzer_lazy_ro.compute(
"quality_metrics", metric_names=metric_names, seed=1205, metric_params=metric_params, save=True

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure to understand the API we trying to save a read only analyzer we should raiuse error no ?
what is the expected behavior ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right now it jus doesn't save. Should we raise? Or warn maybe?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if a user (or external software e.g. spikeinterface-gui) uses read_only then they have a good reason for doing so. And it is correct that we shouldn't allow saving even if they pass save=True (they might accidentally do this). We would expect them to do this:

test_metrics = sorting_analyzer_lazy_ro.compute("quality_metrics", metric_names=metric_names, seed=1205, metric_params=metric_params)

which shouldn't warn or raise, since it's a legit things to do. Note that save=True is default.

So I think the current behavior is correct: don't save and don't warn and don't raise.


correlograms, new_bins = deepcopy(self.get_data())
correlograms = materialize_array(self.data["ccgs"])
new_bins = self.data["bins"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no copy ? this will keep a ref to the old analyzer that will be never garbage collected.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point!

Comment on lines +2353 to +2354
If True the extension is saved to disk (only if sorting analyzer format is not "memory").
If False the extension will only live in memory as long as the object is deleted.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a comment about save being ignored if read_only

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Changes to core module performance Performance issues/improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants