-
Notifications
You must be signed in to change notification settings - Fork 113
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
Spindles detection failing for some users #107
Comments
🤔 I really don't get it. I have tried updating my Pandas, Numpy, SciPy, Numba, re-installing YASA and it's still working fine on my computer. The only difference I see is that you are running Python 3.9+ and I'm running Python 3.8. I really don't see how this could affect YASA to be honest. Has anyone else been able to run successfully the example with Python 3.9+? |
Code is still working fine after updating to Python 3.10.6 🤯 And I have the exact same Python package versions as your 3.10.6 environment @chensnbetter. Are you both using Windows btw? Is this bug specific to Windows? |
Works for me on Windows 🤷 Very mysterious... |
I wonder if someone who is getting the error could mess around with some of the detection parameters to see if that helps identify where the detection is failing. Sorry I can't try it myself, I'm just not able to reproduce the initial problem. |
Thanks. I'm using windows. |
Ok I think I found the problem. I was able to reproduce it on my dusty Desktop. It has to do with the moving correlation thresholding, and I know this sounds insane but I think it depends on a tiny difference in Windows version. Before I go into detail can some people help verify something for me? Please show your output from this slightly modified version of the original sample code. import sys
import platform
import numpy as np
import pandas as pd
import mne
import numba
import scipy
import yasa
import antropy
print("System", platform.platform())
print("Python", sys.version)
print(f"YASA {yasa.__version__}")
print(f"MNE {mne.__version__}")
print(f"NumPy {np.__version__}")
print(f"Pandas {pd.__version__}")
print(f"Numba {numba.__version__}")
print(f"SciPy {scipy.__version__}")
print(f"Antropy {antropy.__version__}")
sf = 200
data = np.loadtxt('data_N2_spindles_15sec_200Hz.txt')
# I expect this to work for everyone.
print("=" * 10, "Run with no moving correlation threshold.", "=" * 10)
sp = yasa.spindles_detect(data, sf, thresh={"corr": None}, verbose=True)
# I expect this to still break (no spindles found) for a subset of users.
print("=" * 10, "Run with moving correlation threshold set to default 0.65.", "=" * 10)
sp = yasa.spindles_detect(data, sf, verbose=True) |
Alright! Thank you so much @chensnbetter! Sorry about all the requests, but I appreciate you running and sharing all these outputs, it's really helpful. We still need to work out the details of this bug, but for now you should be able to get through the tutorials by setting # Apply the detection using yasa.spindles_detect
# sp = yasa.spindles_detect(data, sf) # Old
sp = yasa.spindles_detect(data, sf, thresh={"corr": None}) # New Thanks again for your output message, I'm now sure it was not an issue of Windows versioning, at least from what I can tell (so I guess I was crazy). Spindles are detected on my machine that has the same Windows version as you Moving correlation thresholding is the problemThe problem comes from the Turning on YASA's verbosity gives us insight. On a working system, keeping the default
But on a system that detects no spindles, you will get this:
This message is generated by finding all values of the |
Numba is the problem. If you replace the use of numba-based Based on printing stuff to debug, the breakdown occurs at So why is jfc |
The only immediate solution I can think of is hideous. You could do some kind of check with the return from |
Thanks so much @remrama for your in-depth investigation! So I think the error was introduced in #86. Interestingly, someone opened a very similar PR on antropy recently, and their solution was not to do an Can you please try to run the code with: import sys
eps = sys.float_info.epsilon
@jit("float64(float64[:], float64[:])", nopython=True)
def _corr(x, y):
"""Fast Pearson correlation."""
n = x.size
mx, my = x.mean(), y.mean()
xm2s, ym2s, r_num = 0, 0, 0
for i in range(n):
xm = x[i] - mx
ym = y[i] - my
r_num += xm * ym
xm2s += xm**2
ym2s += ym**2
r_d1 = np.sqrt(xm2s)
r_d2 = np.sqrt(ym2s)
r_den = r_d1 * r_d2
return r_num / (r_den + eps) If this is not working you can just do: return r_num / (r_den + 10e-9) |
@raphaelvallat this doesn't solve the problem :/ Still no spindles detected. I think this issue is different from that in Antropy, because when working properly (on most systems it seems), the The current behavior is still truly bizarre to me. See here, showing no spindles found when making the zero-adjustment. But with SAME technical code but now printing |
It is truly bizarre.. Do you get the same bug when setting I think we'll need to somehow re-implement this function then. The issue is that the spindles detection is already quite slow, and I fear that it will be even worse if we switch to |
Setting But the problem is, there are 100 other things that also fix the problem, and they all fix the problem independently. I've been racking my brain to try and figure out what common underlying change is going on in Numba when any of these fixes are used: Things that fix
|
Wow, you went full-on into the rabbit hole 🤯 From all these solutions, I think I like the To be clear, this is not related to one specific Numba version? |
Yes the I haven't checked with other numba versions. I'll explore that, and if it's all good I'll submit a PR with that simple change. |
Not a version issue, it's some kind of I'm running this import numpy
import scipy
import numba
import llvmlite
print(f"numpy-{numpy.__version__}")
print(f"scipy-{scipy.__version__}")
print(f"numba-{numba.__version__}")
print(f"llvmlite-{llvmlite.__version__}")
import numpy as np
from numba import jit
@jit("float64(float64[:], float64[:])")
def _corr(x, y):
"""Fast Pearson correlation."""
n = x.size
mx, my = x.mean(), y.mean()
xm2s, ym2s, r_num = 0, 0, 0
for i in range(n):
xm = x[i] - mx
ym = y[i] - my
r_num += xm * ym
xm2s += xm**2
ym2s += ym**2
r_d1 = np.sqrt(xm2s)
r_d2 = np.sqrt(ym2s)
r_den = r_d1 * r_d2
return r_num / r_den
xx = np.arange(1, 100, dtype=np.float64)
yy = np.arange(1, 100, dtype=np.float64)
print("Correlation =", _corr(xx, yy)) @raphaelvallat -- want me to just change to |
@remrama really confusing indeed. Btw I realized that we can even simplify further by using for xi, yi in zip(x, y):
xm = xi - mx
ym = yi - my
r_num += xm * ym
xm2s += xm**2
ym2s += ym**2 It seems to be even a bit faster than the previous implementation. Can you check whether you have the bug when using |
Works. Great idea. Submitting PR now 🚀 |
Bugfix implemented in #115 Will need to release a new version of YASA soon |
I have just released a new version of YASA that should fix this issue. Please update YASA with Thanks, |
Wow, this was really some awesome detective work @remrama |
As reported in #102 and #104, the yasa.spindles_detect function seems to be suddenly failing for some users. I am not able to reproduce the error.
Minimal (reproducible) example
Data here: data_N2_spindles_15sec_200Hz.txt
My output ✅
@remrama @chensnbetter @meniua @apavlo89 can you please run this minimal example and copy-paste a screenshot of the output here?
If you're getting the error, can you please try to run this notebook and let us know for any useful warnings/error?
Let's solve this! Thanks all
The text was updated successfully, but these errors were encountered: