def check_kwargs_simple_matching(recording, we, kwargs):
    d = _default_simple_matching.copy()
    d.update(kwargs)

    if d['noise_levels'] is None:
        d['noise_levels'] = get_noise_levels(recording,
                                             **d['random_chunk_kwargs'])

    d['abs_threholds'] = d['noise_levels'] * d['detect_threshold']

    channel_distance = get_channel_distances(recording)
    d['neighbours_mask'] = channel_distance < d['local_radius_um']

    return d
def test_detect_peaks():

    repo = 'https://gin.g-node.org/NeuralEnsemble/ephy_testing_data'
    remote_path = 'mearec/mearec_test_10s.h5'
    local_path = download_dataset(repo=repo, remote_path=remote_path, local_folder=None)
    recording = MEArecRecordingExtractor(local_path)

    # by_channel

    noise_levels = get_noise_levels(recording, return_scaled=False)

    peaks = detect_peaks(recording, method='by_channel',
                         peak_sign='neg', detect_threshold=5, n_shifts=2,
                         chunk_size=10000, verbose=1, progress_bar=False, noise_levels=noise_levels)



    subset_peaks = select_peaks(peaks, max_peaks_per_channel=100)
    subset_peaks = select_peaks(peaks, 'smart_sampling', max_peaks_per_channel=100, noise_levels=noise_levels)

    assert len(subset_peaks) < len(peaks)
def test_find_spikes_from_templates():

    repo = 'https://gin.g-node.org/NeuralEnsemble/ephy_testing_data'
    remote_path = 'mearec/mearec_test_10s.h5'
    local_path = download_dataset(repo=repo,
                                  remote_path=remote_path,
                                  local_folder=None)
    recording, gt_sorting = read_mearec(local_path)

    folder = 'waveforms_mearec'
    we = extract_waveforms(recording,
                           gt_sorting,
                           folder,
                           load_if_exists=True,
                           ms_before=1,
                           ms_after=2.,
                           max_spikes_per_unit=500,
                           return_scaled=False,
                           n_jobs=1,
                           chunk_size=10000)

    method_kwargs = {
        'waveform_extractor': we,
        'noise_levels': get_noise_levels(recording),
    }

    sampling_frequency = recording.get_sampling_frequency()

    result = {}

    for method in template_matching_methods.keys():
        spikes = find_spikes_from_templates(recording,
                                            method=method,
                                            method_kwargs=method_kwargs,
                                            n_jobs=1,
                                            chunk_size=30000,
                                            progress_bar=True)

        result[method] = NumpySorting.from_times_labels(
            spikes['sample_ind'], spikes['cluster_ind'], sampling_frequency)
Example #4
0
def detect_peaks(recording,
                 method='by_channel',
                 peak_sign='neg',
                 detect_threshold=5,
                 n_shifts=2,
                 local_radius_um=100,
                 noise_levels=None,
                 random_chunk_kwargs={},
                 outputs='numpy_compact',
                 **job_kwargs):
    """
    Peak detection ported from tridesclous into spikeinterface.

    Peak detection based on threhold crossing in term of k x MAD
    
    Ifg the MAD is not provide then it is estimated with random snipet
    
    Several methods:

      * 'by_channel' : peak are dettected in each channel independantly
      * 'locally_exclusive' : locally given a radius the best peak only is taken but
          not neirbhoring channels

    Parameters
    ----------
    recording: RecordingExtractor
        The recording extractor object
    
    method: 
    
    peak_sign='neg'/ 'pos' / 'both'
        Signa of the peak.
    detect_threshold: float
        Threshold in median absolute deviations (MAD) to detect peaks
    n_shifts: int
        Number of shifts to find peak. E.g. if n_shift is 2, a peak is detected (if detect_sign is 'negative') if
        a sample is below the threshold, the two samples before are higher than the sample, and the two samples after
        the sample are higher than the sample.
    noise_levels: np.array
        noise_levels can be provide externally if already computed.
    random_chunk_kwargs: dict
        A dict that contain option to randomize chunk for get_noise_levels()
        Only used if noise_levels is None
    numpy_compact: str numpy_compact/numpy_split/sorting
        The type of the output. By default "numpy_compact"
        give a vector with complex dtype.
    """
    assert method in ('by_channel', 'locally_exclusive')
    assert peak_sign in ('both', 'neg', 'pos')
    assert outputs in ('numpy_compact', 'numpy_split', 'sorting')

    if method == 'locally_exclusive' and not HAVE_NUMBA:
        raise ModuleNotFoundError(
            '"locally_exclusive" need numba which is not installed')

    if noise_levels is None:
        noise_levels = get_noise_levels(recording, **random_chunk_kwargs)

    abs_threholds = noise_levels * detect_threshold

    if method == 'locally_exclusive':
        assert local_radius_um is not None
        channel_distance = get_channel_distances(recording)
        neighbours_mask = channel_distance < local_radius_um
    else:
        neighbours_mask = None

    # and run
    func = _detect_peaks_chunk
    init_func = _init_worker_detect_peaks
    init_args = (recording.to_dict(), method, peak_sign, abs_threholds,
                 n_shifts, neighbours_mask)
    processor = ChunkRecordingExecutor(recording,
                                       func,
                                       init_func,
                                       init_args,
                                       handle_returns=True,
                                       **job_kwargs)
    peaks = processor.run()

    peak_sample_inds, peak_chan_inds, peak_amplitudes, peak_segments = zip(
        *peaks)
    peak_sample_inds = np.concatenate(peak_sample_inds)
    peak_chan_inds = np.concatenate(peak_chan_inds)
    peak_amplitudes = np.concatenate(peak_amplitudes)
    peak_segments = np.concatenate(peak_segments)

    if outputs == 'numpy_compact':
        dtype = [('sample_ind', 'int64'), ('channel_ind', 'int64'),
                 ('amplitude', 'float64'), ('segment_ind', 'int64')]
        peaks = np.zeros(peak_sample_inds.size, dtype=dtype)
        peaks['sample_ind'] = peak_sample_inds
        peaks['channel_ind'] = peak_chan_inds
        peaks['amplitude'] = peak_amplitudes
        peaks['segment_ind'] = peak_segments
        return peaks
    elif outputs == 'numpy_split':
        return peak_sample_inds, peak_chan_inds, peak_amplitudes, peak_segments
    elif outputs == 'sorting':
        #@alessio : here we can do what you did in old API
        # the output is a sorting where unit_id is in fact one channel
        raise NotImplementedError
