Edouard@2741: #!/usr/bin/env python Edouard@2741: # -*- coding: utf-8 -*- Edouard@2741: Edouard@2741: # This file is part of Beremiz Edouard@2741: # Copyright (C) 2021: Edouard TISSERANT Edouard@2741: # Edouard@2741: # See COPYING file for copyrights details. Edouard@2741: Edouard@2741: # Based on Eelco Hoogendoorn stackoverflow answer about RingBuffer with numpy Edouard@2741: Edouard@2741: import numpy as np Edouard@2741: Edouard@2741: Edouard@2741: class RingBuffer(object): Edouard@2742: def __init__(self, width=None, size=131072, padding=None): Edouard@2741: self.size = size Edouard@2741: self.padding = size if padding is None else padding Edouard@2741: shape = (self.size+self.padding,) Edouard@2741: if width : Edouard@2741: shape += (width,) Edouard@2741: self.buffer = np.zeros(shape) Edouard@2742: self.cursor = 0 Edouard@2741: Edouard@2741: def append(self, data): Edouard@2741: """this is an O(n) operation""" Edouard@2742: data = data[-self.size:] Edouard@2741: n = len(data) Edouard@2742: if self.size + self.padding - self.cursor < n: Edouard@2742: self.compact() Edouard@2742: self.buffer[self.cursor:][:n] = data Edouard@2742: self.cursor += n Edouard@2741: Edouard@2741: @property Edouard@2741: def count(self): Edouard@2742: return min(self.size, self.cursor) Edouard@2741: Edouard@2741: @property Edouard@2741: def view(self): Edouard@2741: """this is always an O(1) operation""" Edouard@2742: return self.buffer[max(0, self.cursor - self.size):][:self.count] Edouard@2741: Edouard@2741: def compact(self): Edouard@2741: """ Edouard@2741: note: only when this function is called, is an O(size) performance hit incurred, Edouard@2741: and this cost is amortized over the whole padding space Edouard@2741: """ Edouard@2741: print 'compacting' Edouard@2742: self.buffer[:self.count] = self.view Edouard@2742: self.cursor -= self.size Edouard@2741: