## Functions where select and find

The first set of functions we'll cover is where(), select(), and find().

The function find(cond) finds the indices to an array for which a condition is met:

>>> from pylab import * >>> squares = arange(l0)**2 >>> squares array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81]) >>> I = find(squares < 50)

array([0, 1, 2, 3, 4, 5, 6, 7]) >>> squares[I]

We created a vector holding the squares of the numbers 0-9 and found all the indices to the vector that satisfy the condition that the squares are less than 50. Notice that the return value is a vector of indices, and if you require the values and not the indices, you have to access the original array, which is squares[I] in the preceding example.

The function where(cond, x, y) accepts three arrays of the same size: cond, x, and y, and then evaluates every element in cond. If the element evaluates to True, the return value is the corresponding element from x; if the return element evaluates to False, the return value is the corresponding element from y:

>>> up array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> down = arange(l0, 0, -l) >>> down array([l0, 9, 8, 7, 6, 5, 4, 3, 2, l]) >>> highest = where(up > down, up, down) >>> highest array([l0, 9, 8, 1, 6, 5, 6, 7, 8, 9])

The function select(cond, vals, default=o) adds functionality to the function where() by allowing for several conditions. The function accepts a list of conditions specified in cond and returns the corresponding element associated with vals if a condition is met; if none of the conditions are met, the default value is selected.

>>> ramp = select([up <4,up> 7], [4, 7], up) >>> ramp array([4, 4, 4, 4, 4, 5, 6, 1, 7, 7])

The first three elements of up are less than 4, so the condition up<4 is met, causing the selection of value 4. The last three elements are greater than 7, causing the selection of the value 7, and values greater than or equal to 4 yet less than 7 are retained as is because the default is set to be equal to up. As a matter of fact, this functionality is called clipping and is available as both a method of the NumPy ndarray object and as a stand-alone function, clip().

So now that you know of the functions find(), where(), and select(), what can you do with them? The answer is simple: they're great for picking up values, what we call detection in signal processing.

Example: Simple Detection of Signal in Noise, Part 1

The detection of signals in the presence of noise plays an integral role in a great number of applications. For example, it is used in communication systems in the detection of signals such as radio or television broadcasts and differentiating them from noise, in medicine with the detection of an ECG signal, and more.

For the purpose of this example, we'll first construct a clean signal. By a signal, I mean a one-dimensional array (vector), where values are stored as a function of time. Our purpose will be to detect "events," which will be represented by narrow triangles placed randomly in time. There can be several events in a signal.

To generated a triangular pulse, I'll use the signal.triang() function (which is really a window function, more on that later in the chapter in the section "Window Functions"). The function generates a triangular window of a specified size. We randomly place triangular pulses in the signal vector, as shown in Listing 8-2.

Listing 8-2. Randomly Placing Triangular Spikes from pylab import * from scipy import signal

# parameters controlling the signal n = 100

t = arange(n) y = zeros(n) num_pulses = 3 pw = 11 amp = 20

for i in range(num_pulses):

loc = floor(rand()*(n-pw+l)) y[loc:loc+pw] = signal.triang(pw)*amp

figure()

title('Signal and noise') xlabel('t') ylabel('y') plot(t, y)

First I defined some parameters I'll be using. The number of points in the signal is n and is equal to 100. The number of triangular pulses I'll place is 3, denoted by numpulses. Each triangular pulse will be generated using pw=ll points. The maximum value for the triangular spike will be amp, denoting amplitude.

Once I have all the parameters defined, I create two vectors: the time vector, t, and the values vector, y. The vector t is some arbitrary timestamp, in this example incrementing values starting at zero and ending at n - 1. The vector y is initially set at zero.

Next I randomly place triangular spikes. The location, loc, where the triangular spike will be placed is randomly generated with the call to the function rand() that generates a value between 0 and 1, and so I randomly pick a value between 0 and n - pw + 1 to ensure spikes aren't placed outside the vector y. Once I have all the spikes placed, I add noise by use of the function randn() that generates a normally distributed noise, also known as Gaussian distribution, or "white noise." I've chosen to use a normal distribution with variance 1 and mean 0. Notice that randn() is different fromrand().

Figure 8-8 shows a randomly generated signal.

Signal and noise

50 20 40 60 80 100

Figure 8-8. Three triangular spikes with noise

I did not check to see that spikes do not overlap, so as you run the script at times you'll view one or two spikes instead of three. This is fine, since we want to add some randomness to the example.

So far we've just created the signal. Now let's detect it. For detection, we'll use a simple algorithm: whenever a value is above a set threshold, we'll declare this as an event, or detection. We'll set the threshold at amp/2 and make use of the function find(), as shown in Listing 8-3. 50 20 40 60 80 100

Listing 8-3. Detecting Signals

# detect signals thr = amp/2

# plot signal with noise plus detection figure()

hold(True)

plot(t, y, 'b', label='signal with noise') plot(t[I], y[I], 'ro', label='detections') plot([0, n], [thr, thr], 'g-')

# annotate the threshold text(2, thr+.2, 'Threshold', va='bottom')

title('Simple signal detection in noise') legend(loc='best')

Figure 8-9 shows the result.

50 20 40 60 80 100

Figure 8-9. Simple signal detection in the presence of noise

Simple signal detection in noise

- signal with noise 50 20 40 60 80 100

Figure 8-9. Simple signal detection in the presence of noise