-
Notifications
You must be signed in to change notification settings - Fork 34
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
Time-Resolved Spectral Connectivity PLI implementation #30
Comments
As an afterthought (why do we need to press "submit" to have these?), I guess that when resting-state continuous signals are "chunked" in epochs, the "epoch dimension" has a "temporal definition" to it so it still makes some sense in that case. But I don't think that it makes sense for epochs that have a meaning of "repetition" like in ERP studies... In any case, using the standard PLI definition separately on every epoch and then averaging these PLI values across epochs would give a different value. Also, it is definitely problematic when someone wants to compute the standard PLI value between two-signals (no epoching). Anyway, the crux of the problem is really the faverage that should be performed before the absolute value is taken. |
would you have time to open a PR so we can see a clear diff and look at a
test?
… |
Not in a near future but I can have a look at it when possible. |
Hi all, I also had the same problem when working with resting-state epoched data. Mike X Cohen explains the difference quite nicely in his video here: I tried implementing my own version to calculate PLV and wPLI over time and you can see a simple working example here:
Notice I added the option to choose what kind of data should be used. If data_option = 0 then the expected output is that PLV across trials are 1 since I just repeated the first epoch in all other epochs, while if data_option = 1 the PLV across time should be 1 as I use 10Hz sine waves with different phase differences. It is still quite rough and not optimized but should give an idea of the procedure. It would be helpful if anyone could have a look. [1] Hardmeier, Martin, Florian Hatz, Habib Bousleiman, Christian Schindler, Cornelis Jan Stam, and Peter Fuhr. 2014. “Reproducibility of Functional Connectivity and Graph Measures Based on the Phase Lag Index (PLI) and Weighted Phase Lag Index (WPLI) Derived from High Resolution EEG.” PLoS ONE 9 (10). https://doi.org/10.1371/journal.pone.0108648. |
@agramfort The code I wrote includes testing on some simple simulated data and an implementation, but as I wrote it needs to be optimized better and there is nothing wrong with the current spectral_connectivity(), but it is just an option that could be added to address connectivity over time. |
feel free to contribute this to mne when you find the time
… |
Perhaps the implementation in HyPyP may help? |
Hi @Avoide I think the latest commit on mne-connectivity/mne_connectivity/spectral/time.py Lines 202 to 204 in ed40aef
|
Hi @adam2392. I had a look at the PRs and also tested the functions from the newest (dev) version of mne-connectivity on the simulated toy-examples from my earlier response in this Issue, and got the expected output! (Low connectivity over time, around 0.1-0.2 PLV/wPLI for random data, while more than 0.97 PLV/wPLI for a sinus wave), so I agree this have now been resolved. Great work @ruuskas! It was also much easier to use the functions compared to when I last tested them, with the new API. The only minor discrepancy I noticed was that in spectral_connectivity_epochs, the freqs are automatically calculated when I input fmin and fmax, while in spectral_connectivity_time you are required to specify freqs, despite giving fmin and fmax. |
Hi @Avoide! Good to hear that it's also working for you. This is different to |
Yeah good point, we should probably consolidate the API to require freqs for both. WDYT @larsoner ? I think we could still support |
This is just my take, but as far as I understand that wouldn't be possible or practical. Freqs is already required with |
I'm going to close this issue then as resolved via #115. If there's more API discussion to be had regarding |
Describe the bug
I think the implementation of the PLI metric is wrong. The standard definition is:
Note that for a signal of N time samples, this PLI value is obtained as the average of N values. The MNE implementation of this metric follows the implementation of Ortiz and instead of computing this metric in the time domain (e.g. using the Hilbert transform to estimate the instantaneous phase) computes it in the frequency domain using the cross-spectrum. An issue arise when this passage to the frequency domain is used to analyze the PLI results at the individual frequency bands. For example, the default behavior of
spectral_connectivity()
isfaverage=False
, which therefore report a value for each frequency. In this case, the PLI estimate that was the absolute-mean-value of N samples become the absolute-mean-value of 1 sample... so the PLI estimates reduce to 0 or 1 (where it was originally a value taken from the {0/N, 1/N, 2/N, ..., N/N}). Now, if we might think that we would recover the correct values usingfaverage=True
, but we don't because this computes the mean-absolute-value, not the absolute-mean-value... Here is a part of thespectral_connectivity()
code:Note that the
faverage
part comes after the call tocompute_con()
which, in the case of_PLIEst
already applied the absolute operator. So, whereas in the definition, you average N values taken in {-1, 0, 1}, here you average N values taken in {0, 1}.If I am not mistaken, the function "appears" to work when using epochs because then it does the
mean(signs(X))
across the M epochs, before computing the absolute value. But remember that the stuff in X was initially N values saying whether the time-lag at every N time samples was positive or negative. Now X values are still saying whether the phase-difference is positive or negative, but you traded the ability to check it at every time point to have it localized in frequencies (uncertainty principle), so you have just one value per epochs and you average it across M epochs. I might have interesting properties on its own, but I don't think it is still fair to call this a PLI measure, i.e. average_across_epochs(abs(average_across_x)) != average_across_x(abs(average_across_epochs)) (where x can be either time or frequency, depending on whether you transform from temporal representation to frequency).The text was updated successfully, but these errors were encountered: