def _set_h5_signal(self, h5): # ---------------------------- self._h5 = h5 if h5.clock: self.clock = Clock(h5.clock.uri, h5.clock.times, units=h5.clock.units) elif h5.rate: self.clock = UniformClock(None, h5.rate, units=h5.clock.units)
def _set_h5_signal(self, h5): #---------------------------- self._h5 = h5 if h5.clock: self.clock = Clock(h5.clock.uri, h5.clock.times, units=h5.clock.units) elif h5.rate: self.clock = UniformClock(None, h5.rate, units=h5.clock.units)
class HDF5Signal(BSMLSignal): #============================ """ A :class:`~biosignalml.Signal` in a HDF5 Recording. :param uri: The signal's URI. :param units: The physical units of the signal's data. :param kwds: Other :class:`~biosignalml.Signal` attributes to set. """ def __init__(self, uri, units, **kwds): #-------------------------------------- BSMLSignal.__init__(self, uri, units, **kwds) self._h5 = None def __len__(self): #----------------- """ Get the number of data points in a signal. """ return len(self._h5) if self._h5 is not None else 0 def _set_h5_signal(self, h5): #---------------------------- self._h5 = h5 if h5.clock: self.clock = Clock(h5.clock.uri, h5.clock.times, units=h5.clock.units) elif h5.rate: self.clock = UniformClock(None, h5.rate, units=h5.clock.units) @classmethod def create_from_H5Signal(cls, index, signal): #-------------------------------------------- """ Create a new signal from a signal dataset in a BioSignalML HDF5 file. """ self = cls(signal.uri, signal.units, rate=signal.rate, clock=signal.clock) self._set_h5_signal(signal) return self def read(self, interval=None, segment=None, maxduration=None, maxpoints=None): #----------------------------------------------------------------------------- """ Read data from a signal. :param interval: The portion of the signal to read. :type interval: :class:`~biosignaml.time.Interval` :param segment: A 2-tuple with start and finishing data indices, with the end point not included in the returned range. :param maxduration: The maximum duration, in seconds, of a single returned segment. :param maxpoints: The maximum length, in samples, of a single returned segment. :return: An `iterator` returning :class:`~biosignalml.data.DataSegment` segments of the signal data. If both ``maxduration`` and ``maxpoints`` are given their minimum value is used. """ if interval is not None and segment is not None: raise ValueError( "'interval' and 'segment' cannot both be specified") if maxduration: pts = int(self.rate * maxduration + 0.5) if maxpoints: maxpoints = min(maxpoints, pts) else: maxpoints = pts if maxpoints is None or not (0 < maxpoints <= BSMLSignal.MAXPOINTS): maxpoints = BSMLSignal.MAXPOINTS # We need to be consistent as to what an interval is.... # Use model.Interval ?? if interval is not None: segment = (self.clock.index(interval.start), self.clock.index(interval.end)) if segment is None: startpos = 0 length = len(self) else: if segment[0] <= segment[1]: seg = segment else: seg = (segment[1], segment[0]) ##startpos = max(0, int(math.floor(seg[0]))) startpos = max(0, seg[0]) length = min(len(self), seg[1] + 1) - startpos while length > 0: if maxpoints > length: maxpoints = length data = self._h5[startpos:startpos + maxpoints] if isinstance(self.clock, UniformClock): yield DataSegment(self.clock[startpos], UniformTimeSeries(data, self.clock.rate)) else: yield DataSegment( 0, TimeSeries(data, self.clock[startpos:startpos + maxpoints])) startpos += len(data) length -= len(data) def initialise(self, **kwds): #---------------------------- """ Set signal attributes once the HDF5 file of its recording is opened. Creates a signal dataset in the HDF5 file if it doesn't exist. """ if self.recording._h5 is not None: rec_h5 = self.recording._h5 h5 = rec_h5.get_signal(self.uri) if h5 is None and kwds.pop('create', False): if self.clock: rec_h5.create_clock(self.clock.uri) kwds['clock'] = self.clock.uri kwds['rate'] = getattr(self, 'rate', None) h5 = rec_h5.create_signal(self.uri, self.units, **kwds) if h5 is not None: self._set_h5_signal(h5) def append(self, timeseries): #---------------------------- ''' Append data to a signal. :param timeseries: The data points (and times) to append. :type timeseries: :class:`~biosignalml.data.TimeSeries` ''' if self.clock and not isinstance(self.clock, UniformClock): self.recording._h5.extend_clock(self.clock.uri, timeseries.time.times) self.recording._h5.extend_signal(self.uri, timeseries.data) def extend(self, points): #------------------------ ''' Append data points to a signal. :param points: The data points to append. :type points: :class:`numpy.ndarray` or an iterable. ''' self.recording._h5.extend_signal(self.uri, points)
class HDF5Signal(BSMLSignal): # ============================ """ A :class:`~biosignalml.Signal` in a HDF5 Recording. :param uri: The signal's URI. :param units: The physical units of the signal's data. :param kwds: Other :class:`~biosignalml.Signal` attributes to set. """ def __init__(self, uri, units, **kwds): # -------------------------------------- BSMLSignal.__init__(self, uri, units, **kwds) self._h5 = None def __len__(self): # ----------------- """ Get the number of data points in a signal. """ return len(self._h5) if self._h5 is not None else 0 def _set_h5_signal(self, h5): # ---------------------------- self._h5 = h5 if h5.clock: self.clock = Clock(h5.clock.uri, h5.clock.times, units=h5.clock.units) elif h5.rate: self.clock = UniformClock(None, h5.rate, units=h5.clock.units) @classmethod def create_from_H5Signal(cls, index, signal): # -------------------------------------------- """ Create a new signal from a signal dataset in a BioSignalML HDF5 file. """ self = cls(signal.uri, signal.units, rate=signal.rate, clock=signal.clock) self._set_h5_signal(signal) return self def read(self, interval=None, segment=None, maxduration=None, maxpoints=None): # ----------------------------------------------------------------------------- """ Read data from a signal. :param interval: The portion of the signal to read. :type interval: :class:`~biosignaml.time.Interval` :param segment: A 2-tuple with start and finishing data indices, with the end point not included in the returned range. :param maxduration: The maximum duration, in seconds, of a single returned segment. :param maxpoints: The maximum length, in samples, of a single returned segment. :return: An `iterator` returning :class:`~biosignalml.data.DataSegment` segments of the signal data. If both ``maxduration`` and ``maxpoints`` are given their minimum value is used. """ if interval is not None and segment is not None: raise ValueError("'interval' and 'segment' cannot both be specified") if maxduration: pts = int(self.rate * maxduration + 0.5) if maxpoints: maxpoints = min(maxpoints, pts) else: maxpoints = pts if maxpoints is None or not (0 < maxpoints <= BSMLSignal.MAXPOINTS): maxpoints = BSMLSignal.MAXPOINTS # We need to be consistent as to what an interval is.... # Use model.Interval ?? if interval is not None: segment = (self.clock.index(interval.start), self.clock.index(interval.end)) if segment is None: startpos = 0 length = len(self) else: if segment[0] <= segment[1]: seg = segment else: seg = (segment[1], segment[0]) ##startpos = max(0, int(math.floor(seg[0]))) startpos = max(0, seg[0]) length = min(len(self), seg[1] + 1) - startpos while length > 0: if maxpoints > length: maxpoints = length data = self._h5[startpos : startpos + maxpoints] if isinstance(self.clock, UniformClock): yield DataSegment(self.clock[startpos], UniformTimeSeries(data, self.clock.rate)) else: yield DataSegment(0, TimeSeries(data, self.clock[startpos : startpos + maxpoints])) startpos += len(data) length -= len(data) def initialise(self, **kwds): # ---------------------------- """ Set signal attributes once the HDF5 file of its recording is opened. Creates a signal dataset in the HDF5 file if it doesn't exist. """ if self.recording._h5 is not None: rec_h5 = self.recording._h5 h5 = rec_h5.get_signal(self.uri) if h5 is None and kwds.pop("create", False): if self.clock: rec_h5.create_clock(self.clock.uri) kwds["clock"] = self.clock.uri kwds["rate"] = getattr(self, "rate", None) h5 = rec_h5.create_signal(self.uri, self.units, **kwds) if h5 is not None: self._set_h5_signal(h5) def append(self, timeseries): # ---------------------------- """ Append data to a signal. :param timeseries: The data points (and times) to append. :type timeseries: :class:`~biosignalml.data.TimeSeries` """ if self.clock and not isinstance(self.clock, UniformClock): self.recording._h5.extend_clock(self.clock.uri, timeseries.time.times) self.recording._h5.extend_signal(self.uri, timeseries.data) def extend(self, points): # ------------------------ """ Append data points to a signal. :param points: The data points to append. :type points: :class:`numpy.ndarray` or an iterable. """ self.recording._h5.extend_signal(self.uri, points)