_read_old_waveforms_extractor_binary in spikeinterface/core/waveforms_extractor_backwards_compatibility.py invokes ext.set_params() (which triggers _set_params() validation) before running ext._handle_backward_compatibility_on_load(). For extensions whose on-disk params.json contains metric names that were renamed in 0.104 (e.g. peak_to_valley, velocity_above, l_ratio, …), validation raises a ValueError before the compat handler ever runs — even though the compat handler exists specifically to migrate those names.
The result is that legacy WaveformExtractor folders that SI is otherwise still able to read cannot be loaded on SI ≥ 0.104 without rewriting params.json on disk, which is not always possible (e.g. Code Ocean data assets are immutable).
Reproduction
Create or obtain a WaveformExtractor folder that has a template_metrics or quality_metrics extension whose params.json contains any deprecated metric name. For example, a template_metrics/params.json with:
{
"metric_names": ["peak_to_valley", "velocity_above", "velocity_below"],
"metric_params": {
"velocity_above": {"min_channels_for_velocity": 3, "min_r2_velocity": 0.5}
}
}
Then:
import spikeinterface as si
from spikeinterface.core import load_sorting_analyzer_or_waveforms
analyzer = load_sorting_analyzer_or_waveforms("/path/to/legacy_waveforms")
yields:
ValueError: The metric 'peak_to_valley' has been re-named or re-organized.
You can now compute it using the metric name 'peak_to_trough_duration'.
The metric 'velocity_above' has been re-named or re-organized.
You can now compute it using the metric name 'velocity_fits'.
...
Root cause
waveforms_extractor_backwards_compatibility.py:631-637 runs:
new_params = ext._set_params()
updated_params = make_ext_params_up_to_date(ext, params, new_params)
ext.set_params(**updated_params, save=False) # ← validation fires here
if ext.need_backward_compatibility_on_load:
ext._handle_backward_compatibility_on_load() # ← never reached
The deprecated-name validation in BaseMetricExtension._set_params (analyzer_extension_core.py:1127-1134) exists to catch code paths that are constructing extensions with old names at runtime. But it's also triggered on the legacy load path, where the deprecated names come from on-disk params.json — which is exactly the case the per-extension _handle_backward_compatibility_on_load handlers are designed to handle.
ComputeTemplateMetrics._handle_backward_compatibility_on_load (metrics/template/template_metrics.py:100-171) has full, authoritative migration logic for num_positive_peaks/num_negative_peaks → number_of_peaks, velocity_above/velocity_below → velocity_fits (including renaming min_channels_for_velocity → min_channels etc. inside metric_params), peak_to_valley → peak_to_trough_duration, and peak_trough_ratio → waveform_ratios. ComputeQualityMetrics._handle_backward_compatibility_on_load does the same for isolation_distance/l_ratio → mahalanobis. None of it runs, because validation aborts the load first.
Proposed fix
Catch the deprecation ValueError in _read_old_waveforms_extractor_binary, install the raw params on the extension so the compat handler can see them, run the handler, and replay set_params with the migrated values:
# waveforms_extractor_backwards_compatibility.py, replacing lines 634-637
try:
ext.set_params(**updated_params, save=False)
except ValueError as e:
if "has been re-named or re-organized" not in str(e):
raise
# Legacy params.json contains deprecated metric names. Install the
# raw params so _handle_backward_compatibility_on_load can see them,
# run the compat handler to rename metric_names AND migrate
# metric_params sub-keys, then replay set_params with migrated values.
ext.params = dict(updated_params)
if ext.need_backward_compatibility_on_load:
ext._handle_backward_compatibility_on_load()
ext.set_params(**ext.params, save=False)
else:
if ext.need_backward_compatibility_on_load:
ext._handle_backward_compatibility_on_load()
The contained change: one function, no signature changes, non-legacy folders take the existing fast path. Happy to send a PR if this approach looks reasonable.
Environment
- spikeinterface: 0.104.1
- python: 3.13
_read_old_waveforms_extractor_binaryinspikeinterface/core/waveforms_extractor_backwards_compatibility.pyinvokesext.set_params()(which triggers_set_params()validation) before runningext._handle_backward_compatibility_on_load(). For extensions whose on-diskparams.jsoncontains metric names that were renamed in 0.104 (e.g.peak_to_valley,velocity_above,l_ratio, …), validation raises aValueErrorbefore the compat handler ever runs — even though the compat handler exists specifically to migrate those names.The result is that legacy
WaveformExtractorfolders that SI is otherwise still able to read cannot be loaded on SI ≥ 0.104 without rewritingparams.jsonon disk, which is not always possible (e.g. Code Ocean data assets are immutable).Reproduction
Create or obtain a WaveformExtractor folder that has a
template_metricsorquality_metricsextension whoseparams.jsoncontains any deprecated metric name. For example, atemplate_metrics/params.jsonwith:{ "metric_names": ["peak_to_valley", "velocity_above", "velocity_below"], "metric_params": { "velocity_above": {"min_channels_for_velocity": 3, "min_r2_velocity": 0.5} } }Then:
yields:
Root cause
waveforms_extractor_backwards_compatibility.py:631-637runs:The deprecated-name validation in
BaseMetricExtension._set_params(analyzer_extension_core.py:1127-1134) exists to catch code paths that are constructing extensions with old names at runtime. But it's also triggered on the legacy load path, where the deprecated names come from on-diskparams.json— which is exactly the case the per-extension_handle_backward_compatibility_on_loadhandlers are designed to handle.ComputeTemplateMetrics._handle_backward_compatibility_on_load(metrics/template/template_metrics.py:100-171) has full, authoritative migration logic fornum_positive_peaks/num_negative_peaks→number_of_peaks,velocity_above/velocity_below→velocity_fits(including renamingmin_channels_for_velocity→min_channelsetc. insidemetric_params),peak_to_valley→peak_to_trough_duration, andpeak_trough_ratio→waveform_ratios.ComputeQualityMetrics._handle_backward_compatibility_on_loaddoes the same forisolation_distance/l_ratio→mahalanobis. None of it runs, because validation aborts the load first.Proposed fix
Catch the deprecation
ValueErrorin_read_old_waveforms_extractor_binary, install the raw params on the extension so the compat handler can see them, run the handler, and replayset_paramswith the migrated values:The contained change: one function, no signature changes, non-legacy folders take the existing fast path. Happy to send a PR if this approach looks reasonable.
Environment