Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternative Knee Model #312

Open
ryanhammonds opened this issue Jan 20, 2024 · 1 comment
Open

Alternative Knee Model #312

ryanhammonds opened this issue Jan 20, 2024 · 1 comment

Comments

@ryanhammonds
Copy link
Contributor

ryanhammonds commented Jan 20, 2024

The current knee model is slightly incorrect translation of an exponentially decaying ACF, the difference is visually subtle but lies in the the power at the nyquist, e.g. the ACF(1) coeff. Below is a picture of a spectrum that matches what is simulated in OU processes. The power at the nyquist slightly tapers off but the current knee model assumes it should be linearly decreasing.

Screenshot 2024-01-19 at 4 49 25 PM

Below is the model we could be add. It's described in this paper

Screenshot 2024-01-19 at 4 46 00 PM

Where $w$ is the AR(1) or ACF(1) coefficient, which directly translates to the knee frequency, $f_k$. This math is also nice because it lets us compute the knee directly from the AR(1), which could be used as the guess knee param when oscillations aren't present:

# Get knee freq directly from signal
s1 = np.linalg.norm(sig) # singular value
e1 = s1**2 # eigenvalue
w = (1/e1) * sig[:-i] @ sig[i:] # AR(1) weight
fk = -(np.log(w) * fs) / (2 * np.pi) # knee freq

This is the full simulation/model/implementation:

import matplotlib.pyplot as plt
import numpy as np

fs = 1000

fk = 20 # Knee frequency
w = np.exp(-(fk * 2 * np.pi) / fs) # AR(1) coefficient
freqs = np.linspace(.1, 500, 1000)

# Update knee model
num = 1-w**2
den = 1 + w**2 - 2*w * np.cos(2*np.pi*freqs/fs)
powers = num / den

plt.loglog(freqs, powers);

In practice, this won't change much unless fitting up to the nyquist. It could be useful to help validate sims since sim_knee in neurodsp doesn't produce this updated PSD, and the mapping between knee freq and ACF(1) doesn't hold like it does in other timescale sims.

@ryanhammonds
Copy link
Contributor Author

I'm going to close this to reduce noise. This falls into the category of having an api that can support custom curve functions and guess procedures. I just wanted to have this as a note to my future self for something to try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants