import numpy as np
import matplotlib.pyplot as plt
The role of this notebook is to demonstrate how to make easy-to-read ticks on a loglog FFT plot
In this notebook, we will generate some sample FFT by looking at the inverse scaling of damped harmonic oscillator. This is something a buddy of mine worked on in graduate school for measuring pressure. The minimum detectible pressure that he could measure was inversely related to the harmonic oscillator response
def H(f, f0, zeta):
"""The frequency response of a damped harmonic oscillator
f: The range of frequencies to plot
f0: Center frequency
zeta: The damping ratio
"""
return ((1 - (f/f0)**2)**2 + (2*zeta*f/f0)**2)**(-.5)
Next, compute the minimum detectible pressure in units of Pascal/sqrt(Hz)
= 1e3 # 1 kHz
f0 = .05
zeta = np.logspace(0, 5, 2000)
freqs = 1e-3
y0 = H(freqs, f0, zeta)
hs = y0 / hs # Minimum detectible pressure mdp
Here is the code that you want to copy in for quickly looking up SI prefixes
from math import floor
= 'qryzafpnµm1kMGTPEZYRQ'
SI_PREFIXES import matplotlib.ticker as mticks
def fmt_freq(v, _): # Format frequency axis
= floor(np.log10(v) / 3)
frac_exponent_over_3 = 10 + frac_exponent_over_3
idx_prefix = SI_PREFIXES[idx_prefix]
prefix if prefix == '1': prefix = ''
return f'{v/(1000**frac_exponent_over_3):.0f} {prefix}Hz'
def fmt_y(v, _): # Format y axis
= floor(np.log10(v) / 3)
frac_exponent_over_3 = 10 + frac_exponent_over_3
idx_prefix = SI_PREFIXES[idx_prefix]
prefix if prefix == '1': prefix = ''
return f'{v/(1000**frac_exponent_over_3):.0f}{prefix}'
= plt.subplots()
fig, ax /hs)
ax.loglog(freqs, y0
'Minimum detectible pressure\n(Pa/√Hz)')
ax.set_ylabel('Frequency')
ax.set_xlabel(
ax.xaxis.set_major_formatter(fmt_freq)
ax.yaxis.set_major_formatter(fmt_y)=10, numticks=100)) # Make sure you don't skip decades ax.yaxis.set_major_locator(mticks.LogLocator(base