Intervals can carry particular special meaning in the analysis of time-series. For example, a typical case, is when two time-series are recorded simultaneously. One is recorded from measurement of some continuous physilogical variable, such as fMRI BOLD (and is represented by a an object of type UniformTimeSeries). The other is a series of discrete events occuring concurrently (and can be represented by a EventSeries or by a NonUniformTimeSeries). For example, button presses by the subject, or trials of different kinds. If we want to analyze the progression of the physiological time-series, locked to particular kinds of events in the event-series, we would need a notion of an interval of time surrounding those events.
In order to do that, we propose implementing a TimeInterval object.
A TimeInterval object can be thought of as a Slice for time-series objects and therefore should at least implement all attributes and methods of the slice object (sub-classing of slice doesn’t seem to be possible, see interval_from_slice).
In particular, an object of class TimeInterval, TI, has the attributes/functions:
Obviously, knowledge of two of these, should allow calculation of the third. Therefore, this should be implemented in the object with a setattr_on_read() decoration and the object should inherit ResetMixin. Initialization of the object would verify that enough information exists and that the information provided is consistent, in the same manner that is already implemented in UniformTimeSeries.
>>>TI.indices(0)
(TI.t_start TI.t_stop, TI.t_step)
There are various different ways to initialize a TimeInterval:
TimeInterval(t_start=t1,t_stop=t2)
TimeInterval(t_start=t1,duration=t_duration)
TimeInterval(t_start=t1, t_stop=t2, t_step=delta_t)
or
TimeInterval (t_start=t1,duration=delta_t1, t_step=delta_t2)
Finally, we would like allow setting the interval with floating point values, which will be interpreted as time points t_start and t_stop. This convention would be convenient, but requires that the initialization of the object will know what the units are. In order to make this possible, the interval (similar to the current implementation of the time-series object will have an attribute t_unit, which would default to ‘s’. The initialization will then cast the values provided into the appropriate TimeArray objects.
Sub-classing of the slice object doesn’t seem to be possible:
>>> class myslice(slice):
... pass
...
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
TypeError: Error when calling the metaclass bases
type 'slice' is not an acceptable base type
However, it seems that a (scalar) TimeInterval can be implemented using a slice object, provided the time points t_start and t_stop and the time offset t_step implement an __index__ method:
>>> s = slice('t_start','t_stop','t_step')
>>> s.start
't_start'
>>> s.stop
't_stop'
>>> s.step
't_step'
>>> s.indices(1)
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
TypeError: slice indices must be integers or None or have an __index__ method
Alternatively, the TimeInterval can be implemented as an original object with the default constructor as similar as possible to the constructor of the slice object, so that we can use slice-like operations, but still maintain slice algebra and such.
In addition to the possibility of algebraic operations, there are other reasons to have the TimeInterval be an original class that holds a slice object that can be returned by the method TI.asslice().
In addition to scalar TimeInterval objects, it also makes sense to define arrays of TimeInterval objects. These arrays can be implemented as np.ndarray, with an object dtype.