4
$\begingroup$

I am analyzing pressure data sampled at 1Hz. The times series exhibit "ramps" (a linear increase in pressure followed by a sudden drop) for which I would like to automatically detect the start and stop times. Please note that these pressure events are not periodic:

enter image description here

My first attempt was to use SciPy's find_peaks function on a smoothed version of my data.

I first smoothed these time series using the function described in the SciPy's cookbook:

smoothed_pressure = smooth(df['Pressure'], window_len=21)

enter image description here

I then applied find_peaks to find the maximum peaks (in red) above the mean_amplitude of the smoothed data and the minimum peaks (in yellow) below this amplitude:

mean_amplitude = np.mean(smoothed_pressure)
max_indices = find_peaks(smoothed_pressure, distance=200, height=mean_amplitude)[0]
min_indices = find_peaks(smoothed_pressure, distance=200, height=[0,mean_amplitude])[0]

plt.figure(figsize=(20,3))
plt.title(filename)
plt.plot(df['Time'], df["Pressure"])
plt.scatter(df[df.index.isin(max_indices-11)]['Time'], df[df.index.isin(max_indices-11)]["Pressure"], color='red', zorder=5)
plt.scatter(df[df.index.isin(min_indices-11)]['Time'], df[df.index.isin(min_indices-11)]["Pressure"], color='yellow', zorder=5)

enter image description here

After tweaking the distance I managed to get this strategy to work for this specific example, but this solution is not robust enough and fails when applied to other datasets.

I am looking for other strategies to deal with this problem.

I am thinking of differentiating the data before trying to identify the peaks. I am also open to trying machine learning strategies. Any other idea will be welcome!

------------------------------------------------------------------------------------------------------------

EDIT: IMPLEMENTING MAXTRON'S SOLUTION

As suggested by Maxtron in his answer below, computing the second order derivative is an excellent way to nail down the stop time of each ramp.

In the example below I apply the second order derivative on a (heavily) smoothed version of the original data:

ds=pd.DataFrame()
mylength=61
smoothed_time = smooth(df['Time'], window_len=mylength)
smoothed_pressure = smooth(df['Pressure'], window_len=mylength)
ds['Pressure']=smoothed_pressure
ds['Time']=smoothed_time

I then compute the first and second order derivatives of this smoothed signal:

ds['Pressure_first_derivative']=ds['Pressure'].diff() / ds['Time'].diff()
ds['Pressure_second_derivative']=ds['Pressure_first_derivative'].diff() / ds['Time'].diff()

The second order derivative looks like this:

enter image description here

Identifying the samples exceeding a user-defined threshold of 0.15 is a good starting point to identify the end of each ramp:

max_indices=ds[ds['Pressure_second_derivative']>0.15].index-np.int(mylength/2)

enter image description here

There are probably ways to automate the thresholding. Also, because multiple samples exceed this threshold for each peak, I think that find_peaks would still be needed to boil down each group of points to a single sample.

$\endgroup$

1 Answer 1

1
$\begingroup$

The second derivative of a ramp function is a delta function. So essentially, you can construct a new signal by taking the second derivative of the original signal.

Approach: If the original signal $\mathbf{x}$ is given as $x(0), \ldots, x(N-1)$, then the second derivative is given as

\begin{align} y[t] = x[t] - 2 x[t-1] + x[t-2], \quad 2 \le t < N \end{align}

The second derivative is sparse at points when the ramp signal ends. You can avoid find_peaks function when you use the second derivative signal. Applying a simple thresholding technique should help you find the location of the peaks.

$\endgroup$
2
  • $\begingroup$ Thank you for your answer. I will give it a shot! $\endgroup$
    – Sheldon
    Dec 29, 2021 at 23:40
  • $\begingroup$ I tried implementing the approach that you suggested: I edited my post accordingly. I think that your solution is great to identify the end of each ramp, but now I must still find a workaround to identify the beginning of each ramp. Also, as stated above, I think that find_peaks will still come in handy. Anyways, thanks again for your answer! $\endgroup$
    – Sheldon
    Dec 31, 2021 at 11:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.