Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MRG: Speed up browse figure creation if scalings are provided #10109

Merged
merged 8 commits into from Dec 8, 2021

Conversation

hoechenberger
Copy link
Member

@hoechenberger hoechenberger commented Dec 8, 2021

This avoids loading data from disk or performing calculations if we don't actually need to calculate scalings parameters.

Also adds a scalings parameter to Report.add_raw().

Performance improvements:

this branch: 2.17 s ± 214 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
main:        4.07 s ± 625 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

with the following code:

# %%
from pathlib import Path
import mne

sample_dir = Path(mne.datasets.sample.data_path())
sample_fname = sample_dir / 'MEG' / 'sample' / 'sample_audvis_raw.fif'

raw = mne.io.read_raw_fif(sample_fname, verbose=False)
# raw.pick([0])
raw.pick_channels(['MEG 0111', 'MEG 0112', 'EEG 001', 'ECG 001', 'STI 014'])
report = mne.Report()

# %%
%timeit report.add_raw(raw=raw, title='foo', psd=False, replace=True)

x-ref #10107

Copy link
Member

@agramfort agramfort left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm. Thx 🙏 @hoechenberger

mne/viz/utils.py Outdated Show resolved Hide resolved
doc/changes/latest.inc Outdated Show resolved Hide resolved
mne/viz/utils.py Outdated Show resolved Hide resolved
mne/viz/utils.py Outdated
scalings = _handle_default('scalings_plot_raw', scalings)
if not isinstance(inst, (BaseRaw, BaseEpochs)):
raise ValueError('Must supply either Raw or Epochs')

for key, value in scalings.items():
if isinstance(value, str) and value != 'auto':
Copy link
Member

@larsoner larsoner Dec 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic seems wrong now as the not was omitted, should probably still be

Suggested change
if isinstance(value, str) and value != 'auto':
if not (isinstance(value, str) and value == 'auto'):

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... if you were trying to distribute the not, you probably meant:

Suggested change
if isinstance(value, str) and value != 'auto':
if not isinstance(value, str) or value != 'auto':

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I believe we could probably change this this to

        if value != 'auto' and not isinstance(value, float):

WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed a respective change in cbc14e8

Copy link
Member

@larsoner larsoner Dec 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the old conditional better, for example:

>>> import numpy as np
>>> np.array([1.]).item()
1.0
>>> float(np.array([1.]))
1.0
>>> np.array([1.]) == 'auto'
<stdin>:1: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
False

That warning would not happen with the isinstance(thing, str) call version of the code

To me the logic of if not (string and equal to 'auto'): then convert to float is clearer and more general

@hoechenberger hoechenberger marked this pull request as ready for review December 8, 2021 19:50
@hoechenberger hoechenberger changed the title Speed up browse figure creation if scalings are provided MRG: Speed up browse figure creation if scalings are provided Dec 8, 2021
@hoechenberger
Copy link
Member Author

@larsoner Please merge if you're happy!

Copy link
Member

@larsoner larsoner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM

mne/viz/utils.py Outdated
@@ -1158,14 +1158,33 @@ def _compute_scalings(scalings, inst, remove_dc=False, duration=10):
"""
from ..io.base import BaseRaw
from ..epochs import BaseEpochs

scalings = deepcopy(scalings)
Copy link
Member

@larsoner larsoner Dec 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need this line. _handle_default should EDIT: already make a copy internally

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(at least if you're worried about the user passing a dict and it being modified, it shouldn't be -- the values in principle could be if they're mutable and modified inplace but in practice this shouldn't really happen I think)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed the deepcopy now.

@larsoner larsoner merged commit 6a26583 into mne-tools:main Dec 8, 2021
@larsoner
Copy link
Member

larsoner commented Dec 8, 2021

Thanks @hoechenberger !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants