`output="complex"` for Welch method should only allow `average=None`
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 74/100
Línea de trabajo
Empieza siguiendo el manejo de Welch de output="complex" y average en epochs.compute_psd(), y luego comprueba cómo Spectrum.plot() convierte los coeficientes en potencia. Añade una comprobación que rechace los valores de average distintos de None para la salida compleja, y busca pruebas existentes que cubran los modos de salida de Welch y la representación gráfica. Se considera terminado cuando la combinación no válida genera un error claro y average=None y la salida de potencia conservan el comportamiento esperado.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Description of the problem
For Welch method, if average is requested with output="complex", segments are aggregated for complex coefficients, which can mess up the phase information in the resulting coefficients. Subsequently computing power from these coefficients gives very different results to if output="power" was used directly. This also affects the conversion to power from coefficients in Spectrum.plot().
Steps to reproduce
import numpy as np
import mne
from mne.time_frequency.psd import _median_biases
data_path = mne.datasets.sample.data_path()
raw = mne.io.read_raw_fif(
data_path / "MEG" / "sample" / "sample_audvis_filt-0-40_raw.fif", verbose=False
)
raw.pick("eeg", exclude="bads").crop(tmax=60).load_data(verbose=False)
epochs = mne.make_fixed_length_epochs(raw, duration=4.0, preload=True, verbose=False)
kwargs = dict(method="welch", n_fft=128, verbose=False) # 4 segments per epoch
def coefs_to_power(spectrum):
"""Convert complex Welch coefficients to one-sided power."""
coefs = spectrum.get_data()
freqs, sfreq = spectrum.freqs, spectrum.info["sfreq"]
# double all bins except DC and Nyquist (scipy.signal.spectrogram does this for
# mode="psd", but not for mode="complex")
scale = np.where((freqs == 0) | np.isclose(freqs, sfreq / 2), 1.0, 2.0)
if coefs.ndim == 4: # unaggregated: (epoch, channel, freq, segment)
scale = scale[:, np.newaxis]
return (coefs * coefs.conj()).real * scale
for average in ("mean", "median"):
power = epochs.compute_psd(output="power", average=average, **kwargs).get_data()
# output="complex" with average!=None aggregates the complex coefficients across
# segments, so power computed afterwards is wrong
spec = epochs.compute_psd(output="complex", average=average, **kwargs)
power_agg_first = coefs_to_power(spec)
# correct: average=None, compute power per segment, then aggregate
spec = epochs.compute_psd(output="complex", average=None, **kwargs)
power_seg = coefs_to_power(spec)
if average == "mean":
power_agg_last = power_seg.mean(axis=-1)
else:
n_segments = power_seg.shape[-1]
power_agg_last = (
np.median(power_seg, axis=-1) / _median_biases(n_segments)[n_segments]
)
print(f"average={average!r}")
for name, psd in (
("complex -> aggregate -> power", power_agg_first),
("complex -> power -> aggregate", power_agg_last),
):
ratio = psd / power
print(
f" {name}: ratio to output='power' median={np.median(ratio):.3f} "
f"min={ratio.min():.3g} max={ratio.max():.3g} "
f"allclose={np.allclose(psd, power, rtol=1e-6, atol=0)}"
)
Link to data
No response
Expected results
average!=None with output="complex" is not allowed, as it gives invalid coefficients.
Actual results
Computing output="complex" with average!=None is allowed, and gives very different results when trying to compute power from these coefficients, compared to the proper approach of unaggregated coefficients → unaggregated power → aggregated power (which is what happens with output="power").
average='mean'
complex -> aggregate -> power: ratio to output='power' median=0.131 min=2.06e-08 max=0.992 allclose=False
complex -> power -> aggregate: ratio to output='power' median=1.000 min=1 max=1 allclose=True
average='median'
complex -> aggregate -> power: ratio to output='power' median=0.326 min=9.42e-08 max=36.2 allclose=False
complex -> power -> aggregate: ratio to output='power' median=1.000 min=1 max=1 allclose=True
Additional information
AI disclosure: Claude Opus 5.5 initially identified the problem, which I further investigated.
- Lenguaje dominante
- Python
- Estrellas
- 3.6k
- Forks
- 1.6k
- Merge medio
- 1 d 17 h
- PR fusionados (30 d)
- 74
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de mne-tools/mne-python
-
`mne.stats.f_oneway` returns wrong (even negative) F for small integer dtypesPosiblemente ocupada @darshpatel1052 la tomó hace 3 días. AbiertoBUG
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
mne-tools/mne-python#14477 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
ENH: Add `description` filter parameter to `Raw.crop_by_annotations()`Posiblemente ocupada @aman-coder03 la tomó hace 214 días. AbiertoENH
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
mne-tools/mne-python#13743 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Nihon Kohden V2.0 supportAbiertoBUG
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
mne-tools/mne-python#14502 ·
Los mantenedores suelen responder en 1 día
-
cannot plot into matplotlib subfigurePosiblemente ocupada @ishaaaan17 la tomó hace 4 días. AbiertoBUG
Dificultad 3/5 1-2 días Aptitud para principiantes 35/100
mne-tools/mne-python#14481 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
BUG: One layer BEM construction fails for current ANTS6-0Months3T templatePosiblemente ocupada @sruthisureshkumar-arch la tomó hace 5 días. AbiertoBUG
Dificultad 3/5 1-2 días Aptitud para principiantes 57/100
mne-tools/mne-python#14468 · 8 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de mne-tools/mne-python
Issues similares
-
bug good first issue
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
graphql-python/graphql-core#304 ·
Los mantenedores suelen responder en 1 día
-
docs size:S
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 88/100
Gathin23/cleanyourtv#3464 ·
Los mantenedores suelen responder en 1 día
-
documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día