Skip to content

Commit febd798

Browse files
authored
to_data_frame API change (mne-tools#10925)
* finally do promised API change * fix tests * changelog
1 parent 94433a3 commit febd798

File tree

10 files changed

+29
-17
lines changed

10 files changed

+29
-17
lines changed

doc/changes/latest.inc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ Bugs
148148
- Fix bug in coregistration GUI that prevented it from starting up if only a high-resolution head model was available (:gh:`10543` by `Richard Höchenberger`_)
149149

150150
- Fix bug with :class:`mne.Epochs.add_reference_channels` where attributes were not updated properly so subsequent `~mne.Epochs.pick_types` calls were broken (:gh:`10912` by `Eric Larson`_)
151-
-
151+
-
152152
- Fix bug in the :class:`mne.viz.Brain` tool bar that prevented the buttons to call the corresponding feature (:gh:`10560` by `Guillaume Favelier`_)
153153

154154
- Fix issue with saving epochs once :func:`~mne.preprocessing.compute_current_source_density` has been used if a rejection threshold was used first (:gh:`10619` by `Alex Rockhill`_ and `Richard Höchenberger`_)
@@ -201,3 +201,5 @@ API and behavior changes
201201
- For :func:`mne.viz.plot_topomap`, :func:`mne.viz.plot_evoked_topomap`, :func:`mne.viz.plot_arrowmap`, :func:`mne.viz.plot_ica_components`, :meth:`mne.Covariance.plot_topomap`, :meth:`mne.Evoked.plot_topomap`, :meth:`mne.Evoked.animate_topomap`, :meth:`mne.decoding.CSP.plot_patterns`, :meth:`mne.Projection.plot_topomap` and :meth:`mne.preprocessing.ICA.plot_components` the topomap image interpolation was previously a cubic interpolation but now can be ``'linear'`` and ``'nearest'`` as well. Unless ``image_interp='nearest'`` is passed mne uses a subsequent matplotlib bilinear interpolation to make the interpolated image smoother. Previously, ``'image_interp'`` controlled this second interpolation step and, for the first interpolation, the only option was cubic. To simplify, ``image_interp`` is now responsible for the main interpolation and the subsequent matplotlib image interpolation is bilinear but can be changed afterward using ``im.set_interpolation`` (:gh:`10617` by `Alex Rockhill`_)
202202

203203
- The FLASH BEM surface generation via :func:`mne.bem.make_flash_bem` or the :ref:`mne flash_bem` command has now been clarified in terms of expected inputs. In :func:`mne.bem.convert_flash_mris` the ``convert`` parameter is now deprecated and the ``flash5`` and ``flash30`` now accept list of file names or nibabel images. One breaking change is that now the flash files are looked for as mef05_*.mgz and mef30_*.mgz in mri/flash folder (:gh:`10715` by `Alex Gramfort`_)
204+
205+
- The ``to_data_frame`` methods for :meth:`Raw <mne.io.Raw.to_data_frame>`, :meth:`Epochs <mne.Epochs.to_data_frame>`, :meth:`Evoked <mne.Evoked.to_data_frame>`, :meth:`SourceEstimate <mne.SourceEstimate.to_data_frame>`, :meth:`EpochsTFR <mne.time_frequency.EpochsTFR.to_data_frame>`, and :meth:`AverageTFR <mne.time_frequency.AverageTFR.to_data_frame>` all now have default ``time_format=None`` (keep time in seconds) instead of ``time_format='ms'`` (convert time to milliseconds) (:gh:`10925` by `Daniel McCloy`_)

mne/epochs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2119,7 +2119,7 @@ def equalize_event_counts(self, event_ids=None, method='mintime'):
21192119
@verbose
21202120
def to_data_frame(self, picks=None, index=None,
21212121
scalings=None, copy=True, long_format=False,
2122-
time_format='ms', *, verbose=None):
2122+
time_format=None, *, verbose=None):
21232123
"""Export data in tabular structure as a pandas DataFrame.
21242124
21252125
Channels are converted to columns in the DataFrame. By default,

mne/evoked.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ def get_peak(self, ch_type=None, tmin=None, tmax=None,
811811
@verbose
812812
def to_data_frame(self, picks=None, index=None,
813813
scalings=None, copy=True, long_format=False,
814-
time_format='ms', *, verbose=None):
814+
time_format=None, *, verbose=None):
815815
"""Export data in tabular structure as a pandas DataFrame.
816816
817817
Channels are converted to columns in the DataFrame. By default,

