Can I combine an IIR (an EWMA) with a maximum? I'd like to have a exponentially weighted moving average (EWMA) which is raised to the value of the input signal whenever this is higher than the filter output.  This taking of the maximum shall take place during the iteration, not afterwards (which would be simple).

So, the algorithm should look like this:

o = 0  # or some arbitrary initial value
for i in input:
    o = (o * 99 + i) / 100
    if i &gt; o:
      o = i
    print o


So effectively, my output shall fall slowly after a quickly falling edge in the input without rising quickly before a rising edge.



In fact, any other algorithm which just copies the input except for the places where it has a rapidly falling edge (there it should play parachute and let the output fall slower) would do fine.

The only restriction I have is that this needs to be implemented in the usual Python libraries (numpy, scipy, pandas); iterating myself will not be fast enough.

I tried applying a rolling maximum, followed by a rolling mean with a Gaussian window of the same width (using pandas.Series(arr).rolling()); this gives me nice smoothing of the fall after a falling edge; unfortunately it also gives me an equal smoothing before the rising edges (which I don't want).

If there was a way to apply an asymmetric Gaussian window (e. g. rising slowly and falling quickly) that would be a solution I guess.  But I haven't found a way to achieve this yet.
What you are describing is an envelope detector which can be formed by a Peak Detector followed by an ADSR.

The peak detection is performed by the non linear 'max' filter as per your description. This, on its own, would track the maximum of the signal and stay at that max value.

To now modify that signal's dynamics so that it 'launches' and 'parachutes' at specific rates, you add the Attack-Decay-Sustain-Release component. You don't need all four stages. This could simply be an Attack-Decay (as per your needs).

In fact, in your application, the Attack is zero. As soon as a new max is detected the output of the system is reset immediately. But, while the new values are lower than the maximum, this 'output' now decreases at a desired rate (The Decay stage). In your case this could be as simple as o-=aRate if o&gt;0 else 0 in the else branch of the if.

Hope this helps.