Spaces:
Running
Running
| # Authors: The MNE-Python contributors. | |
| # License: BSD-3-Clause | |
| # Copyright the MNE-Python contributors. | |
| from ..utils import get_config, verbose | |
| def coregistration( | |
| *, | |
| width=None, | |
| height=None, | |
| inst=None, | |
| subject=None, | |
| subjects_dir=None, | |
| head_opacity=None, | |
| head_high_res=None, | |
| trans=None, | |
| orient_to_surface=None, | |
| scale_by_distance=None, | |
| mark_inside=None, | |
| interaction=None, | |
| fullscreen=None, | |
| show=True, | |
| block=False, | |
| verbose=None, | |
| ): | |
| """Coregister an MRI with a subject's head shape. | |
| The GUI can be launched through the command line interface: | |
| .. code-block:: bash | |
| $ mne coreg | |
| or using a python interpreter as shown in :ref:`tut-source-alignment`. | |
| Parameters | |
| ---------- | |
| width : int | None | |
| Specify the width for window (in logical pixels). | |
| Default is None, which uses ``MNE_COREG_WINDOW_WIDTH`` config value | |
| (which defaults to ``800``). | |
| height : int | None | |
| Specify a height for window (in logical pixels). | |
| Default is None, which uses ``MNE_COREG_WINDOW_WIDTH`` config value | |
| (which defaults to ``400``). | |
| inst : None | path-like | |
| Path to an instance file containing the digitizer data. Compatible for | |
| Raw, Epochs, and Evoked files. | |
| subject : None | str | |
| Name of the mri subject. | |
| %(subjects_dir)s | |
| head_opacity : float | None | |
| The opacity of the head surface in the range ``[0., 1.]``. | |
| Default is None, which uses ``MNE_COREG_HEAD_OPACITY`` config value | |
| (which defaults to ``1.``). | |
| head_high_res : bool | None | |
| Use a high resolution head surface. | |
| Default is None, which uses ``MNE_COREG_HEAD_HIGH_RES`` config value | |
| (which defaults to True). | |
| trans : path-like | Transform | None | |
| The Head<->MRI transform or the path to its FIF file (``"-trans.fif"``). | |
| orient_to_surface : bool | None | |
| If True (default), orient EEG electrode and head shape points to the head | |
| surface. | |
| .. versionadded:: 0.16 | |
| scale_by_distance : bool | None | |
| If True (default), scale the digitization points by their distance from the | |
| scalp surface. | |
| .. versionadded:: 0.16 | |
| mark_inside : bool | None | |
| If True (default), mark points inside the head surface in a | |
| different color. | |
| .. versionadded:: 0.16 | |
| %(interaction_scene_none)s | |
| Defaults to ``'terrain'``. | |
| .. versionadded:: 0.16 | |
| .. versionchanged:: 1.0 | |
| Default interaction mode if ``None`` and no config setting found | |
| changed from ``'trackball'`` to ``'terrain'``. | |
| %(fullscreen)s | |
| Default is ``None``, which uses ``MNE_COREG_FULLSCREEN`` config value | |
| (which defaults to ``False``). | |
| .. versionadded:: 1.1 | |
| show : bool | |
| Show the GUI if True. | |
| block : bool | |
| Whether to halt program execution until the figure is closed. | |
| %(verbose)s | |
| Returns | |
| ------- | |
| frame : instance of CoregistrationUI | |
| The coregistration frame. | |
| Notes | |
| ----- | |
| Many parameters (e.g., ``head_opacity``) take None as a parameter, | |
| which means that the default will be read from the MNE-Python | |
| configuration file (which gets saved when exiting). | |
| Step by step instructions for the coregistrations are shown below: | |
| .. youtube:: ALV5qqMHLlQ | |
| """ | |
| config = get_config() | |
| if head_high_res is None: | |
| head_high_res = config.get("MNE_COREG_HEAD_HIGH_RES", "true") == "true" | |
| if head_opacity is None: | |
| head_opacity = config.get("MNE_COREG_HEAD_OPACITY", 0.8) | |
| if width is None: | |
| width = config.get("MNE_COREG_WINDOW_WIDTH", 800) | |
| if height is None: | |
| height = config.get("MNE_COREG_WINDOW_HEIGHT", 600) | |
| if subjects_dir is None: | |
| if "SUBJECTS_DIR" in config: | |
| subjects_dir = config["SUBJECTS_DIR"] | |
| elif "MNE_COREG_SUBJECTS_DIR" in config: | |
| subjects_dir = config["MNE_COREG_SUBJECTS_DIR"] | |
| false_like = ("false", "0") | |
| if orient_to_surface is None: | |
| orient_to_surface = config.get("MNE_COREG_ORIENT_TO_SURFACE", "true").lower() | |
| orient_to_surface = orient_to_surface not in false_like | |
| if scale_by_distance is None: | |
| scale_by_distance = config.get("MNE_COREG_SCALE_BY_DISTANCE", "true").lower() | |
| scale_by_distance = scale_by_distance not in false_like | |
| if interaction is None: | |
| interaction = config.get("MNE_COREG_INTERACTION", "terrain") | |
| if mark_inside is None: | |
| mark_inside = config.get("MNE_COREG_MARK_INSIDE", "true").lower() | |
| mark_inside = mark_inside not in false_like | |
| if fullscreen is None: | |
| fullscreen = config.get("MNE_COREG_FULLSCREEN", "") == "true" | |
| head_opacity = float(head_opacity) | |
| width = int(width) | |
| height = int(height) | |
| from ..viz.backends.renderer import MNE_3D_BACKEND_TESTING | |
| from ._coreg import CoregistrationUI | |
| if MNE_3D_BACKEND_TESTING: | |
| show = block = False | |
| return CoregistrationUI( | |
| info_file=inst, | |
| subject=subject, | |
| subjects_dir=subjects_dir, | |
| head_resolution=head_high_res, | |
| head_opacity=head_opacity, | |
| orient_glyphs=orient_to_surface, | |
| scale_by_distance=scale_by_distance, | |
| mark_inside=mark_inside, | |
| trans=trans, | |
| size=(width, height), | |
| show=show, | |
| block=block, | |
| interaction=interaction, | |
| fullscreen=fullscreen, | |
| verbose=verbose, | |
| ) | |
| class _GUIScraper: | |
| """Scrape GUI outputs.""" | |
| def __repr__(self): | |
| return "<GUIScraper>" | |
| def __call__(self, block, block_vars, gallery_conf): | |
| from ._coreg import CoregistrationUI | |
| gui_classes = (CoregistrationUI,) | |
| try: | |
| from mne_gui_addons._ieeg_locate import IntracranialElectrodeLocator | |
| except Exception: | |
| pass | |
| else: | |
| gui_classes = gui_classes + (IntracranialElectrodeLocator,) | |
| from qtpy import QtGui | |
| from sphinx_gallery.scrapers import figure_rst | |
| for gui in block_vars["example_globals"].values(): | |
| if ( | |
| isinstance(gui, gui_classes) | |
| and not getattr(gui, "_scraped", False) | |
| and gallery_conf["builder_name"] == "html" | |
| ): | |
| gui._scraped = True # monkey-patch but it's easy enough | |
| img_fname = next(block_vars["image_path_iterator"]) | |
| # TODO fix in window refactor | |
| window = gui if hasattr(gui, "grab") else gui._renderer._window | |
| # window is QWindow | |
| # https://doc.qt.io/qt-5/qwidget.html#grab | |
| pixmap = window.grab() | |
| if hasattr(gui, "_renderer"): # if no renderer, no need | |
| # Now the tricky part: we need to get the 3D renderer, | |
| # extract the image from it, and put it in the correct | |
| # place in the pixmap. The easiest way to do this is | |
| # actually to save the 3D image first, then load it | |
| # using QPixmap and Qt geometry. | |
| plotter = gui._renderer.plotter | |
| plotter.screenshot(img_fname) | |
| sub_pixmap = QtGui.QPixmap(img_fname) | |
| # https://doc.qt.io/qt-5/qwidget.html#mapTo | |
| # https://doc.qt.io/qt-5/qpainter.html#drawPixmap-1 | |
| QtGui.QPainter(pixmap).drawPixmap( | |
| plotter.mapTo(window, plotter.rect().topLeft()), sub_pixmap | |
| ) | |
| # https://doc.qt.io/qt-5/qpixmap.html#save | |
| pixmap.save(img_fname) | |
| try: # for compatibility with both GUIs, will be refactored | |
| gui._renderer.close() # TODO should be triggered by close | |
| except Exception: | |
| pass | |
| gui.close() | |
| return figure_rst([img_fname], gallery_conf["src_dir"], "GUI") | |
| return "" | |