Monitor.py 3.94 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
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"""
21
        if t is  None: t = self.env.now
22 23 24 25 26 27 28 29 30 31 32 33 34
        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[:] = []
35
        if t is None: t = self.env.now
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
        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,
84
        otherwise t =  self.sim.now
85 86 87 88 89 90

        """
        N = self.__len__()
        if N  == 0:
            return None

91
        if t is None: t = self.env.now
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
        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,
110
            otherwise t =  self.sim.now
111 112 113 114
        """
        N = self.__len__()
        if N  == 0:
            return None
115
        if t is None: t = self.env.now
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
        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