3d power spectrum of an sinus signal

Hello everyone!

within the scope of a scientific work. My task is to create and save the power spectrum (amplitude spectrum in decibel [dB]) of a sinusoidal signal (.CSV). But the whole thing 3-dimensional over the time. To make sure that my code is correct, I also want to plot the whole thing in a 3D diagram (x-axis: frequency range [Hz]; y-axis: time; z-axis: power spectrum [dB]). For this I also got an orientation from the professor (see picture).
2 dimensional is no problem, only 3 dimensional is difficult for me.

What I want to achieve:

  • x-axis from -x1 to +x1 Hertz (e.g. -250Hz to +250Hz)

  • if my frequency is at constant 100Hz I want the peak to appear at that point and then lie like a vertical

  • plane in the diagram (parallel to the y-z-axis)

  • if the amplitude increases or decreases I want the height of the peak to change accordingly (this should also be the case with a power spectrum)

  • for the sake of computational effort the calculation should be done section by section (10sec time window) over which the value is then averaged

  • later there must be 50.000 samples per second, which leads to a high memory requirement (irrelevant at first, but therefore the time windows)

I want/do to solve this with:

  • np.fft.fft()

  • for loop

  • plot.surface

Where it hangs:

  • my plotted spectrum is constant despite quadratic increasing amplitude

  • guess the problem is the last array with the averaged values

Note: I have already tried to solve this problem in many directions. I limit myself here however to the “most successful” one so far

Here is my code:

Definitions etc.

# Signal-Parameter
    #Form ax²+bx+b
a = 1
b = 1
c = 10
traegerfrequenz = 100 #in Hertz

# Funktions-Parameter
sample_rate = 200 #Abtastpunkte pro Sekunde
total_time = 100 #in Sekunden
zeitfenster_size = 10 #in Sekunden
total_samples = sample_rate * total_time #Abtastpunkte insgesamt
window_number = int(total_time/zeitfenster_size)
samples_zeitfenster = int(total_samples/window_number) #Abtastpunkte pro Zeitfenster

# Berechnung Zeit
time = np.linspace(1, total_time, total_samples, dtype=np.int32)

calculation

# Zeitfenster-Schleife + Berechnung
powerspektrum_signal = []
gemittelt = []

for i in range(window_number):
    start_index = i * samples_zeitfenster
    end_index = start_index + samples_zeitfenster

    #Amplitudenberechnung für jedes Fenster
    amp = a * time[start_index:end_index] * time[start_index:end_index] + b * time[start_index:end_index] + c
    print("AMPLITUDE: ", amp) #Überprüfung

    #Signalberechnung
    signal = amp * np.sin(2*np.pi * traegerfrequenz * time[start_index:end_index])
    print("SIGNAL: ", signal) #Überprüfung

    #Fourier Transformation
    fourier_transform = np.fft.fft(signal)
    print("FFT_VALUES: ", fourier_transform) #Überprüfung

    #Power-Spektrum Berechnung + dB Umwandlung
    fourier_abs = np.abs(fourier_transform)
    Power_Spektrum_dB = 20 * np.log10(fourier_abs)
    print("dB_VALUES: ", Power_Spektrum_dB) #Überprüfung

    #Mitteln
    mittelwert_dB = np.mean(Power_Spektrum_dB)
    print("MITTELWERTE: ", mittelwert_dB) #Überprüfung

    #Überführung in Array
    gemittelt.append([mittelwert_dB])

#Umwandlung
gemittelt = np.array(gemittelt)
print("FINAL_VALUES: ", gemittelt)

Plotting

#3D Plot
plt.figure()
ax = plt.axes(projection='3d')
ax.set_xlabel('Frequenz [Hz]')
ax.set_ylabel('Zeit [s]')
ax.set_zlabel('dB')
ax.set_title('Powerspektrum')

ax.plot_surface(traegerfrequenz, time, gemittelt)
plt.show()

Thanks to everyone who wants to help!