'Normalize the series to have a fixed period over a fixed time range.
Supports two modes, depending on the type of data:
NORMALIZE_MODE_GAUGE: support gauge values. If multiple original data
points lie within an output interval, the output value is an average of
the original data point.  if no original data points lie within an
output interval, the output value is None.
NORMALIZE_MODE_COUNTER: supports counter values. Assumes that the sequence
is already increasing (typically, MakeIncreasing will have been
called). Each output value is the largest value seen during or before
the corresponding output interval.
Args:
period: The desired time between points. Should be an rdfvalue.Duration or
a count of microseconds.
start_time: The first timestamp will be at start_time. Should be an
rdfvalue.RDFDatetime or a count of microseconds since epoch.
stop_time: The last timestamp will be at stop_time - period. Should be an
rdfvalue.RDFDatetime or a count of microseconds since epoch.
mode: The type of normalization to perform. May be NORMALIZE_MODE_GAUGE or
NORMALIZE_MODE_COUNTER.
Raises:
RuntimeError: In case the sequence timestamps are misordered.'

def Normalize(self, period, start_time, stop_time, mode=NORMALIZE_MODE_GAUGE):

    period = self._NormalizeTime(period)
    start_time = self._NormalizeTime(start_time)
    stop_time = self._NormalizeTime(stop_time)
    if (not self.data):
        return
    self.FilterRange(start_time, stop_time)
    grouped = {}
    for (value, timestamp) in self.data:
        offset = (timestamp - start_time)
        shifted_offset = (offset - (offset % period))
        grouped.setdefault(shifted_offset, []).append(value)
    self.data = []
    last_value = None
    for offset in range(0, (stop_time - start_time), period):
        g = grouped.get(offset)
        if (mode == NORMALIZE_MODE_GAUGE):
            v = None
            if g:
                v = (float(sum(g)) / float(len(g)))
            self.data.append([v, (offset + start_time)])
        else:
            if g:
                for v in g:
                    if (v < last_value):
                        raise RuntimeError('Next    value    must    not    be    smaller.')
                    last_value = v
            self.data.append([last_value, (offset + start_time)])
