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

ENH: Add OTP processing option #356

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ec9ac11
Merge pull request #1 from LABSN/master
mdclarke Jun 26, 2018
719c8ec
Update _report.py
mdclarke Jun 26, 2018
45d641e
Merge pull request #3 from mdclarke/mdclarke-reports-1
mdclarke Jun 26, 2018
c8f9cb2
Merge branch 'LABSN:main' into master
mdclarke Feb 4, 2022
20d4def
Create _otp.py
mdclarke Feb 4, 2022
4850332
Update _paths.py
mdclarke Feb 4, 2022
1d06fab
Update _otp.py
mdclarke Feb 4, 2022
860d1a1
Update _mnefun.py
mdclarke Feb 4, 2022
ead4693
Update canonical.yml
mdclarke Feb 4, 2022
10a4b93
Update overview.rst
mdclarke Feb 4, 2022
f3b2a74
Update overview.rst
mdclarke Feb 4, 2022
0a783e9
Update overview.rst
mdclarke Feb 4, 2022
fc865e9
Update overview.rst
mdclarke Feb 4, 2022
6f756dd
Update _mnefun.py
mdclarke Feb 4, 2022
206d80d
Update _mnefun.py
mdclarke Feb 4, 2022
b57ebbc
Update _mnefun.py
mdclarke Feb 4, 2022
3c00104
Update _otp.py
mdclarke Feb 4, 2022
26a9669
Update _paths.py
mdclarke Feb 4, 2022
cf35b98
Update _otp.py
mdclarke Feb 4, 2022
9805a02
Update _report.py
mdclarke Feb 4, 2022
e2f1997
FIX: Cis
larsoner Feb 7, 2022
10de96d
FIX: Another
larsoner Feb 7, 2022
bb37fe8
FIX: Another
larsoner Feb 7, 2022
3861061
FIX: Another
larsoner Feb 7, 2022
9032614
FIX: Dev
larsoner Feb 7, 2022
00bab06
FIX: Another
larsoner Feb 7, 2022
bb841e5
FIX: Okay
larsoner Feb 7, 2022
243b1c6
FIX: Missed
larsoner Feb 7, 2022
95403eb
FIX: Closer
larsoner Feb 7, 2022
c60a2bc
FIX: Order
larsoner Feb 7, 2022
e65a10a
FIX: One more
larsoner Feb 7, 2022
e4aac95
CI: Split
larsoner Feb 7, 2022
8ccdba8
FIX: Naming
larsoner Feb 7, 2022
d2984ee
FIX: Even better
larsoner Feb 7, 2022
a534a85
STY: Flake
larsoner Feb 7, 2022
bd46b62
Update _flow.py
mdclarke Feb 8, 2022
6dab0f4
Update _flow.py
mdclarke Feb 8, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,37 @@ version: 2
jobs:
build_docs:
docker:
- image: circleci/python:3.7-buster
- image: cimg/base:stable-20.04
steps:
# Get our data and merge with upstream
- checkout
- run: sudo apt-get install graphviz-dev graphviz
- run: python -m pip install --quiet --upgrade --user pip
- run: python -m pip install --quiet --upgrade --user numpy scipy https://github.com/mne-tools/mne-python/zipball/main numpydoc sphinx sphinx_fontawesome sphinx_bootstrap_theme pygraphviz
- run: python -c "import mne; mne.sys_info()"
- run: python setup.py develop --user
- run: cd doc && make html
- run:
name: Setup system
command: |
set -e
echo "set -e" >> $BASH_ENV
sudo apt update -qq
sudo apt install -qq graphviz-dev graphviz python3-venv python3.9-venv python3.9-dev
python3.9 -m venv ~/python_env
source ~/python_env/bin/activate
echo "source ~/python_env/bin/activate" >> $BASH_ENV
mkdir -p ~/.local/bin
ln -s ~/python_env/bin/python ~/.local/bin/python
- run:
name: Setup Python env
command: |
echo "Pip..."
pip install --quiet --upgrade pip
echo "Dependencies..."
pip install --quiet --upgrade numpy scipy https://github.com/mne-tools/mne-python/zipball/main numpydoc sphinx sphinx_fontawesome sphinx_bootstrap_theme
echo "PyGraphViz..."
pip install --upgrade pygraphviz
python -c "import mne; mne.sys_info()"
pip install -ve .
- run:
name: Build docs
command: |
make -C doc html

