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

Connectivity: wPLI and trial-averaging #571

Open
Moo-Marc opened this issue Sep 7, 2022 · 4 comments
Open

Connectivity: wPLI and trial-averaging #571

Moo-Marc opened this issue Sep 7, 2022 · 4 comments
Assignees

Comments

@Moo-Marc
Copy link
Collaborator

Moo-Marc commented Sep 7, 2022

After reviewing the math and connectivity code to answer a forum question, I flagged some issues in the recently added wPLI measure (PR #497, related forum post), and in trial-averaging that may apply to other measures as well.

  1. I don't think the code actually corresponds to wPLI as it was published. It uses phase differences, phaseA*phaseB', whereas wPLI in Vinck et al. 2011 is defined with the cross-spectrum XA*XB'. @danielemarinazzo Where did this formula come from?
  2. Furthermore, it's not currently the "debiased" version. So this comment should be corrected.
  3. There's also an important question of how trial-averaging should be performed (which we can discuss at a Brainstorm meeting). Many of the connectivity measures, such as wPLI, have multiple expectation value terms, or other operations after the expectation value. This means the computation should proceed in two steps: trial averaging each expectation value term separately, then the final assembly of the terms after looping through files (like how the absolute value is currently applied for PLV after looping, which is currently done in the SaveFile subfunction). Computing the measure for each trial and then averaging is not equivalent and will probably result in increased variance among other things. This is similar to what was done for coherence (in a somewhat roundabout way). This would also allow implementing the debiased wPLI, "unbiased square PLV", etc.
@danielemarinazzo
Copy link
Contributor

danielemarinazzo commented Sep 20, 2022

Dear @Moo-Marc

  1. The code is just a faster one, the result is the same, you can check this script https://github.com/danielemarinazzo/test_brainstorm/blob/main/compare_PLV_ciPLV_wPLI_wPLIdb.m
  2. You are right, I have now pushed a new version with the comment removed, and the debiased implementation commented below
  3. Indeed the way Brainstorm hands the trials makes it difficult to implement the time-varying version of the debiased wPLI, we should check if it's possible to do it (maybe starting from the coherence routines).
    This function
    https://github.com/danielemarinazzo/test_brainstorm/blob/main/test_timevarying.m
    implements the debiased wPLI (together with other measures), but it's not compatible with the way Brainstorm handles the trials.

Importantly, wPLI was originally introduced to deal with different trials. Possibly due to this, both wPLIs have a few instances of quite high values for the static case

wPLI_ciPLV
wPLIdb_ciPLV

For me, it's a reason more to use ciPLV instead.

So maybe we could even think of removing wPLI completely from the static part (or leaving it with a caveat), and leave only the time-varying one, which uses different trials (for the moment the regular wPLI, and see if we can implement the debiased one). Something to discuss also with @sbaillet and others.

danielemarinazzo added a commit to danielemarinazzo/brainstorm3 that referenced this issue Sep 20, 2022
Specified that wPLI is not the debiased one (see brainstorm-tools#571), and added the debiased version commented below. This until we figure out how to implement the debiased wPLI in time domain
@Moo-Marc
Copy link
Collaborator Author

Moo-Marc commented Sep 20, 2022

Thanks for checking this again Daniele. I also spent some time yesterday reviewing the math and code and I was going to write a reply today. So I think for 2 and 3 we are in agreement. For 3, I'll propose a PR to do averaging properly and also implement the debiased version.

For 1 however, I stand by my earlier comment. The paper (Vinck et al. 2011) defines wPLI as a function of frequency:

CrossSpectrum = F1 * F2';  % where F1 is the Fourier transform of signal 1.
WPLI = abs(E{imag(CrossSpectrum)}) / E{abs(imag(CrossSpectrum));

Where E{.} is the expectation value, i.e. what needs to be averaged over trials.
The issue is that in all your formulae, you replaced the cross spectral density by (exp(iPhase1) * exp(iPhase2)') or something mathematically equivalent. It's missing the amplitude part of the cross-spectrum.

What I verified yesterday (wasn't obvious to me), was how to go from the cross spectrum definition of WPLI, which is a function of frequency only, to a compatible extended definition in terms of instantaneous phase and envelope, a function time. To get an equivalence, we can apply the same narrow band pass filter and integrate over frequencies in the first formula, and integrate over time (take the expectation value) in the second formula. For the cross spectrum, this gives this relation:
image
where hat indicates Fourier transform, "a" subscript indicates analytical signal (Matlab hilbert), tilde indicates the signals were filtered with a narrow band pass, and W is the corresponding narrow band filter window in the frequency domain. So the equivalent WPLI formula must replace CrossSpectrum by (H1 * H2'), the full analytical signals including their amplitudes, not just the exp(i*phase) part. Those amplitudes are precisely the relative weights that give the name "weighted PLI".

Again, here the separate averaging of the E{.} terms is crucial, otherwise we could cancel some factors in the numerator and denominator.

I hope this clarifies what I meant. Please let me know what you think.

@danielemarinazzo
Copy link
Contributor

danielemarinazzo commented Sep 20, 2022

Hi
I think you're right wrt to using HA and HB.
I have now implemented the fixes in the test repo https://github.com/danielemarinazzo/test_brainstorm
I have updated the PR for both the static and time-varying version.
For the static case I have also inserted the debiased version, leaving it commented.
Not sure whether there's a straightforward way to implement the debiased wPLI time-varying (with many trials) where it is now, or maybe it's easier to do it starting from the coherence, as I suggested quite some time ago.
@ftadel any suggestion?

@ftadel
Copy link
Member

ftadel commented Sep 21, 2022

@ftadel any suggestion?

I'm sorry, I won't be of much help here.
The math is beyond my grasp, and the coding is probably beyond my processing capacity at the moment.

@Moo-Marc if you need to change the way the input data is passed to the function, please prepare a separate PR dedicated to this. Thanks.

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

No branches or pull requests

3 participants