Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refractory Period Distance? #3567

Open
karmenrai2 opened this issue Dec 3, 2024 · 7 comments
Open

Refractory Period Distance? #3567

karmenrai2 opened this issue Dec 3, 2024 · 7 comments
Labels
question General question regarding SI

Comments

@karmenrai2
Copy link

karmenrai2 commented Dec 3, 2024

when calculating refractory period violations, I am getting nan for several of the values. Does this mean there are no violations as I can't see any value with 0 or did the calculation fail and it's inconclusive?

import spikeinterface as si
import spikeinterface.extractors as se
import spikeinterface.widgets as sw
import spikeinterface.qualitymetrics as sqm
from spikeinterface.extractors import read_phy
from probeinterface import get_probe
from pathlib import Path
import numpy as np
import csv


# Cluster iterator
i = 0

# File paths 
rec_file_path = Path(r"C:\Users\cognp\Documents\Kilosort4\kilosort4data_day4\continuous1.dat") # Recording file
sort_file_path = Path(r"C:\Users\cognp\Documents\Kilosort4\kilosort4data_day4") # Folder with the kilosort data
cluster_label = Path(r"C:\Users\cognp\Documents\Kilosort4\kilosort4data_day4\spike_clusters.npy") # spike_clusters npy file
pcs = Path(r"C:\Users\cognp\Documents\Kilosort4\kilosort4data_day4\spike_positions.npy") # spike_positions npy file

# Define recording parameters
sampling_frequency = 30_000.0  
num_channels = 384  
dtype = "float64"  

# Load data using SpikeInterface
recording = si.read_binary(file_paths=rec_file_path, sampling_frequency=sampling_frequency,
                           num_channels=num_channels, dtype=dtype)
sorting = read_phy(sort_file_path)

# Load data using numpy
all_labels = np.load(cluster_label)
all_pcs = np.load(pcs)

# Set the probe
other_probe = get_probe('cambridgeneurotech', 'ASSY-37-E-1')
other_probe.set_device_channel_indices(np.arange(32))
recording = recording.set_probe(other_probe, group_mode='by_shank')

# Create sorting analyzer
analyzer = si.create_sorting_analyzer(sorting=sorting, recording=recording, format="memory")

# Quality Metrics
presence_ratio = sqm.compute_presence_ratios(sorting_analyzer=analyzer)
refractory_period = sqm.compute_sliding_rp_violations(sorting_analyzer=analyzer, bin_size_ms=0.25, exclude_ref_period_below_ms=0.5)

# CSV file 
with open('spikesorting.csv', 'w') as file:
    writer = csv.writer(file)
    writer.writerow(["Cluster", "Presence Ratio", "Amplitude Cutoff", "Isolation Distance", "Refractory Period Violations"])
    for cluster in presence_ratio.keys():
        isolation_distance, _ = sqm.mahalanobis_metrics(all_pcs=all_pcs, all_labels=all_labels, this_unit_id=cluster)
        i+=1
        print(str(i) + "th cluster done")
        writer.writerow([cluster, presence_ratio[cluster], isolation_distance, refractory_period.get(cluster, "")])

