This module provides data structure for two types of time series: Signal and Annotation.
Both structures extend ndarray by providing attributes, such as sampling frequency, metadata, name. More importantly, time series provide specific features such as indexing with time strings.
>>> import pyrem as pr
>>> import numpy as np
>>> # generate white noise:
>>> noise = np.random.normal(size=int(1e6))
>>> # a million point sampled at 256 Hz
Then, to create a time series from this vector of random numbers:
>>> sig = pr.time_series.Signal(noise, 256.0,
>>> type="noise", name="channel_1",
>>> metadata={"patient": "John_Doe"})
Display information about this time series:
>>> sig
To resample at 100 Hz:
>>> sig_short = sig.resample(100.0)
>>> sig_short
Time series derive from numpy arrays, so you can just use them as such:
>>> sig_norm = sig - np.mean(sig)
Note that the resulting signal is conveniently a time series (not a regular numpy array)
>>> np.diff(sig)
Since time series are derived from numpy array, the numpy indexing rule apply:
>>> sig[1:1000:3] # one to 999, every 3 values
>>> sig[: -100] # from start to 0 to 100 before the end
See numpy documentation for more info.
It is common to have to extract a signal between two different time points. Instead of having to tediously calculate index from time, pyrem offers the possibility to use stings and datetime.timedelta
Time strings are represented with the following format:
“29h33m1.02s”
Where:
Example:
>>> # string indexing:
>>> print sig.duration
>>> sig2 = sig["1h2m2s":] # everything after 1 hour, 2 min and 2 seconds
>>> print sig2.duration
>>> # this should be exactly 1h2m2s
>>> print sig.duration - sig2.duration
>>> print sig["1h2m2s":"1h2m2.1s"]
Note
When indexing a signal with time strings, we query the values of a discrete representation of a continuous signal. Therefore, it makes no sense to obtain a signal of length zero. For instance, imagine a signal of 10 seconds sampled at 1Hz. If we query the value between 1.5 and 1.6s, no points fall in this interval. However, the signal does have a value. In this case, pyrem returns a signal of length 1 where the unique value is the value of the former neighbour.
>>> sig = pr.time_series.Signal([3,4,2,6,4,7,4,5,7,9], 10.0,)
>>> sig["0s":"0.001s"])
>>> sig["0s":"0.011s"])
A common task is to extract successive temporal slices (i.e. epochs) of a signal, for instance, in order to compute features. iter_window() iterator facilitates this.
Let us work wit a one minute signal as an example:
>>> sig1m = sig[:"1m"]
Get every 5 seconds of a the first minutes of a signal:
>>> for time, sub_signal in sig1m.iter_window(5,1.0):
>>> print time, sub_signal.duration
Get 10 second epochs, overlapping of 50% (5s):
>>> for time, sub_signal in sig1m.iter_window(10,0.5):
>>> print time, sub_signal.duration
Get 1 second epochs, skipping every other epoch
>>> for time, sub_signal in sig1m.iter_window(1,2.0):
>>> print time, sub_signal.duration
Bases: pyrem.time_series.BiologicalTimeSeries
Annotations are time series of discrete values associated with a probability/confidence of observing this value. BiologicalTimeSeries indexing rules apply to them.
Parameters: |
|
---|
The probabilities/confidences associated to the annotation values.
Returns: | an array of float32 |
---|---|
Return type: | ndarray |
Resample annotations to a new sampling frequency. Values are resampled with nearest neighbour interpolation, while associated probabilities are linearly interpolated.
Parameters: | target_fs (float) – The target sampling frequency |
---|---|
Returns: | a new Annotation object |
Bases: numpy.ndarray
An abstract class for time series.
Parameters: |
|
---|
Deep copy a time series.
Returns: | A new time series with identical values and attributes |
---|---|
Return type: | BiologicalTimeSeries |
Iterate through an array by successive (possibly overlapping) slices (i.e. epochs). Conveniently, the central time ot the epoch is also returned.
Parameters: | |
---|---|
Returns: | (centre_of_window, BiologicalTimeSeries) |
Returns: | a dictionary of metadata (i.e. information about data acquisition) |
---|---|
Return type: | dict |
The name of the signal. It is expected to be unique.
Returns: | the user-defined name for this signal |
---|---|
Return type: | str |
Abstract method for resampling a time series (behaves differently according to the type of time series)
Note
Because time series are digital (i.e. discrete) the resulting sampling rate is expected to be slightly different from the target sampling rate.
Parameters: | new_fs (float) – the target time series |
---|---|
Returns: | a new BiologicalTimeSeries |
Bases: pyrem.time_series.BiologicalTimeSeries
Resample the signal. One implication of the signal being digital, is that the resulting sampling frequency is not guaranteed to be exactly at target_fs. This method wraps resample()
Parameters: |
|
---|---|
Returns: |