Baz
Baz

Reputation: 13135

Apply square wave function to numpy array

I can quickly apply a cos function as follows to a float32 numpy array:

 cos_f = np.vectorize(lambda x: math.cos(2 * math.pi * x))
 signal = square_f(integral)

However if I try this:

 square_f = np.vectorize(lambda x: sig.square(2 * math.pi * x))
 signal = square_f(integral)

it takes 15 seconds for 60,000 samples. integral has a length of 1024 and is used as a buffer.

How should I be applying the square wave to my signal?

Upvotes: 2

Views: 745

Answers (2)

tenhjo
tenhjo

Reputation: 4537

I am not sure you need the np.vectorize here at all:

import numpy as np
from scipy import signal as sig

integral = np.linspace(0, 10, 1024)
signal1 = np.cos(2*np.pi * integral)
signal2 = sig.square(2*np.pi * integral)

You can of course also create a function and than call it with an array as input:

def cos2pi(x):
    return np.cos(2*np.pi * x)

signal1 = cos2pi(integral)

And one could go even further and call the function just once for all samples simultaneously.

samples = np.random.random((60000, 1024))
signal1 = cos2pi(samples)

Upvotes: 3

mathfux
mathfux

Reputation: 5949

sig.square(2*np.pi * x) is three times slower than np.cos(2*np.pi * x), however, this is not a bottleneck here. This nice np.vectorize - based decoration actually costs 120x slowdown! The reason why this happens is that square_f applies scipy.signal.square on items being iterated which is a bunch of aritmetics designed to work with arrays instead (unlike math.cos). This is an example of arithmetics done inside scipy.signal.square:

def example(x, w=0.5):
    return (1 - (w > 1) | (w < 0)) & (np.mod(x, 2 * pi) < w * 2 * np.pi)

Assuming arr is a large array, this is obviously more efficient to call example(arr) instead of

ex = np.vectorize(lambda x: example(x))
ex(arr)

The timings show that as well:

arr = np.linspace(0,1,1000000)
%timeit ex(arr)
%timeit example(arr)
8.13 s ± 208 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
18.5 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

Upvotes: 1

Related Questions