def test_dispersionCalcForError(self): """With non-zero error contribution, the dispersion at different times is additional to that of the parent clock, both before and after the correlation time""" a = self.newSysClock(tickRate=1000) b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0, 0.5, 0.1)) self.assertEquals( a.dispersionAtTime(10) + 0.5 + 0.1 * 10 / 1000, b.dispersionAtTime(10)) self.assertEquals( a.dispersionAtTime(20) + 0.5 + 0.1 * 20 / 1000, b.dispersionAtTime(20)) self.assertEquals( a.dispersionAtTime(-10) + 0.5 + 0.1 * 10 / 1000, b.dispersionAtTime(-10))
def algorithm(self): candidateClock = CorrelatedClock(self.clock.getParent(), tickRate=self.clock.tickRate, correlation=self.clock.correlation) while True: update = False cumulativeOffset = None candidate = (yield self.timeoutSecs) t = self.clock.ticks currentDispersion = self.clock.dispersionAtTime(t) if candidate is not None: candidateClock.correlation = candidate.calcCorrelationFor( self.clock, self.localMaxFreqErrorPpm) candidateDispersion = candidateClock.dispersionAtTime(t) update = candidateDispersion < currentDispersion if update: pt = self.clock.toParentTicks(t) adjustment = candidateClock.fromParentTicks(pt) - t if cumulativeOffset is None: cumulativeOffset = 0 else: cumulativeOffset += adjustment self.clock.correlation = candidateClock.correlation self.onClockAdjusted( self.clock.ticks, adjustment, 1000000000 * currentDispersion, 1000000000 * candidateDispersion, self.clock.correlation.errorGrowthRate) else: pass # update worst dispersion seen so far self.worstDispersion = max(self.worstDispersion, currentDispersion, candidateDispersion) co = cumulativeOffset or 0 # convert None to 0 self.log.info( "Old / New dispersion (millis) is %.5f / %.5f ... offset=%20d new best candidate? %s\n" % (1000 * currentDispersion, 1000 * candidateDispersion, co, str(update))) else: self.log.info("Timeout. Dispersion (millis) is %.5f\n" % (1000 * currentDispersion, )) # retry more quickly if we didn't get an improved candidate if update: time.sleep(self.repeatSecs) else: time.sleep(self.timeoutSecs)
class FilterLowestDispersionCandidate(object): """\ Simple filter that will reject a candidate unless its dispersion is lower than that currently being used by the clock. Note that at initialisation, the clock's dispersion is forced to +infinity. """ def __init__(self, clock): """\ :param clock: A :class:`~dvbcss.clock.CorrelatedClock` object representing that will be adjusted to match the Wall Clock. """ self.clock = clock self.clock.correlation = clock.correlation.butWith( initialError=float("+inf")) self.tmpClock = CorrelatedClock(self.clock.getParent(), self.clock.tickRate) def checkCandidate(self, candidate): self.tmpClock.correlation = candidate.calcCorrelationFor(self.clock) t = self.clock.ticks if self.clock.dispersionAtTime(t) > self.tmpClock.dispersionAtTime(t): return True else: return False
def test_dispersionCalcForZeroError(self): """With zero error contribution, the dispersion at different times is the same as for the parent clock""" a = self.newSysClock(tickRate=1000) b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0)) self.assertEquals(a.dispersionAtTime(10), b.dispersionAtTime(10)) self.assertEquals(a.dispersionAtTime(20), b.dispersionAtTime(20))