# Print data for verification
print(recording)
print(sorting)
print(analyzer)
print(presence_ratio)
print(refractory_period)
exit()`
Cluster Presence Ratio Amplitude Cutoff Isolation Distance Refractory Period Violations
         
0 1 nan 1.89105441986244 0.11
         
1 1 nan 21.9754870562538 0.015
         
2 1 nan 2.08639005321337 0.01
         
3 1 nan 1.42021378063038 nan
         
4 1 nan 0.614645809462376 0.185
         
5 1 nan 0.209511255264518 nan
         
6 1 nan 0.548317966330339 0.265
         
7 1 nan 0.492024220726647 nan
         
8 1 nan 0.0672568742271259 nan
         
9 1 nan 2.09064727504505 0.065
         
10 1 nan 0.64246598552092 0.2
         
11 1 nan 1.75604923652422 0.035
         
12 1 nan 16.469823279801 0.02
         
13 1 nan 19.148817333648 0.025
         
14 1 nan 81.7195861151427 nan
         
15 1 nan 24.3185509096019 0.01
         
16 1 nan 2.01138983826387 0.02
         
17 1 nan 0.159849371240687 nan
         
18 1 nan 2.73207881475302 0.11
         
19 1 nan 6.44073858039389 0.025
@zm711
Copy link
Collaborator

zm711 commented Dec 3, 2024

Hey @karmenrai2

So if you look here:

if unit_n_spikes <= min_spikes:
contamination[unit_id] = np.nan
continue

you see the assumption you like failed in using the sliding_rp. You could try using one of our other rp violation metrics which all have their different assumptions (we explain some of the assumptions/math in the docs see:
https://spikeinterface.readthedocs.io/en/stable/modules/qualitymetrics/sliding_rp_violations.html
and
https://spikeinterface.readthedocs.io/en/stable/modules/qualitymetrics/isi_violations.html

If you need more detail then that you could look in the actual code to see what is happening or ask more questions here :)

In general nan would indicate failed assumptions for any of our metrics (for example isolation distance fails if the covariance matrix is singular for a unit).

@zm711 zm711 added the question General question regarding SI label Dec 3, 2024
@zm711
Copy link
Collaborator

zm711 commented Dec 13, 2024

Out of curiosity is there a reason you want to do all of this at the low level rather than using the SortingAnalyzer object that will already great and save a pandas dataframe of all quality metrics for you?

@karmenrai2
Copy link
Author

Thank you. The ISI violations seemed to work.

@karmenrai2
Copy link
Author

karmenrai2 commented Jan 9, 2025

@zm711 Also, how do I obtain this "pandas dataframe" you speak of.

@zm711
Copy link
Collaborator

zm711 commented Jan 9, 2025

Hey @karmenrai2,

sure. So what you can do with spikeinterface is something like this:

recording = si.read_binary(xx)
sorting = si.read_phy(xx)

# binary folder will give you a csv. We also offer a zarr backend which adds compression
analyzer = si.create_sorting_analyzer(sorting, recording, format='binary_folder', folder='where you want to save')

analyzer.compute(['random_spikes', 'waveforms', 'templates', 'noise_levels', 'template_similarity', 'spike_amplitudes', 'principal_components', 'qualitrymetrics'])

This will save csv of all the qualitry metrics for you.

Otherwise to use the pandas dataframe you would do

quality_df = analyzer.get_extension('qualitymetrics').get_data()

and the quality_df will be a dataframe of all the values. We have tons of stuff about how to use the analyzer and you can fine tune your analyses for exactly what you need. So I'll share the docs here so take a look if you want to understand what is actually happening.

Let us know if you don't understand something.

@karmenrai2
Copy link
Author

karmenrai2 commented Jan 14, 2025

When trying this im getitng the error.
File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\core\sortinganalyzer.py", line 1811, in get_extension_class raise ValueError(f"Extension '{extension_name}' is unknown maybe this is an external extension or a typo.") ValueError: Extension 'qualitymetrics' is unknown maybe this is an external extension or a typo.

I proceeded to change it to 'quality_metrics' but then I got this error.

C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\core\waveform_tools.py:894: RuntimeWarning: invalid value encountered in subtract
  waveforms_squared_sum[unit_index] - 2 * template_means[unit_index] * waveforms_sum[unit_index]
C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\core\recording_tools.py:687: RuntimeWarning: invalid value encountered in subtract
  noise_levels = np.median(np.abs(random_chunks - med), axis=0) / 0.6744897501960817
Traceback (most recent call last):
  File "c:\Users\cognp\Documents\npyfiles\sort.py", line 44, in <module>
    analyzer.compute(['random_spikes', 'templates', 'noise_levels', 'template_similarity', 'spike_amplitudes', 'principal_components', 'quality_metrics'])
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\core\sortinganalyzer.py", line 1339, in compute
    self.compute_several_extensions(extensions=extensions, save=save, verbose=verbose, **job_kwargs)
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\core\sortinganalyzer.py", line 1466, in compute_several_extensions
    self.compute_one_extension(extension_name, save=save, verbose=verbose, **extension_params)
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\core\sortinganalyzer.py", line 1405, in compute_one_extension
    extension_instance.run(save=save, verbose=verbose)
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\core\sortinganalyzer.py", line 2164, in run
    self._run(**kwargs)
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\postprocessing\template_similarity.py", line 130, in _run
    similarity = compute_similarity_with_templates_array(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\postprocessing\template_similarity.py", line 233, in compute_similarity_with_templates_array
    distances[count, i, j] = sklearn.metrics.pairwise.pairwise_distances(
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\utils\_param_validation.py", line 213, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\metrics\pairwise.py", line 2375, in pairwise_distances
    return _parallel_pairwise(X, Y, func, n_jobs, **kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\metrics\pairwise.py", line 1893, in _parallel_pairwise
    return func(X, Y, **kwds)
           ^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\utils\_param_validation.py", line 186, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\metrics\pairwise.py", line 1130, in cosine_distances
    S = cosine_similarity(X, Y)
        ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\utils\_param_validation.py", line 186, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\metrics\pairwise.py", line 1679, in cosine_similarity
    X, Y = check_pairwise_arrays(X, Y)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\metrics\pairwise.py", line 185, in check_pairwise_arrays
    X = check_array(
        ^^^^^^^^^^^^
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\utils\validation.py", line 1064, in check_array
    _assert_all_finite(
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\utils\validation.py", line 123, in _assert_all_finite
    _assert_all_finite_element_wise(
  File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\sklearn\utils\validation.py", line 172, in _assert_all_finite_element_wise
    raise ValueError(msg_err)
ValueError: Input contains NaN.

@zm711
Copy link
Collaborator

zm711 commented Jan 14, 2025

When trying this im getitng the error.
File "C:\Users\cognp\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\spikeinterface\core\sortinganalyzer.py", line 1811, in get_extension_class raise ValueError(f"Extension '{extension_name}' is unknown maybe this is an external extension or a typo.") ValueError: Extension 'qualitymetrics' is unknown maybe this is an external extension or a typo.

That was my typo. Sorry. It is quality_metrics.

That's a strange error. How are you getting these neurons (ie what sorter and what recording equipment)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question General question regarding SI
Projects
None yet
Development

No branches or pull requests

2 participants