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)
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())
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