def intervals_from_traces(recording: RecordingExtractor): """Extract interval times from TTL pulses.""" traces = recording.get_traces(channel_ids=[1, 2]) sf = recording.get_sampling_frequency() ttls = [] states = [] for tr in traces: threshold = np.ptp(tr) / 2 + np.min(tr) crossings = np.array(tr > threshold).astype("int8") rising = np.nonzero(np.diff(crossings, 1) > 0)[0] falling = np.nonzero(np.diff(crossings, 1) < 0)[0] ttl = np.concatenate((rising, falling)) sort_order = np.argsort(ttl) ttl = np.sort(ttl) state = [1] * len(rising) + [-1] * len(falling) state = np.array(state)[sort_order] ttls.append(ttl) states.append(state) conditions = [] for ttl, state in zip(ttls, states): assert len(ttl[state == 1]) == len( ttl[state == -1]), "Different number of rising/falling edges!" condition = np.zeros((len(ttl[state == 1]), 2), dtype="int") condition[:, 0] = ttl[state == 1] / sf condition[:, 1] = ttl[state == -1] / sf conditions.append(condition) return conditions
def estimate_noise_level(recording: se.RecordingExtractor): N = recording.get_num_frames() samplerate = recording.get_sampling_frequency() start_frame = 0 end_frame = int(np.minimum(samplerate * 1, N)) X = recording.get_traces( channel_ids=[int(id) for id in recording.get_channel_ids()], start_frame=start_frame, end_frame=end_frame) est_noise_level = np.median(np.abs(X.squeeze( ))) / 0.6745 # median absolute deviation (MAD) estimate of stdev if (est_noise_level == 0): est_noise_level = 1 return est_noise_level
def ephys_nlm_v1(recording: se.RecordingExtractor, *, opts: EphysNlmV1Opts, device: Union[None, str], verbose: int = 1) -> Tuple[OutputRecordingExtractor, EphysNlmV1Info]: """Denoise an ephys recording using non-local means. The input and output recordings are RecordingExtractors from SpikeInterface. Parameters ---------- recording : se.RecordingExtractor The ephys recording to denoise (see SpikeInterface) opts : EphysNlmV1Opts Options created using EphysNlmV1Opts(...) device : Union[str, None] Either cuda or cpu (cuda is highly recommended, but you need to have CUDA/PyTorch working on your system). If None, then the EPHYS_NLM_DEVICE environment variable will be used. verbose : int, optional Verbosity level, by default 1 Returns ------- Tuple[OutputRecordingExtractor, EphysNlmV1Info] The output recording extractor see SpikeInterface and info about the run """ channel_ids = recording.get_channel_ids() M = len(channel_ids) N = recording.get_num_frames() T = opts.clip_size assert T % 2 == 0, 'clip size must be divisible by 2.' info = EphysNlmV1Info() info.recording = recording info.opts = opts info.start_time = time.time() if opts.block_size is None: if opts.block_size_sec is None: raise Exception('block_size and block_size_sec are both None') opts.block_size = int( recording.get_sampling_frequency() * opts.block_size_sec) block_size = opts.block_size N = recording.get_num_frames() num_blocks = max(1, math.floor(N / block_size)) assert opts.sigma == 'auto', 'Only sigma=auto allowed at this time' assert opts.whitening == 'auto', 'Only whitening=auto allowed at this time' if device is None: device = os.getenv('EPHYS_NLM_DEVICE', None) if device is None or device == '': print('Warning: EPHYS_NLM_DEVICE not set -- defaulting to cpu. To use GPU, set EPHYS_NLM_DEVICE=cuda') device = 'cpu' elif device == 'cpu': print('Using device=cpu. Warning: GPU is much faster. To use GPU, set device=cuda') if device == 'cuda': assert torch.cuda.is_available(), f'Cannot use device=cuda. PyTorch/CUDA is not configured properly -- torch.cuda.is_available() is returning False.' print('Using device=cuda') elif device == 'cpu': print('Using device=cpu') else: raise Exception(f'Invalid device: {device}') # pragma: no cover info.device = device opts._device = device # for convenience neighborhoods = _get_neighborhoods(recording=recording, opts=opts) if verbose >= 1: print(f'Denoising recording of size {M} x {N} using {len(neighborhoods)} neighborhoods and {num_blocks} time blocks') initial_traces = recording.get_traces( start_frame=0, end_frame=min(N, block_size)) _estimate_sigma_and_whitening( traces=initial_traces, neighborhoods=neighborhoods, opts=opts, verbose=verbose) recording_out = OutputRecordingExtractor( base_recording=recording, block_size=opts.block_size) for ii in range(num_blocks): if verbose >= 1: print(f'Denoising block {ii} of {num_blocks}') t1 = ii * block_size t2 = t1 + block_size # The last block is potentially larger if ii == num_blocks - 1: t2 = N block_traces = recording.get_traces(start_frame=t1, end_frame=t2) block_traces_denoised, block_info = _denoise_block( traces=block_traces, opts=opts, neighborhoods=neighborhoods, verbose=verbose ) info.blocks.append(block_info) recording_out.add_block(block_traces_denoised) info.end_time = time.time() info.elapsed_time = info.end_time - info.start_time return recording_out, info