[Tutor] Seismometer alarm Python

Steven D'Aprano steve at pearwood.info
Sun Jan 4 17:41:09 CET 2015

On Sat, Jan 03, 2015 at 10:06:10AM -0700, Ted wrote:

> Hi Folks, I have a small python code to write.  It has at least three 
> parts, 1,2 and 3. I think I have 1 and 3 working.
> I do not know how this Tutor at python.org works, but if someone can 
> email me I can explain my questions.

You can read many years of archived emails to get a feel of how it 


I don't expect anyone to read thousands of emails, but spending a couple 
of minutes reading a few random posts to get a bit of an understanding 
of how the process works is not terribly hard. Here is a good place to 


After you've read the message, click "Next Message" and continue until 
you get bored :-)

> I do not wish to get into too much detail, on this first email.  

Thank you, but without some detail we can't do a thing to help you.

> Basically, I am receiving a list of numbers (int)? on a serial port in 
> python. I want to add a trigger, which will play an alarm file on the 
> computer when these numbers reach a certain condition.

Sorry, I have no idea how to read from the serial port, but I'll assume 
that you have the numbers in a list called "data".

> Actually two conditions, or two IF’s?  First IF..........if the 
> number/average, go up or down by (x percent)..........Second IF, if 
> the number/average stays above or below this average for (x number of 
> seconds)

This sounds like you need to calculate a running average. I'm going to 
guess a window-size of 5 for the running average. Let's start with a 
small function to calculate the average. If you are using Python 3.4, 
you can do this:

from statistics import mean

Otherwise, in older versions:

from math import fsum
def mean(alist):
    return fsum(alist)/len(alist)

Now let's calculate the running averages of the data, using a 
window-size of five:

def running_averages(data):
    for i in range(len(data)-4):
        yield mean(data[i:i+5])

Now we write a function that gets called by the trigger:

def trigger():

Now let's inspect those running averages, and trigger if we see a jump 
greater than 10% that lasts for at least three samples:

prev = None
count = 0
for ra in running_averages(data):
    if prev is not None:
        if abs(ra - prev)/ra < 0.1:
            # no spike, just background activity, so reset the count
            count = 0
            prev = ra
            # a spike of 10% is detected, increment the count but
            # don't update the previous average
            count += 1
            # check if this is the third spike
            if count >= 3:

Something like this might do the job for you.


More information about the Tutor mailing list