Beispiel #1
0
    def _update_buffer(self, data: np.ndarray, cache: PerFrameCache) -> None:
        """
        Update self._buffer by adding `data` and a step function.
        Data is reshaped to taper away from the center.

        :param data: Wave data. WILL BE MODIFIED.
        """
        assert cache.mean is not None
        assert cache.period is not None
        buffer_falloff = self.cfg.buffer_falloff
        responsiveness = self.cfg.responsiveness

        N = len(data)
        if N != self._buffer_nsamp:
            raise ValueError(f"invalid data length {len(data)} does not match "
                             f"CorrelationTrigger {self._buffer_nsamp}")

        # New waveform
        data -= cache.mean
        normalize_buffer(data)
        window = windows.gaussian(N,
                                  std=(cache.period / self._stride) *
                                  buffer_falloff)
        data *= window

        # Old buffer
        normalize_buffer(self._buffer)
        self._buffer = lerp(self._buffer, data, responsiveness)
Beispiel #2
0
def gaussian_or_zero(M: int, std: float, sym: bool = True) -> np.ndarray:
    """
    Sometimes `std` is computed based on period.

    If period is zero (cannot be estimated), return all zeros.
    """
    if std == 0:
        return np.zeros(M, dtype=f32)
    else:
        return windows.gaussian(M, std, sym)
Beispiel #3
0
def calc_step(nsamp: int, peak: float, stdev: float) -> np.ndarray:
    """ Step function used for approximate edge triggering.
    TODO deduplicate CorrelationTrigger._calc_step() """
    N = nsamp
    halfN = N // 2

    step = np.empty(N, dtype=FLOAT)  # type: np.ndarray[FLOAT]
    step[:halfN] = -peak / 2
    step[halfN:] = peak / 2
    step *= windows.gaussian(N, std=halfN * stdev)
    return step
Beispiel #4
0
    def _calc_step(self) -> np.ndarray:
        """ Step function used for approximate edge triggering. """

        # Increasing buffer_falloff (width of history buffer)
        # causes buffer to affect triggering, more than the step function.
        # So we multiply edge_strength (step function height) by buffer_falloff.

        edge_strength = self.cfg.edge_strength * self.cfg.buffer_falloff
        N = self._buffer_nsamp
        halfN = N // 2

        step = np.empty(N, dtype=FLOAT)  # type: np.ndarray[FLOAT]
        step[:halfN] = -edge_strength / 2
        step[halfN:] = edge_strength / 2
        step *= windows.gaussian(N, std=halfN / 3)
        return step
Beispiel #5
0
    def _calc_slope_finder(self, period: float) -> np.ndarray:
        """Called whenever period changes substantially.
        Returns a kernel to be correlated with input data to find positive slopes,
        with length A+B."""

        cfg = self.cfg
        kernel_size = self.A + self.B

        # noinspection PyTypeChecker
        slope_width: float = np.clip(cfg.slope_width * period, 1.0, self.A / 3)

        # This is a fudge factor. Adjust it until it feels right.
        slope_strength = cfg.edge_strength * 5
        # slope_width is 1.0 or greater, so this doesn't divide by 0.

        slope_finder = np.empty(kernel_size,
                                dtype=f32)  # type: np.ndarray[f32]
        slope_finder[:self.A] = -slope_strength / 2
        slope_finder[self.A:] = slope_strength / 2

        slope_finder *= windows.gaussian(kernel_size, std=slope_width)
        return slope_finder