4

I am trying to determine the amplitude for each day of a time series. The frequency is constant and the series varies only in amplitude. I have tried using Fast Fourier transforms and Lombscargle periodigrams but they return the amplitude for each frequency and the amplitude seems to be the mean over the entire time series. If I split the time series and compute an fft for each day I have problems with making the wave start from zero and it returns incorrect values. Does anyone know how I can reliably compute the amplitude for each day?

Below is some example data:

import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(0, 240, 240) # time
fs = 1/24 # frequency
## Create a time series
series = np.sin(fs * 2 * np.pi * t) 
series = series * np.sin(fs * 1/10 * 2 * np.pi * t) + 25
## Plot
plt.ylabel("Temperature ($^oC$)")
plt.xlabel("Time (hrs)")
plt.plot(t, series)
plt.show()

enter image description here

Robin
  • 389
  • 5
  • 19
  • It is not clear what you mean with amplitude within each day. What amplitude-value per day would you like to get for the graph shown? – KlausCPH Aug 04 '18 at 13:37

1 Answers1

1

If you need the series' time average for each day, you do not need to compute the FFT on the sections after splitting the array. Simply compute the time average (with numpy mean) on each of those section as follows:

# compute number of full days in the time series
days = int(np.floor(len(series)*fs))

# truncate the series, keeping full days
# (may not be necessary if total samples is a multiple of fs)
M = int(np.floor(days/fs))
series = series[0:M]
t      = t[0:M]

# compute the average for each day
avg  = np.mean(np.split(series, days), axis=1)
tmid = np.mean(np.split(t, days), axis=1)

# plot the results
plt.ylabel("Temperature ($^oC$)")
plt.xlabel("Time (hrs)")
plt.ylim(24, 26)
plt.bar(tmid, avg, 0.9/fs, color=(0.8,0.8,0.8))
plt.plot(t, series)
plt.show()

enter image description here

You may similarly compute other characteristics of each time sections. For example, to obtain how much the temperature fluctuates in any given day, you could use the following:

reshaped  = np.split(series, days)
minvalue  = np.amin(reshaped, axis=1)
maxvalue  = np.amax(reshaped, axis=1)
variation = maxvalue - minvalue
amplitude = 0.5*variation

plt.ylabel("Temperature ($^oC$)")
plt.xlabel("Time (hrs)")
plt.ylim(24, 26)
plt.bar(tmid, 2*amplitude, 1/fs, minvalue, color=(0.8,0.8,0.8), edgecolor=(0.7,0.7,0.7))
plt.plot(t, series)
plt.show()

enter image description here

SleuthEye
  • 14,379
  • 2
  • 32
  • 61