Configuring MNE-Python

This tutorial covers how to configure MNE-Python to suit your local system and your analysis preferences.

We begin by importing the necessary Python modules:

import os
import mne

Getting and setting configuration variables

Configuration variables are read and written using the functions mne.get_config() and mne.set_config(). To read a specific configuration variable, pass its name to get_config() as the key parameter (key is the first parameter so you can pass it unnamed if you want):

print(mne.get_config('MNE_USE_CUDA'))
print(type(mne.get_config('MNE_USE_CUDA')))

Out:

false
<class 'str'>

Note that the string values read from the JSON file are not parsed in any way, so get_config() returns a string even for true/false config values, rather than a Python boolean. Similarly, set_config() will only set string values (or None values, to unset a variable):

try:
    mne.set_config('MNE_USE_CUDA', True)
except TypeError as err:
    print(err)

Out:

value must be an instance of str, path-like, or NoneType, got <class 'bool'> instead

If you’re unsure whether a config variable has been set, there is a convenient way to check it and provide a fallback in case it doesn’t exist: get_config() has a default parameter.

print(mne.get_config('missing_config_key', default='fallback value'))

Out:

fallback value

There are also two convenience modes of get_config(). The first will return a dict containing all config variables (and their values) that have been set on your system; this is done by passing key=None (which is the default, so it can be omitted):

print(mne.get_config())  # same as mne.get_config(key=None)

Out:

{'MNE_DATASETS_BRAINSTORM_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_EEGBCI_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_FIELDTRIP_CMC_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_FNIRS_MOTOR_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_HF_SEF_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_KILOWORD_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_LIMO_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_MISC_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_MTRF_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_MULTIMODAL_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_OPM_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_PHANTOM_4DBTI_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_REFMEG_NOISE_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_SAMPLE_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_SOMATO_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_SPM_FACE_PATH': '/home/circleci/mne_data', 'MNE_DATASETS_TESTING_PATH': '/home/circleci/mne_data', 'MNE_LOGGING_LEVEL': 'info', 'MNE_USE_CUDA': 'false', 'SUBJECTS_DIR': '/home/circleci/mne_data/MNE-fsaverage-data'}

The second convenience mode will return a tuple of all the keys that MNE-Python recognizes and uses, regardless of whether they’ve been set on your system. This is done by passing an empty string '' as the key:

print(mne.get_config(key=''))

Out:

('MNE_3D_OPTION_ANTIALIAS', 'MNE_BROWSE_RAW_SIZE', 'MNE_CACHE_DIR', 'MNE_COREG_ADVANCED_RENDERING', 'MNE_COREG_COPY_ANNOT', 'MNE_COREG_GUESS_MRI_SUBJECT', 'MNE_COREG_HEAD_HIGH_RES', 'MNE_COREG_HEAD_OPACITY', 'MNE_COREG_INTERACTION', 'MNE_COREG_MARK_INSIDE', 'MNE_COREG_PREPARE_BEM', 'MNE_COREG_PROJECT_EEG', 'MNE_COREG_ORIENT_TO_SURFACE', 'MNE_COREG_SCALE_LABELS', 'MNE_COREG_SCALE_BY_DISTANCE', 'MNE_COREG_SCENE_SCALE', 'MNE_COREG_WINDOW_HEIGHT', 'MNE_COREG_WINDOW_WIDTH', 'MNE_COREG_SUBJECTS_DIR', 'MNE_CUDA_DEVICE', 'MNE_CUDA_IGNORE_PRECISION', 'MNE_DATA', 'MNE_DATASETS_BRAINSTORM_PATH', 'MNE_DATASETS_EEGBCI_PATH', 'MNE_DATASETS_HF_SEF_PATH', 'MNE_DATASETS_MEGSIM_PATH', 'MNE_DATASETS_MISC_PATH', 'MNE_DATASETS_MTRF_PATH', 'MNE_DATASETS_SAMPLE_PATH', 'MNE_DATASETS_SOMATO_PATH', 'MNE_DATASETS_MULTIMODAL_PATH', 'MNE_DATASETS_FNIRS_MOTOR_PATH', 'MNE_DATASETS_OPM_PATH', 'MNE_DATASETS_SPM_FACE_DATASETS_TESTS', 'MNE_DATASETS_SPM_FACE_PATH', 'MNE_DATASETS_TESTING_PATH', 'MNE_DATASETS_VISUAL_92_CATEGORIES_PATH', 'MNE_DATASETS_KILOWORD_PATH', 'MNE_DATASETS_FIELDTRIP_CMC_PATH', 'MNE_DATASETS_PHANTOM_4DBTI_PATH', 'MNE_DATASETS_LIMO_PATH', 'MNE_DATASETS_REFMEG_NOISE_PATH', 'MNE_FORCE_SERIAL', 'MNE_KIT2FIFF_STIM_CHANNELS', 'MNE_KIT2FIFF_STIM_CHANNEL_CODING', 'MNE_KIT2FIFF_STIM_CHANNEL_SLOPE', 'MNE_KIT2FIFF_STIM_CHANNEL_THRESHOLD', 'MNE_LOGGING_LEVEL', 'MNE_MEMMAP_MIN_SIZE', 'MNE_SKIP_FTP_TESTS', 'MNE_SKIP_NETWORK_TESTS', 'MNE_SKIP_TESTING_DATASET_TESTS', 'MNE_STIM_CHANNEL', 'MNE_TQDM', 'MNE_USE_CUDA', 'MNE_USE_NUMBA', 'SUBJECTS_DIR')

It is possible to add config variables that are not part of the recognized list, by passing any arbitrary key to set_config(). This will yield a warning, however, which is a nice check in cases where you meant to set a valid key but simply misspelled it:

mne.set_config('MNEE_USE_CUUDAA', 'false')

Out:

/home/circleci/project/tutorials/intro/plot_50_configure_mne.py:76: RuntimeWarning: Setting non-standard config type: "MNEE_USE_CUUDAA"
  mne.set_config('MNEE_USE_CUUDAA', 'false')

Let’s delete that config variable we just created. To unset a config variable, use set_config() with value=None. Since we’re still dealing with an unrecognized key (as far as MNE-Python is concerned) we’ll still get a warning, but the key will be unset:

mne.set_config('MNEE_USE_CUUDAA', None)
assert 'MNEE_USE_CUUDAA' not in mne.get_config('')

Out:

/home/circleci/project/tutorials/intro/plot_50_configure_mne.py:84: RuntimeWarning: Setting non-standard config type: "MNEE_USE_CUUDAA"
  mne.set_config('MNEE_USE_CUUDAA', None)

Where configurations are stored

MNE-Python stores configuration variables in a JSON file. By default, this file is located in %USERPROFILE%\.mne\mne-python.json on Windows and $HOME/.mne/mne-python.json on Linux or macOS. You can get the full path to the config file with mne.get_config_path().

Out:

/home/circleci/.mne/mne-python.json

However it is not a good idea to directly edit files in the .mne directory; use the getting and setting functions described in the previous section.

If for some reason you want to load the configuration from a different location, you can pass the home_dir parameter to get_config_path(), specifying the parent directory of the .mne directory where the configuration file you wish to load is stored.

Using environment variables

For compatibility with MNE-C, MNE-Python also reads and writes environment variables to specify configuration. This is done with the same functions that read and write the JSON configuration, and is controlled with the parameters use_env and set_env. By default, get_config() will check os.environ before checking the MNE-Python JSON file; to check only the JSON file use use_env=False. To demonstrate, here’s an environment variable that is not specific to MNE-Python (and thus is not in the JSON config file):

# make sure it's not in the JSON file (no error means our assertion held):
assert mne.get_config('PATH', use_env=False) is None
# but it *is* in the environment:
print(mne.get_config('PATH'))

Out:

/home/circleci/.local/bin/:/home/circleci/minimal_cmds/bin:/home/circleci/minimal_cmds/bin:/home/circleci/.local/bin:/home/circleci/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Also by default, set_config() will set values in both the JSON file and in os.environ; to set a config variable only in the JSON file use set_env=False. Here we’ll use print() statement to confirm that an environment variable is being created and deleted (we could have used the Python assert statement instead, but it doesn’t print any output when it succeeds so it’s a little less obvious):

mne.set_config('foo', 'bar', set_env=False)
print('foo' in os.environ.keys())
mne.set_config('foo', 'bar')
print('foo' in os.environ.keys())
mne.set_config('foo', None)  # unsetting a key deletes var from environment
print('foo' in os.environ.keys())

Out:

/home/circleci/project/tutorials/intro/plot_50_configure_mne.py:135: RuntimeWarning: Setting non-standard config type: "foo"
  mne.set_config('foo', 'bar', set_env=False)
False
/home/circleci/project/tutorials/intro/plot_50_configure_mne.py:137: RuntimeWarning: Setting non-standard config type: "foo"
  mne.set_config('foo', 'bar')
True
/home/circleci/project/tutorials/intro/plot_50_configure_mne.py:139: RuntimeWarning: Setting non-standard config type: "foo"
  mne.set_config('foo', None)  # unsetting a key deletes var from environment
False

Logging

One important configuration variable is MNE_LOGGING_LEVEL. Throughout the module, messages are generated describing the actions MNE-Python is taking behind-the-scenes. How you set MNE_LOGGING_LEVEL determines how many of those messages you see. The default logging level on a fresh install of MNE-Python is info:

print(mne.get_config('MNE_LOGGING_LEVEL'))

Out:

info

The logging levels that can be set as config variables are debug, info, warning, error, and critical. Around 90% of the log messages in MNE-Python are info messages, so for most users the choice is between info (tell me what is happening) and warning (tell me only if something worrisome happens). The debug logging level is intended for MNE-Python developers.

In an earlier section we saw how mne.set_config() is used to change the logging level for the current Python session and all future sessions. To change the logging level only for the current Python session, you can use mne.set_log_level() instead. The set_log_level() function takes the same five string options that are used for the MNE_LOGGING_LEVEL config variable; additionally, it can accept int or bool values that are equivalent to those strings. The equivalencies are given in this table:

String

Integer

Boolean

DEBUG

10

INFO

20

True

WARNING

30

False

ERROR

40

CRITICAL

50

With many MNE-Python functions it is possible to change the logging level temporarily for just that function call, by using the verbose parameter. To illustrate this, we’ll load some sample data with different logging levels set. First, with log level warning:

kit_data_path = os.path.join(os.path.abspath(os.path.dirname(mne.__file__)),
                             'io', 'kit', 'tests', 'data', 'test.sqd')
raw = mne.io.read_raw_kit(kit_data_path, verbose='warning')

No messages were generated, because none of the messages were of severity “warning” or worse. Next, we’ll load the same file with log level info (the default level):

raw = mne.io.read_raw_kit(kit_data_path, verbose='info')

Out:

Extracting SQD Parameters from /home/circleci/project/mne/io/kit/tests/data/test.sqd...
Creating Raw.info structure...
Setting channel info structure...
Creating Info structure...
Ready.

This time, we got a few messages about extracting information from the file, converting that information into the MNE-Python Info format, etc. Finally, if we request debug-level information, we get even more detail:

raw = mne.io.read_raw_kit(kit_data_path, verbose='debug')

Out:

Extracting SQD Parameters from /home/circleci/project/mne/io/kit/tests/data/test.sqd...
Creating Raw.info structure...
SQD file basic information:
Meg160 version = V2R004
System ID      = 34
System name    = NYU 160ch System since Jan24 2009
Model name     = EQ1160C
Channel count  = 192
Comment        =
Dewar style    = 2
FLL type       = 10
Trigger type   = 21
A/D board type = 12
ADC range      = +/-5.0[V]
ADC allocate   = 16[bit]
ADC bit        = 12[bit]
Setting channel info structure...
Creating Info structure...
Ready.

We’ve been passing string values to the verbose parameter, but we can see from the table above that verbose=True will give us the info messages and verbose=False will suppress them; this is a useful shorthand to use in scripts, so you don’t have to remember the specific names of the different logging levels. One final note: verbose=None (which is the default for functions that have a verbose parameter) will fall back on whatever logging level was most recently set by mne.set_log_level(), or if that hasn’t been called during the current Python session, it will fall back to the value of mne.get_config('MNE_LOGGING_LEVEL').

Total running time of the script: ( 0 minutes 5.425 seconds)

Estimated memory usage: 8 MB

Gallery generated by Sphinx-Gallery