[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
works:

https://mail.python.org/pipermail/tutor/

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
start:

https://mail.python.org/pipermail/tutor/2014-August/102232.html

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():
# YOU HAVE TO WRITE THE CODE FOR THIS
# PLAY THE WAV FILE

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
else:
# 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:
trigger()

Something like this might do the job for you.

--
Steve
```