Parcourir la source

continues_statistic reworked

master
Dirk Alders il y a 4 ans
Parent
révision
43e0d556d1
1 fichiers modifiés avec 75 ajouts et 125 suppressions
  1. 75
    125
      __init__.py

+ 75
- 125
__init__.py Voir le fichier

@@ -8,71 +8,90 @@ logger = logging.getLogger(logger_name)
8 8
 
9 9
 
10 10
 class continues_statistic(dict):
11
-    KEY_SINGLE_VALUE = '_'
12
-    KEY_MEAN_VALUE = 'mean_val'
13
-    KEY_MIN_VALUE = 'min_val'
14
-    KEY_MAX_VALUE = 'max_val'
15
-    KEY_NUM_VALUES = 'num_val'
16
-    """
17
-    Value can be a single single numeric value: continues_statistic(num) or multivalue statistic: continues_statistic(val_a=continues_statistic(num_a), val_b=continues_statistic(num_b)). 
18
-    """
19
-    def __init__(self, *args, **kwargs):
20
-        if len(args) == 1 and isinstance(args[0], numbers.Number):
21
-            dict.__init__(self)
22
-            self[self.KEY_SINGLE_VALUE] = {
23
-                self.KEY_MIN_VALUE: args[0],
24
-                self.KEY_MEAN_VALUE: args[0],
25
-                self.KEY_MAX_VALUE: args[0],
26
-                self.KEY_NUM_VALUES: 1,
27
-            }
11
+    def __init__(self, mean=None, min_val=None, max_val=None, quantifier=None):
12
+        dict.__init__(self)
13
+        if mean is None:
14
+            self.__init_data__(None, None, None, None)
15
+        elif min_val is not None and max_val is not None and quantifier is not None:
16
+            self.__init_data__(mean, min_val, max_val, quantifier)
17
+        else:
18
+            self.__init_data__(mean, mean, mean, 1)
19
+
20
+    def __init_data__(self, mean, min_val, max_val, quantifier):
21
+        self['quantifier'] = quantifier
22
+        self['max_val'] = max_val
23
+        self['min_val'] = min_val
24
+        self['mean'] = mean
25
+
26
+    def expand(self, value):
27
+        if self['quantifier'] is None:
28
+            self.__init_data__(value, value, value, 1)
28 29
         else:
29
-            for key in kwargs:
30
-                if isinstance(kwargs[key], numbers.Number):
31
-                    kwargs[key] = continues_statistic(kwargs[key])
32
-            dict.__init__(self, *args, **kwargs)
30
+            cs_sum = self + continues_statistic(value)
33 31
             for key in self:
34
-                if type(self[key]) is not continues_statistic:
35
-                    data = continues_statistic()
36
-                    if key == self.KEY_SINGLE_VALUE:
37
-                        data[self.KEY_SINGLE_VALUE] = self[key]
38
-                    else:
39
-                        data[self.KEY_SINGLE_VALUE] = self[key][self.KEY_SINGLE_VALUE]
40
-                    self[key] = data
32
+                self[key] = cs_sum[key]
33
+
34
+    def __add__(self, other):
35
+        rv = continues_statistic()
36
+        rv['mean'] = (self.mean * self.quantifier + other.mean * other.quantifier) / (self.quantifier + other.quantifier)
37
+        rv['min_val'] = min(self.min, other.min)
38
+        rv['max_val'] = max(self.max, other.max)
39
+        rv['quantifier'] = self.quantifier + other.quantifier
40
+        return rv
41 41
 
42 42
     @property
43
-    def __multivalue__(self):
44
-        if len(self.keys()) == 0:
45
-            raise AttributeError('No data stored in continues statistic')
46
-        elif len(self.keys()) == 1:
47
-            if list(self.keys())[0] != self.KEY_SINGLE_VALUE:
48
-                raise AttributeError("The single value key needs to be %s." % self.KEY_SINGLE_VALUE)
49
-            return False
50
-        return True
43
+    def mean(self):
44
+        return self.get('mean')
51 45
 
52
-    def __add__(self, other):
53
-        rv = continues_statistic(self)
54
-        if self.__multivalue__:
55
-            if self.__multivalue__ != other.__multivalue__ or self.keys() != other.keys():
56
-                raise AttributeError("Instances are incompatible")
57
-            else:
58
-                for key in rv:
59
-                    rv[key] += other[key]
60
-        else:
61
-            rv[self.KEY_SINGLE_VALUE][self.KEY_MEAN_VALUE] = (self[self.KEY_SINGLE_VALUE][self.KEY_MEAN_VALUE] * self[self.KEY_SINGLE_VALUE][self.KEY_NUM_VALUES] + other[self.KEY_SINGLE_VALUE][self.KEY_MEAN_VALUE] * other[self.KEY_SINGLE_VALUE][self.KEY_NUM_VALUES]) / (self[self.KEY_SINGLE_VALUE][self.KEY_NUM_VALUES] + other[self.KEY_SINGLE_VALUE][self.KEY_NUM_VALUES])
62
-            rv[self.KEY_SINGLE_VALUE][self.KEY_MIN_VALUE] = min(self[self.KEY_SINGLE_VALUE][self.KEY_MIN_VALUE], other[self.KEY_SINGLE_VALUE][self.KEY_MIN_VALUE])
63
-            rv[self.KEY_SINGLE_VALUE][self.KEY_MAX_VALUE] = max(self[self.KEY_SINGLE_VALUE][self.KEY_MAX_VALUE], other[self.KEY_SINGLE_VALUE][self.KEY_MAX_VALUE])
64
-            rv[self.KEY_SINGLE_VALUE][self.KEY_NUM_VALUES] = self[self.KEY_SINGLE_VALUE][self.KEY_NUM_VALUES]+other[self.KEY_SINGLE_VALUE][self.KEY_NUM_VALUES]
46
+    @property
47
+    def min(self):
48
+        return self.get('min_val')
49
+
50
+    @property
51
+    def max(self):
52
+        return self.get('max_val')
53
+
54
+    @property
55
+    def quantifier(self):
56
+        return self.get('quantifier')
57
+
58
+    def pop(self):
59
+        rv = continues_statistic(self.mean, self.min, self.max, self.quantifier)
60
+        self.__init_data__(None, None, None, None)
65 61
         return rv
66
-    
62
+
67 63
     def __str__(self):
68
-        output_for_value = "mean=%%(%s)s, min=%%(%s)s, max=%%(%s)s, num=%%(%s)s" % (self.KEY_MEAN_VALUE, self.KEY_MIN_VALUE, self.KEY_MAX_VALUE, self.KEY_NUM_VALUES)
69
-        if self.__multivalue__:
70
-            rv = ""
71
-            for key in self:
72
-                rv += key + ': ' + str(self[key]) + "\n"
64
+        return "mean=%(mean)s, min=%(min_val)s, max=%(max_val)s, quantifier=%(quantifier)s" % self
65
+
66
+
67
+class continues_statistic_multivalue(dict):
68
+    def __init__(self, **kwargs):
69
+        dict.__init__(self)
70
+        for key in kwargs:
71
+            if type(kwargs[key]) is continues_statistic:
72
+                self[key] = kwargs[key]
73
+            elif type(kwargs[key]) is dict:
74
+                self[key] = continues_statistic(**kwargs[key])
75
+            else:
76
+                self[key] = continues_statistic(kwargs[key])
77
+
78
+    def expand(self, **kwargs):
79
+        for key in kwargs:
80
+            if key in self:
81
+                self[key].expand(kwargs[key])
82
+            else:
83
+                self[key] = continues_statistic(kwargs[key])
84
+
85
+    def pop(self, key=None):
86
+        if key is None:
87
+            rv = continues_statistic_multivalue(**self)
88
+            self.clear()
73 89
             return rv
74 90
         else:
75
-            return output_for_value % self[self.KEY_SINGLE_VALUE]
91
+            return self[key].pop()
92
+
93
+    def __str__(self):
94
+        return '\n'.join([key + ': ' + str(self[key]) for key in self])
76 95
 
77 96
 
78 97
 class ringbuffer(list):
@@ -89,72 +108,3 @@ class ringbuffer(list):
89 108
         rv = list.append(self, *args, **kwargs)
90 109
         self.__reduce_list__()
91 110
         return rv
92
-
93
-
94
-class data_collector(object):
95
-    def __init__(self, bufferlength, current_max_age=300.):
96
-        self.__current_max_age__ = current_max_age
97
-        self.__current_data_rinbuffer__ = ringbuffer(length=3)
98
-        #
99
-        self.__last_add_data__ = 0
100
-        self.__continues_statistic__ = None
101
-        self.__yesterdays_statistic__ = None
102
-        self.__measurement_day__ = None
103
-        #
104
-        self.__ringbuffer__ = ringbuffer(length=bufferlength)
105
-
106
-    def __process_continues_statistic__(self, **kwargs):
107
-        # rotate continues_statistic day by day
108
-        today = time.strftime('%Y' + os.path.sep + '%m' + os.path.sep + '%d')
109
-        if self.__measurement_day__ is None:
110
-            self.__measurement_day__ = today
111
-        if self.__measurement_day__ != today:
112
-            self.__yesterdays_statistic__ = self.__continues_statistic__
113
-            self.__continues_statistic__ = None
114
-            self.__measurement_day__ = None
115
-        # Set or update continues statistic
116
-        if self.__continues_statistic__ is None:
117
-            self.__continues_statistic__ = continues_statistic(**kwargs)
118
-        else:
119
-            self.__continues_statistic__ += continues_statistic(**kwargs)
120
-
121
-
122
-    def add_data(self, **kwargs):
123
-        logger.debug('Got data %s', repr(kwargs))
124
-        self.__last_add_data__ = time.time()
125
-        self.__current_data_rinbuffer__.append(kwargs)
126
-        self.__process_continues_statistic__(**kwargs)
127
-        self.__ringbuffer__.append(kwargs)
128
-
129
-    @property
130
-    def current(self):
131
-        if len(self.__current_data_rinbuffer__) == 0:
132
-            logger.info('No data available, yet.')
133
-            return None
134
-        elif  time.time() > self.__last_add_data__ + self.__current_max_age__:
135
-            logger.info('Data max age reached. No current data available.')
136
-            return None
137
-        elif  len(self.__current_data_rinbuffer__) < 3:
138
-            return self.__current_data_rinbuffer__[-1]
139
-        else:
140
-            rv = {}
141
-            for key in self.__current_data_rinbuffer__[0]:
142
-                data = []
143
-                for entry in self.__current_data_rinbuffer__:
144
-                    data.append(entry[key])
145
-                else:
146
-                    data.sort()
147
-                    rv[key] = data[1]
148
-            return rv
149
-
150
-    @property
151
-    def todays_statistic(self):
152
-        return self.__continues_statistic__
153
-
154
-    @property
155
-    def yesterdays_statistic(self):
156
-        return self.__yesterdays_statistic__
157
-
158
-    @property
159
-    def databuffer(self):
160
-        return self.__ringbuffer__[:]

Chargement…
Annuler
Enregistrer