Coverage for brainbox/core.py: 81%

16 statements  

« prev     ^ index     » next       coverage.py v7.5.4, created at 2024-07-08 17:16 +0100

1""" 

2Creates core data types and functions which support all of brainbox. 

3""" 

4import numpy as np 

5 

6 

7class TimeSeries(dict): 

8 """A subclass of dict with dot syntax, enforcement of time stamping""" 

9 

10 def __init__(self, times, values, columns=None, *args, **kwargs): 

11 """TimeSeries objects are explicity for storing time series data in which entry (row) has 

12 a time stamp associated. TS objects have obligatory 'times' and 'values' entries which 

13 must be passed at construction, the length of both of which must match. TimeSeries takes an 

14 optional 'columns' argument, which defaults to None, that is a set of labels for the 

15 columns in 'values'. These are also exposed via the dot syntax as pointers to the specific 

16 columns which they reference. 

17 

18 :param times: an ordered object containing a list of timestamps for the time series data 

19 :param values: an ordered object containing the associated measurements for each time stamp 

20 :param columns: a tuple or list of column labels, defaults to none. Each column name will 

21 be exposed as ts.colname in the TimeSeries object unless colnames are not strings. 

22 

23 Also can take any additional kwargs beyond times, values, and columns for additional data 

24 storage like session date, experimenter notes, etc. 

25 

26 Example: 

27 timestamps, mousepos = load_my_data() # in which mouspos is T x 2 array of x,y coordinates 

28 positions = TimeSeries(times=timestamps, values=mousepos, columns=('x', 'y'), 

29 analyst='John Cleese', petshop=True, 

30 notes=("Look, matey, I know a dead mouse when I see one, " 

31 'and I'm looking at one right now.")) 

32 """ 

33 super(TimeSeries, self).__init__(times=np.array(times), values=np.array(values), 1a

34 columns=columns, *args, **kwargs) 

35 self.__dict__ = self 1a

36 self.columns = columns 1a

37 if self.values.ndim == 1: 1a

38 self.values = self.values.reshape(-1, 1) 1a

39 

40 # Enforce times dict key which contains a list or array of timestamps 

41 if len(self.times) != len(values): 1a

42 raise ValueError('Time and values must be of the same length') 

43 

44 # If column labels are passed ensure same number of labels as columns, then expose 

45 # each column label using the dot syntax of a Bunch 

46 if isinstance(self.values, np.ndarray) and columns is not None: 1a

47 if self.values.shape[1] != len(columns): 1a

48 raise ValueError('Number of column labels must equal number of columns in values') 

49 self.update({col: self.values[:, i] for i, col in enumerate(columns)}) 1a

50 

51 def copy(self): 

52 """Return a new TimeSeries instance which is a copy of the current TimeSeries instance.""" 

53 return TimeSeries(super(TimeSeries, self).copy())