def append(self, timeData_Point_or_Slot, trust_me=False): '''You can append TimeDataPoints and TimeDataSlots''' if not trust_me: # A) Check data types for DataTimePoint or DataTimeSLot #if not isinstance(timeData_Point_or_Slot, DataTimePoint) and not isinstance(timeData_Point_or_Slot, DataTimeSlot): # raise Exception("Data type not supported (got {})".format(type(timeData_Point_or_Slot))) # B) Check for TimePoint os TimeSLot and that the DATA attribute is present if not isinstance(timeData_Point_or_Slot, TimePoint) and not isinstance(timeData_Point_or_Slot, TimeSlot): raise Exception("Got unsupported data type while appending to the DataTimeSeries (got {})".format(type(timeData_Point_or_Slot))) # Now try access data (Will automatically raise) TODO: improve _ = timeData_Point_or_Slot.data if self._data: last_timeData_Point_or_Slot = self._data[-1] if isinstance (timeData_Point_or_Slot, TimeSlot): this_t = timeData_Point_or_Slot.start.t last_t = last_timeData_Point_or_Slot.start.t elif isinstance (timeData_Point_or_Slot, TimePoint): this_t = timeData_Point_or_Slot.t last_t = last_timeData_Point_or_Slot.t else: raise InputException('Got {} ??'.format(type(last_timeData_Point_or_Slot))) # Check that the item being appended is the same type of the already added ones if self._data and not isinstance(timeData_Point_or_Slot, last_timeData_Point_or_Slot.__class__): raise InputException("Wrong data Type") # Check that we are adding time-ordered data. As TimeDataPoint and TimeDataSlot extends # TimePoint, we are sure that there is a time dimension ("t") to check if this_t <= last_t: raise InputException("Sorry, you are trying to append data with a timestamp which preceeds (or is equal to) the last one stored. As last I have {}, and I got {}" .format(dt_from_s(last_t, tz=self.tz), dt_from_s(this_t, tz=self.tz))) # If the data of timeData_Point_or_Slot is dimensional (lives in a Space, ex DimensionalData), check compatibility if isinstance(timeData_Point_or_Slot.data, Space): timeData_Point_or_Slot.data.is_compatible_with(last_timeData_Point_or_Slot.data, raises=True) # Check also the tz if last_timeData_Point_or_Slot.tz != timeData_Point_or_Slot.tz: raise InputException('Error, you are trying to add data with timezone "{}" but I have timezone "{}"'.format(timeData_Point_or_Slot.tz, last_timeData_Point_or_Slot.tz)) else: # Only check timezone consistence if any if self._tz and timeData_Point_or_Slot.tz != self.tz: raise InputException('Error, you are trying to add data with timezone "{}" but I have timezone "{}"'.format(timeData_Point_or_Slot.tz, self._tz)) if self.index is not None: self.index[timeData_Point_or_Slot.t] = len(self._data) self._data.append(timeData_Point_or_Slot)
def __getitem__(self, key): # Sanitize input if isinstance(key, datetime): epoch_s = dt_from_s(key) elif isinstance(key, int): epoch_s = key else: raise InputException("key not int or datetime") # Use index table? if self.index is not None: return self._data[self.index[epoch_s]] # Search with bisection for the right element. Surely improvable # TODO: add timestamps <-> position in list mapping table? floor = 0 ceil = len(self._data)-1 count = 0 while True: if count > len(self._data): raise Exception("Internal error when looking for the given timestamp (too many iterations)") # Bisection mid point: middle = floor + int((ceil-floor)/2) # Not found? if floor==ceil or floor==middle or ceil==middle: raise IndexError('Timestamp {} not found in TimeSeries!'.format(key)) # We found? if self._data[floor].t == epoch_s: return self._data[floor] if self._data[ceil].t == epoch_s: return self._data[ceil] if self._data[middle].t == epoch_s: return self._data[middle] if epoch_s > self._data[middle].t: floor = middle elif epoch_s < self._data[middle].t: ceil = middle else: raise Exception("Internal error when looking for the given timestamp (unconsistent condition)") count += 1
def __repr__(self): return '{} @ {}, first data label: {}, with value: {}'.format(self.__class__.__name__, dt_from_s(self.values[0], tz=self.tz), self.data.labels[0], self.data.values[0])