- store_artifacts:
path: doc/_build/html/
Expand All @@ -25,7 +46,7 @@ jobs:

deploy:
docker:
- image: circleci/python:3.6-stretch
- image: cimg/base:stable-20.04
steps:
- add_ssh_keys:
fingerprints:
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: 'linux'
concurrency:
group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
cancel-in-progress: true
on:
push:
branches:
- '*'
pull_request:
branches:
- '*'

jobs:
job:
name: 'py3.10'
runs-on: ubuntu-20.04
defaults:
run:
shell: bash
env:
MNE_LOGGING_LEVEL: 'info'
MNE_STIM_CHANNEL: 'STI101'
OPENBLAS_NUM_THREADS: '1'
PYTHON_VERSION: '3.10'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ env.PYTHON_VERSION }}
name: 'Setup python'
- shell: bash -el {0}
run: |
pip install --upgrade --only-binary=":all:" numpy scipy matplotlib
pip install --upgrade pyyaml patsy pytest pytest-cov codecov flake8 pydocstyle numpydoc https://github.com/mne-tools/mne-python/archive/main.zip
pip install -ve .
- shell: bash -el {0}
run: pytest mnefun
name: 'Run tests'
- shell: bash -el {0}
run: make flake
- uses: codecov/codecov-action@v1
if: success()
name: 'Upload coverage to CodeCov'
File renamed without changes.
23 changes: 0 additions & 23 deletions .travis.yml

This file was deleted.

36 changes: 25 additions & 11 deletions doc/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,19 @@ score : callable | None
on_process : callable
Called at each processing step.

.. _do_sss:
3. do_otp
---------
Run OTP processing.

1. Run OTP locally using :func:`mne.preprocessing.oversampled_temporal_projection`.

``preprocessing: otp``: OTP parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
otp_dur : float | None
The window duration (in seconds) to use. Must be > or equal to tsss_dur if combining with tSSS processing.

3. do_sss

4. do_sss
---------

.. warning:: Before running SSS, set ``params.mf_prebad[SUBJ]`` to a
Expand Down Expand Up @@ -281,12 +291,12 @@ cont_as_esss : bool
Only supported when Python is used for SSS.


4. do_ch_fix
5. do_ch_fix
------------

Fix EEG channel ordering, and also anonymize files.

5. gen_ssp
6. gen_ssp
----------

.. warning:: Before running SSP, examine SSS'ed files and make
Expand Down Expand Up @@ -441,12 +451,12 @@ plot_drop_logs : bool
If True, plot drop logs after preprocessing.


6. apply_ssp
7. apply_ssp
------------
Apply SSP vectors and filtering to the files.


7. write_epochs
8. write_epochs
---------------
Write epochs to disk.

Expand Down Expand Up @@ -537,7 +547,7 @@ allow_resample : bool
matching sample rate. This is useful when recordings were errantly
performed at different sample rates.

8. gen_covs
9. gen_covs
-----------
Generate covariances.

Expand Down Expand Up @@ -566,8 +576,8 @@ force_erm_cov_rank_full : bool
is short and/or there are a lot of head movements.


9. gen_fwd
----------
10. gen_fwd
-----------
.. warning:: Make SUBJ/trans/SUBJ-trans.fif using :ref:`mne:mne coreg`.

Generate forward solutions (and source space if necessary).
Expand All @@ -591,7 +601,7 @@ fwd_mindist : float
Minimum distance (mm) for sources in the brain from the skull in order
for them to be included in the forward solution source space.

10. gen_inv
11. gen_inv
-----------