def detect_peaks(recording,
                 method='by_channel',
                 peak_sign='neg',
                 detect_threshold=5,
                 n_shifts=2,
                 local_radius_um=50,
                 noise_levels=None,
                 random_chunk_kwargs={},
                 outputs='numpy_compact',
                 localization_dict=None,
                 **job_kwargs):
    """Peak detection based on threshold crossing in term of k x MAD.

    Parameters
    ----------
    recording: RecordingExtractor
        The recording extractor object.
    method: 'by_channel', 'locally_exclusive'
        Method to use. Options:
            * 'by_channel' : peak are detected in each channel independently
            * 'locally_exclusive' : a single best peak is taken from a set of neighboring channels
    peak_sign: 'neg', 'pos', 'both'
        Sign of the peak.
    detect_threshold: float
        Threshold, in median absolute deviations (MAD), to use to detect peaks.
    n_shifts: int
        Number of shifts to find peak.
        For example, if `n_shift` is 2, a peak is detected if a sample crosses the threshold,
        and the two samples before and after are above the sample.
    local_radius_um: float
        The radius to use for detection across local channels.
    noise_levels: array, optional
        Estimated noise levels to use, if already computed.
        If not provide then it is estimated from a random snippet of the data.
    random_chunk_kwargs: dict, optional
        A dict that contain option to randomize chunk for get_noise_levels().
        Only used if noise_levels is None.
    outputs: 'numpy_compact', 'numpy_split', 'sorting'
        The type of the output. By default, "numpy_compact" returns an array with complex dtype.
        In case of 'sorting', each unit corresponds to a recording channel.
    localization_dict : dict, optional
        Can optionally do peak localization at the same time as detection.
        This avoids running `localize_peaks` separately and re-reading the entire dataset.
    {}

    Returns
    -------
    peaks: array
        Detected peaks.

    Notes
    -----
    This peak detection ported from tridesclous into spikeinterface.
    """

    assert method in ('by_channel', 'locally_exclusive')
    assert peak_sign in ('both', 'neg', 'pos')
    assert outputs in ('numpy_compact', 'numpy_split', 'sorting')

    if method == 'locally_exclusive' and not HAVE_NUMBA:
        raise ModuleNotFoundError(
            '"locally_exclusive" need numba which is not installed')

    if noise_levels is None:
        noise_levels = get_noise_levels(recording,
                                        return_scaled=False,
                                        **random_chunk_kwargs)

    abs_threholds = noise_levels * detect_threshold

    if method == 'locally_exclusive':
        assert local_radius_um is not None
        channel_distance = get_channel_distances(recording)
        neighbours_mask = channel_distance < local_radius_um
    else:
        neighbours_mask = None

    # deal with margin
    if localization_dict is None:
        extra_margin = 0
    else:
        assert isinstance(localization_dict, dict)
        assert localization_dict['method'] in dtype_localize_by_method.keys()
        localization_dict = init_kwargs_dict(localization_dict['method'],
                                             localization_dict)

        nbefore = int(localization_dict['ms_before'] *
                      recording.get_sampling_frequency() / 1000.)
        nafter = int(localization_dict['ms_after'] *
                     recording.get_sampling_frequency() / 1000.)
        extra_margin = max(nbefore, nafter)

    # and run
    func = _detect_peaks_chunk
    init_func = _init_worker_detect_peaks
    init_args = (recording.to_dict(), method, peak_sign, abs_threholds,
                 n_shifts, neighbours_mask, extra_margin, localization_dict)
    processor = ChunkRecordingExecutor(recording,
                                       func,
                                       init_func,
                                       init_args,
                                       handle_returns=True,
                                       job_name='detect peaks',
                                       **job_kwargs)
    peaks = processor.run()
    peaks = np.concatenate(peaks)

    if outputs == 'numpy_compact':
        return peaks
    elif outputs == 'sorting':
        return NumpySorting.from_peaks(
            peaks, sampling_frequency=recording.get_sampling_frequency())
