My dataset:
I have the following dataset which when plotted using Plotly produces the following result (simplified):
My task:
I want to create an envelope function that extracts the local maxima and minima from data from the above dataset and plots an envelope curve. It would roughly look like this:
I have tried approaching the solutions provided here and the one for the envelope provided here. However, none of them works for me in this approach. For some strange reason, the scatter plots are producing the following results (for local min), which is not exactly what I need.
Here's my code for the initial plot:
import plotly.express as px
import plotly.graph_objects as go
fig= go.Figure()
fig.add_traces(go.Scatter(x= mem_df['time'], y=mem_df['volatge']))
fig.update_layout(xaxis_title = r'$\text{Time } T \text{ in s} $',
yaxis_title = r'$\text{Deflection angle } \text{ in radians}$')
fig.update_layout(title= r'$\text{Deflection angles versus time for the damping sheet}$')
fig.show()
Any help, in this case, would be appreciated! Thank you in advance!
The problem is that your data contains a bit of noise. One possible approach is to find an appropriate curve fit, then find the local maximum and minimum on the fit. scipy
comes to help:
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
from scipy.optimize import curve_fit
from scipy.signal import argrelextrema
mem_df = pd.read_csv("path/to/file")
x = mem_df['time'].values
y = mem_df['deflection'].values
# dampened oscillator
func = lambda x, xi, k, phi, a, b: a * np.sin(k * x - phi) * np.exp(-xi * x) + b
popt, pcov = curve_fit(func, x, y)
fig= go.Figure()
fig.add_traces(go.Scatter(x=x, y=y, name="data"))
# plot the curve fit
xx = np.linspace(0, 20, 150)
yy = func(xx, *popt)
fig.add_traces(go.Scatter(x=xx, y=yy, name="fit"))
idx_max = argrelextrema(yy, np.greater)
idx_min = argrelextrema(yy, np.less)
fig.add_traces(go.Scatter(x=xx[idx_max], y=yy[idx_max], name="top"))
fig.add_traces(go.Scatter(x=xx[idx_min], y=yy[idx_min], name="bottom"))
fig.update_layout(xaxis_title = r'$\text{Time } T \text{ in s} $',
yaxis_title = r'$\text{Deflection angle } \text{ in radians}$')
fig.update_layout(title= r'$\text{Deflection angles versus time for the damping sheet}$')
fig.show()