Skip to content

Instantly share code, notes, and snippets.

@pukpr
Created July 2, 2025 01:40
Show Gist options
  • Select an option

  • Save pukpr/498dba4e518b35d78a8553e5f6ef8114 to your computer and use it in GitHub Desktop.

Select an option

Save pukpr/498dba4e518b35d78a8553e5f6ef8114 to your computer and use it in GitHub Desktop.
ENSO power spectrum periodogram generated by ChatGPT
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import periodogram, windows
# Parameters
years = 500
dt = 1 / 365.25 # daily resolution
t = np.arange(0, years, dt)
fs = 1 / dt # sampling frequency in cycles per year
# Sharp annual impulse (high-order sine)
N = 80 # sharpness of annual impulse
annual_impulse = np.sin(np.pi * t) ** N
# Lunar tidal cycles in days
lunar_periods_days = {
'Draconic Month': 27.2122,
'Tropical Month': 27.3216,
'Anomalistic Month': 27.5546,
'Synodic Month': 29.5306,
'Lunar Perigee (Mm)': 27.5546,
'Lunar Apogee (Mf)': 13.6608,
'Lunar Nodal (18.6 years)': 6798.4
}
# Convert to frequencies in cycles/year
lunar_frequencies = {name: 365.25 / days for name, days in lunar_periods_days.items()}
# Simulate combined tidal signal (sum of sinusoids)
tidal_signal = np.zeros_like(t)
for freq in lunar_frequencies.values():
tidal_signal += np.sin(2 * np.pi * freq * t)*freq ### only added *freq to simulate a derivative
# Combined forcing: annual impulse modulating lunar tides
modulated_signal = annual_impulse * tidal_signal
# Compute spectrum
window = windows.hann(len(modulated_signal))
frequencies, power = periodogram(modulated_signal, fs=fs, window=window, scaling='spectrum')
# Plot spectrum
plt.figure(figsize=(12, 6))
plt.semilogy(frequencies, power, label='Synthetic ENSO-like Signal')
plt.axvline(0.5, color='gray', linestyle='--', label='0.5 cycles/year')
for name, freq in lunar_frequencies.items():
if freq < 2: # Show only long-period components
plt.axvline(freq, linestyle=':', label=name)
plt.xlim(0, 2)
plt.xlabel('Frequency (cycles/year)')
plt.ylabel('Spectral Power')
plt.title('Spectrum of Annual-Impulse Modulated Lunar Tidal Signal')
plt.legend(loc='upper right', fontsize='small')
plt.grid(True)
plt.tight_layout()
plt.show()
### shell command
python .\enso_periodogram_modify.py
@pukpr
Copy link
Author

pukpr commented Jul 2, 2025

NINO4 spectrum

see above peaks at
0.052 (18.6 lunar nodal) -- star symbol
0.258 (lunar anom Mm or Mf) -- open square
0.367 (lunar trop) -- small open circles
0.426 (lunar drac) -- large open circles

NINO34

Another view showing more detail with possible biennial (2) and quad (4) modulations and the mirror folding about 0.5

@eabase
Copy link

eabase commented Jul 28, 2025

How do you generate the plots above?

@pukpr
Copy link
Author

pukpr commented Aug 12, 2025

"How do you generate the plots above?"

Some are created by ChatGPT, run the script generated in a Python session and it will plot as shown.

Some of the other plots are customized, those with extra annotations and labeling. Not sure what you are asking as apart from that, it is either plotting straight data or model results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment