class Monitor(list): """ Monitored variables A Class for monitored variables, that is, variables that allow one to gather simple statistics. A Monitor is a subclass of list and list operations can be performed on it. An object is established using m = Monitor(name = '..'). It can be given a unique name for use in debugging and in tracing and ylab and tlab strings for labelling graphs. """ def __init__(self, env , name = 'a_Monitor', ylab = 'y', tlab = 't'): list.__init__(self) self.env = env self.startTime = 0.0 self.name = name self.ylab = ylab self.tlab = tlab def observe(self, y,t = None): """record y and t""" if t is None: t = self.env.now self.append([t, y]) def tally(self, y): """ deprecated: tally for backward compatibility""" self.observe(y, 0) def accum(self, y,t = None): """ deprecated: accum for backward compatibility""" self.observe(y, t) def reset(self, t = None): """reset the sums and counts for the monitored variable """ self[:] = [] if t is None: t = self.env.now self.startTime = t def tseries(self): """ the series of measured times""" return list(zip(*self))[0] def yseries(self): """ the series of measured values""" return list(zip(*self))[1] def count(self): """ deprecated: the number of observations made """ return self.__len__() def total(self): """ the sum of the y""" if self.__len__() == 0: return 0 else: sum = 0.0 for i in range(self.__len__()): sum += self[i][1] return sum # replace by sum() later def mean(self): """ the simple average of the monitored variable""" try: return 1.0 * self.total() / self.__len__() except ZeroDivisionError: raise ZeroDivisionError('SimPy: No observations for mean') def var(self): """ the sample variance of the monitored variable """ n = len(self) tot = self.total() ssq = 0.0 for i in range(self.__len__()): ssq += self[i][1] ** 2 # replace by sum() eventually try: return (ssq - float(tot * tot) / n) / n except: raise ZeroDivisionError( 'SimPy: No observations for sample variance') def timeAverage(self, t = None): """ The time-weighted average of the monitored variable. If t is used it is assumed to be the current time, otherwise t = self.sim.now """ N = self.__len__() if N == 0: return None if t is None: t = self.env.now sum = 0.0 tlast = self[0][0] ylast = self[0][1] for i in range(N): ti, yi = self[i] sum += ylast * (ti - tlast) tlast = ti ylast = yi sum += ylast * (t - tlast) T = t - self[0][0] if T == 0: return None return sum / float(T) def timeVariance(self, t = None): """ the time - weighted Variance of the monitored variable. If t is used it is assumed to be the current time, otherwise t = self.sim.now """ N = self.__len__() if N == 0: return None if t is None: t = self.env.now sm = 0.0 ssq = 0.0 tlast = self[0][0] # print 'DEBUG: 1 twVar ', t, tlast ylast = self[0][1] for i in range(N): ti, yi = self[i] sm += ylast * (ti - tlast) ssq += ylast * ylast * (ti - tlast) tlast = ti ylast = yi sm += ylast * (t - tlast) ssq += ylast * ylast * (t - tlast) T = t - self[0][0] if T == 0: return None mn = sm / float(T) return ssq / float(T) - mn * mn