def derivative(signal): ''' Calculate the derivative of an AnalogSignal. Parameters ---------- signal : neo.AnalogSignal The signal to differentiate. If `signal` contains more than one channel, each is differentiated separately. Returns ------- neo.AnalogSignal The returned object is an AnalogSignal containing the differences between each successive sample value of the input signal divided by the sampling period. Times are centered between the successive samples of the input. The output signal will have the same number of channels as the input signal. Raises ------ TypeError If the input signal is not a neo.AnalogSignal. ''' if not isinstance(signal, neo.AnalogSignal): raise TypeError('Input signal is not a neo.AnalogSignal!') derivative_sig = neo.AnalogSignal( np.diff(signal.as_quantity(), axis=0) / signal.sampling_period, t_start=signal.t_start + signal.sampling_period / 2, sampling_period=signal.sampling_period) return derivative_sig
def derivative(signal): ''' Calculate the derivative of an AnalogSignal. Parameters ---------- signal : neo.AnalogSignal The signal to differentiate. If `signal` contains more than one channel, each is differentiated separately. Returns ------- neo.AnalogSignal The returned object is an AnalogSignal containing the differences between each successive sample value of the input signal divided by the sampling period. Times are centered between the successive samples of the input. The output signal will have the same number of channels as the input signal. Raises ------ TypeError If the input signal is not a neo.AnalogSignal. ''' if not isinstance(signal, neo.AnalogSignal): raise TypeError('Input signal is not a neo.AnalogSignal!') derivative_sig = neo.AnalogSignal( np.diff(signal.as_quantity(), axis=0) / signal.sampling_period, t_start=signal.t_start+signal.sampling_period/2, sampling_period=signal.sampling_period) return derivative_sig
def derivative(signal): """ Calculate the derivative of a `neo.AnalogSignal`. Parameters ---------- signal : neo.AnalogSignal The signal to differentiate. If `signal` contains more than one channel, each is differentiated separately. Returns ------- derivative_sig : neo.AnalogSignal The returned object is a `neo.AnalogSignal` containing the differences between each successive sample value of the input signal divided by the sampling period. Times are centered between the successive samples of the input. The output signal will have the same number of channels as the input signal. Raises ------ TypeError If `signal` is not a `neo.AnalogSignal`. Examples -------- >>> import neo >>> import numpy as np >>> import quantities as pq >>> from elephant.signal_processing import derivative >>> signal = neo.AnalogSignal([0, 3, 4, 11, -1], sampling_rate=1 * pq.Hz, ... units='mV') >>> print(derivative(signal)) [[ 3.] [ 1.] [ 7.] [-12.]] mV*Hz """ if not isinstance(signal, neo.AnalogSignal): raise TypeError('Input signal is not a neo.AnalogSignal!') derivative_sig = neo.AnalogSignal( np.diff(signal.as_quantity(), axis=0) / signal.sampling_period, t_start=signal.t_start + signal.sampling_period / 2, sampling_period=signal.sampling_period) return derivative_sig
def rauc(signal, baseline=None, bin_duration=None, t_start=None, t_stop=None): ''' Calculate the rectified area under the curve (RAUC) for an AnalogSignal. The signal is optionally divided into bins with duration `bin_duration`, and the rectified signal (absolute value) is integrated within each bin to find the area under the curve. The mean or median of the signal or an arbitrary baseline may optionally be subtracted before rectification. If the number of bins is 1 (default), a single value is returned for each channel in the input signal. Otherwise, an AnalogSignal containing the values for each bin is returned along with the times of the centers of the bins. Parameters ---------- signal : neo.AnalogSignal The signal to integrate. If `signal` contains more than one channel, each is integrated separately. bin_duration : quantities.Quantity The length of time that each integration should span. If None, there will be only one bin spanning the entire signal duration. If `bin_duration` does not divide evenly into the signal duration, the end of the signal is padded with zeros to accomodate the final, overextending bin. Default: None baseline : string or quantities.Quantity A factor to subtract from the signal before rectification. If `'mean'` or `'median'`, the mean or median value of the entire signal is subtracted on a channel-by-channel basis. Default: None t_start, t_stop : quantities.Quantity Times to start and end the algorithm. The signal is cropped using `signal.time_slice(t_start, t_stop)` after baseline removal. Useful if you want the RAUC for a short section of the signal but want the mean or median calculation (`baseline='mean'` or `baseline='median'`) to use the entire signal for better baseline estimation. Default: None Returns ------- quantities.Quantity or neo.AnalogSignal If the number of bins is 1, the returned object is a scalar or vector Quantity containing a single RAUC value for each channel. Otherwise, the returned object is an AnalogSignal containing the RAUC(s) for each bin stored as a sample, with times corresponding to the center of each bin. The output signal will have the same number of channels as the input signal. Raises ------ TypeError If the input signal is not a neo.AnalogSignal. TypeError If `bin_duration` is not None or a Quantity. TypeError If `baseline` is not None, `'mean'`, `'median'`, or a Quantity. ''' if not isinstance(signal, neo.AnalogSignal): raise TypeError('Input signal is not a neo.AnalogSignal!') if baseline is None: pass elif baseline is 'mean': # subtract mean from each channel signal = signal - signal.mean(axis=0) elif baseline is 'median': # subtract median from each channel signal = signal - np.median(signal.as_quantity(), axis=0) elif isinstance(baseline, pq.Quantity): # subtract arbitrary baseline signal = signal - baseline else: raise TypeError('baseline must be None, \'mean\', \'median\', ' 'or a Quantity: {}'.format(baseline)) # slice the signal after subtracting baseline signal = signal.time_slice(t_start, t_stop) if bin_duration is not None: # from bin duration, determine samples per bin and number of bins if isinstance(bin_duration, pq.Quantity): samples_per_bin = int( np.round( bin_duration.rescale('s') / signal.sampling_period.rescale('s'))) n_bins = int(np.ceil(signal.shape[0] / samples_per_bin)) else: raise TypeError( 'bin_duration must be a Quantity: {}'.format(bin_duration)) else: # all samples in one bin samples_per_bin = signal.shape[0] n_bins = 1 # store the actual bin duration bin_duration = samples_per_bin * signal.sampling_period # reshape into equal size bins, padding the end with zeros if necessary n_channels = signal.shape[1] sig_binned = signal.as_quantity().copy() sig_binned.resize(n_bins * samples_per_bin, n_channels, refcheck=False) sig_binned = sig_binned.reshape(n_bins, samples_per_bin, n_channels) # rectify and integrate over each bin rauc = np.trapz(np.abs(sig_binned), dx=signal.sampling_period, axis=1) if n_bins == 1: # return a single value for each channel return rauc.squeeze() else: # return an AnalogSignal with times corresponding to center of each bin rauc_sig = neo.AnalogSignal( rauc, t_start=signal.t_start.rescale(bin_duration.units) + bin_duration / 2, sampling_period=bin_duration) return rauc_sig
def rauc(signal, baseline=None, bin_duration=None, t_start=None, t_stop=None): """ Calculate the rectified area under the curve (RAUC) for a `neo.AnalogSignal`. The signal is optionally divided into bins with duration `bin_duration`, and the rectified signal (absolute value) is integrated within each bin to find the area under the curve. The mean or median of the signal or an arbitrary baseline may optionally be subtracted before rectification. Parameters ---------- signal : neo.AnalogSignal The signal to integrate. If `signal` contains more than one channel, each is integrated separately. baseline : pq.Quantity or {'mean', 'median'}, optional A factor to subtract from the signal before rectification. If 'mean', the mean value of the entire `signal` is subtracted on a channel-by-channel basis. If 'median', the median value of the entire `signal` is subtracted on a channel-by-channel basis. Default: None bin_duration : pq.Quantity, optional The length of time that each integration should span. If None, there will be only one bin spanning the entire signal duration. If `bin_duration` does not divide evenly into the signal duration, the end of the signal is padded with zeros to accomodate the final, overextending bin. Default: None t_start : pq.Quantity, optional Time to start the algorithm. If None, starts at the beginning of `signal`. Default: None t_stop : pq.Quantity, optional Time to end the algorithm. If None, ends at the last time of `signal`. The signal is cropped using `signal.time_slice(t_start, t_stop)` after baseline removal. Useful if you want the RAUC for a short section of the signal but want the mean or median calculation (`baseline`='mean' or `baseline`='median') to use the entire signal for better baseline estimation. Default: None Returns ------- pq.Quantity or neo.AnalogSignal If the number of bins is 1, the returned object is a scalar or vector `pq.Quantity` containing a single RAUC value for each channel. Otherwise, the returned object is a `neo.AnalogSignal` containing the RAUC(s) for each bin stored as a sample, with times corresponding to the center of each bin. The output signal will have the same number of channels as the input signal. Raises ------ ValueError If `signal` is not `neo.AnalogSignal`. If `bin_duration` is not None or `pq.Quantity`. If `baseline` is not None, 'mean', 'median', or `pq.Quantity`. See Also -------- neo.AnalogSignal.time_slice : how `t_start` and `t_stop` are used Examples -------- >>> import neo >>> import numpy as np >>> import quantities as pq >>> from elephant.signal_processing import rauc >>> signal = neo.AnalogSignal(np.arange(10), sampling_rate=20 * pq.Hz, ... units='mV') >>> rauc(signal) array(2.025) * mV/Hz """ if not isinstance(signal, neo.AnalogSignal): raise ValueError('Input signal is not a neo.AnalogSignal!') if baseline is None: pass elif baseline == 'mean': # subtract mean from each channel signal = signal - signal.mean(axis=0) elif baseline == 'median': # subtract median from each channel signal = signal - np.median(signal.as_quantity(), axis=0) elif isinstance(baseline, pq.Quantity): # subtract arbitrary baseline signal = signal - baseline else: raise ValueError("baseline must be either None, 'mean', 'median', or " "a Quantity. Got {}".format(baseline)) # slice the signal after subtracting baseline signal = signal.time_slice(t_start, t_stop) if bin_duration is not None: # from bin duration, determine samples per bin and number of bins if isinstance(bin_duration, pq.Quantity): samples_per_bin = int( np.round( bin_duration.rescale('s') / signal.sampling_period.rescale('s'))) n_bins = int(np.ceil(signal.shape[0] / samples_per_bin)) else: raise ValueError( "bin_duration must be a Quantity. Got {}".format(bin_duration)) else: # all samples in one bin samples_per_bin = signal.shape[0] n_bins = 1 # store the actual bin duration bin_duration = samples_per_bin * signal.sampling_period # reshape into equal size bins, padding the end with zeros if necessary n_channels = signal.shape[1] sig_binned = signal.as_quantity().copy() sig_binned.resize(n_bins * samples_per_bin, n_channels, refcheck=False) sig_binned = sig_binned.reshape(n_bins, samples_per_bin, n_channels) # rectify and integrate over each bin rauc = np.trapz(np.abs(sig_binned), dx=signal.sampling_period, axis=1) if n_bins == 1: # return a single value for each channel return rauc.squeeze() else: # return an AnalogSignal with times corresponding to center of each bin t_start = signal.t_start.rescale(bin_duration.units) + bin_duration / 2 rauc_sig = neo.AnalogSignal(rauc, t_start=t_start, sampling_period=bin_duration) return rauc_sig
def rauc(signal, baseline=None, bin_duration=None, t_start=None, t_stop=None): ''' Calculate the rectified area under the curve (RAUC) for an AnalogSignal. The signal is optionally divided into bins with duration `bin_duration`, and the rectified signal (absolute value) is integrated within each bin to find the area under the curve. The mean or median of the signal or an arbitrary baseline may optionally be subtracted before rectification. If the number of bins is 1 (default), a single value is returned for each channel in the input signal. Otherwise, an AnalogSignal containing the values for each bin is returned along with the times of the centers of the bins. Parameters ---------- signal : neo.AnalogSignal The signal to integrate. If `signal` contains more than one channel, each is integrated separately. bin_duration : quantities.Quantity The length of time that each integration should span. If None, there will be only one bin spanning the entire signal duration. If `bin_duration` does not divide evenly into the signal duration, the end of the signal is padded with zeros to accomodate the final, overextending bin. Default: None baseline : string or quantities.Quantity A factor to subtract from the signal before rectification. If `'mean'` or `'median'`, the mean or median value of the entire signal is subtracted on a channel-by-channel basis. Default: None t_start, t_stop : quantities.Quantity Times to start and end the algorithm. The signal is cropped using `signal.time_slice(t_start, t_stop)` after baseline removal. Useful if you want the RAUC for a short section of the signal but want the mean or median calculation (`baseline='mean'` or `baseline='median'`) to use the entire signal for better baseline estimation. Default: None Returns ------- quantities.Quantity or neo.AnalogSignal If the number of bins is 1, the returned object is a scalar or vector Quantity containing a single RAUC value for each channel. Otherwise, the returned object is an AnalogSignal containing the RAUC(s) for each bin stored as a sample, with times corresponding to the center of each bin. The output signal will have the same number of channels as the input signal. Raises ------ TypeError If the input signal is not a neo.AnalogSignal. TypeError If `bin_duration` is not None or a Quantity. TypeError If `baseline` is not None, `'mean'`, `'median'`, or a Quantity. ''' if not isinstance(signal, neo.AnalogSignal): raise TypeError('Input signal is not a neo.AnalogSignal!') if baseline is None: pass elif baseline is 'mean': # subtract mean from each channel signal = signal - signal.mean(axis=0) elif baseline is 'median': # subtract median from each channel signal = signal - np.median(signal.as_quantity(), axis=0) elif isinstance(baseline, pq.Quantity): # subtract arbitrary baseline signal = signal - baseline else: raise TypeError( 'baseline must be None, \'mean\', \'median\', ' 'or a Quantity: {}'.format(baseline)) # slice the signal after subtracting baseline signal = signal.time_slice(t_start, t_stop) if bin_duration is not None: # from bin duration, determine samples per bin and number of bins if isinstance(bin_duration, pq.Quantity): samples_per_bin = int(np.round( bin_duration.rescale('s')/signal.sampling_period.rescale('s'))) n_bins = int(np.ceil(signal.shape[0]/samples_per_bin)) else: raise TypeError( 'bin_duration must be a Quantity: {}'.format(bin_duration)) else: # all samples in one bin samples_per_bin = signal.shape[0] n_bins = 1 # store the actual bin duration bin_duration = samples_per_bin * signal.sampling_period # reshape into equal size bins, padding the end with zeros if necessary n_channels = signal.shape[1] sig_binned = signal.as_quantity().copy() sig_binned.resize(n_bins * samples_per_bin, n_channels) sig_binned = sig_binned.reshape(n_bins, samples_per_bin, n_channels) # rectify and integrate over each bin rauc = np.trapz(np.abs(sig_binned), dx=signal.sampling_period, axis=1) if n_bins == 1: # return a single value for each channel return rauc.squeeze() else: # return an AnalogSignal with times corresponding to center of each bin rauc_sig = neo.AnalogSignal( rauc, t_start=signal.t_start.rescale(bin_duration.units)+bin_duration/2, sampling_period=bin_duration) return rauc_sig