Saving a multi-segment recording fails when only some segments have a t_start
Los mantenedores suelen responder en 1 día
@AxelNoun ya está trabajando en esto.
Desde el 5/11/2026.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 84/100
Línea de trabajo
Empieza por los tres constructores mencionados en el issue: NumpyRecording y SharedMemoryRecording en src/spikeinterface/core/numpyextractors.py, y BinaryRecordingExtractor en src/spikeinterface/core/binaryrecordingextractor.py. Lee cómo gestiona cada uno get_segment_t_starts y, después, ejecuta la reproducción y las pruebas indicadas para recording y binary extractor. Se considera terminado cuando las grabaciones binarias y en memoria conservan los tiempos de inicio mixtos y los traces sin dejar shared memory sin liberar.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
get_segment_t_starts returns a mixed list such as [None, 100.0] when only some segments have a start time. Three constructors then call float() on every entry. This happens with append_recordings([rec_without_t_start, rec_with_t_start]), and more generally when shift_times has been applied to only some segments.
Reproduction
main at 9ef464e66, Linux (WSL Ubuntu 24.04), Python 3.12.3, numpy 2.5.4, zarr 3.4.2:
import spikeinterface.core as sc
a = sc.generate_recording(num_channels=2, sampling_frequency=1000.0, durations=[3.0], seed=0)
b = sc.generate_recording(num_channels=2, sampling_frequency=1000.0, durations=[2.0], seed=1)
b.shift_times(100.0)
rec = sc.append_recordings([a, b])
print(rec.get_segment_t_starts(), [rec.get_start_time(i) for i in range(2)])
for kwargs in [
dict(format="binary", folder="rec_binary"),
dict(format="memory", shared_memory=False),
dict(format="memory", shared_memory=True),
dict(format="zarr", folder="rec.zarr"),
]:
try:
saved = rec.save(**kwargs)
print(kwargs["format"], "OK", [saved.get_start_time(i) for i in range(2)])
except TypeError as ex:
print(kwargs["format"], f"TypeError: {ex}")
[None, 100.0] [0.0, 100.0]
binary TypeError: float() argument must be a string or a real number, not 'NoneType'
memory TypeError: float() argument must be a string or a real number, not 'NoneType'
memory TypeError: float() argument must be a string or a real number, not 'NoneType'
zarr OK [0.0, array(100.)]
Three details make this worse:
- Binary: the exception comes after all traces are written. In the example,
rec_binarycontainstraces_cached_seg0.rawandtraces_cached_seg1.raw, but neitherbinary.jsonnorsi_folder.json. For a long recording, this means that hours of writing end in a folder that cannot be loaded. - Shared memory: the exception comes before
self.main_shm_owneris set, so__del__raisesAttributeError: 'SharedMemoryRecording' object has no attribute 'main_shm_owner', and the segments are not unlinked. The script ends withresource_tracker: There appear to be 4 leaked shared_memory objects to clean up at shutdown. - Zarr: saving works, but
get_start_time(1)returns a 0-darray(100.)instead of a float.
Cause
get_segment_t_starts only returns None when all segments have no start time. The conversion is in NumpyRecording, SharedMemoryRecording and BinaryRecordingExtractor. In SharedMemoryRecording, main_shm_owner is set after this line, and __del__ reads it.
Possible fix
In the three constructors, keep None:
t_starts = [None if t_start is None else float(t_start) for t_start in t_starts]
With this, the binary and both memory saves work, with start times [0.0, 100.0] and identical traces, and the script no longer reports leaked segments. test_basesorting.py, test_baserecording.py, test_binaryfolder.py, test_binaryrecordingextractor.py and test_numpy_extractors.py still pass (33 tests).
Two separate points would remain: setting main_shm_owner before anything that can fail, so that __del__ is safe after another error, and the 0-d array from zarr. I have not changed them.
I found no report of this case. Nearby: #2515 and #3120 (t_starts lost by save_to_memory) and #3940 (shift_times when t_start is None). I can open a PR with this change and a round-trip test.
- Lenguaje dominante
- Python
- Estrellas
- 870
- Forks
- 284
- Merge medio
- 3 d 1 h
- PR fusionados (30 d)
- 41
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de SpikeInterface/spikeinterface
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
SpikeInterface/spikeinterface#4842 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
SpikeInterface/spikeinterface#4510 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
MountainSort5: expose `pca_seed` / `random_seed` sorter param (pair with MS5 configurable PCA seed)Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 43/100
SpikeInterface/spikeinterface#4919 ·
Los mantenedores suelen responder en 1 día
-
BaseSorting.select_periods() drops properties, annotations and the registered recordingPosiblemente ocupada @AxelNoun la tomó hoy. Abiertobug core
Dificultad 2/5 1-3 horas Aptitud para principiantes 20/100
SpikeInterface/spikeinterface#4915 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
Optional dependencies don't participate in extension invalidationPosiblemente ocupada @alejoe91 la tomó hace 1 día. Abiertobug core
Dificultad 4/5 3-5 días Aptitud para principiantes 25/100
SpikeInterface/spikeinterface#4912 ·
Los mantenedores suelen responder en 1 día
Todos los issues de SpikeInterface/spikeinterface
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 64/100
FinanceFlash/unvibecode#577 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
area/test type/bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Clodmony/starship-coop#70 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 77/100
punitarani/fli#270 ·
-
🐛 Bug 🔔 Pending processing
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
jumpserver/jumpserver#17980 ·
Los mantenedores suelen responder en 1 día
-
community enhancement good first issue
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
Los mantenedores suelen responder en 1 día