def _initialize_subrecording_extractor(self, recording): if isinstance(self._bad_channel_ids, (list, np.ndarray)): active_channels = [] for chan in recording.get_channel_ids(): if chan not in self._bad_channel_ids: active_channels.append(chan) self._subrecording = SubRecordingExtractor( recording, channel_ids=active_channels) elif self._bad_channel_ids is None: start_frame = recording.get_num_frames() // 2 end_frame = int(start_frame + self._seconds * recording.get_sampling_frequency()) if end_frame > recording.get_num_frames(): end_frame = recording.get_num_frames() traces = recording.get_traces(start_frame=start_frame, end_frame=end_frame) stds = np.std(traces, axis=1) bad_channel_ids = [ ch for ch, std in enumerate(stds) if std > self._bad_threshold * np.median(stds) ] if self.verbose: print('Automatically removing channels:', bad_channel_ids) active_channels = [] for chan in recording.get_channel_ids(): if chan not in bad_channel_ids: active_channels.append(chan) self._subrecording = SubRecordingExtractor( recording, channel_ids=active_channels) else: self._subrecording = recording self.active_channels = self._subrecording.get_channel_ids()
class RemoveBadChannelsRecording(BasePreprocessorRecordingExtractor): preprocessor_name = 'RemoveBadChannels' def __init__(self, recording, bad_channel_ids, bad_threshold, seconds, verbose): self._bad_channel_ids = bad_channel_ids self._bad_threshold = bad_threshold self._seconds = seconds self.verbose = verbose self._initialize_subrecording_extractor(recording) BasePreprocessorRecordingExtractor.__init__(self, self._subrecording) self._kwargs = { 'recording': recording.make_serialized_dict(), 'bad_channel_ids': bad_channel_ids, 'bad_threshold': bad_threshold, 'seconds': seconds, 'verbose': verbose } @check_get_traces_args def get_traces(self, channel_ids=None, start_frame=None, end_frame=None): traces = self._subrecording.get_traces(channel_ids=channel_ids, start_frame=start_frame, end_frame=end_frame) return traces def _initialize_subrecording_extractor(self, recording): if isinstance(self._bad_channel_ids, (list, np.ndarray)): active_channels = [] for chan in recording.get_channel_ids(): if chan not in self._bad_channel_ids: active_channels.append(chan) self._subrecording = SubRecordingExtractor( recording, channel_ids=active_channels) elif self._bad_channel_ids is None: start_frame = recording.get_num_frames() // 2 end_frame = int(start_frame + self._seconds * recording.get_sampling_frequency()) if end_frame > recording.get_num_frames(): end_frame = recording.get_num_frames() traces = recording.get_traces(start_frame=start_frame, end_frame=end_frame) stds = np.std(traces, axis=1) bad_channel_ids = [ ch for ch, std in enumerate(stds) if std > self._bad_threshold * np.median(stds) ] if self.verbose: print('Automatically removing channels:', bad_channel_ids) active_channels = [] for chan in recording.get_channel_ids(): if chan not in bad_channel_ids: active_channels.append(chan) self._subrecording = SubRecordingExtractor( recording, channel_ids=active_channels) else: self._subrecording = recording self.active_channels = self._subrecording.get_channel_ids()
def get_sub_extractors_by_property(extractor, property_name, return_property_list=False): '''Returns a list of SubRecordingExtractors from this RecordingExtractor based on the given property_name (e.g. group) Parameters ---------- property_name: str The property used to subdivide the extractor return_property_list: bool If True the property list is returned Returns ------- sub_list: list The list of subextractors to be returned. OR sub_list, prop_list If return_property_list is True, the property list will be returned as well. ''' from spikeextractors import RecordingExtractor, SortingExtractor, SubRecordingExtractor, SubSortingExtractor if isinstance(extractor, RecordingExtractor): if property_name not in extractor.get_shared_channel_property_names(): raise ValueError("'property_name' must be must be a property of the recording channels") else: sub_list = [] recording = extractor properties = np.array([recording.get_channel_property(chan, property_name) for chan in recording.get_channel_ids()]) prop_list = np.unique(properties) for prop in prop_list: prop_idx = np.where(prop == properties) chan_idx = list(np.array(recording.get_channel_ids())[prop_idx]) sub_list.append(SubRecordingExtractor(recording, channel_ids=chan_idx)) if return_property_list: return sub_list, prop_list else: return sub_list elif isinstance(extractor, SortingExtractor): if property_name not in extractor.get_shared_unit_property_names(): raise ValueError("'property_name' must be must be a property of the units") else: sub_list = [] sorting = extractor properties = np.array([sorting.get_unit_property(unit, property_name) for unit in sorting.get_unit_ids()]) prop_list = np.unique(properties) for prop in prop_list: prop_idx = np.where(prop == properties) unit_idx = list(np.array(sorting.get_unit_ids())[prop_idx]) sub_list.append(SubSortingExtractor(sorting, unit_ids=unit_idx)) if return_property_list: return sub_list, prop_list else: return sub_list else: raise ValueError("'extractor' must be a RecordingExtractor or a SortingExtractor")
def getSubExtractorsByProperty(extractor, property_name): '''Divides Recording or Sorting Extractor based on the property_name (e.g. group) Parameters ---------- extractor: RecordingExtractor or SortingExtractor The extractor to be subdivided in subextractors property_name: str The property used to subdivide the extractor Returns ------- List of subextractors ''' if isinstance(extractor, RecordingExtractor): if property_name not in extractor.get_channel_property_names(): raise ValueError( "'property_name' must be must be a property of the recording channels" ) else: sub_list = [] recording = extractor properties = np.array([ recording.get_channel_property(chan, property_name) for chan in recording.get_channel_ids() ]) prop_list = np.unique(properties) for prop in prop_list: prop_idx = np.where(prop == properties) chan_idx = list( np.array(recording.get_channel_ids())[prop_idx]) sub_list.append( SubRecordingExtractor(recording, channel_ids=chan_idx)) return sub_list elif isinstance(extractor, SortingExtractor): if property_name not in extractor.get_unit_propertyNames(): raise ValueError( "'property_name' must be must be a property of the units") else: sub_list = [] sorting = extractor properties = np.array([ sorting.get_unit_property(unit, property_name) for unit in sorting.get_unit_ids() ]) prop_list = np.unique(properties) for prop in prop_list: prop_idx = np.where(prop == properties) unit_idx = list(np.array(sorting.get_unit_ids())[prop_idx]) sub_list.append(SubSortingExtractor(sorting, unit_ids=unit_idx)) return sub_list else: raise ValueError( "'extractor' must be a RecordingExtractor or a SortingExtractor")
def clip_recording( trial_numbers: Iterable, trial_times: Iterable, recording: RecordingExtractor = None) -> SubRecordingExtractor: """ Clip the recording to align with the trials information. It was found in the test data that sometimes the nidq and recording start at unreset trial values; this clips that end of the recording and returns all data and times starting from the new point (trial number zero). Parameters ---------- recording : RecordingExtractor If passed, will return a SubRecordingExtractor clipped to align with the trials info. """ return SubRecordingExtractor( parent_recording=recording, start_frame=recording.time_to_frame( times=trial_times[list(trial_numbers).index(0)][0]))
def load_probe_file(recording, probe_file, channel_map=None, channel_groups=None, verbose=False): '''This function returns a SubRecordingExtractor that contains information from the given probe file (channel locations, groups, etc.) If a .prb file is given, then 'location' and 'group' information for each channel is added to the SubRecordingExtractor. If a .csv file is given, then it will only add 'location' to the SubRecordingExtractor. Parameters ---------- recording: RecordingExtractor The recording extractor to channel information probe_file: str Path to probe file. Either .prb or .csv verbose: bool If True, output is verbose Returns --------- subrecording = SubRecordingExtractor The extractor containing all of the probe information. ''' from .subrecordingextractor import SubRecordingExtractor probe_file = Path(probe_file) if probe_file.suffix == '.prb': probe_dict = read_python(probe_file) if 'channel_groups' in probe_dict.keys(): ordered_channels = np.array([], dtype=int) groups = sorted(probe_dict['channel_groups'].keys()) for cgroup_id in groups: cgroup = probe_dict['channel_groups'][cgroup_id] for key_prop, prop_val in cgroup.items(): if key_prop == 'channels': ordered_channels = np.concatenate((ordered_channels, prop_val)) if not np.all([chan in recording.get_channel_ids() for chan in ordered_channels]) and verbose: print('Some channel in PRB file are not in original recording') present_ordered_channels = [chan for chan in ordered_channels if chan in recording.get_channel_ids()] subrecording = SubRecordingExtractor(recording, channel_ids=present_ordered_channels) for cgroup_id in groups: cgroup = probe_dict['channel_groups'][cgroup_id] if 'channels' not in cgroup.keys() and len(groups) > 1: raise Exception("If more than one 'channel_group' is in the probe file, the 'channels' field" "for each channel group is required") elif 'channels' not in cgroup.keys(): channels_in_group = subrecording.get_num_channels() channels_id_in_group = subrecording.get_channel_ids() else: channels_in_group = len(cgroup['channels']) channels_id_in_group = cgroup['channels'] for key_prop, prop_val in cgroup.items(): if key_prop == 'channels': for i_ch, prop in enumerate(prop_val): if prop in subrecording.get_channel_ids(): subrecording.set_channel_property(prop, 'group', int(cgroup_id)) elif key_prop == 'geometry' or key_prop == 'location': if isinstance(prop_val, dict): if len(prop_val.keys()) != channels_in_group and verbose: print('geometry in PRB does not have the same length as channel in group') for (i_ch, prop) in prop_val.items(): if i_ch in subrecording.get_channel_ids(): subrecording.set_channel_property(i_ch, 'location', prop) elif isinstance(prop_val, (list, np.ndarray)) and len(prop_val) == channels_in_group: if 'channels' not in cgroup.keys(): raise Exception("'geometry'/'location' in the .prb file can be a list only if " "'channels' field is specified.") if len(prop_val) != channels_in_group and verbose: print('geometry in PRB does not have the same length as channel in group') for (i_ch, prop) in zip(channels_id_in_group, prop_val): if i_ch in subrecording.get_channel_ids(): subrecording.set_channel_property(i_ch, 'location', prop) else: if isinstance(prop_val, dict) and len(prop_val.keys()) == channels_in_group: for (i_ch, prop) in prop_val.items(): if i_ch in subrecording.get_channel_ids(): subrecording.set_channel_property(i_ch, key_prop, prop) elif isinstance(prop_val, (list, np.ndarray)) and len(prop_val) == channels_in_group: for (i_ch, prop) in zip(channels_id_in_group, prop_val): if i_ch in subrecording.get_channel_ids(): subrecording.set_channel_property(i_ch, key_prop, prop) # create dummy locations if 'geometry' not in cgroup.keys() and 'location' not in cgroup.keys(): for i, chan in enumerate(subrecording.get_channel_ids()): subrecording.set_channel_property(chan, 'location', [0, i]) else: raise AttributeError("'.prb' file should contain the 'channel_groups' field") elif probe_file.suffix == '.csv': if channel_map is not None: assert np.all([chan in channel_map for chan in recording.get_channel_ids()]), \ "all channel_ids in 'channel_map' must be in the original recording channel ids" subrecording = SubRecordingExtractor(recording, channel_ids=channel_map) else: subrecording = SubRecordingExtractor(recording, channel_ids=recording.get_channel_ids()) with probe_file.open() as csvfile: posreader = csv.reader(csvfile) row_count = 0 loaded_pos = [] for pos in (posreader): row_count += 1 loaded_pos.append(pos) assert len(subrecording.get_channel_ids()) == row_count, "The .csv file must contain as many " \ "rows as the number of channels in the recordings" for i_ch, pos in zip(subrecording.get_channel_ids(), loaded_pos): if i_ch in subrecording.get_channel_ids(): subrecording.set_channel_property(i_ch, 'location', list(np.array(pos).astype(float))) if channel_groups is not None and len(channel_groups) == len(subrecording.get_channel_ids()): for i_ch, chg in zip(subrecording.get_channel_ids(), channel_groups): if i_ch in subrecording.get_channel_ids(): subrecording.set_channel_property(i_ch, 'group', chg) else: raise NotImplementedError("Only .csv and .prb probe files can be loaded.") subrecording._kwargs['probe_file'] = str(probe_file.absolute()) return subrecording
def loadProbeFile(recording, probe_file, channel_map=None, channel_groups=None): '''Loads channel information into recording extractor. If a .prb file is given, then 'location' and 'group' information for each channel is stored. If a .csv file is given, then it will only store 'location' Parameters ---------- recording: RecordingExtractor The recording extractor to channel information probe_file: str Path to probe file. Either .prb or .csv Returns --------- subRecordingExtractor ''' probe_file = Path(probe_file) if probe_file.suffix == '.prb': probe_dict = read_python(probe_file) if 'channel_groups' in probe_dict.keys(): ordered_channels = np.array([], dtype=int) groups = sorted(probe_dict['channel_groups'].keys()) for cgroup_id in groups: cgroup = probe_dict['channel_groups'][cgroup_id] for key_prop, prop_val in cgroup.items(): if key_prop == 'channels': ordered_channels = np.concatenate( (ordered_channels, prop_val)) if list(ordered_channels) == recording.get_channel_ids(): subrecording = recording else: assert np.all([chan in recording.get_channel_ids() for chan in ordered_channels]), \ "all channel_ids in the 'channels' section of the probe file " \ "must be in the original recording channel ids" subrecording = SubRecordingExtractor( recording, channel_ids=list(ordered_channels)) for cgroup_id in groups: cgroup = probe_dict['channel_groups'][cgroup_id] if 'channels' not in cgroup.keys() and len(groups) > 1: raise Exception( "If more than one 'channel_group' is in the probe file, the 'channels' field" "for each channel group is required") elif 'channels' not in cgroup.keys(): channels_in_group = subrecording.get_num_channels() else: channels_in_group = len(cgroup['channels']) for key_prop, prop_val in cgroup.items(): if key_prop == 'channels': for i_ch, prop in enumerate(prop_val): subrecording.set_channel_property( prop, 'group', int(cgroup_id)) elif key_prop == 'geometry' or key_prop == 'location': if isinstance(prop_val, dict) and len( prop_val.keys()) == channels_in_group: for (i_ch, prop) in prop_val.items(): subrecording.set_channel_property( i_ch, 'location', prop) elif isinstance(prop_val, (list, np.ndarray)) and len( prop_val) == channels_in_group: for (i_ch, prop) in zip(subrecording.get_channel_ids(), prop_val): subrecording.set_channel_property( i_ch, 'location', prop) else: if isinstance(prop_val, dict) and len( prop_val.keys()) == channels_in_group: for (i_ch, prop) in prop_val.items(): subrecording.set_channel_property( i_ch, key_prop, prop) elif isinstance(prop_val, (list, np.ndarray)) and len( prop_val) == channels_in_group: for (i_ch, prop) in zip(subrecording.get_channel_ids(), prop_val): subrecording.set_channel_property( i_ch, key_prop, prop) # create dummy locations if 'geometry' not in cgroup.keys( ) and 'location' not in cgroup.keys(): for i, chan in enumerate(subrecording.get_channel_ids()): subrecording.set_channel_property( chan, 'location', [i, 0]) else: raise AttributeError( "'.prb' file should contain the 'channel_groups' field") elif probe_file.suffix == '.csv': if channel_map is not None: assert np.all([chan in recording.get_channel_ids() for chan in channel_map]), \ "all channel_ids in 'channel_map' must be in the original recording channel ids" subrecording = SubRecordingExtractor(recording, channel_ids=channel_map) else: subrecording = recording with open(probe_file) as csvfile: posreader = csv.reader(csvfile) row_count = 0 loaded_pos = [] for pos in (posreader): row_count += 1 loaded_pos.append(pos) assert len( subrecording.get_channel_ids() ) == row_count, "The .csv file must contain as many rows as the number of channels in the recordings" for i_ch, pos in zip(subrecording.get_channel_ids(), loaded_pos): subrecording.set_channel_property( i_ch, 'location', list(np.array(pos).astype(float))) if channel_groups is not None and len(channel_groups) == len( subrecording.get_channel_ids()): for i_ch, chg in zip(subrecording.get_channel_ids(), channel_groups): subrecording.set_channel_property(i_ch, 'group', chg) else: raise NotImplementedError( "Only .csv and .prb probe files can be loaded.") return subrecording
class RemoveBadChannelsRecording(RecordingExtractor): preprocessor_name = 'RemoveBadChannels' installed = True # check at class level if installed or not installation_mesg = "" # err def __init__(self, recording, bad_channel_ids, bad_threshold, seconds, verbose): if not isinstance(recording, RecordingExtractor): raise ValueError("'recording' must be a RecordingExtractor") self._recording = recording self._bad_channel_ids = bad_channel_ids self._bad_threshold = bad_threshold self._seconds = seconds self.verbose = verbose self._initialize_subrecording_extractor() RecordingExtractor.__init__(self) self.copy_channel_properties(recording=self._subrecording) self.is_filtered = self._recording.is_filtered self._kwargs = {'recording': recording.make_serialized_dict(), 'bad_channel_ids': bad_channel_ids, 'bad_threshold': bad_threshold, 'seconds': seconds, 'verbose': verbose} def get_sampling_frequency(self): return self._subrecording.get_sampling_frequency() def get_num_frames(self): return self._subrecording.get_num_frames() def get_channel_ids(self): return self._subrecording.get_channel_ids() @check_get_traces_args def get_traces(self, channel_ids=None, start_frame=None, end_frame=None): traces = self._subrecording.get_traces(channel_ids=channel_ids, start_frame=start_frame, end_frame=end_frame) return traces def _initialize_subrecording_extractor(self): if isinstance(self._bad_channel_ids, (list, np.ndarray)): active_channels = [] for chan in self._recording.get_channel_ids(): if chan not in self._bad_channel_ids: active_channels.append(chan) self._subrecording = SubRecordingExtractor(self._recording, channel_ids=active_channels) elif self._bad_channel_ids is None: start_frame = self._recording.get_num_frames() // 2 end_frame = int(start_frame + self._seconds * self._recording.get_sampling_frequency()) if end_frame > self._recording.get_num_frames(): end_frame = self._recording.get_num_frames() traces = self._recording.get_traces(start_frame=start_frame, end_frame=end_frame) stds = np.std(traces, axis=1) bad_channel_ids = [ch for ch, std in enumerate(stds) if std > self._bad_threshold * np.median(stds)] if self.verbose: print('Automatically removing channels:', bad_channel_ids) active_channels = [] for chan in self._recording.get_channel_ids(): if chan not in bad_channel_ids: active_channels.append(chan) self._subrecording = SubRecordingExtractor(self._recording, channel_ids=active_channels) else: self._subrecording = self._recording self.active_channels = self._subrecording.get_channel_ids()
class RemoveBadChannelsRecording(RecordingExtractor): preprocessor_name = 'RemoveBadChannels' installed = True # check at class level if installed or not preprocessor_gui_params = [ { 'name': 'bad_channel_ids', 'type': 'int_list', 'value': None, 'default': None, 'title': "List of bad channels. If None, automatic removal will be done based on standard deviation." }, { 'name': 'bad_threshold', 'type': 'float', 'title': "Threshold in number of sd to remove channels (when automatic)" }, { 'name': 'seconds', 'type': 'float', 'title': "Number of seconds to compute standard deviation (when automatic)" }, { 'name': 'verbose', 'type': 'bool', 'title': "If True output is verbose" }, ] installation_mesg = "" # err def __init__(self, recording, bad_channel_ids, bad_threshold, seconds, verbose): if not isinstance(recording, RecordingExtractor): raise ValueError("'recording' must be a RecordingExtractor") self._recording = recording self._bad_channel_ids = bad_channel_ids self._bad_threshold = bad_threshold self._seconds = seconds self.verbose = verbose self._initialize_subrecording_extractor() RecordingExtractor.__init__(self) self.copy_channel_properties(recording=self._subrecording) def get_sampling_frequency(self): return self._subrecording.get_sampling_frequency() def get_num_frames(self): return self._subrecording.get_num_frames() def get_channel_ids(self): return self._subrecording.get_channel_ids() def get_traces(self, channel_ids=None, start_frame=None, end_frame=None): if start_frame is None: start_frame = 0 if end_frame is None: end_frame = self.get_num_frames() if channel_ids is None: channel_ids = self.get_channel_ids() traces = self._subrecording.get_traces(channel_ids=channel_ids, start_frame=start_frame, end_frame=end_frame) return traces def _initialize_subrecording_extractor(self): if isinstance(self._bad_channel_ids, (list, np.ndarray)): active_channels = [] for chan in self._recording.get_channel_ids(): if chan not in self._bad_channel_ids: active_channels.append(chan) self._subrecording = SubRecordingExtractor( self._recording, channel_ids=active_channels) elif self._bad_channel_ids is None: start_frame = self._recording.get_num_frames() // 2 end_frame = int(start_frame + self._seconds * self._recording.get_sampling_frequency()) traces = self._recording.get_traces(start_frame=start_frame, end_frame=end_frame) stds = np.std(traces, axis=1) bad_channel_ids = [ ch for ch, std in enumerate(stds) if std > self._bad_threshold * np.median(stds) ] if self.verbose: print('Automatically removing channels:', bad_channel_ids) active_channels = [] for chan in self._recording.get_channel_ids(): if chan not in bad_channel_ids: active_channels.append(chan) self._subrecording = SubRecordingExtractor( self._recording, channel_ids=active_channels) else: self._subrecording = self._recording self.active_channels = self._subrecording.get_channel_ids()