views:

127

answers:

2

I want to do exactly what this guy did:

Python - count sign changes

However I need to optimize it to run super fast. In brief I want to take a time series and tell every time it crosses crosses zero (changes sign). I want to record the time in between zero crossings. Since this is real data (32 bit float) I doubt I'll every have a number which is exactly zero, so that is not important. I currently have a timing program in place so I'll time your results to see who wins.

My solution gives (micro seconds):

open data       8384
sign data       8123
zcd data        415466

As you can see the zero-crossing detector is the slow part. Here's my code.

import numpy, datetime

class timer():
    def __init__(self):
        self.t0 = datetime.datetime.now()
        self.t = datetime.datetime.now()
    def __call__(self,text='unknown'):
        print text,'\t',(datetime.datetime.now()-self.t).microseconds
        self.t=datetime.datetime.now()

def zcd(data,t):
    sign_array=numpy.sign(data)
    t('sign data')
    out=[]
    current = sign_array[0]
    count=0
    for i in sign_array[1:]:
        if i!=current:
            out.append(count)
            current=i
            count=0
        else: count+=1
    t('zcd data')
    return out

def main():
    t = timer()
    data = numpy.fromfile('deci.dat',dtype=numpy.float32)
    t('open data')
    zcd(data,t)

if __name__=='__main__':
    main()
+5  A: 

What about:

import numpy
a = [1, 2, 1, 1, -3, -4, 7, 8, 9, 10, -2, 1, -3, 5, 6, 7, -10]
zero_crossings = numpy.where(numpy.diff(numpy.sign(a)))[0]

Output:

> zero_crossings
array([ 3,  5,  9, 10, 11, 12, 15])

i.e. zero_crossings will contain the indices of elements after which a zero crossing occurs. If you want the elements before, just add 1 to that array.

Jim Brissom
+2  A: 

Do you want to time it? Or do you want to make it as fast as possible?

Timing is easy. Run it a zillion times, stopwatch it, and divide by a zillion.

To make it as fast as possible, what you need to do is find out what's taking time and that you could do in a better way. I use either 1) the random-pause technique, or 2) the single-step technique.

Mike Dunlavey
+1 random pause is great
knitti
Timing it is easy and it runs fast enough that you can get an accurate time by running it once. I want the script to run fast because it is part of a semi-realtime data processor.
dustynachos
@dustynachos: FWIW, here's a blow-by-blow account of using random-pause to get a series of speedups compounding to over 40x. http://stackoverflow.com/questions/926266/performance-optimization-strategies-of-last-resort/927773#927773
Mike Dunlavey