SpikeInterface / spikeinterface

A Python-based module for creating flexible and robust spike sorting pipelines.
https://spikeinterface.readthedocs.io
MIT License
500 stars 187 forks source link

Spike amplitudes crashes on sorting with no units #2264

Open DradeAW opened 10 months ago

DradeAW commented 10 months ago

Computing the spike amplitudes crashes when giving a sorting with no unit, rather than simply doing nothing.

import spikeinterface.core as si
import spikeinterface.postprocessing as spost

recording = si.load_extractor("recording.bin")
sorting = si.NumpySorting.from_unit_dict({}, 30000)  # Also works with si.load_extractor("sorting").select_units([])

wvf_extractor = si.extract_waveforms(recording, sorting, mode="memory", allow_unfiltered=True)  # Also same error message when using `mode="folder"`
extract waveforms shared_memory multi buffer: 

spost.compute_spike_amplitudes(wvf_extractor)

extract amplitudes:   0%|                                                                                             | 0/1765 [00:00<?, ?it/s]Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/export/home1/users/nsr/wyngaard/dev/spikeinterface/spikeinterface/src/spikeinterface/postprocessing/spike_amplitudes.py", line 171, in compute_spike_amplitudes
    sac.run(**job_kwargs)
  File "/export/home1/users/nsr/wyngaard/dev/spikeinterface/spikeinterface/src/spikeinterface/core/waveform_extractor.py", line 1964, in run
    self._run(**kwargs)
  File "/export/home1/users/nsr/wyngaard/dev/spikeinterface/spikeinterface/src/spikeinterface/postprocessing/spike_amplitudes.py", line 80, in _run
    out = processor.run()
          ^^^^^^^^^^^^^^^
  File "/export/home1/users/nsr/wyngaard/dev/spikeinterface/spikeinterface/src/spikeinterface/core/job_tools.py", line 377, in run
    worker_ctx = self.init_func(*self.init_args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/export/home1/users/nsr/wyngaard/dev/spikeinterface/spikeinterface/src/spikeinterface/postprocessing/spike_amplitudes.py", line 186, in _init_worker_spike_amplitudes
    worker_ctx["min_shift"] = np.min(peak_shifts)
                              ^^^^^^^^^^^^^^^^^^^
  File "/users/nsr/wyngaard/dev/miniconda3/envs/lussac/lib/python3.11/site-packages/numpy/core/fromnumeric.py", line 2953, in min
    return _wrapreduction(a, np.minimum, 'min', axis, None, out,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/users/nsr/wyngaard/dev/miniconda3/envs/lussac/lib/python3.11/site-packages/numpy/core/fromnumeric.py", line 88, in _wrapreduction
    return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: zero-size array to reduction operation minimum which has no identity
alejoe91 commented 10 months ago

In this case, would you expect a spike_amplitudes folder with an empty numpy array? Or should the function just warn and return nothing?

DradeAW commented 10 months ago

I don't even expect a warning, just returning an empty array (and if in folder mode, making sure you can load the empty array).

I don't think a warning should be thrown, I think it should work in all cases?

rat-h commented 7 months ago

I think I have a similar issue. Spike sorting finishes complitely fine, but the wave extractor crashes with an error:


extract waveforms memmap multi buffer:   0%|          | 0/3 [00:00<?, ?it/s]
extract waveforms memmap multi buffer: 100%|██████████| 3/3 [00:00<00:00, 77.41it/s]

Fitting PCA: 0it [00:00, ?it/s]
Fitting PCA: 0it [00:00, ?it/s]

Projecting waveforms: 0it [00:00, ?it/s]
Projecting waveforms: 0it [00:00, ?it/s]
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/misc_metrics.py:702: UserWarning: 
  warnings.warn("")
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:132: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, col] = pd.Series(res[i])
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:132: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, col] = pd.Series(res[i])
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:132: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, col] = pd.Series(res[i])
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:132: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, col] = pd.Series(res[i])
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/misc_metrics.py:1429: UserWarning: The `sd_ratio` metric require the `spike_amplitudes` waveform extension. Use the `postprocessing.compute_spike_amplitudes()` functions. SD ratio metric will be set to NaN
  warnings.warn(
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:127: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, metric_name] = pd.Series(res)
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:132: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, col] = pd.Series(res[i])
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:132: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, col] = pd.Series(res[i])
~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py:132: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  metrics.loc[non_empty_unit_ids, col] = pd.Series(res[i])
Traceback (most recent call last):
  File "~/spikeinterface/runthepipe2.py", line 501, in <module>
    runextractors(last,job_kwargs,preproc_saved,sorting_saved)
  File "~/spikeinterface/runthepipe2.py", line 171, in runextractors
    metrics = compute_quality_metrics(we, load_if_exists=True,**job_kwargs)
  File "~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py", line 235, in compute_quality_metrics
    qmc.run(verbose=verbose, **job_kwargs)
  File "~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/core/waveform_extractor.py", line 2017, in run
    self._run(**kwargs)
  File "~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/quality_metric_calculator.py", line 140, in _run
    pc_metrics = calculate_pc_metrics(
  File "~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/qualitymetrics/pca_metrics.py", line 137, in calculate_pc_metrics
    all_labels, all_pcs = pca.get_all_projections()
  File "~/.local/apps/spikes/lib/python3.10/site-packages/spikeinterface/postprocessing/principal_component.py", line 162, in get_all_projections
    all_labels = np.concatenate(all_labels, axis=0)
  File "<__array_function__ internals>", line 180, in concatenate
ValueError: need at least one array to concatenate

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "~/spikeinterface/runthepipe2.py", line 504, in <module>
    raise RuntimeError(f'Exctractors failed: {e}')
RuntimeError: Exctractors failed: need at least one array to concatenate

If this is the same problem, is there any hope to fix it?