From e121ed9cd656e8bc4cc3262b83883775aae46d1f Mon Sep 17 00:00:00 2001 From: zm711 <92116279+zm711@users.noreply.github.com> Date: Mon, 5 Feb 2024 17:12:59 -0500 Subject: [PATCH] first round of docstring updates --- neo/io/basefromrawio.py | 97 ++++---- neo/io/baseio.py | 12 + neo/rawio/baserawio.py | 494 ++++++++++++++++++++++++++++++++++------ 3 files changed, 497 insertions(+), 106 deletions(-) diff --git a/neo/io/basefromrawio.py b/neo/io/basefromrawio.py index e63d060ea..b54322928 100644 --- a/neo/io/basefromrawio.py +++ b/neo/io/basefromrawio.py @@ -4,12 +4,12 @@ BaseFromRaw implement a bridge between the new neo.rawio API and the neo.io legacy that give neo.core object. -The neo.rawio API is more restricted and limited and do not cover tricky +The neo.rawio API is more restricted and limited and does not cover tricky cases with asymetrical tree of neo object. But if a format is done in neo.rawio the neo.io is done for free by inheritance of this class. -Furthermore, IOs that inherits this BaseFromRaw also have the ability -of the lazy load with proxy objects. +Furthermore, IOs that inherit this BaseFromRaw also have the ability +to lazy load with proxy objects. """ @@ -80,26 +80,35 @@ def read_block( self, block_index=0, lazy=False, create_group_across_segment=None, signal_group_mode=None, load_waveforms=False ): """ - :param block_index: int default 0. In case of several block block_index can be specified. - - :param lazy: False by default. - - :param create_group_across_segment: bool or dict + Reads one block of data from a file + + Parameters + ---------- + block_index: int, default: 0 + In the case of multiple blocks, the block_index specifies which block to read + lazy: bool, default: False + Whether to read the block lazily (True) or load into memory (false) + create_group_across_segment: bool | dict | None, default: None If True : - * Create a neo.Group to group AnalogSignal segments - * Create a neo.Group to group SpikeTrain across segments - * Create a neo.Group to group Event across segments - * Create a neo.Group to group Epoch across segments + * Create a neo.Group to group AnalogSignal segments + * Create a neo.Group to group SpikeTrain across segments + * Create a neo.Group to group Event across segments + * Create a neo.Group to group Epoch across segments With a dict the behavior can be controlled more finely - create_group_across_segment = { 'AnalogSignal': True, 'SpikeTrain': False, ...} - - :param signal_group_mode: 'split-all' or 'group-by-same-units' (default depend IO): - This control behavior for grouping channels in AnalogSignal. - * 'split-all': each channel will give an AnalogSignal - * 'group-by-same-units' all channel sharing the same quantity units ar grouped in - a 2D AnalogSignal - - :param load_waveforms: False by default. Control SpikeTrains.waveforms is None or not. + * for example: create_group_across_segment = { 'AnalogSignal': True, 'SpikeTrain': False, ...} + signal_group_mode: 'split-all' | 'group-by-same-units' | None, default: None + This control behavior for grouping channels in AnalogSignal. + * 'split-all': each channel will give an AnalogSignal + * 'group-by-same-units' all channel sharing the same quantity units ar grouped in + a 2D AnalogSignal + By default None since the default is dependant on the IO + load_waveforms: bool, default: False + Determines whether SpikeTrains.waveforms is created + + Returns + ------- + bl: neo.core.Block + The block of data """ @@ -200,27 +209,37 @@ def read_segment( strict_slicing=True, ): """ - :param block_index: int default 0. In case of several blocks block_index can be specified. - - :param seg_index: int default 0. Index of segment. - - :param lazy: False by default. - - :param signal_group_mode: 'split-all' or 'group-by-same-units' (default depend IO): - This control behavior for grouping channels in AnalogSignal. + Reads one segment of the data file + + Parameters + ---------- + block_index: int, default: 0 + In the case of a multiblock dataset, this specifies which block to read + seg_index: int, default: 0 + In the case of a multisegment block, this specifies which segmeent to read + lazy: bool, default: False + Whether to lazily load the segment (True) or to load the segment into memory (False) + signal_group_mode: 'split-all' | 'group-by-same-units' | None, default: None + This control behavior for grouping channels in AnalogSignal. * 'split-all': each channel will give an AnalogSignal * 'group-by-same-units' all channel sharing the same quantity units ar grouped in a 2D AnalogSignal - - :param load_waveforms: False by default. Control SpikeTrains.waveforms is None or not. - - :param time_slice: None by default means no limit. - A time slice is (t_start, t_stop) both are quantities. - All object AnalogSignal, SpikeTrain, Event, Epoch will load only in the slice. - - :param strict_slicing: True by default. - Control if an error is raised or not when t_start or t_stop + load_waveforms: bool, default: False + Determines whether SpikeTrains.waveforms is created + time_slice: tuple[float | None] | None, default: None + Whether to take a time slice of the data + * None: indicates from beginning of segment to the end of the segment + * tuple: (t_start, t_stop) with t_start and t_stop being quantities in seconds + * tuple: (None, t_stop) indicates the beginning of the segment to t_stop + * tuple: (t_start, None) indicates from t_start to the end of the segment + strict_slicing: bool, default: True + Control if an error is raised or not when t_start or t_stop is outside the real time range of the segment. + + Returns + ------- + seg: neo.core.Segment + Returns the desired segment based on the parameters given """ if lazy: @@ -317,7 +336,7 @@ def get_sub_signal_streams(self, signal_group_mode="group-by-same-units"): if len(all_units) == 1: # no substream - #  None iwill be transform as slice later + # None iwill be transform as slice later inner_stream_channels = None name = stream_name sub_stream = (stream_index, inner_stream_channels, name) diff --git a/neo/io/baseio.py b/neo/io/baseio.py index ea5a6eafc..abc368f84 100644 --- a/neo/io/baseio.py +++ b/neo/io/baseio.py @@ -125,6 +125,18 @@ def __init__(self, filename: str | Path = None, **kargs): def read(self, lazy: bool = False, **kargs): """ Return all data from the file as a list of Blocks + + Parameters + ---------- + lazy: bool, default: False + Whether to lazily load the data (True) or to load into memory (False) + kargs: dict + IO specific additional arguments + + Returns + ------ + block_list: list[neo.Block] + Returns all the data from the file as Blocks """ if lazy and not self.support_lazy: raise ValueError("This IO module does not support lazy loading") diff --git a/neo/rawio/baserawio.py b/neo/rawio/baserawio.py index 4780cfbbd..b85d8e941 100644 --- a/neo/rawio/baserawio.py +++ b/neo/rawio/baserawio.py @@ -17,7 +17,7 @@ For this level, datasets of recordings are mapped as follows: -A channel refers to a physical channel of recording in an experiment. It is identified by a +A channel refers to a physical channel of a recording in an experiment. It is identified by a channel_id. Recordings from a channel consist of sections of samples which are recorded contiguously in time; in other words, a section of a channel has a specific sampling_rate, start_time, and length (and thus also stop_time, which is the time of the sample which would @@ -133,20 +133,23 @@ class BaseRawIO: """ - name = "BaseIO" + name = "BaseRawIO" description = "" extensions = [] rawmode = None # one key from possible_raw_modes + # TODO Why multi-file would have a single filename is confusing here - shouldn't + # the name of this argument be filenames_list or filenames_base or similar? + # + # When rawmode=='one-file' kargs MUST contains 'filename' the filename + # When rawmode=='multi-file' kargs MUST contains 'filename' one of the filenames. + # When rawmode=='one-dir' kargs MUST contains 'dirname' the dirname. + def __init__(self, use_cache: bool = False, cache_path: str = "same_as_resource", **kargs): """ - :TODO: Why multi-file would have a single filename is confusing here - shouldn't - the name of this argument be filenames_list or filenames_base or similar? - - When rawmode=='one-file' kargs MUST contains 'filename' the filename - When rawmode=='multi-file' kargs MUST contains 'filename' one of the filenames. - When rawmode=='one-dir' kargs MUST contains 'dirname' the dirname. + init docstring should be filled out at the rawio level so the user knows whether to + input filename or dirname. """ # create a logger for the IO class @@ -171,17 +174,18 @@ def __init__(self, use_cache: bool = False, cache_path: str = "same_as_resource" def parse_header(self): """ - This must parse the file header to get all stuff for fast use later on. - - This must create - self.header['nb_block'] - self.header['nb_segment'] - self.header['signal_streams'] - self.header['signal_channels'] - self.header['spike_channels'] - self.header['event_channels'] + Parses the header of the file(s) to allow for faster computations + for all other functions """ + # this must create + # self.header['nb_block'] + # self.header['nb_segment'] + # self.header['signal_streams'] + # self.header['signal_channels'] + # self.header['spike_channels'] + # self.header['event_channels'] + self._parse_header() self._check_stream_signal_channel_characteristics() self.is_header_parsed = True @@ -382,11 +386,23 @@ def print_annotations(self): print(self._repr_annotations()) def block_count(self): - """return number of blocks""" + """Returns the number of blocks""" return self.header["nb_block"] def segment_count(self, block_index: int): - """return number of segments for a given block""" + """ + Returns count of segments for a given block + + Parameters + ---------- + block_index: int + The index of the block to do the segment count for + Returns + ------- + count: int + The number of segments for a given block + + """ return self.header["nb_segment"][block_index] def signal_streams_count(self): @@ -396,8 +412,18 @@ def signal_streams_count(self): return len(self.header["signal_streams"]) def signal_channels_count(self, stream_index: int): - """Return the number of signal channels for a given stream. + """Returns the number of signal channels for a given stream. This number is the same for all Blocks and Segments. + + Parameters + ---------- + stream_index: int + the stream index in which to count the signal channels + + Returns + ------- + count: int + the number of signal channels of a given stream """ stream_id = self.header["signal_streams"][stream_index]["id"] channels = self.header["signal_channels"] @@ -417,14 +443,42 @@ def event_channels_count(self): return len(self.header["event_channels"]) def segment_t_start(self, block_index: int, seg_index: int): - """Global t_start of a Segment in s. Shared by all objects except + """ + Global t_start of a Segment Shared by all objects except for AnalogSignal. + + Parameters + ---------- + block_index: int + The index of the block to find the segment t_start + seg_index: int + The index of the segment within the block_index in which to find the t_start + + Returns + ------- + t_start: float + the time of global t_start of a segment within a block + """ return self._segment_t_start(block_index, seg_index) def segment_t_stop(self, block_index, seg_index): - """Global t_start of a Segment in s. Shared by all objects except + """ + Global t_stop of a Segment in s. Shared by all objects except for AnalogSignal. + + Parameters + ---------- + block_index: int + The index of the block to find the segment t_start + seg_index: int + The index of the segment within the block_index in which to find the t_start + + Returns + ------- + t_stop: float + the time of global t_stop of a segment within a block + """ return self._segment_t_stop(block_index, seg_index) @@ -435,7 +489,7 @@ def _check_stream_signal_channel_characteristics(self): """ Check that all channels that belonging to the same stream_id have the same stream id and _common_sig_characteristics. These - presently include: + presently includes: * sampling_rate * units * dtype @@ -451,7 +505,7 @@ def _check_stream_signal_channel_characteristics(self): characteristics = signal_channels[mask][_common_sig_characteristics] unique_characteristics = np.unique(characteristics) assert unique_characteristics.size == 1, ( - f"Some channel in stream_id {stream_id} " + f"Some channels in stream_id {stream_id} " f"do not have same {_common_sig_characteristics} {unique_characteristics}" ) @@ -468,6 +522,19 @@ def channel_name_to_index(self, stream_index: int, channel_names: list[str]): Inside a stream, transform channel_names to channel_indexes. Based on self.header['signal_channels'] channel_indexes are zero-based offsets within the stream + + Parameters + ---------- + stream_index: int + The stream in which to convert channel_names to their respective channel_indexes + channel_names: list[str] + The channel names to convert to channel_indexes + + Returns + ------- + channel_indexes: np.array[int] + the channel_indexes associated with the given channel_ids + """ stream_id = self.header["signal_streams"][stream_index]["id"] mask = self.header["signal_channels"]["stream_id"] == stream_id @@ -482,6 +549,18 @@ def channel_id_to_index(self, stream_index: int, channel_ids: list[str]): Inside a stream, transform channel_ids to channel_indexes. Based on self.header['signal_channels'] channel_indexes are zero-based offsets within the stream + + Parameters + ---------- + stream_index: int + the stream index in which to convert the channel_ids to channel_indexes + channel_ids: list[str] + the list of channel_ids to convert to channel_indexes + + Returns + ------- + channel_indexes: np.array[int] + the channel_indexes associated with the given channel_ids """ # unique ids is already checked in _check_stream_signal_channel_characteristics stream_id = self.header["signal_streams"][stream_index]["id"] @@ -500,7 +579,24 @@ def _get_channel_indexes( ): """ Select channel_indexes for a stream based on channel_indexes/channel_names/channel_ids - depending which is not None. + depending on which one is not None. + + Parameters + ---------- + stream_index: int, + the stream index in which to get channel_indexes + channel_indexes: list[int] | None + the channel_indexes desired + channel_names: list[str] | None + the names of the channels to be converted to channel_indexes. Give this or channel_ids for conversion + channel_ids: list[str] | None + the ids of the channels to be converted to channel_indexes. Give this or channel_names for conversion + + Returns + ------- + channel_indexes: np.array[int] + The desired channel_indexes for functions requiring channel_indexes + """ if channel_indexes is None and channel_names is not None: channel_indexes = self.channel_name_to_index(stream_index, channel_names) @@ -509,21 +605,49 @@ def _get_channel_indexes( return channel_indexes def _get_stream_index_from_arg(self, stream_index_arg: int | None): + """ + Verifies the desired stream_index exists + + Parameters + ---------- + stream_index_arg: int | None, default: None + The stream_index to verify + If None checks if only one stream exists and then returns 0 if this it is single stream + + Returns + ------- + stream_index: int + The stream_index to be used for function requiring a stream_index + """ if stream_index_arg is None: - assert self.header["signal_streams"].size == 1 + assert self.header["signal_streams"].size == 1, "stream_index must be given for multiple stream files" stream_index = 0 else: - assert 0 <= stream_index_arg < self.header["signal_streams"].size + assert 0 <= stream_index_arg < self.header["signal_streams"].size, ( + f"stream_index must be between 0 and {self.header['signal_streams'].size}" + ) stream_index = stream_index_arg return stream_index def get_signal_size(self, block_index: int, seg_index: int, stream_index: int | None = None): """ Retrieve the length of a single section of the channels in a stream. - :param block_index: - :param seg_index: - :param stream_index: - :return: number of samples + + Parameters + ---------- + block_index: int + The desired block in which to get a signal size + seg_index: int + The desired segment of the block in which to get the signal size + stream_index: int | None, default: None + The optional stream index in which to determine signal size + This is required for data with multiple streams + + Returns + ------- + signal_size: int + The number of samples for a given signal within the given block, segment, and stream + """ stream_index = self._get_stream_index_from_arg(stream_index) return self._get_signal_size(block_index, seg_index, stream_index) @@ -531,10 +655,22 @@ def get_signal_size(self, block_index: int, seg_index: int, stream_index: int | def get_signal_t_start(self, block_index: int, seg_index: int, stream_index: int | None = None): """ Retrieve the t_start of a single section of the channels in a stream. - :param block_index: - :param seg_index: - :param stream_index: - :return: start time of section + + Parameters + ---------- + block_index: int + The desired block in which to get a signal size + seg_index: int + The desired segment of the block in which to get the signal size + stream_index: int | None, default: None + The optional stream index in which to determine signal size + This is required for data with multiple streams + + Returns + ------- + signal_t_start: float + The start time for a given signal within the given block, segment, and stream + """ stream_index = self._get_stream_index_from_arg(stream_index) return self._get_signal_t_start(block_index, seg_index, stream_index) @@ -542,8 +678,18 @@ def get_signal_t_start(self, block_index: int, seg_index: int, stream_index: int def get_signal_sampling_rate(self, stream_index: int | None = None): """ Retrieve sampling rate for a stream and all channels in that stream. - :param stream_index: - :return: sampling rate + + Parameters + ---------- + stream_index: int | None, default: None + The desired stream index in which to get the sampling_rate + This is required for data with multiple streams + + Returns + ------- + sr: float + The sampling rate of a given stream and all channels in that stream + """ stream_index = self._get_stream_index_from_arg(stream_index) stream_id = self.header["signal_streams"][stream_index]["id"] @@ -565,23 +711,53 @@ def get_analogsignal_chunk( prefer_slice: bool = False, ): """ - Return a chunk of raw signal as a Numpy array. columns correspond to samples from a - section of a single channel of recording. The channels are chosen either by channel_names, + Return a chunk of raw signal as a Numpy array. + + Parameters + ---------- + block_index: int, default: 0 + The block with the desired segment to assess + seg_index: int, default: 0 + The segment containing the desired section to assess + i_start: int | None, default: None + The index of the first sample to retrieve within the section + i_stop: int | None, default: None + The index of one past the last sample to retrieve within the section + stream_index: int | None, default: None + The index of the stream containing the channels to assess + channel_indexes: list[int] | np.array[int]| slice | None, default: None + The list of indexes of channels to retrieve + channel_names: list[str] | None, default: None + The list of channel names to retrieve + channel_ids: list[str] | None, default: None + list of channel_ids to retrieve + + Returns + ------- + raw_chunk: np.array (n_samples, n_channels) + The array with the raw signal samples + + Notes + ----- + Rows are the samples and columns are the channels + The channels are chosen either by channel_names, if provided, otherwise by channel_ids, if provided, otherwise by channel_indexes, if provided, otherwise all channels are selected. - :param block_index: block containing segment with section - :param seg_index: segment containing section - :param i_start: index of first sample to retrieve within section - :param i_stop: index of one past last sample to retrieve within section - :param stream_index: index of stream containing channels - :param channel_indexes: list of indexes of channels to retrieve. Can be a list, slice, - np.array of int, or None - :param channel_names: list of channels names to retrieve, or None - :param channel_ids: list of channel ids to retrieve, or None - :param prefer_slice: use slicing with lazy read if channel_indexes are provided as an - np.ndarray and are contiguous - :return: array with raw signal samples + Examples + -------- + # tetrode with 1 sec recording at sampling_rate = 1000. Hz + >>> raw_sigs = rawio_reader.get_analogsignal_chunk(block_index=2, seg_index=0, stream_index=0) + >>> raw_sigs.shape + >>> (1000,4) # 1000 samples by 4 channels + >>> raw_sigs.dtype + >>> 'int16' # returns the dtype from the recording itself + + # If we only want one electrode + >>> raw_sigs_one_electrode = rawio_reader.get_analogsignal_chunk(block_index=2, seg_index=0, stream_index=0, channel_indexes=[0]) + >>> raw_sigs_one_electrode.shape + >>> (1000,1) + """ signal_streams = self.header["signal_streams"] @@ -633,13 +809,39 @@ def rescale_signal_raw_to_float( channel_names, if provided, otherwise by channel_ids, if provided, otherwise by channel_indexes, if provided, otherwise all channels are selected. - :param raw_signal: Numpy array of samples. columns are samples for a single channel - :param dtype: data type for returned scaled samples - :param stream_index: index of stream containing channels - :param channel_indexes: list of indexes of channels to retrieve or None - :param channel_names: list of channels names to retrieve, or None - :param channel_ids: list of channel ids to retrieve, or None - :return: array of scaled sample values + Parameters + ---------- + raw_signal: np.array (n_samples, n_channels) + The numpy array of samples with columns being samples for a single channel + dtype: np.dype, default: "float32" + The datatype for returning scaled samples, must be acceptable by the numpy dtype constructor + stream_index: int | None, default: None + The index of the stream containing the channels to assess + channel_indexes: list[int], np.array[int], slice | None, default: None + The list of indexes of channels to retrieve + channel_names: list[str] | None, default: None + The list of channel names to retrieve + channel_ids: list[str] | None, default: None + list of channel_ids to retrieve + + Returns + ------- + float_signal: np.array (n_samples, n_channels) + The rescaled signal + + Examples + -------- + # Once we have a `raw_sigs` using rawio.get_analogsignal_chunk() we can convert to voltages with a desired dtype + # If we used `stream_index=0` with `get_analogsignal_chunk` we use `stream_index=0` here + >>> float_sigs = rawio_reader.rescale_signal_raw_to_float(raw_signal=raw_sigs, dtype='float32', stream_index=0) + >>> float_sigs.dtype + >>> 'float32' + >>> float_sigs.shape + >>> (1000,4) + >>> float_sigs.shape == raw_sigs.shape + >>> True + + """ stream_index = self._get_stream_index_from_arg(stream_index) channel_indexes = self._get_channel_indexes(stream_index, channel_indexes, channel_names, channel_ids) @@ -665,6 +867,24 @@ def rescale_signal_raw_to_float( # spiketrain and unit zone def spike_count(self, block_index: int = 0, seg_index: int = 0, spike_channel_index: int = 0): + """ + Returns the spike count for a given block, segment, and spike_channel_index + + Parameters + ---------- + block_index: int, default: 0 + The block with the desired segment to assess + seg_index: int, default: 0 + The segment containing the desired section to assess + spike_channel_index: int, default: 0 + The spike_channel_index for assessing spike_count + + Returns + ------- + spike_count: int + The number of spikes in the block and segment + + """ return self._spike_count(block_index, seg_index, spike_channel_index) def get_spike_timestamps( @@ -676,11 +896,33 @@ def get_spike_timestamps( t_stop: float | None = None, ): """ + Returns the spike_timestamps in samples (see note for dtype) + + Parameters + ---------- + block_index: int, default: 0 + The block containing the section to get the timestamps + seg_index: int, default: 0 + The segment containing the section to get the timestamps + spike_channel_index: int, default: 0 + The channels in which to count the spikes on + t_start: float | None, default: None + The time in seconds for the start of the section to get spike timestamps + None indicates to start at the beginning of the section + t_stop: float | None, default: None + The time in seconds for the end of the section to get spike timestamps + None indicates to end at the end of the section + + Returns + ------- + timestamp: np.array + The spike timestamps + + Notes + ----- The timestamp datatype is as close to the format itself. Sometimes float/int32/int64. Sometimes it is the index on the signal but not always. The conversion to second or index_on_signal is done outside this method. - - t_start/t_stop are limits in seconds. """ timestamp = self._get_spike_timestamps(block_index, seg_index, spike_channel_index, t_start, t_stop) return timestamp @@ -688,6 +930,18 @@ def get_spike_timestamps( def rescale_spike_timestamp(self, spike_timestamps: np.ndarray, dtype: np.dtype = "float64"): """ Rescale spike timestamps to seconds. + + Parameters + ---------- + spike_timestamps: np.ndarray + The array containing the spike_timestamps to convert + dtype: np.dtype, default: "float64" + The dtype in which to convert the spike time in seconds. Must be accepted by the numpy.dtype constructor + + Returns + ------- + scaled_spike_timestamps: np.array + The spiketimes in seconds """ return self._rescale_spike_timestamp(spike_timestamps, dtype) @@ -700,12 +954,52 @@ def get_spike_raw_waveforms( t_start: float | None = None, t_stop: float | None = None, ): + """ + Gets the waveforms for a particular set of channels + + Parameters + ---------- + block_index: int, default: 0 + The block containing the section to get the waveforms + seg_index: int, default: 0 + The segment containing the section to get the wavforms + spike_channel_index: int, default: 0 + The channels in which to count the spikes on + t_start: float | None, default: None + The time in seconds for the start of the section to get waveforms + None indicates to start at the beginning of the section + t_stop: float | None, default: None + The time in seconds for the end of the section to waveforms + None indicates to end at the end of the section + + Returns + ------- + wf: np.ndarray + #SAM what is the shape of this + """ wf = self._get_spike_raw_waveforms(block_index, seg_index, spike_channel_index, t_start, t_stop) return wf def rescale_waveforms_to_float( self, raw_waveforms: np.ndarray, dtype: np.dtype = "float32", spike_channel_index: int = 0 ): + """ + Rescale waveforms to seconds. + + Parameters + ---------- + raw_waveforms: np.ndarray + The array containing the spike_timestamps to convert + dtype: np.dtype, default: "float64" + The dtype in which to convert the spike time in seconds. Must be accepted by the numpy.dtype constructor + spike_channel_index: int, default: 0 + The channels on which to index for scaling the waveforms + + Returns + ------- + float_waveforms: np.array + The scaled waveforms + """ wf_gain = self.header["spike_channels"]["wf_gain"][spike_channel_index] wf_offset = self.header["spike_channels"]["wf_offset"][spike_channel_index] @@ -720,6 +1014,23 @@ def rescale_waveforms_to_float( # event and epoch zone def event_count(self, block_index: int = 0, seg_index: int = 0, event_channel_index: int = 0): + """ + Returns the count of evens for a particular block segment and channel index + + Parameters + ---------- + block_index: int, default: 0 + The block in which to count the events + seg_index: int, default: 0 + The segment within the block given by block_index in which to count events + event_channel_index: int, default: 0 + The index of the channel in which to count events + + Returns + ------- + n_events: int + The number of events in the given block, segment, and event_channel_index + """ return self._event_count(block_index, seg_index, event_channel_index) def get_event_timestamps( @@ -731,17 +1042,38 @@ def get_event_timestamps( t_stop: float | None = None, ): """ + Returns the event timestamps along with their labels and durations + + Parameters + ---------- + block_index: int, default: 0 + The block in which to count the events + seg_index: int, default: 0 + The segment within the block given by block_index in which to count events + event_channel_index: int, default: 0 + The index of the channel in which to count events + t_start: float | None, default: None + The time in seconds for the start of the section to get waveforms + None indicates to start at the beginning of the section + t_stop: float | None, default: None + The time in seconds for the end of the section to waveforms + None indicates to end at the end of the section + + Returns + ------- + timestamp: np.array + The timestamps of events + labels: np.array + The labels of the events + durations: np.array + The durations of each event + + Notes + ----- The timestamp datatype is as close to the format itself. Sometimes float/int32/int64. Sometimes it is the index on the signal but not always. The conversion to second or index_on_signal is done outside this method. - t_start/t_sop are limits in seconds. - - returns - timestamp - labels - durations - """ timestamp, durations, labels = self._get_event_timestamps( block_index, seg_index, event_channel_index, t_start, t_stop @@ -753,6 +1085,20 @@ def rescale_event_timestamp( ): """ Rescale event timestamps to seconds. + + Parameters + ---------- + event_timestamps: np.ndarray + The array containing the spike_timestamps to convert + dtype: np.dtype, default: "float64" + The dtype in which to convert the spike time in seconds. Must be accepted by the numpy.dtype constructor + event_channel_index: int, default: 0 + The channels on which to index for scaling the events + + Returns + ------- + scaled_event_timestamps: np.array + The scaled event_timestamps """ return self._rescale_event_timestamp(event_timestamps, dtype, event_channel_index) @@ -761,6 +1107,20 @@ def rescale_epoch_duration( ): """ Rescale epoch raw duration to seconds. + + Parameters + ---------- + raw_duration: np.ndarray + The array containing the spike_timestamps to convert + dtype: np.dtype, default: "float64" + The dtype in which to convert the spike time in seconds. Must be accepted by the numpy.dtype constructor + event_channel_index: int, default: 0 + The channels on which to index for scaling epochs + + Returns + ------- + scaled_epoch_durations: np.array + The scaled epoch durations """ return self._rescale_epoch_duration(raw_duration, dtype, event_channel_index)