Skip to content

Commit

Permalink
MAINT: Clean up circular imports (mne-tools#11920)
Browse files Browse the repository at this point in the history
  • Loading branch information
larsoner authored Aug 28, 2023
1 parent 4af14f4 commit b33f3a8
Show file tree
Hide file tree
Showing 79 changed files with 566 additions and 444 deletions.
5 changes: 4 additions & 1 deletion mne/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,20 @@
"cuda",
"datasets",
"decoding",
"defaults",
"dipole",
"epochs",
"event",
"export",
"filter",
"forward",
"gui",
"inverse_sparse",
"io",
"minimum_norm",
"preprocessing",
"report",
"source_space",
"simulation",
"stats",
"surface",
Expand Down Expand Up @@ -255,7 +258,7 @@
"spatio_temporal_tris_adjacency",
"stc_near_sensors",
],
"source_space": [
"source_space._source_space": [
"SourceSpaces",
"add_source_space_distances",
"get_volume_labels_from_src",
Expand Down
8 changes: 5 additions & 3 deletions mne/_fiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
# All imports should be done directly to submodules, so we don't import
# anything here or use lazy_loader.

# This warn import (made private as _warn) is just for the temporary
# _io_dep_getattr and can be removed in 1.6 along with _dep_msg and _io_dep_getattr.
from ..utils import warn as _warn


# Helpers for keeping some attributes in mne/io/*.py, remove in 1.6
_dep_msg = (
"is deprecated will be removed in 1.6, use documented public API instead. "
"If no appropriate public API exists, please open an issue on GitHub."
Expand All @@ -17,9 +20,8 @@

def _io_dep_getattr(name, mod):
import importlib
from ..utils import warn

fiff_mod = importlib.import_module(f"mne._fiff.{mod}")
obj = getattr(fiff_mod, name)
warn(f"mne.io.{mod}.{name} {_dep_msg}", FutureWarning)
_warn(f"mne.io.{mod}.{name} {_dep_msg}", FutureWarning)
return obj
19 changes: 10 additions & 9 deletions mne/_fiff/meas_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,6 @@
write_name_list_sanitized,
)
from .proc_history import _read_proc_history, _write_proc_history
from ..transforms import (
invert_transform,
Transform,
_coord_frame_name,
_ensure_trans,
_frame_to_str,
)
from ..html_templates import _get_html_template
from ..utils import (
logger,
Expand Down Expand Up @@ -327,6 +320,7 @@ def get_montage(self):
%(montage)s
"""
from ..channels.montage import make_dig_montage
from ..transforms import _frame_to_str

info = self if isinstance(self, Info) else self.info
if info["dig"] is None:
Expand Down Expand Up @@ -920,6 +914,8 @@ def get_channel_types(self, picks=None, unique=False, only_data_chs=False):


def _format_trans(obj, key):
from ..transforms import Transform

try:
t = obj[key]
except KeyError:
Expand Down Expand Up @@ -954,6 +950,8 @@ def _check_description(description):


def _check_dev_head_t(dev_head_t):
from ..transforms import Transform, _ensure_trans

_validate_type(dev_head_t, (Transform, None), "info['dev_head_t']")
if dev_head_t is not None:
dev_head_t = _ensure_trans(dev_head_t, "meg", "head")
Expand Down Expand Up @@ -1581,6 +1579,7 @@ def normalize_proj(self):
def __repr__(self):
"""Summarize info instead of printing all."""
from ..io.kit.constants import KIT_SYSNAMES
from ..transforms import _coord_frame_name, Transform

MAX_WIDTH = 68
strs = ["<Info | %s non-empty values"]
Expand Down Expand Up @@ -2064,6 +2063,8 @@ def read_meas_info(fid, tree, clean_bads=False, verbose=None):
meas : dict
Node in tree that contains the info.
"""
from ..transforms import invert_transform, Transform

# Find the desired blocks
meas = dir_tree_find(tree, FIFF.FIFFB_MEAS)
if len(meas) == 0:
Expand Down Expand Up @@ -2511,8 +2512,6 @@ def read_meas_info(fid, tree, clean_bads=False, verbose=None):
info["ctf_head_t"] = ctf_head_t
info["dev_ctf_t"] = dev_ctf_t
if dev_head_t is not None and ctf_head_t is not None and dev_ctf_t is None:
from ..transforms import Transform

head_ctf_trans = np.linalg.inv(ctf_head_t["trans"])
dev_ctf_trans = np.dot(head_ctf_trans, info["dev_head_t"]["trans"])
info["dev_ctf_t"] = Transform("meg", "ctf_head", dev_ctf_trans)
Expand Down Expand Up @@ -3253,6 +3252,8 @@ def create_info(ch_names, sfreq, ch_types="misc", verbose=None):

def _empty_info(sfreq):
"""Create an empty info dictionary."""
from ..transforms import Transform

_none_keys = (
"acq_pars",
"acq_stim",
Expand Down
5 changes: 1 addition & 4 deletions mne/_freesurfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
read_ras_mni_t,
Transform,
)
from .surface import read_surface, _read_mri_surface
from .utils import (
verbose,
_validate_type,
Expand Down Expand Up @@ -356,8 +357,6 @@ def vertex_to_mni(vertices, hemis, subject, subjects_dir=None, verbose=None):
coordinates : array, shape (n_vertices, 3)
The MNI coordinates (in mm) of the vertices.
"""
from .surface import read_surface

singleton = False
if not isinstance(vertices, list) and not isinstance(vertices, np.ndarray):
singleton = True
Expand Down Expand Up @@ -757,7 +756,6 @@ def _get_head_surface(surf, subject, subjects_dir, bem=None, verbose=None):
.. versionadded: 0.24
"""
from .bem import _bem_find_surface, read_bem_surfaces
from .surface import _read_mri_surface

_check_option("surf", surf, ("auto", "head", "outer_skin", "head-dense", "seghead"))
if surf in ("auto", "head", "outer_skin"):
Expand Down Expand Up @@ -831,7 +829,6 @@ def _get_skull_surface(surf, subject, subjects_dir, bem=None, verbose=None):
.. versionadded: 0.24
"""
from .bem import _bem_find_surface
from .surface import _read_mri_surface

if bem is not None:
try:
Expand Down
2 changes: 1 addition & 1 deletion mne/beamformer/_compute_beamformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from ..forward.forward import is_fixed_orient, _restrict_forward_to_src_sel
from .._fiff.proj import make_projector, Projection
from ..minimum_norm.inverse import _get_vertno, _prepare_forward
from ..source_space import label_src_vertno_sel
from ..source_space._source_space import label_src_vertno_sel
from ..utils import (
verbose,
check_fname,
Expand Down
5 changes: 1 addition & 4 deletions mne/bem.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
transform_surface_to,
)
from .transforms import _ensure_trans, apply_trans, Transform
from .viz.misc import plot_bem
from .utils import (
verbose,
logger,
Expand Down Expand Up @@ -1250,8 +1251,6 @@ def make_watershed_bem(
.. versionadded:: 0.10
"""
from .viz.misc import plot_bem

env, mri_dir, bem_dir = _prepare_env(subject, subjects_dir)
tempdir = _TempDir() # fsl and Freesurfer create some random junk in CWD
run_subprocess_env = partial(run_subprocess, env=env, cwd=tempdir)
Expand Down Expand Up @@ -2127,8 +2126,6 @@ def make_flash_bem(
outer skin) from a FLASH 5 MRI image synthesized from multiecho FLASH
images acquired with spin angles of 5 and 30 degrees.
"""
from .viz.misc import plot_bem

env, mri_dir, bem_dir = _prepare_env(subject, subjects_dir)
tempdir = _TempDir() # fsl and Freesurfer create some random junk in CWD
run_subprocess_env = partial(run_subprocess, env=env, cwd=tempdir)
Expand Down
1 change: 0 additions & 1 deletion mne/channels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"rename_channels",
"fix_mag_coil_types",
"read_ch_adjacency",
"_get_ch_type",
"find_ch_adjacency",
"make_1020_channel_selections",
"combine_channels",
Expand Down
47 changes: 4 additions & 43 deletions mne/channels/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from scipy.spatial import Delaunay
from scipy.stats import zscore

from ..bem import _check_origin
from ..defaults import HEAD_SIZE_DEFAULT, _handle_default
from ..utils import (
verbose,
Expand Down Expand Up @@ -55,7 +56,6 @@
pick_types,
_picks_by_type,
_check_excludes_includes,
_contains_ch_type,
channel_indices_by_type,
pick_channels,
_picks_to_idx,
Expand Down Expand Up @@ -107,45 +107,6 @@ def _get_meg_system(info):
return system, have_helmet


# TODO: Deal with name dup with mne._fiff.reference._get_ch_type
def _get_ch_type(inst, ch_type, allow_ref_meg=False):
"""Choose a single channel type (usually for plotting).
Usually used in plotting to plot a single datatype, e.g. look for mags,
then grads, then ... to plot.
"""
if ch_type is None:
allowed_types = [
"mag",
"grad",
"planar1",
"planar2",
"eeg",
"csd",
"fnirs_cw_amplitude",
"fnirs_fd_ac_amplitude",
"fnirs_fd_phase",
"fnirs_od",
"hbo",
"hbr",
"ecog",
"seeg",
"dbs",
]
allowed_types += ["ref_meg"] if allow_ref_meg else []
for type_ in allowed_types:
if isinstance(inst, Info):
if _contains_ch_type(inst, type_):
ch_type = type_
break
elif type_ in inst:
ch_type = type_
break
else:
raise RuntimeError("No plottable channel types found")
return ch_type


@verbose
def equalize_channels(instances, copy=True, verbose=None):
"""Equalize channel picks and ordering across multiple MNE-Python objects.
Expand Down Expand Up @@ -803,7 +764,6 @@ def interpolate_bads(
-----
.. versionadded:: 0.9.0
"""
from ..bem import _check_origin
from .interpolation import (
_interpolate_bads_eeg,
_interpolate_bads_meeg,
Expand Down Expand Up @@ -1497,7 +1457,7 @@ def _compute_ch_adjacency(info, ch_type):
ch_names : list
The list of channel names present in adjacency matrix.
"""
from .. import spatial_tris_adjacency
from ..source_estimate import spatial_tris_adjacency
from ..channels.layout import _find_topomap_coords, _pair_grad_sensors

combine_grads = ch_type == "grad" and any(
Expand Down Expand Up @@ -1795,7 +1755,8 @@ def combine_channels(
is ``True``, also containing stimulus channels).
"""
from ..io import BaseRaw, RawArray
from .. import BaseEpochs, EpochsArray, Evoked, EvokedArray
from ..epochs import BaseEpochs, EpochsArray
from ..evoked import Evoked, EvokedArray

ch_axis = 1 if isinstance(inst, BaseEpochs) else 0
ch_idx = list(range(inst.info["nchan"]))
Expand Down
3 changes: 2 additions & 1 deletion mne/channels/interpolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from .._fiff.meas_info import _simplify_info
from .._fiff.pick import pick_types, pick_channels, pick_info
from ..surface import _normalize_vectors
from ..forward import _map_meg_or_eeg_channels
from ..utils import _check_option, _validate_type


Expand Down Expand Up @@ -194,6 +193,8 @@ def _interpolate_bads_meeg(
exclude=(),
verbose=None,
):
from ..forward import _map_meg_or_eeg_channels

bools = dict(meg=meg, eeg=eeg)
info = _simplify_info(inst.info)
for ch_type, do in bools.items():
Expand Down
3 changes: 1 addition & 2 deletions mne/channels/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
logger,
)
from .channels import _get_ch_info
from ..viz.topomap import plot_layout


class Layout:
Expand Down Expand Up @@ -131,8 +132,6 @@ def plot(self, picks=None, show_axes=False, show=True):
-----
.. versionadded:: 0.12.0
"""
from ..viz.topomap import plot_layout

return plot_layout(self, picks=picks, show_axes=show_axes, show=show)


Expand Down
6 changes: 1 addition & 5 deletions mne/channels/montage.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import numpy as np

from ..defaults import HEAD_SIZE_DEFAULT
from .._freesurfer import get_mni_fiducials
from ..viz import plot_montage
from ..transforms import (
apply_trans,
Expand Down Expand Up @@ -609,9 +610,6 @@ def add_estimated_fiducials(self, subject, subjects_dir=None, verbose=None):
and then use ``mne.channels.compute_native_head_t(montage)``
to get the head <-> MRI transform.
"""
# Avoid circular import
from .._freesurfer import get_mni_fiducials

# get coordframe and fiducial coordinates
montage_bunch = _get_data_as_dict_from_dig(self.dig)

Expand Down Expand Up @@ -654,8 +652,6 @@ def add_mni_fiducials(self, subjects_dir=None, verbose=None):
those coordinate to be transformed to "head" space (origin
between LPA and RPA).
"""
from .._freesurfer import get_mni_fiducials

montage_bunch = _get_data_as_dict_from_dig(self.dig)

# get the coordinate frame and check that it's MNI TAL
Expand Down
9 changes: 7 additions & 2 deletions mne/channels/tests/test_montage.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@
)
import matplotlib.pyplot as plt

from mne import __file__ as _mne_file, create_info, read_evokeds, pick_types
from mne.source_space import get_mni_fiducials
from mne import (
__file__ as _mne_file,
create_info,
read_evokeds,
pick_types,
)
from mne.coreg import get_mni_fiducials
from mne.utils._testing import assert_object_equal
from mne.channels import (
get_builtin_montages,
Expand Down
3 changes: 1 addition & 2 deletions mne/chpi.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from .io import BaseRaw
from .io.ctf.trans import _make_ctf_coord_trans_set
from .io.kit.kit import RawKIT as _RawKIT
from .io.kit.constants import KIT
from .channels.channels import _get_meg_system
from ._fiff.meas_info import _simplify_info, Info
from ._fiff.pick import (
Expand Down Expand Up @@ -262,8 +263,6 @@ def extract_chpi_locs_kit(raw, stim_channel="MISC 064", *, verbose=None):
-----
.. versionadded:: 0.23
"""
from .io.kit.constants import KIT

_validate_type(raw, (_RawKIT,), "raw")
stim_chs = [
raw.info["ch_names"][pick]
Expand Down
Loading

0 comments on commit b33f3a8

Please sign in to comment.