Three defects in compute_nmPLV (hypyp/analyses.py:851-931). Found while auditing the duplicated einsum helpers; not related to the hypyp.sync backends.
1. The n:m phase exponentiation is applied along the time axis.
After the reshape at hypyp/analyses.py:914, phase has shape (n_epoch, n_freq, 2*n_ch, n_samp) — axis 2 is channels, axis 3 is time. But hypyp/analyses.py:923-924 slice axis 3:
phase[:, :, :, :n_ch] = phase[:, :, :, :n_ch] ** n
phase[:, :, :, n_ch:] = phase[:, :, :, n_ch:] ** m
Verified on a (2, 3, 8, 100) array with n_ch = 4:
phase[:, :, :, :n_ch] -> shape (2, 3, 8, 4) : 8 channels x 4 TIME SAMPLES (of 100)
phase[:, :, :n_ch, :] -> shape (2, 3, 4, 100): 4 CHANNELS x 100 samples <- intended
So the exponent n is applied to the first n_ch time samples of all channels and m to the remaining samples. Participant 1 and participant 2 are never separated, which is the entire purpose of the function. It should be phase[:, :, :n_ch, :] and phase[:, :, n_ch:, :].
2. The final average collapses the wrong axis.
hypyp/analyses.py:930:
con = np.nanmean(con, axis=1)
con has shape (n_epoch, n_freq, C, C), so axis=1 averages over frequency and returns (n_epoch, C, C). The docstring (analyses.py:876-877) promises (n_freq, 2*n_channels, 2*n_channels). compute_sync does con.swapaxes(0, 1) before its nanmean (analyses.py:556); this function does not. The returned leading axis is epochs, labelled as frequencies.
3. It calls a deprecated private helper.
hypyp/analyses.py:928 calls _multiply_conjugate, which emits a DeprecationWarning and is scheduled for removal in 1.0.0 (analyses.py:1111-1116). A public, non-deprecated function therefore emits a deprecation warning the user cannot trace to their own code, and will hard-break at 1.0.0. It should use hypyp.sync.multiply_conjugate (byte-identical implementation, hypyp/sync/base.py:132-136).
compute_nmPLV also open-codes the PLV formula inline (analyses.py:916-929), bypassing get_metric entirely, so it gets no backend acceleration.
Given defects 1 and 2, this function cannot currently produce a correct n:m PLV. Worth considering whether to fix it or deprecate it — there are no callers in the repository, tests, or tutorials.
Three defects in
compute_nmPLV(hypyp/analyses.py:851-931). Found while auditing the duplicated einsum helpers; not related to thehypyp.syncbackends.1. The n:m phase exponentiation is applied along the time axis.
After the reshape at
hypyp/analyses.py:914,phasehas shape(n_epoch, n_freq, 2*n_ch, n_samp)— axis 2 is channels, axis 3 is time. Buthypyp/analyses.py:923-924slice axis 3:Verified on a
(2, 3, 8, 100)array withn_ch = 4:So the exponent
nis applied to the firstn_chtime samples of all channels andmto the remaining samples. Participant 1 and participant 2 are never separated, which is the entire purpose of the function. It should bephase[:, :, :n_ch, :]andphase[:, :, n_ch:, :].2. The final average collapses the wrong axis.
hypyp/analyses.py:930:conhas shape(n_epoch, n_freq, C, C), soaxis=1averages over frequency and returns(n_epoch, C, C). The docstring (analyses.py:876-877) promises(n_freq, 2*n_channels, 2*n_channels).compute_syncdoescon.swapaxes(0, 1)before itsnanmean(analyses.py:556); this function does not. The returned leading axis is epochs, labelled as frequencies.3. It calls a deprecated private helper.
hypyp/analyses.py:928calls_multiply_conjugate, which emits aDeprecationWarningand is scheduled for removal in 1.0.0 (analyses.py:1111-1116). A public, non-deprecated function therefore emits a deprecation warning the user cannot trace to their own code, and will hard-break at 1.0.0. It should usehypyp.sync.multiply_conjugate(byte-identical implementation,hypyp/sync/base.py:132-136).compute_nmPLValso open-codes the PLV formula inline (analyses.py:916-929), bypassingget_metricentirely, so it gets no backend acceleration.Given defects 1 and 2, this function cannot currently produce a correct n:m PLV. Worth considering whether to fix it or deprecate it — there are no callers in the repository, tests, or tutorials.