I am trying to decompose the periodicities present in a signal into its individual components, to calculate their time-periods.
Say the following is my sample signal:
You can reproduce the signal using the following code:
t_week = np.linspace(1,480, 480)
t_weekend=np.linspace(1,192,192)
T=96 #Time Period
x_weekday = 10*np.sin(2*np.pi*t_week/T)+10
x_weekend = 2*np.sin(2*np.pi*t_weekend/T)+10
x_daily_weekly_sinu = np.concatenate((x_weekday, x_weekend))
#Creating the Signal
x_daily_weekly_long_sinu = np.concatenate((x_daily_weekly_sinu,x_daily_weekly_sinu,x_daily_weekly_sinu,x_daily_weekly_sinu,x_daily_weekly_sinu,x_daily_weekly_sinu,x_daily_weekly_sinu,x_daily_weekly_sinu,x_daily_weekly_sinu,x_daily_weekly_sinu))
#Visualization
plt.plot(x_daily_weekly_long_sinu)
plt.show()
My objective is to split this signal into 3 separate isolated component signals consisting of:
- Days as period
- Weekdays as period
- Weekends as period
Periods as shown below:
I tried using the STL decomposition method from statsmodel:
sm.tsa.seasonal_decompose()
But this is suitable only if you know the period beforehand. And is only applicable for decomposing a single period at a time. While, I need to decompose any signal having multiple periodicities and whose periods are not known beforehand.
Can anyone please help how to achieve this?
Have you tried more of an algorithmic approach? We could first try to identify the changes in the signal, either amplitude or frequency. Identify all threshold points where there is a major change, with some epsilon, and then do FFT on that window.
Here was my approach:
Note there are many ways you could mess with this. I would say starting with a wavelet transform, personally, is a good start.
Here is the code, try adding some Gaussian noise or other variability to test it out. You see the more noise the higher your min epsilon for DWT will need to be so you do need to tune some of it.
With your example that printed the following (note results weren't exact).
Note this is what the DWT coefs look like.