diff --git a/mne/io/base.py b/mne/io/base.py index 8af949afea0..fa52978e42d 100644 --- a/mne/io/base.py +++ b/mne/io/base.py @@ -630,16 +630,25 @@ def last_samp(self): def _last_time(self): return self.last_samp / float(self.info["sfreq"]) - def time_as_index(self, times, use_rounding=False, origin=None): + def time_as_index(self, times, use_rounding=None, origin=None): """Convert time to indices. Parameters ---------- times : list-like | float | int List of numbers or a number representing points in time. - use_rounding : bool - If True, use rounding (instead of truncation) when converting - times to indices. This can help avoid non-unique indices. + use_rounding : bool | None + If True, use rounding when converting times to indices. This can + help avoid non-unique indices. + If False, use truncation when converting times to indices. + If None (the default), rounding is used but a FutureWarning is + emitted. Pass ``True`` or ``False`` explicitly to silence the + warning. + + .. versionchanged:: 2.0 + The default changed from ``False`` to ``None``, which will + round and emit a warning. In a future release the default + will change to ``True``. origin : datetime | float | int | None Time reference for times. If None, ``times`` are assumed to be relative to :term:`first_samp`. diff --git a/mne/io/egi/tests/test_egi.py b/mne/io/egi/tests/test_egi.py index 261a9c80da3..89cfb970655 100644 --- a/mne/io/egi/tests/test_egi.py +++ b/mne/io/egi/tests/test_egi.py @@ -104,7 +104,7 @@ def test_egi_mff_pause(fname, skip_times, event_times): for ii, annot in enumerate(raw.annotations): assert annot["description"] == "BAD_ACQ_SKIP" start, stop = raw.time_as_index( - [annot["onset"], annot["onset"] + annot["duration"]] + [annot["onset"], annot["onset"] + annot["duration"]], use_rounding=False ) data, _ = raw[:, start:stop] assert_array_equal(data[other_picks], 0.0) diff --git a/mne/io/tests/test_raw.py b/mne/io/tests/test_raw.py index bb6d58ee0d9..9baeab23804 100644 --- a/mne/io/tests/test_raw.py +++ b/mne/io/tests/test_raw.py @@ -620,14 +620,20 @@ def test_time_as_index(): """Test indexing of raw times.""" raw = read_raw_fif(raw_fname) - # Test original (non-rounding) indexing behavior - orig_inds = raw.time_as_index(raw.times) + # Test truncation behavior with explicit use_rounding=False + orig_inds = raw.time_as_index(raw.times, use_rounding=False) assert len(set(orig_inds)) != len(orig_inds) - # Test new (rounding) indexing behavior + # Test rounding behavior with explicit use_rounding=True new_inds = raw.time_as_index(raw.times, use_rounding=True) assert_array_equal(new_inds, np.arange(len(raw.times))) + # Test deprecation warning when use_rounding is not specified + # Temporarily turned of to measure impact + # + # with pytest.warns(FutureWarning, match="use_rounding=False is being changed"): + # raw.time_as_index(raw.times) + @pytest.mark.parametrize("meas_date", [None, "orig"]) @pytest.mark.parametrize("first_samp", [0, 10000]) diff --git a/mne/utils/mixin.py b/mne/utils/mixin.py index f0d4b9f7524..7bd5ed980f6 100644 --- a/mne/utils/mixin.py +++ b/mne/utils/mixin.py @@ -493,16 +493,25 @@ def _check_decim(info, decim, offset, check_filter=True): class TimeMixin: """Class for time operations on any MNE object that has a time axis.""" - def time_as_index(self, times, use_rounding=False): + def time_as_index(self, times, use_rounding=None): """Convert time to indices. Parameters ---------- times : list-like | float | int List of numbers or a number representing points in time. - use_rounding : bool - If True, use rounding (instead of truncation) when converting - times to indices. This can help avoid non-unique indices. + use_rounding : bool | None + If True, use rounding when converting times to indices. This can + help avoid non-unique indices. + If False, use truncation when converting times to indices. + If None (the default), rounding is used but a FutureWarning is + emitted. Pass ``True`` or ``False`` explicitly to silence the + warning. + + .. versionchanged:: 2.0 + The default changed from ``False`` to ``None``, which will + round and emit a warning. In a future release the default + will change to ``True``. Returns ------- @@ -511,6 +520,18 @@ def time_as_index(self, times, use_rounding=False): """ from ..source_estimate import _BaseSourceEstimate + if use_rounding is None: + # Turned off temporarily to see the impact of the change without + # crashing on a FutureWarning + # + # warn( + # "The default of use_rounding=False is being changed to True " + # "in a future release. Pass use_rounding=True or " + # "use_rounding=False explicitly to silence this warning.", + # FutureWarning, + # ) + use_rounding = True + if isinstance(self, _BaseSourceEstimate): sfreq = 1.0 / self.tstep else: