How do I upgrade my code from 1.5.1 to 1.10?

I have

Platform             Linux-6.12.10-76061203-generic-x86_64-with-glibc2.35
Python               3.10.12 (main, May 27 2025, 17:12:29) [GCC 11.4.0]
mne                  1.10.0

The last time I used MNE was 1.5 years ago and I am now trying to resurrect my code.

The first issue I ran into is that mne.io.edf.edf.RawEDF returned by mne.io.read_raw_edf no longer has tmax field. :wink:

I will try to downgrade to 1.5.1, but, obviously, this is not the ideal solution.

How do I go about upgrading my code to 1.10?

Thank you!

Can you tell us what you want to do and show us the code that works with 1.5 but not with 1.10?

def edf2psd(edf, config, *, stats=None, verbose=None, logger=pu.stdout):
    """Extract the bands from the Raw EDF data.
    Remove flatlines using annotate_amplitude() and expand them.
    Process each channel one-by-one so that a flatline on one channel
    does not affect the others.
    Limit processing to channels.
    Use welch method, limiting frequencies to [fmin,fmax].
    Ensure frequency step is at most .25Hz."""
    start_time = pu.start_time()
    edf_df = edf.to_data_frame()
    sfreq = edf.info["sfreq"]
    psdd = {}
    freqs = None
    bad = {}
    data_end = edf.tmax
    dropped = []
    for ch in config.channels or edf.ch_names:
        ra = mne.io.RawArray(edf_df[ch].values.reshape((-1, edf_df.shape[0])),
                             mne.create_info(ch_names=[ch], sfreq=sfreq, ch_types="eeg"),
                             verbose=verbose)
        # https://mne.tools/stable/generated/mne.preprocessing.annotate_amplitude.html
        anns, bads = mne.preprocessing.annotate_amplitude(
            ra, flat=0, bad_percent=100, verbose=verbose)
        if bads:
            bad.setdefault("annotate_amplitude",[]).append(ch)
            dropped.append(1)
            continue
        if anns:                # non-trivial
            anns = expand_annotations(anns, data_end=data_end, min_good=config.min_good)
            if anns is None:
                bad.setdefault("expand_annotations",[]).append(ch)
                dropped.append(1)
                continue
            ra.set_annotations(anns)
            dropped.append(anns.duration.sum()/(edf.tmax - edf.tmin))
        else:
            dropped.append(0)   # nothing was dropped!
        # https://mne.tools/stable/generated/mne.io.Raw.html#mne.io.Raw.filter
        ra = ra.filter(l_freq=config.l_freq, h_freq=config.h_freq,
                       skip_by_annotation="BAD_", verbose=verbose)
        # https://mne.tools/stable/generated/mne.io.Raw.html#mne.io.Raw.compute_psd
        # n_jobs > #channels -- does not yield any performance benefit
        # https://github.com/mne-tools/mne-python/pull/11298
        # https://github.com/mne-tools/mne-python/issues/11297
        spectrum = ra.compute_psd(method="welch", fmin=config.fmin, fmax=config.fmax,
                                  n_fft=2048, n_jobs=1, verbose=verbose)
        psds, freqs0 = spectrum.get_data(return_freqs=True)
        psds0 = np.isnan(psds)
        if psds0.any():
            bad.setdefault("spectrum NaN",[]).append(ch)
            if not psds0.all():
                raise ValueError("edf2psd: some but not all PSD are NaN",edf,ch,psds)
        else:
            if freqs is None:
                freqs = freqs0
                if np.diff(freqs).mean() > 0.25:
                    raise ValueError("edf2psd: freq step too high",
                                     edf.info, np.diff(freqs).mean())
            elif not np.array_equal(freqs,freqs0):
                raise ValueError("edf2psd: inconsistent freq",edf,ch,freqs,freqs0)
            psdd[ch] = psds.flatten()
    if not psdd:
        raise ValueError("edf2psd: no useful data", edf, bad)
    df = pd.DataFrame(psdd, index=freqs)
    df.index.name = "Freq"
    elapsed = pu.elapsed(start_time)
    logger.info("edf2psd: %s [%s]", pu.shape(df), elapsed)
    if stats is not None:
        for d in dropped:
            stats.dropped.add(d)
        stats.run_time.add(elapsed)
        stats.edf_len.add(len(edf))
    if bad:
        logger.info(" %d failed:%s", sum(map(len,bad.values())), "".join(
            f"\n  {kind}  {len(chans)}: {chans}" for kind,chans in bad.items()))
    return df

Hello, maybe try edf.times[-1]

As @richard mentioned, edf.times[-1] will work. I just wanted to note that the last MNE version where raw.tmax worked is 1.4 (not 1.5). I’m not sure this was an intentional change, but the issue here is that the tmin and tmax properties were moved from TimeMixin to ExtendedTimeMixin, and Raw continued to use TimeMixin and therefore lost these properties. The relevant PR is #11853 (a follow-up to #10945). @larsoner this looks like an oversight to me, right?

1 Like

I think it was an oversight to remove them without a deprecation period (assuming we did that). But having tmin and tmax just for Epochs, Evoked, etc. that are built with a tmin/tmax during construction makes sense. Having it for raw doesn’t make much sense to me (esp. tmin which will always be zero!) so I wouldn’t add them back

2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.