Fix copy-view issue in epochs#12121
Conversation
for more information, see https://pre-commit.ci
|
@pablomainar thx for the PR. you'll need to add tests. thx |
mne/epochs.py
Outdated
| if copy: | ||
| data = data.copy() |
There was a problem hiding this comment.
I suggest moving this up about 25 lines, inside the if branch of the if self.preload conditional. The else branch defines data = np.empty(...) so that will never be a view of the object's data and thus the copy will never be necessary.
mne/epochs.py
Outdated
| units=None, | ||
| tmin=None, | ||
| tmax=None, | ||
| copy=True, |
There was a problem hiding this comment.
in this private method we should probably default to copy=False so that we're not making unnecessary copies in internal calls that use the private API.
|
@drammock thanks for the suggestions, I updated the PR accordingly |
|
@pablomainar there are several failing CIs. Can you look into them? LMK if you need help or guidance. Here's a link to two failures that look related: https://github.com/mne-tools/mne-python/actions/runs/6639926213/job/18137375032?pr=12121#step:17:4209 I recommend running those two tests locally and seeing if you can figure out what is causing the failure. |
|
Done. I changed the test slightly because the two failing ones were assuming that a view was returned from get_data(), which is no longer the case by default. Should I also write other tests to check that a copy is returned instead of a view when the copy argument is set to True? |
yes, a small test to verify that a copy is returned would be good. Using |
|
also heads-up that I merged in |
for more information, see https://pre-commit.ci
Well, I'm not sure if using base would work because get_data(copy=True) returns a view of a copy of the underlying _data. Therefore calling base on it, will return an array, not a None value. |
Ah OK, that's because we always do import mne
sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = sample_data_folder / "MEG" / "sample" / "sample_audvis_raw.fif"
raw = mne.io.read_raw_fif(sample_data_raw_file, verbose=False, preload=False)
events = mne.find_events(raw, stim_channel="STI 014")
event_dict = {"auditory/left": 1}
kwargs = dict(event_id=event_dict, proj=False)
ondisk_epochs = mne.Epochs(raw, events, preload=False, **kwargs)
preloaded_epochs = mne.Epochs(raw, events, preload=True, **kwargs)
print(
preloaded_epochs.get_data(copy=False).flags.owndata,
preloaded_epochs.get_data(copy=True).flags.owndata,
)
# False False
print(
ondisk_epochs.get_data(copy=False).flags.owndata,
ondisk_epochs.get_data(copy=True).flags.owndata,
)
# True TrueIdeally for preloaded epochs we should get |
|
Instead of checking owndata directly in the preloaded case we can use https://numpy.org/doc/stable/reference/generated/numpy.may_share_memory.html#numpy.may_share_memory |
|
Good idea @larsoner, I changed the test to use np.shares_memory. Because it is just a test with a small dataset, it won't be much slower than np.may_share_memory. |
|
I think that's a pretty advanced use case / user who would do this so it's okay |
|
FYI I'm going to merge in |
larsoner
left a comment
There was a problem hiding this comment.
Last we need a changelog entry. We have two options:
- Make the default
copy=Nonewhich means "use copy=False and if it matters (epochs preloaded and no fancy indexing so it's a view), emit a warning that the default will change to copy=True in 1.6". This is the safest but most annoying option to code. Then you would add an entry in the API section because it's a deprecation. I think I'm +0.5 on this one. (I can help with this step with more explanation or a quick commit if it's not clear.) - Make the default
copy=Truenow, which you've done. This is the simplest, and would then require an entry in the Bug section saying that this kwarg was added with defaultcopy=Trueto avoid silent, possibly errant / dangerous behavior from 1.5.
@drammock any opinion on which we should do?
|
|
This sounds a bit bold in the light of many previous discussions on deprecations and not breaking people's code, given that this behavior is (was) clearly documented: Why do you now say "people should not have been relying on the fact that we returned a view"? |
argh, you're right, I forgot (again) that this was documented behavior. Sorry. I switch my vote to doing a proper deprecation. |
|
@pablomainar do you need help with the deprecation? If so I can push some quick commits. We'll probably release 1.6 in the next week or so and it would be great to get this in! |
|
Sorry @larsoner, I've been quite busy this week. I'm not sure I'll find time to finish this in the next week, it would be very helpful if you could help me out. Thanks a lot! |
* upstream/main: BUG: Fix bug with spectrum warning (mne-tools#12186) Add argument splash to disable splash-screen from Qt-browser (mne-tools#12185) BUG: Fix bug with logging and n_jobs>1 (mne-tools#12154) Use gray logo (works in light and dark modes) (mne-tools#12184) Tweak logo for dark mode (mne-tools#12176) ENH: Improve Covariance.__repr__ (mne-tools#12181) ENH: Enable sensor-specific OPM coregistration in mne coreg (mne-tools#11405) Tweak README.rst (mne-tools#12166) [pre-commit.ci] pre-commit autoupdate (mne-tools#12177) MAINT: Add branch coverage (mne-tools#12174) OpenSSF (mne-tools#12175) fix docstring in 60_sleep.py (mne-tools#12171) FIX: skip empty lines in read_raw_eyelink (mne-tools#12172) FIX: Fix bug with coreg scalars (mne-tools#12164) Changed casting rule in np.clip to allow reading of raw GDF files (mne-tools#12168) [DOC] Add documentation for setting montage order (mne-tools#12160) Fix inferring fiducials from EEGLAB (mne-tools#12165)
* upstream/main: MAINT: Fix CIs (mne-tools#12188) BUG: Fix bug with default alpha and axes (mne-tools#12187)
|
Deprecation complete, ready for review/merge @drammock I ran |
|
🎉 Congrats on merging your first pull request! 🥳 Looking forward to seeing more from you in the future! 💪 |
…o-pyproject.toml * upstream/main: Fix copy-view issue in epochs (mne-tools#12121)
|
@drammock, tagging you as you seem to have stumbled over my issue in mne-bids (and autoreject) --> shouldn't the new "copy" parameter for the |
|
Yes it should have that, too, I'll add it in the soon-to-be-merged #12178 |
* MAINT: Update documentation and logging - Nice new landing page - Added covenience makefile commands - improved logging of flagged epochs * FIX, MAINT: Bump iclabel version and ignore mne warning We already throw an error if the user has mne iclabel version less than .5, so added a pin for minimum version of .5 in the requirements file. MNE is also throwing a future warnign for an API kwarg change in epochs.get_data, where the current default copy=False is changing to copy=True. See mne-tools/mne-python#12121 . I'm a little worried about the additional copies we will incur every single time that we call that method, but I dont have a strong reason to stray from what MNE believes is a bug fix so lets go with it and see how it plays. * FIX, MAINT: Bumpg GH actions checkout versions - This should resolve the core issue of the runner not being able to find the most up to date mne_iclabel wheel. * FIX, TST: Install torch in doc building CI Since MNE iclabel 0.5, torch is NOT installed by default.
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel McCloy <dan@mccloy.info> Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
* MAINT: Update documentation and logging - Nice new landing page - Added covenience makefile commands - improved logging of flagged epochs * FIX, MAINT: Bump iclabel version and ignore mne warning We already throw an error if the user has mne iclabel version less than .5, so added a pin for minimum version of .5 in the requirements file. MNE is also throwing a future warnign for an API kwarg change in epochs.get_data, where the current default copy=False is changing to copy=True. See mne-tools/mne-python#12121 . I'm a little worried about the additional copies we will incur every single time that we call that method, but I dont have a strong reason to stray from what MNE believes is a bug fix so lets go with it and see how it plays. * FIX, MAINT: Bumpg GH actions checkout versions - This should resolve the core issue of the runner not being able to find the most up to date mne_iclabel wheel. * FIX, TST: Install torch in doc building CI Since MNE iclabel 0.5, torch is NOT installed by default.
* MAINT: Update documentation and logging - Nice new landing page - Added covenience makefile commands - improved logging of flagged epochs * FIX, MAINT: Bump iclabel version and ignore mne warning We already throw an error if the user has mne iclabel version less than .5, so added a pin for minimum version of .5 in the requirements file. MNE is also throwing a future warnign for an API kwarg change in epochs.get_data, where the current default copy=False is changing to copy=True. See mne-tools/mne-python#12121 . I'm a little worried about the additional copies we will incur every single time that we call that method, but I dont have a strong reason to stray from what MNE believes is a bug fix so lets go with it and see how it plays. * FIX, MAINT: Bumpg GH actions checkout versions - This should resolve the core issue of the runner not being able to find the most up to date mne_iclabel wheel. * FIX, TST: Install torch in doc building CI Since MNE iclabel 0.5, torch is NOT installed by default.

Closes #12114
[circle full]green