Example #6
0
def detect_peaks(recording,
                 method='by_channel',
                 peak_sign='neg',
                 detect_threshold=5,
                 n_shifts=2,
                 local_radius_um=50,
                 noise_levels=None,
                 random_chunk_kwargs={},
                 outputs='numpy_compact',
                 localization_dict=None,
                 **job_kwargs):
    """
    Peak detection ported from tridesclous into spikeinterface.

    Peak detection based on threhold crossing in term of k x MAD
    
    If the MAD is not provide then it is estimated with random snipet
    
    Several methods:

      * 'by_channel' : peak are dettected in each channel independantly
      * 'locally_exclusive' : locally given a radius the best peak only is taken but
        not neighboring channels

    Parameters
    ----------
    recording: RecordingExtractor
        The recording extractor object
    
    method: 
    
    peak_sign='neg'/ 'pos' / 'both'
        Signa of the peak.
    detect_threshold: float
        Threshold in median absolute deviations (MAD) to detect peaks
    n_shifts: int
        Number of shifts to find peak. E.g. if n_shift is 2, a peak is detected (if detect_sign is 'negative') if
        a sample is below the threshold, the two samples before are higher than the sample, and the two samples after
        the sample are higher than the sample.
    noise_levels: np.array
        noise_levels can be provide externally if already computed.
    random_chunk_kwargs: dict
        A dict that contain option to randomize chunk for get_noise_levels()
        Only used if noise_levels is None
    numpy_compact: str numpy_compact/numpy_split/sorting
        The type of the output. By default "numpy_compact"
        give a vector with complex dtype.
    localization_dict : None or dict
        Can optionally do peak localisation at the same time as detection.
        This avoids to run localize_peaks separately and re read the entire dataset.
    
    job_kwargs: dict
        Parameters for ChunkRecordingExecutor
    """
    assert method in ('by_channel', 'locally_exclusive')
    assert peak_sign in ('both', 'neg', 'pos')
    assert outputs in ('numpy_compact', 'numpy_split', 'sorting')

    if method == 'locally_exclusive' and not HAVE_NUMBA:
        raise ModuleNotFoundError(
            '"locally_exclusive" need numba which is not installed')

    if noise_levels is None:
        noise_levels = get_noise_levels(recording, **random_chunk_kwargs)

    abs_threholds = noise_levels * detect_threshold

    if method == 'locally_exclusive':
        assert local_radius_um is not None
        channel_distance = get_channel_distances(recording)
        neighbours_mask = channel_distance < local_radius_um
    else:
        neighbours_mask = None

    # deal with margin
    if localization_dict is None:
        extra_margin = 0
    else:
        assert isinstance(localization_dict, dict)
        assert localization_dict['method'] in dtype_localize_by_method.keys()
        localization_dict = init_kwargs_dict(localization_dict['method'],
                                             localization_dict)

        nbefore = int(localization_dict['ms_before'] *
                      recording.get_sampling_frequency() / 1000.)
        nafter = int(localization_dict['ms_after'] *
                     recording.get_sampling_frequency() / 1000.)
        extra_margin = max(nbefore, nafter)

    # and run
    func = _detect_peaks_chunk
    init_func = _init_worker_detect_peaks
    init_args = (recording.to_dict(), method, peak_sign, abs_threholds,
                 n_shifts, neighbours_mask, extra_margin, localization_dict)
    processor = ChunkRecordingExecutor(recording,
                                       func,
                                       init_func,
                                       init_args,
                                       handle_returns=True,
                                       job_name='detect peaks',
                                       **job_kwargs)
    peaks = processor.run()
    peaks = np.concatenate(peaks)

    if outputs == 'numpy_compact':
        return peaks
    elif outputs == 'sorting':
        # @alessio : here we can do what you did in old API
        # the output is a sorting where unit_id is in fact one channel
        raise NotImplementedError