Generate inverses.
Expand All @@ -604,7 +614,7 @@ inv_runs : list of int
Runs to use for each inverse.


11. gen_report
12. gen_report
--------------

Write :class:`mne.Report` HTML of results to disk.
Expand Down Expand Up @@ -673,10 +683,14 @@ bad_tag : str
Tag for bid channel filename, usually "_post-sss.txt".
raw_dir : str
Raw directory, usually "raw_fif".
otp_dir : str
Directory for OTP-processed files, usually "otp_fif".
keep_orig : bool
Keep original files after anonymization.
raw_fif_tag : str
File tag for raw data, usually "_raw.fif".
otp_fif_tag : str
File tag for OTP-processed files, usually "_raw_otp.fif".
sss_fif_tag : str
File tag for SSS-processed files, usually "_raw_sss.fif".
sss_dir : str
Expand Down
13 changes: 11 additions & 2 deletions mnefun/_mnefun.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from ._status import print_proc_status
from ._paths import _get_config_file
from ._utils import timestring
from ._otp import run_otp


# Class adapted from:
Expand Down Expand Up @@ -156,6 +157,7 @@ def __init__(self, tmin=None, tmax=None, t_adjust=0, bmin=-0.2, bmax=0.0,
self.trans_dir = 'trans'
self.bad_dir = 'bads'
self.raw_dir = 'raw_fif'
self.otp_dir = 'otp_fif'
self.sss_dir = 'sss_fif'
self.pca_dir = 'sss_pca_fif'

Expand All @@ -167,6 +169,7 @@ def __init__(self, tmin=None, tmax=None, t_adjust=0, bmin=-0.2, bmax=0.0,
self.inv_erm_tag = '-erm'
self.eq_tag = 'eq'
self.sss_fif_tag = '_raw_sss.fif'
self.otp_fif_tag = '_raw_otp.fif'
self.bad_tag = '_post-sss.txt'
self.keep_orig = False
# This is used by fix_eeg_channels to fix original files
Expand All @@ -178,6 +181,7 @@ def __init__(self, tmin=None, tmax=None, t_adjust=0, bmin=-0.2, bmax=0.0,
self.hp_type = 'maxfilter'
self.mf_args = ''
self.tsss_dur = 60.
self.otp_dur = None
self.trans_to = 'median' # where to transform head positions to
self.sss_format = 'float' # output type for MaxFilter
self.movecomp = 'inter'
Expand Down Expand Up @@ -366,8 +370,8 @@ def _set_static(p):


def do_processing(p, fetch_raw=False, do_score=False, push_raw=False,
do_sss=False, fetch_sss=False, do_ch_fix=False,
gen_ssp=False, apply_ssp=False,
do_otp=False, do_sss=False, fetch_sss=False,
do_ch_fix=False, gen_ssp=False, apply_ssp=False,
write_epochs=False, gen_covs=False, gen_fwd=False,
gen_inv=False, gen_report=False, print_status=True):
"""Do M/EEG data processing.
Expand All @@ -382,6 +386,8 @@ def do_processing(p, fetch_raw=False, do_score=False, push_raw=False,
Do scoring.
push_raw : bool
Push raw recording files to SSS workstation.
do_otp: bool
Apply OTP locally.
do_sss : bool
Run SSS remotely on SSS workstation.
fetch_sss : bool
Expand Down Expand Up @@ -413,6 +419,7 @@ def do_processing(p, fetch_raw=False, do_score=False, push_raw=False,
bools = [fetch_raw,
do_score,
push_raw,
do_otp,
do_sss,
fetch_sss,
do_ch_fix,
Expand All @@ -428,6 +435,7 @@ def do_processing(p, fetch_raw=False, do_score=False, push_raw=False,
texts = ['Pulling raw files from acquisition machine',
'Scoring subjects',
'Pushing raw files to remote workstation',
'Running OTP',
'Running SSS using %s' % p.sss_type,
'Pulling SSS files from remote workstation',
'Fixing EEG order',
Expand All @@ -449,6 +457,7 @@ def score_fun(p, subjects, run_indices):
funcs = [fetch_raw_files,
score_fun,
push_raw_files,
run_otp,
run_sss,
fetch_sss_files,
fix_eeg_files,
Expand Down
46 changes: 46 additions & 0 deletions mnefun/_otp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import os
import os.path as op
import time
from ._paths import get_raw_fnames
from mne.preprocessing import oversampled_temporal_projection
from ._sss import _read_raw_prebad

def run_otp(p, subjects, run_indices):
""" Run Oversampled Temporal Projection (OTP) on raw data.
"""

assert isinstance(p.otp_dur, float) and p.tsss_dur > 0
duration = p.otp_dur
if p.otp_dur is not None:
assert p.otp_dur >= p.tsss_dur

for si, subj in enumerate(subjects):
if p.disp_files:
print(' Denoising subject %g/%g (%s).'
% (si + 1, len(subjects), subj))
# locate raw files with splits
otp_dir = op.join(p.work_dir, subj, p.otp_dir)
if not op.isdir(otp_dir):
os.mkdir(otp_dir)
raw_files = get_raw_fnames(p, subj, 'raw', erm=False,
run_indices=run_indices[si])
raw_files_out = get_raw_fnames(p, subj, 'otp', erm=False,
run_indices=run_indices[si])
erm_files = get_raw_fnames(p, subj, 'raw', 'only')
erm_files_out = get_raw_fnames(p, subj, 'otp', 'only')

# process raw files
assert len(raw_files) > 0
for ii, (r, o) in enumerate(zip(raw_files + erm_files,
raw_files_out + erm_files_out)):
if not op.isfile(r):
raise NameError('File not found (' + r + ')')
raw = _read_raw_prebad(p, subj, r, disp=True).load_data()

# apply maxwell filter
t0 = time.time()
print(' Running OTP ...', end='')
raw_otp = oversampled_temporal_projection(
raw, duration=duration)
print('%i sec' % (time.time() - t0,))
raw_otp.save(o, overwrite=True, buffer_size_sec=None)
7 changes: 5 additions & 2 deletions mnefun/_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def get_raw_fnames(p, subj, which='raw', erm=True, add_splits=False,
subj : str
Subject name.
which : str
Type of raw filenames. Must be 'sss', 'raw', or 'pca'.
Type of raw filenames. Must be 'sss', 'raw', 'pca' or 'otp'.
erm : bool | str
If True, include empty-room files (appended to end). If 'only', then
only return empty-room files.
Expand All @@ -98,7 +98,7 @@ def get_raw_fnames(p, subj, which='raw', erm=True, add_splits=False,
fnames : list
List of filenames.
"""
assert which in ('sss', 'raw', 'pca')
assert which in ('sss', 'raw', 'pca', 'otp')
if which == 'sss':
raw_dir = op.join(p.work_dir, subj, p.sss_dir)
tag = p.sss_fif_tag
Expand All @@ -108,6 +108,9 @@ def get_raw_fnames(p, subj, which='raw', erm=True, add_splits=False,
elif which == 'pca':
raw_dir = op.join(p.work_dir, subj, p.pca_dir)
tag = p.pca_extra + p.sss_fif_tag
elif which == 'otp':
raw_dir = op.join(p.work_dir, subj, p.otp_dir)
tag = p.otp_fif_tag

if run_indices is None:
run_indices = np.arange(len(p.run_names))
Expand Down
4 changes: 2 additions & 2 deletions mnefun/_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
_KEYS_TO_FLATTEN = {
'general', 'naming', 'fetch_raw', 'scoring', 'bads', 'raw', 'annotations',
'multithreading',
'preprocessing', 'head_position_estimation', 'sss', 'filtering', 'ssp',
'epochs', 'epoching',
'preprocessing', 'head_position_estimation', 'otp', 'sss', 'filtering',
'ssp', 'epochs', 'epoching',
'covariance', 'forward', 'inverse',
}

Expand Down
Loading