mne/io/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1902,7 +1902,7 @@ def _get_buffer_size(self, buffer_size_sec=None):
19021902
@verbose
19031903
def to_data_frame(self, picks=None, index=None,
19041904
scalings=None, copy=True, start=None, stop=None,
1905-
long_format=False, time_format='ms', *,
1905+
long_format=False, time_format=None, *,
19061906
verbose=None):
19071907
"""Export data in tabular structure as a pandas DataFrame.
19081908

mne/io/edf/tests/test_edf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ def test_to_data_frame(fname):
276276
_, times = raw[0, :10]
277277
df = raw.to_data_frame(index='time')
278278
assert (df.columns == raw.ch_names).all()
279-
assert_array_equal(np.round(times * 1e3), df.index.values[:10])
279+
assert_array_equal(times, df.index.values[:10])
280280
df = raw.to_data_frame(index=None, scalings={'eeg': 1e13})
281281
assert 'time' in df.columns
282282
assert_array_equal(df.values[:, 1], raw._data[0] * 1e13)

mne/io/fiff/tests/test_raw_fiff.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,10 +1284,8 @@ def test_to_data_frame():
12841284
"""Test raw Pandas exporter."""
12851285
from pandas import Timedelta
12861286
raw = read_raw_fif(test_fif_fname).crop(0, 1).load_data()
1287-
_, times = raw[0, :10]
12881287
df = raw.to_data_frame(index='time')
12891288
assert ((df.columns == raw.ch_names).all())
1290-
assert_array_equal(np.round(times * 1e3), df.index.values[:10])
12911289
df = raw.to_data_frame(index=None)
12921290
assert ('time' in df.columns)
12931291
assert_array_equal(df.values[:, 1], raw._data[0] * 1e13)
@@ -1311,13 +1309,27 @@ def test_to_data_frame():
13111309
@pytest.mark.parametrize('time_format', (None, 'ms', 'timedelta', 'datetime'))
13121310
def test_to_data_frame_time_format(time_format):
13131311
"""Test time conversion in epochs Pandas exporter."""
1314-
from pandas import Timedelta, Timestamp
1312+
from pandas import Timedelta, Timestamp, to_timedelta
13151313
raw = read_raw_fif(test_fif_fname, preload=True)
13161314
# test time_format
13171315
df = raw.to_data_frame(time_format=time_format)
13181316
dtypes = {None: np.float64, 'ms': np.int64, 'timedelta': Timedelta,
13191317
'datetime': Timestamp}
13201318
assert isinstance(df['time'].iloc[0], dtypes[time_format])
1319+
# test values
1320+
_, times = raw[0, :10]
1321+
offset = 0.
1322+
if time_format == 'datetime':
1323+
times += raw.first_time
1324+
offset = raw.info['meas_date']
1325+
elif time_format == 'timedelta':
1326+
offset = Timedelta(0.)
1327+
funcs = {None: lambda x: x,
1328+
'ms': lambda x: np.rint(x * 1e3).astype(int), # s → ms
1329+
'timedelta': partial(to_timedelta, unit='s'),
1330+
'datetime': partial(to_timedelta, unit='s')
1331+
}
1332+
assert_array_equal(funcs[time_format](times) + offset, df['time'][:10])
13211333

13221334

13231335
def test_add_channels():

mne/source_estimate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ def transform(self, func, idx=None, tmin=None, tmax=None, copy=False):
12021202

12031203
@verbose
12041204
def to_data_frame(self, index=None, scalings=None,
1205-
long_format=False, time_format='ms', *,
1205+
long_format=False, time_format=None, *,
12061206
verbose=None):
12071207
"""Export data in tabular structure as a pandas DataFrame.
12081208

mne/time_frequency/tests/test_tfr.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,8 +1062,8 @@ def test_to_data_frame():
10621062
assert_array_equal(df.values[:, 0],
10631063
data[:, 0, :, :].reshape(1, -1).squeeze())
10641064
# compare arbitrary observation:
1065-
assert df.loc[('he', slice(None), freqs[1], times[2] * srate),
1066-
ch_names[3]].iloc[0] == data[1, 3, 1, 2]
1065+
assert (df.loc[('he', slice(None), freqs[1], times[2]), ch_names[3]].iat[0]
1066+
== data[1, 3, 1, 2])
10671067

10681068
# Check also for AverageTFR:
10691069
tfr = tfr.average()
@@ -1092,8 +1092,7 @@ def test_to_data_frame():
10921092
assert_array_equal(df.values[:, 0],
10931093
data[0, :, :].reshape(1, -1).squeeze())
10941094
# compare arbitrary observation:
1095-
assert df.loc[(freqs[1], times[2] * srate), ch_names[3]] == \
1096-
data[3, 1, 2]
1095+
assert df.loc[(freqs[1], times[2]), ch_names[3]] == data[3, 1, 2]
10971096

10981097

10991098
@requires_pandas

mne/time_frequency/tfr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,7 @@ def save(self, fname, overwrite=False, *, verbose=None):
10341034

10351035
@verbose
10361036
def to_data_frame(self, picks=None, index=None, long_format=False,
1037-
time_format='ms', *, verbose=None):
1037+
time_format=None, *, verbose=None):
10381038
"""Export data in tabular structure as a pandas DataFrame.
10391039
10401040
Channels are converted to columns in the DataFrame. By default,

mne/utils/docs.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3223,9 +3223,8 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):
32233223
remain as float values in seconds. If ``'ms'``, time values will be rounded
32243224
to the nearest millisecond and converted to integers. If ``'timedelta'``,
32253225
time values will be converted to :class:`pandas.Timedelta` values. {}
3226-
Default is ``'ms'`` in version 0.22, and will change to ``None`` in
3227-
version 0.23.
3228-
""" # XXX make sure we deal with this deprecation in 0.23
3226+
Default is ``None``.
3227+
"""
32293228

32303229
docdict['time_format_df'] = _time_format_df_base.format('')
32313230

0 commit comments

Comments
 (0)