Detecting extreme values in Python
· 2 min read
Detecting extrema in a signal.
Generating a spurious signal as an example.
- 3 [Hz] signal + 0.01 [Hz] signal + noise
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy import signal

Examining the properties of the signal.
def acorr(df: pd.DataFrame, ra: int = 3, fs=100):
x = np.correlate(df.Data.values, df.Data.values, mode='full')
t = (np.arange(len(x)) - len(x) / 2 + 0.5) / fs
x /= x.max()
fig, ax = plt.subplots()
ax.set_xlim(-ra, ra)
ax.set_ylim(0, 1)
ax.plot(t, x)
ax.set_title('Autocorrelation')
ax.grid(axis='x')
ax.set_xticks(np.linspace(-ra, ra, 2 * ra + 1))
plt.show()
acorr(df)
The main signal is 1/3 [Hz]. Therefore, a low-pass filter with a cutoff of 1/3 [Hz] is applied.

Applying a low-pass filter and detecting extrema.
If the extrema are not correctly detected even after applying a low-pass filter at 1/3 [Hz], the frequency is lowered.

fs = 10
lpf = 0.1
b, a = signal.butter(5, lpf / fs * 2, 'low')
df['Filter'] = signal.filtfilt(b, a, df.Data.values)
max_idx = signal.argrelextrema(df['Filter'].values, np.greater)[0]
min_idx = signal.argrelextrema(df['Filter'].values, np.less)[0]
df['max_index'] = False
df.iloc[max_idx[0], 2] = True
df['min_index'] = False
df.iloc[min_idx[0], 3] = True
fig, ax = plt.subplots()
df.plot(ax=ax)
ax.set_xlim(['00:00:00', '00:00:30'])
ax.scatter(
df.loc[df['max_index'], ['Filter']].index,
df.loc[df['max_index'], ['Filter']],
color='tab:orange',
zorder=3)
ax.scatter(
df.loc[df['min_index'], ['Filter']].index,
df.loc[df['min_index'], ['Filter']],
color='tab:green',
zorder=3)
plt.show()
