On 16 April 2018 at 10:49, Peter O'Connor <peter.ed.oconnor@gmail.com> wrote:
Are you able to show how you'd implement the moving average example with your package?

Sure! The single pole IIR filter you've shown is implemented here:

I tried: 

    def exponential_moving_average_pyscan(signal, decay, initial=0):
        yield from ((1-decay)*(average or initial) + decay*x for x in signal)
    smooth_signal_9 = list(exponential_moving_average_pyscan(signal, decay=decay))[1:]

Which almost gave the right result, but seemed to get the initial conditions wrong. 

I'm not sure what you were expecting. A sentinel as the first "average" value?

Before the loop begins, this scan-generator just echoes the first input, like itertools.accumulate.
That is, the first value this generator yields is the first "signal" value, which is then the first "average" value.

To put an initial memory state, you should do something like this (I've removed the floating point trailing noise):

>>> from pyscanprev import enable_scan, prepend
>>> @enable_scan("y")
>>> def iir_filter(signal, decay, memory=0):
...     return ((1 - decay) * y + decay * x for x in prepend(memory, signal))
>>> list(iir_filter([1, 2, 3, 2, 1, -1, -2], decay=.1, memory=5))
[5, 4.6, 4.34, 4.206, 3.9854, 3.68686, 3.218174, 2.6963566]

In that example, "y" is the "previous result" (a.k.a. accumulator, or what had been called "average" here).

Danilo J. S. Bellini
"It is not our business to set up prohibitions, but to arrive at conventions." (R. Carnap)