Efficient Algorithm for Computing Windowed Negative Amplitude Form

in

But before we dive into that, let me first explain why you might want to do this.

Imagine you have a signal that looks something like this:

# Import necessary libraries
import numpy as np # Import numpy library and alias it as "np" for easier use
from matplotlib import pyplot as plt # Import pyplot from matplotlib library and alias it as "plt" for easier use

# Create a time axis from 0 to 10 seconds with 1ms resolution
t = np.linspace(0, 10, num=1024) # Use numpy's linspace function to create an array of 1024 evenly spaced numbers from 0 to 10 and assign it to the variable "t"

# Create a signal with two sinusoidal components
s = np.sin(2*np.pi * t / 5) + 0.5 * np.cos(4*np.pi * t / 3) # Use numpy's sin and cos functions to create two sinusoidal components and add them together, then assign it to the variable "s"

# Plot the signal
plt.plot(t, s) # Use pyplot's plot function to plot the signal with time on the x-axis and the signal values on the y-axis
plt.show() # Use pyplot's show function to display the plot

This is a pretty simple example, but it’s enough to illustrate the concept of WNAF. If you look closely at this plot, you can see that there are two peaks: one around 2 seconds and another around 6 seconds. These correspond to the sinusoidal components with frequencies of 5 Hz (period = 10/5 = 2 seconds) and 3 Hz (period = 10/3 = 3.33 seconds), respectively.

Now, let’s say you want to find these peaks automatically without having to manually inspect the plot every time. This is where WNAF comes in handy! The basic idea behind this algorithm is to window your signal and then compute its negative amplitude form (NAF) for each windowed segment. NAF is simply the absolute value of the complex conjugate of a given signal, which can be used to identify peaks because it amplifies any positive-going signals while attenuating any negative-going ones.

Here’s how you might implement this algorithm in Python using NumPy and SciPy:

# Import necessary libraries
import numpy as np # Importing NumPy library for array manipulation
from scipy import signal # Importing SciPy library for signal processing
from matplotlib import pyplot as plt # Importing Matplotlib library for plotting

# Define time axis
t = np.linspace(0, 10, num=1024) # Creating a time axis from 0 to 10 seconds with 1ms resolution

# Define signal
s = np.sin(2*np.pi * t / 5) + 0.5 * np.cos(4*np.pi * t / 3) # Creating a signal with two sinusoidal components

# Define sampling frequency and signal duration
fs = 1e6 # Sampling frequency in Hz (assuming 1 MS/s resolution)
T = 10 # Duration of the signal in seconds

# Calculate number of samples in the signal
N = int(round(T * fs)) # Number of samples in the signal

# Calculate window size for WNAF computation
f1, f2 = 5, 3 # Frequencies of the sinusoids in Hz
window_size = int(round(fs / (2*f1))) # Window size for WNAF computation

# Compute NAF using a Hanning window and plot it
hann = np.hanning(window_size) # Creating a Hanning window of size window_size
y = s * hann # Multiplying the signal with the window
naf = 20*np.log10(np.abs(signal.fft(y)) / (fs/2)**2) # Computing the NAF using FFT and converting to decibels for better visibility
plt.plot(t, y) # Plotting the original signal
plt.plot(np.arange(window_size)*(fs/window_size), naf[0:window_size], color='red') # Plotting the NAF with the corresponding frequency axis
plt.show() # Displaying the plot

In this example, we first define the signal and its parameters (sampling frequency, window size, etc.). We then compute NAF using a Hanning window with length equal to the window size specified by `window_size`. The resulting plot shows both the original signal and its WNAF for the first windowed segment.

As you can see from this example, computing WNAF is not too difficult once you have your data in hand! By using a sliding window approach with appropriate windowing functions (such as Hanning or Hamming), you can easily identify peaks in your signal without having to manually inspect the plot every time. This can be especially useful for real-time applications where speed and accuracy are critical factors.

Give it a try on your own data and see how it performs!

SICORPS