BaseSorting.select_periods() drops properties, annotations and the registered recording

Fermée
#4,915 3 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Une pull request liée a déjà été fusionnée.

  • #4921 par @AxelNoun — fusionnée

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
20/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
À l'abandon
Stack technique
python
Domaine
backend

Piste de recherche

The issue points to src/spikeinterface/core/sorting_tools.py around select_sorting_periods and describes a reproduction using BaseSorting.select_periods(). Read that function and the related tests in test_basesorting.py; verify that the selected sorting retains properties, annotations, its registered recording, and correct returned spike times. An open pull request, #4921, is already linked to this issue.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

bug core

select_sorting_periods overwrites sorting with the new object, then copies the metadata from this object onto itself:

sorting = NumpySorting(
    sliced_spike_vector, sampling_frequency=sorting.sampling_frequency, unit_ids=sorting.unit_ids
)
sorting.copy_metadata(sorting)
return sorting

So after select_periods, all properties and annotations are lost. The recording is also no longer registered, so get_unit_spike_train(..., return_times=True) ignores the start time or time vector of the recording.

Reproduction

main at 9ef464e66, Linux (WSL Ubuntu 24.04), Python 3.12.3, numpy 2.5.4:

import numpy as np
import spikeinterface.core as sc
from spikeinterface.core.base import unit_period_dtype

fs = 1000.0
rec = sc.generate_recording(num_channels=2, sampling_frequency=fs, durations=[10.0], seed=0)
rec.shift_times(500.0)  # the recording starts at t = 500 s
sorting = sc.NumpySorting.from_unit_dict(
    {"a": np.array([10, 2000, 5000]), "b": np.array([30, 3000])}, sampling_frequency=fs
)
sorting.set_property("quality", np.array(["good", "mua"]))
sorting.annotate(probe_name="NP2.0")
sorting.register_recording(rec)

periods = np.array([(0, 0, 4000, 0), (0, 0, 4000, 1)], dtype=unit_period_dtype)
selected = sorting.select_periods(periods)

print("properties:   ", sorting.get_property_keys(), "->", selected.get_property_keys())
print("annotations:  ", sorting.get_annotation_keys(), "->", selected.get_annotation_keys())
print("has_recording:", sorting.has_recording(), "->", selected.has_recording())
print("spike times of 'a' (s):", sorting.get_unit_spike_train("a", return_times=True)[:2],
      "->", selected.get_unit_spike_train("a", return_times=True))
properties:    ['quality'] -> []
annotations:   ['probe_name'] -> []
has_recording: True -> False
spike times of 'a' (s): [500.01 502.  ] -> [0.01 2.  ]

The spike times are off by 500 s.

Possible fix
-        sorting = NumpySorting(
+        new_sorting = NumpySorting(
             sliced_spike_vector, sampling_frequency=sorting.sampling_frequency, unit_ids=sorting.unit_ids
         )
-        sorting.copy_metadata(sorting)
-        return sorting
+        sorting.copy_metadata(new_sorting)
+        if sorting.has_recording():
+            new_sorting.register_recording(sorting._recording)
+        return new_sorting

With this, the properties, annotations and spike times are preserved in the example above. test_basesorting.py, test_baserecording.py, test_binaryfolder.py, test_binaryrecordingextractor.py and test_numpy_extractors.py still pass (33 tests).

I found no existing report, and no open PR changes this line. It comes from #4316. #4796 fixed a similar loss of start times in NumpySorting.from_sorting. I can open a PR with this change and a test.

Langage dominant
Python
Étoiles
872
Forks
287
Merge moyen
2 j 9 h
PR mergées (30 j)
47

Préparer son environnement

Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de SpikeInterface/spikeinterface

Toutes les issues de SpikeInterface/spikeinterface

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.