Compare commits

...

7 Commits

Author SHA1 Message Date
jaeilepp 952de45498 Fix to sklearn imports. (#3773)
* Fix to sklearn imports.

* Fixes.

* Format fix.

* setup.cfg

* Except.

* Fix to nibabel import.
2016-11-18 12:30:01 +01:00
jaeilepp 1eeddd3da3 n_splits for sklearn 0.18. 2016-11-17 09:37:28 +01:00
Alexandre Gramfort ee15c3d0a2 require tvtk 2016-11-10 21:05:48 +01:00
jaeilepp aece2b28af Added entry to whats_new. 2016-09-05 07:36:17 +02:00
Eric Larson e9cf773014 FIX: Fixes for TRIUX and MEG ordering 2016-05-13 10:25:01 -04:00
Eric Larson 8f7d9e5635 FIX: Fix circle 2016-05-12 09:29:44 -04:00
Eric Larson c57235e8a8 ENH: Automated build 2016-05-10 18:34:23 -04:00
21 changed files with 373 additions and 148 deletions
+12 -2
View File
@@ -34,6 +34,7 @@ dependencies:
- ls -al /home/ubuntu/miniconda;
- ls -al /home/ubuntu/miniconda/bin;
- echo $PATH;
- echo $CIRCLE_BRANCH
- which python;
- which pip;
- git clone https://github.com/sphinx-gallery/sphinx-gallery.git;
@@ -43,7 +44,7 @@ dependencies:
override:
- cd /home/ubuntu/mne-python && python setup.py develop;
- if [ "$CIRCLE_BRANCH" == "master" ]; then
- if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "maint/0.12" ]; then
mkdir -p ~/mne_data;
python -c "import mne; mne.datasets._download_all_example_data()";
fi
@@ -56,13 +57,15 @@ dependencies:
test:
override:
- if [ "$CIRCLE_BRANCH" == "master" ]; then
- if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "maint/0.12" ]; then
make test-doc;
else
cd doc && make html_dev-noplot;
fi
- if [ "$CIRCLE_BRANCH" == "master" ]; then cd doc && make html_dev; fi:
timeout: 1500
- if [ "$CIRCLE_BRANCH" == "maint/0.12" ]; then cd doc && make html_stable; fi:
timeout: 1500
general:
# branches:
@@ -81,3 +84,10 @@ deployment:
- cd ../mne-tools.github.io && git checkout master && git pull origin master
- cd doc/_build/html && cp -rf * ~/mne-tools.github.io/dev
- cd ../mne-tools.github.io && git add -A && git commit -m 'Automated update of dev docs.' && git push origin master
#branch: maint/0.12
#commands:
# - git config --global user.email "circle@mne.com"
# - git config --global user.name "Circle Ci"
# - cd ../mne-tools.github.io && git checkout master && git pull origin master
# - cd doc/_build/html_stable && cp -rf * ~/mne-tools.github.io/stable
# - cd ../mne-tools.github.io && git add -A && git commit -m 'Automated update of stable docs.' && git push origin master
+2
View File
@@ -173,6 +173,8 @@ API
- The ``events`` parameter of :func:`mne.epochs.EpochsArray` is set by default to chronological time-samples and event values to 1, by `Jean-Remi King`_
- Deprecated ``axis`` parameter from :func:`mne.viz.plot_topomap` (use ``axes`` instead) by `Jaakko Leppakangas`_
Authors
~~~~~~~
@@ -101,7 +101,7 @@ for width in (0.7, 3.0):
power = tfr_stockwell(epochs, fmin=fmin, fmax=fmax, width=width)
power.plot([0], baseline=(0., 0.1), mode='mean',
title='Sim: Using S transform, width '
'= {:0.1f}'.format(width), show=True)
'= {0:0.1f}'.format(width), show=True)
# #############################################################################
# Finally, compare to morlet wavelet
+4 -4
View File
@@ -220,7 +220,7 @@ class SetChannelsMixin(object):
n_zero = np.sum(np.sum(np.abs(pos), axis=1) == 0)
if n_zero > 1: # XXX some systems have origin (0, 0, 0)
raise ValueError('Could not extract channel positions for '
'{} channels'.format(n_zero))
'{0} channels'.format(n_zero))
return pos
def _set_channel_positions(self, pos, names):
@@ -771,7 +771,7 @@ def read_ch_connectivity(fname, picks=None):
break
else:
raise ValueError('I do not know about this neighbor '
'template: "{}"'.format(fname))
'template: "{0}"'.format(fname))
fname = op.join(templates_dir, fname)
@@ -783,8 +783,8 @@ def read_ch_connectivity(fname, picks=None):
if picks is not None:
if max(picks) >= len(ch_names):
raise ValueError('The picks must be compatible with '
'channels. Found a pick ({}) which exceeds '
'the channel range ({})'
'channels. Found a pick ({0}) which exceeds '
'the channel range ({1})'
.format(max(picks), len(ch_names)))
connectivity = _ch_neighbor_connectivity(ch_names, neighbors)
if picks is not None:
+3
View File
@@ -127,6 +127,9 @@ def read_head_pos(fname):
_check_fname(fname, must_exist=True, overwrite=True)
data = np.loadtxt(fname, skiprows=1) # first line is header, skip it
data.shape = (-1, 10) # ensure it's the right size even if empty
if np.isnan(data).any(): # make sure we didn't do something dumb
raise RuntimeError('positions could not be read properly from %s'
% fname)
return data
+2 -2
View File
@@ -167,7 +167,7 @@ def _data_path(path=None, force_update=False, update_path=True, download=True,
path = _get_path(path, key, name)
# To update the testing or misc dataset, push commits, then make a new
# release on GitHub. Then update the "releases" variable:
releases = dict(testing='0.19', misc='0.1')
releases = dict(testing='0.20', misc='0.1')
# And also update the "hashes['testing']" variable below.
# To update any other dataset, update the data archive itself (upload
@@ -211,7 +211,7 @@ def _data_path(path=None, force_update=False, update_path=True, download=True,
sample='1d5da3a809fded1ef5734444ab5bf857',
somato='f3e3a8441477bb5bacae1d0c6e0964fb',
spm='f61041e3f3f2ba0def8a2ca71592cc41',
testing='77b2a435d80adb23cbe7e19144e7bc47'
testing='625cb9c1c62de03bd2bc6a3ca9a6f2d8'
)
folder_origs = dict( # not listed means None
misc='mne-misc-data-%s' % releases['misc'],
+4 -3
View File
@@ -59,13 +59,14 @@ def test_generalization_across_time():
y_4classes = np.hstack((epochs.events[:7, 2], epochs.events[7:, 2] + 1))
if check_version('sklearn', '0.18'):
from sklearn.model_selection import (KFold, StratifiedKFold,
ShuffleSplit, LeaveOneLabelOut)
ShuffleSplit, LeaveOneGroupOut)
cv_shuffle = ShuffleSplit()
cv = LeaveOneLabelOut()
cv = LeaveOneGroupOut()
# XXX we cannot pass any other parameters than X and y to cv.split
# so we have to build it before hand
cv_lolo = [(train, test) for train, test in cv.split(
X=y_4classes, y=y_4classes, labels=y_4classes)]
X=y_4classes, y=y_4classes, groups=y_4classes)]
# With sklearn >= 0.17, `clf` can be identified as a regressor, and
# the scoring metrics can therefore be automatically assigned.
+1 -1
View File
@@ -1571,7 +1571,7 @@ def _set_cv(cv, clf=None, X=None, y=None):
from sklearn.model_selection import (check_cv, StratifiedKFold, KFold)
if isinstance(cv, (int, np.int)):
XFold = StratifiedKFold if is_classifier(clf) else KFold
cv = XFold(n_folds=cv)
cv = XFold(n_splits=cv)
cv = check_cv(cv=cv, y=y, classifier=is_classifier(clf))
else:
from sklearn.cross_validation import (check_cv, StratifiedKFold, KFold)
+1 -1
View File
@@ -272,7 +272,7 @@ def pick_types(info, meg=True, eeg=False, stim=False, eog=False, ecg=False,
ias, syst, seeg, dipole, gof, bio, ecog):
if not isinstance(param, bool):
w = ('Parameters for all channel types (with the exception '
'of "meg" and "ref_meg") must be of type bool, not {}.')
'of "meg" and "ref_meg") must be of type bool, not {0}.')
raise ValueError(w.format(type(param)))
for k in range(nchan):
+84
View File
@@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
# Authors: Eric Larson <larson.eric.d@gmail.com>
# License: BSD (3-clause)
import numpy as np
from ..utils import check_fname, _check_fname
def read_fine_calibration(fname):
"""Read fine calibration information from a .dat file
The fine calibration typically includes improved sensor locations,
calibration coefficients, and gradiometer imbalance information.
Parameters
----------
fname : str
The filename.
Returns
-------
calibration : dict
Fine calibration information.
"""
# Read new sensor locations
_check_fname(fname, overwrite=True, must_exist=True)
check_fname(fname, 'cal', ('.dat',))
ch_names = list()
locs = list()
imb_cals = list()
with open(fname, 'r') as fid:
for line in fid:
if line[0] in '#\n':
continue
vals = line.strip().split()
if len(vals) not in [14, 16]:
raise RuntimeError('Error parsing fine calibration file, '
'should have 14 or 16 entries per line '
'but found %s on line:\n%s'
% (len(vals), line))
# `vals` contains channel number
ch_name = vals[0]
if len(ch_name) in (3, 4): # heuristic for Neuromag fix
try:
ch_name = int(ch_name)
except ValueError: # something other than e.g. 113 or 2642
pass
else:
ch_name = 'MEG' + '%04d' % ch_name
ch_names.append(ch_name)
# (x, y, z), x-norm 3-vec, y-norm 3-vec, z-norm 3-vec
locs.append(np.array([float(x) for x in vals[1:13]]))
# and 1 or 3 imbalance terms
imb_cals.append([float(x) for x in vals[13:]])
locs = np.array(locs)
return dict(ch_names=ch_names, locs=locs, imb_cals=imb_cals)
def write_fine_calibration(fname, calibration):
"""Write fine calibration information to a .dat file
Parameters
----------
fname : str
The filename to write out.
calibration : dict
Fine calibration information.
"""
_check_fname(fname, overwrite=True)
check_fname(fname, 'cal', ('.dat',))
with open(fname, 'wb') as cal_file:
for ci, chan in enumerate(calibration['ch_names']):
# Write string containing 1) channel, 2) loc info, 3) calib info
# with field widths (e.g., %.6f) chosen to match how Elekta writes
# them out
cal_line = np.concatenate([calibration['locs'][ci],
calibration['imb_cals'][ci]]).round(6)
cal_str = str(chan) + ' ' + ' '.join(map(lambda x: "%.6f" % x,
cal_line))
cal_file.write((cal_str + '\n').encode('ASCII'))
+132 -108
View File
@@ -25,7 +25,7 @@ from ..io.write import _generate_meas_id, _date_now
from ..io import _loc_to_coil_trans, _BaseRaw
from ..io.pick import pick_types, pick_info, pick_channels
from ..utils import verbose, logger, _clean_names, warn, _time_mask
from ..fixes import _get_args, partial
from ..fixes import _get_args, partial, in1d
from ..externals.six import string_types
from ..channels.channels import _get_T1T2_mag_inds
@@ -247,11 +247,12 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
recon_trans = _check_destination(destination, raw.info, head_frame)
if st_duration is not None:
st_duration = float(st_duration)
if not 0. < st_duration <= raw.times[-1]:
if not 0. < st_duration <= raw.times[-1] + 1. / raw.info['sfreq']:
raise ValueError('st_duration (%0.1fs) must be between 0 and the '
'duration of the data (%0.1fs).'
% (st_duration, raw.times[-1]))
st_correlation = float(st_correlation)
st_duration = int(round(st_duration * raw.info['sfreq']))
if not 0. < st_correlation <= 1:
raise ValueError('st_correlation must be between 0. and 1.')
if not isinstance(bad_condition, string_types) or \
@@ -279,7 +280,7 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
raw, add_channels=add_channels)
del raw
_remove_meg_projs(raw_sss) # remove MEG projectors, they won't apply now
info, times = raw_sss.info, raw_sss.times
info = raw_sss.info
meg_picks, mag_picks, grad_picks, good_picks, coil_scale, mag_or_fine = \
_get_mf_picks(info, int_order, ext_order, ignore_ref, mag_scale=100.)
@@ -289,11 +290,11 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
sss_cal = dict()
if calibration is not None:
calibration, sss_cal = _update_sensor_geometry(info, calibration,
head_frame, ignore_ref)
ignore_ref)
mag_or_fine.fill(True) # all channels now have some mag-type data
# Determine/check the origin of the expansion
origin = _check_origin(origin, raw_sss.info, coord_frame, disp=True)
origin = _check_origin(origin, info, coord_frame, disp=True)
origin.setflags(write=False)
n_in, n_out = _get_n_moments([int_order, ext_order])
@@ -312,7 +313,9 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
if len(missing) > 0:
warn('Not all cross-talk channels in raw:\n%s' % missing)
ctc_picks = pick_channels(ctc_chs,
[info['ch_names'][c] for c in good_picks])
[info['ch_names'][c]
for c in meg_picks[good_picks]])
assert len(ctc_picks) == len(good_picks) # otherwise we errored
ctc = sss_ctc['decoupler'][ctc_picks][:, ctc_picks]
# I have no idea why, but MF transposes this for storage..
sss_ctc['decoupler'] = sss_ctc['decoupler'].T.tocsc()
@@ -322,8 +325,7 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
#
# Translate to destination frame (always use non-fine-cal bases)
#
exp = dict(origin=origin, int_order=int_order, ext_order=0,
head_frame=head_frame)
exp = dict(origin=origin, int_order=int_order, ext_order=0)
all_coils = _prep_mf_coils(info, ignore_ref)
S_recon = _trans_sss_basis(exp, all_coils, recon_trans, coil_scale)
exp['ext_order'] = ext_order
@@ -341,29 +343,33 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
# Reconstruct raw file object with spatiotemporal processed data
max_st = dict()
if st_duration is not None:
max_st.update(job=10, subspcorr=st_correlation, buflen=st_duration)
max_st.update(job=10, subspcorr=st_correlation,
buflen=st_duration / info['sfreq'])
logger.info(' Processing data using tSSS with st_duration=%s'
% st_duration)
% max_st['buflen'])
st_when = 'before' if st_fixed else 'after' # relative to movecomp
else:
st_duration = min(raw_sss.times[-1], 10.) # chunk size
# st_duration from here on will act like the chunk size
st_duration = max(int(round(10. * info['sfreq'])), 1)
st_correlation = None
st_when = 'never'
st_duration = min(len(raw_sss.times), st_duration)
del st_fixed
# Generate time points to break up data into windows
chunk_times = np.arange(times[0], times[-1], st_duration)
read_lims = raw_sss.time_as_index(chunk_times)
len_last_buf = raw_sss.times[-1] - raw_sss.times[read_lims[-1]]
if len_last_buf == st_duration:
# Generate time points to break up data into equal-length windows
read_lims = np.arange(0, len(raw_sss.times) + 1, st_duration)
if len(read_lims) == 1:
read_lims = np.concatenate([read_lims, [len(raw_sss.times)]])
else:
# len_last_buf < st_dur so fold it into the previous buffer
if read_lims[-1] != len(raw_sss.times):
read_lims[-1] = len(raw_sss.times)
if st_correlation is not None:
# len_last_buf < st_dur so fold it into the previous buffer
if st_correlation is not None and len(read_lims) > 2:
logger.info(' Spatiotemporal window did not fit evenly into '
'raw object. The final %0.2f seconds were lumped '
'onto the previous window.' % len_last_buf)
'onto the previous window.'
% ((read_lims[-1] - read_lims[-2]) / info['sfreq'],))
assert len(read_lims) >= 2
assert read_lims[0] == 0 and read_lims[-1] == len(raw_sss.times)
#
# Do the heavy lifting
@@ -373,7 +379,7 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
# (and transform pos[1] to times)
head_pos[1] = raw_sss.time_as_index(head_pos[1], use_rounding=True)
# Compute the first bit of pos_data for cHPI reporting
if raw_sss.info['dev_head_t'] is not None and head_pos[0] is not None:
if info['dev_head_t'] is not None and head_pos[0] is not None:
this_pos_quat = np.concatenate([
rot_to_quat(info['dev_head_t']['trans'][:3, :3]),
info['dev_head_t']['trans'][:3, 3],
@@ -387,17 +393,21 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
grad_picks=grad_picks, mag_picks=mag_picks, good_picks=good_picks,
mag_or_fine=mag_or_fine, bad_condition=bad_condition)
S_decomp, pS_decomp, reg_moments, n_use_in = _get_this_decomp_trans(
info['dev_head_t'])
info['dev_head_t'], t=0.)
reg_moments_0 = reg_moments.copy()
# Loop through buffer windows of data
n_sig = int(np.floor(np.log10(max(len(read_lims), 0)))) + 1
pl = 's' if len(read_lims) != 2 else ''
logger.info(' Processing %s data chunk%s of (at least) %0.1f sec'
% (len(read_lims) - 1, pl, st_duration))
for start, stop in zip(read_lims[:-1], read_lims[1:]):
t_str = '% 8.2f - % 8.2f sec' % tuple(raw_sss.times[[start, stop - 1]])
% (len(read_lims) - 1, pl, st_duration / info['sfreq']))
for ii, (start, stop) in enumerate(zip(read_lims[:-1], read_lims[1:])):
rel_times = raw_sss.times[start:stop]
t_str = '%8.3f - %8.3f sec' % tuple(rel_times[[0, -1]])
t_str += ('(#%d/%d)'
% (ii + 1, len(read_lims) - 1)).rjust(2 * n_sig + 5)
# Get original data
orig_data = raw_sss._data[good_picks, start:stop]
orig_data = raw_sss._data[meg_picks[good_picks], start:stop]
# This could just be np.empty if not st_only, but shouldn't be slow
# this way so might as well just always take the original data
out_meg_data = raw_sss._data[meg_picks, start:stop]
@@ -422,7 +432,7 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
if avg_trans is not None:
# if doing movecomp
S_decomp_st, pS_decomp_st, _, n_use_in_st = \
_get_this_decomp_trans(avg_trans, verbose=False)
_get_this_decomp_trans(avg_trans, t=rel_times[0])
else:
S_decomp_st, pS_decomp_st = S_decomp, pS_decomp
n_use_in_st = n_use_in
@@ -446,7 +456,7 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
# previous interval)
if trans is not None:
S_decomp, pS_decomp, reg_moments, n_use_in = \
_get_this_decomp_trans(trans, verbose=False)
_get_this_decomp_trans(trans, t=rel_times[rel_start])
# Determine multipole moments for this interval
mm_in = np.dot(pS_decomp[:n_use_in],
@@ -477,7 +487,7 @@ def maxwell_filter(raw, origin='auto', int_order=8, ext_order=3,
if st_when == 'after':
_do_tSSS(out_meg_data, orig_in_data, resid, st_correlation,
n_positions, t_str)
else:
elif st_when == 'never' and head_pos[0] is not None:
pl = 's' if n_positions > 1 else ''
logger.info(' Used % 2d head position%s for %s'
% (n_positions, pl, t_str))
@@ -620,10 +630,10 @@ def _do_tSSS(clean_data, orig_in_data, resid, st_correlation,
np.asarray_chkfinite(resid)
t_proj = _overlap_projector(orig_in_data, resid, st_correlation)
# Apply projector according to Eq. 12 in [2]_
msg = (' Projecting % 2d intersecting tSSS components '
msg = (' Projecting %2d intersecting tSSS components '
'for %s' % (t_proj.shape[1], t_str))
if n_positions > 1:
msg += ' (across % 2d positions)' % n_positions
msg += ' (across %2d positions)' % n_positions
logger.info(msg)
clean_data -= np.dot(np.dot(clean_data, t_proj), t_proj.T)
@@ -701,33 +711,23 @@ def _check_pos(pos, head_frame, raw, st_fixed, sfreq):
return pos
@verbose
def _get_decomp(trans, all_coils, cal, regularize, exp, ignore_ref,
coil_scale, grad_picks, mag_picks, good_picks, mag_or_fine,
bad_condition, verbose=None):
"""Helper to get a decomposition matrix"""
bad_condition, t):
"""Helper to get a decomposition matrix and pseudoinverse matrices"""
#
# Fine calibration processing (point-like magnetometers and calib. coeffs)
#
S_decomp = _trans_sss_basis(exp, all_coils, trans, coil_scale)
if cal is not None:
# Compute point-like mags to incorporate gradiometer imbalance
cal['grad_cals'] = _sss_basis_point(exp, trans, cal, ignore_ref)
# Add point like magnetometer data to bases.
S_decomp[grad_picks, :] += cal['grad_cals']
# Scale magnetometers by calibration coefficient
S_decomp[mag_picks, :] /= cal['mag_cals']
# We need to be careful about KIT gradiometers
S_decomp = S_decomp[good_picks]
S_decomp = _get_s_decomp(exp, all_coils, trans, coil_scale, cal,
ignore_ref, grad_picks, mag_picks, good_picks)
#
# Regularization
#
reg_moments, n_use_in = _regularize(regularize, exp, S_decomp, mag_or_fine)
S_decomp = S_decomp.take(reg_moments, axis=1)
S_decomp, pS_decomp, sing, reg_moments, n_use_in = _regularize(
regularize, exp, S_decomp, mag_or_fine, t=t)
# Pseudo-inverse of total multipolar moment basis set (Part of Eq. 37)
pS_decomp, sing = _col_norm_pinv(S_decomp.copy())
cond = sing[0] / sing[-1]
logger.debug(' Decomposition matrix condition: %0.1f' % cond)
if bad_condition != 'ignore' and cond >= 1000.:
@@ -743,13 +743,31 @@ def _get_decomp(trans, all_coils, cal, regularize, exp, ignore_ref,
return S_decomp, pS_decomp, reg_moments, n_use_in
def _regularize(regularize, exp, S_decomp, mag_or_fine):
def _get_s_decomp(exp, all_coils, trans, coil_scale, cal, ignore_ref,
grad_picks, mag_picks, good_picks):
"""Helper to get S_decomp"""
S_decomp = _trans_sss_basis(exp, all_coils, trans, coil_scale)
if cal is not None:
# Compute point-like mags to incorporate gradiometer imbalance
grad_cals = _sss_basis_point(exp, trans, cal, ignore_ref)
# Add point like magnetometer data to bases.
S_decomp[grad_picks, :] += grad_cals
# Scale magnetometers by calibration coefficient
S_decomp[mag_picks, :] /= cal['mag_cals']
# We need to be careful about KIT gradiometers
S_decomp = S_decomp[good_picks]
return S_decomp
@verbose
def _regularize(regularize, exp, S_decomp, mag_or_fine, t, verbose=None):
"""Regularize a decomposition matrix"""
# ALWAYS regularize the out components according to norm, since
# gradiometer-only setups (e.g., KIT) can have zero first-order
# components
int_order, ext_order = exp['int_order'], exp['ext_order']
n_in, n_out = _get_n_moments([int_order, ext_order])
t_str = '%8.3f' % t
if regularize is not None: # regularize='in'
logger.info(' Computing regularization')
in_removes, out_removes = _regularize_in(
@@ -762,11 +780,15 @@ def _regularize(regularize, exp, S_decomp, mag_or_fine):
out_removes)
n_use_in = len(reg_in_moments)
n_use_out = len(reg_out_moments)
if regularize is not None or n_use_out != n_out:
logger.info(' Using %s/%s inside and %s/%s outside harmonic '
'components' % (n_use_in, n_in, n_use_out, n_out))
reg_moments = np.concatenate((reg_in_moments, reg_out_moments))
return reg_moments, n_use_in
S_decomp = S_decomp.take(reg_moments, axis=1)
pS_decomp, sing = _col_norm_pinv(S_decomp.copy())
if regularize is not None or n_use_out != n_out:
logger.info(' Using %s/%s harmonic components for %s '
'(%s/%s in, %s/%s out)'
% (n_use_in + n_use_out, n_in + n_out, t_str,
n_use_in, n_in, n_use_out, n_out))
return S_decomp, pS_decomp, sing, reg_moments, n_use_in
def _get_mf_picks(info, int_order, ext_order, ignore_ref=False,
@@ -1618,45 +1640,63 @@ def _read_fine_cal(fine_cal):
return cal_chs, cal_ch_numbers
def _update_sensor_geometry(info, fine_cal, head_frame, ignore_ref):
def _update_sensor_geometry(info, fine_cal, ignore_ref):
"""Helper to replace sensor geometry information and reorder cal_chs"""
from ._fine_cal import read_fine_calibration
logger.info(' Using fine calibration %s' % op.basename(fine_cal))
cal_chs, cal_ch_numbers = _read_fine_cal(fine_cal)
fine_cal = read_fine_calibration(fine_cal) # filename -> dict
ch_names = _clean_names(info['ch_names'], remove_whitespace=True)
info_order = pick_channels(ch_names, fine_cal['ch_names'])
meg_picks = pick_types(info, meg=True, exclude=[])
if len(set(info_order) - set(meg_picks)) != 0:
# this should never happen
raise RuntimeError('Found channels in cal file that are not marked '
'as MEG channels in the data file')
if len(info_order) != len(meg_picks):
raise RuntimeError(
'Not all MEG channels found in fine calibration file, missing:\n%s'
% sorted(list(set(ch_names[pick] for pick in meg_picks) -
set(fine_cal['ch_names']))))
rev_order = np.argsort(info_order)
rev_grad = rev_order[in1d(meg_picks,
pick_types(info, meg='grad', exclude=()))]
rev_mag = rev_order[in1d(meg_picks,
pick_types(info, meg='mag', exclude=()))]
# Check that we ended up with correct channels
meg_info = pick_info(info, pick_types(info, meg=True, exclude=[]))
clean_meg_names = _clean_names(meg_info['ch_names'],
remove_whitespace=True)
cal_names = [c['ch_name'] for c in cal_chs]
order = pick_channels(cal_names, clean_meg_names)
if meg_info['nchan'] != len(order):
raise RuntimeError('Not all MEG channels found in fine calibration '
'file, missing:\n%s'
% sorted(list(set(clean_meg_names) -
set(cal_names))))
# ensure they're ordered like our data
cal_chs = [cal_chs[ii] for ii in order]
# Determine gradiometer imbalances and magnetometer calibrations
grad_imbalances = np.array([fine_cal['imb_cals'][ri] for ri in rev_grad]).T
if grad_imbalances.shape[0] not in [1, 3]:
raise ValueError('Must have 1 (x) or 3 (x, y, z) point-like ' +
'magnetometers. Currently have %i' %
grad_imbalances.shape[0])
mag_cals = np.array([fine_cal['imb_cals'][ri] for ri in rev_mag])
del rev_order, rev_grad, rev_mag
# Now let's actually construct our point-like adjustment coils for grads
grad_coilsets = _get_grad_point_coilsets(
info, n_types=len(grad_imbalances), ignore_ref=ignore_ref)
calibration = dict(grad_imbalances=grad_imbalances,
grad_coilsets=grad_coilsets, mag_cals=mag_cals)
# Replace sensor locations (and track differences) for fine calibration
ang_shift = np.zeros((len(cal_chs), 3))
ang_shift = np.zeros((len(fine_cal['ch_names']), 3))
used = np.zeros(len(info['chs']), bool)
cal_corrs = list()
coil_types = list()
grad_picks = pick_types(meg_info, meg='grad')
cal_chans = list()
grad_picks = pick_types(info, meg='grad', exclude=())
adjust_logged = False
clean_info_names = _clean_names(info['ch_names'], remove_whitespace=True)
for ci, cal_ch in enumerate(cal_chs):
idx = clean_info_names.index(cal_ch['ch_name'])
assert not used[idx]
used[idx] = True
info_ch = info['chs'][idx]
coil_types.append(info_ch['coil_type'])
for ci, info_idx in enumerate(info_order):
assert ch_names[info_idx] == fine_cal['ch_names'][ci]
assert not used[info_idx]
used[info_idx] = True
info_ch = info['chs'][info_idx]
ch_num = int(fine_cal['ch_names'][ci].lstrip('MEG').lstrip('0'))
cal_chans.append([ch_num, info_ch['coil_type']])
# Some .dat files might only rotate EZ, so we must check first that
# EX and EY are orthogonal to EZ. If not, we find the rotation between
# the original and fine-cal ez, and rotate EX and EY accordingly:
ch_coil_rot = _loc_to_coil_trans(info_ch['loc'])[:3, :3]
cal_loc = cal_ch['loc'].copy()
cal_loc = fine_cal['locs'][ci].copy()
cal_coil_rot = _loc_to_coil_trans(cal_loc)[:3, :3]
if np.max([np.abs(np.dot(cal_coil_rot[:, ii], cal_coil_rot[:, 2]))
for ii in range(2)]) > 1e-6: # X or Y not orthogonal
@@ -1669,51 +1709,34 @@ def _update_sensor_geometry(info, fine_cal, head_frame, ignore_ref):
cal_loc[3:] = np.dot(this_trans, ch_coil_rot).T.ravel()
# calculate shift angle
v1 = _loc_to_coil_trans(cal_ch['loc'])[:3, :3]
v1 = _loc_to_coil_trans(cal_loc)[:3, :3]
_normalize_vectors(v1)
v2 = _loc_to_coil_trans(info_ch['loc'])[:3, :3]
_normalize_vectors(v2)
ang_shift[ci] = np.sum(v1 * v2, axis=0)
if idx in grad_picks:
extra = [1., cal_ch['calib_coeff'][0]]
if info_idx in grad_picks:
extra = [1., fine_cal['imb_cals'][ci][0]]
else:
extra = [cal_ch['calib_coeff'][0], 0.]
extra = [fine_cal['imb_cals'][ci][0], 0.]
cal_corrs.append(np.concatenate([extra, cal_loc]))
# Adjust channel normal orientations with those from fine calibration
# Channel positions are not changed
info_ch['loc'][3:] = cal_loc[3:]
assert (info_ch['coord_frame'] == cal_ch['coord_frame'] ==
FIFF.FIFFV_COORD_DEVICE)
cal_chans = [[sc, ct] for sc, ct in zip(cal_ch_numbers, coil_types)]
assert (info_ch['coord_frame'] == FIFF.FIFFV_COORD_DEVICE)
assert used[meg_picks].all()
assert not used[np.setdiff1d(np.arange(len(used)), meg_picks)].any()
# This gets written to the Info struct
sss_cal = dict(cal_corrs=np.array(cal_corrs),
cal_chans=np.array(cal_chans))
# Log quantification of sensor changes
# Deal with numerical precision giving absolute vals slightly more than 1.
np.clip(ang_shift, -1., 1., ang_shift)
np.rad2deg(np.arccos(ang_shift), ang_shift) # Convert to degrees
# Log quantification of sensor changes
logger.info(' Adjusted coil positions by (μ ± σ): '
'%0.1f° ± %0.1f° (max: %0.1f°)' %
(np.mean(ang_shift), np.std(ang_shift),
np.max(np.abs(ang_shift))))
# Determine gradiometer imbalances and magnetometer calibrations
grad_picks = pick_types(info, meg='grad', exclude=[])
mag_picks = pick_types(info, meg='mag', exclude=[])
grad_imbalances = np.array([cal_chs[ii]['calib_coeff']
for ii in grad_picks]).T
if grad_imbalances.shape[0] not in [1, 3]:
raise ValueError('Must have 1 (x) or 3 (x, y, z) point-like ' +
'magnetometers. Currently have %i' %
grad_imbalances.shape[0])
mag_cals = np.array([cal_chs[ii]['calib_coeff'] for ii in mag_picks])
# Now let's actually construct our point-like adjustment coils for grads
grad_coilsets = _get_grad_point_coilsets(
info, n_types=len(grad_imbalances), ignore_ref=ignore_ref)
calibration = dict(grad_imbalances=grad_imbalances,
grad_coilsets=grad_coilsets, mag_cals=mag_cals)
return calibration, sss_cal
@@ -1845,10 +1868,10 @@ def _regularize_in(int_order, ext_order, S_decomp, mag_or_fine):
'Removing in component %s: l=%s, m=%+0.0f'
% (tuple(eigs[ii]) + (eigs[ii, 0] / eigs[ii, 1],
ri, degrees[ri], orders[ri])))
logger.info(' Resulting information: %0.1f bits/sample '
'(%0.1f%% of peak %0.1f)'
% (I_tots[lim_idx], 100 * I_tots[lim_idx] / max_info,
max_info))
logger.debug(' Resulting information: %0.1f bits/sample '
'(%0.1f%% of peak %0.1f)'
% (I_tots[lim_idx], 100 * I_tots[lim_idx] / max_info,
max_info))
return in_removes, out_removes
@@ -1901,6 +1924,7 @@ def _trans_sss_basis(exp, all_coils, trans=None, coil_scale=100.):
if trans is not None:
if not isinstance(trans, Transform):
trans = Transform('meg', 'head', trans)
assert not np.isnan(trans['trans']).any()
all_coils = (apply_trans(trans, all_coils[0]),
apply_trans(trans, all_coils[1], move=False),
) + all_coils[2:]
+40
View File
@@ -0,0 +1,40 @@
# Author: Mark Wronkiewicz <wronk@uw.edu>
#
# License: BSD (3-clause)
import os.path as op
import warnings
from mne.datasets import testing
from mne.preprocessing._fine_cal import (read_fine_calibration,
write_fine_calibration)
from mne.utils import _TempDir, object_hash, run_tests_if_main
from nose.tools import assert_equal
warnings.simplefilter('always') # Always throw warnings
# Define fine calibration filepaths
data_path = testing.data_path(download=False)
fine_cal_fname = op.join(data_path, 'SSS', 'sss_cal_3053.dat')
fine_cal_fname_3d = op.join(data_path, 'SSS', 'sss_cal_3053_3d.dat')
@testing.requires_testing_data
def test_read_write_fine_cal():
"""Test round trip reading/writing of fine calibration .dat file"""
temp_dir = _TempDir()
temp_fname = op.join(temp_dir, 'fine_cal_temp.dat')
for fname in [fine_cal_fname, fine_cal_fname_3d]:
# Load fine calibration file
fine_cal_dict = read_fine_calibration(fname)
# Save temp version of fine calibration file
write_fine_calibration(temp_fname, fine_cal_dict)
fine_cal_dict_reload = read_fine_calibration(temp_fname)
# Load temp version of fine calibration file and compare hashes
assert_equal(object_hash(fine_cal_dict),
object_hash(fine_cal_dict_reload))
run_tests_if_main()
+75 -14
View File
@@ -76,6 +76,20 @@ ctc_mgh_fname = op.join(sss_path, 'ct_sparse_mgh.fif')
sample_fname = op.join(data_path, 'MEG', 'sample',
'sample_audvis_trunc_raw.fif')
triux_path = op.join(data_path, 'SSS', 'TRIUX')
tri_fname = op.join(triux_path, 'triux_bmlhus_erm_raw.fif')
tri_sss_fname = op.join(triux_path, 'triux_bmlhus_erm_raw_sss.fif')
tri_sss_reg_fname = op.join(triux_path, 'triux_bmlhus_erm_regIn_raw_sss.fif')
tri_sss_st4_fname = op.join(triux_path, 'triux_bmlhus_erm_st4_raw_sss.fif')
tri_sss_ctc_fname = op.join(triux_path, 'triux_bmlhus_erm_ctc_raw_sss.fif')
tri_sss_cal_fname = op.join(triux_path, 'triux_bmlhus_erm_cal_raw_sss.fif')
tri_sss_ctc_cal_fname = op.join(
triux_path, 'triux_bmlhus_erm_ctc_cal_raw_sss.fif')
tri_sss_ctc_cal_reg_in_fname = op.join(
triux_path, 'triux_bmlhus_erm_ctc_cal_regIn_raw_sss.fif')
tri_ctc_fname = op.join(triux_path, 'ct_sparse_BMLHUS.fif')
tri_cal_fname = op.join(triux_path, 'sss_cal_BMLHUS.dat')
io_dir = op.join(op.dirname(__file__), '..', '..', 'io')
fname_ctf_raw = op.join(io_dir, 'tests', 'data', 'test_ctf_comp_raw.fif')
@@ -629,19 +643,24 @@ def test_regularization():
assert_meg_snr(raw_sss, sss_reg_in, min_tols[ii], med_tols[ii], msg=rf)
# check components match
py_info = raw_sss.info['proc_history'][0]['max_info']['sss_info']
assert_true(py_info is not None)
assert_true(len(py_info) > 0)
mf_info = sss_reg_in.info['proc_history'][0]['max_info']['sss_info']
n_in = None
for inf in py_info, mf_info:
if n_in is None:
n_in = _get_n_moments(inf['in_order'])
else:
assert_equal(n_in, _get_n_moments(inf['in_order']))
assert_equal(inf['components'][:n_in].sum(), inf['nfree'])
assert_allclose(py_info['nfree'], mf_info['nfree'],
atol=comp_tols[ii], err_msg=rf)
_check_reg_match(raw_sss, sss_reg_in, comp_tols[ii])
def _check_reg_match(sss_py, sss_mf, comp_tol):
"""Helper to check regularization"""
info_py = sss_py.info['proc_history'][0]['max_info']['sss_info']
assert_true(info_py is not None)
assert_true(len(info_py) > 0)
info_mf = sss_mf.info['proc_history'][0]['max_info']['sss_info']
n_in = None
for inf in (info_py, info_mf):
if n_in is None:
n_in = _get_n_moments(inf['in_order'])
else:
assert_equal(n_in, _get_n_moments(inf['in_order']))
assert_equal(inf['components'][:n_in].sum(), inf['nfree'])
assert_allclose(info_py['nfree'], info_mf['nfree'],
atol=comp_tol, err_msg=sss_py._filenames[0])
@testing.requires_testing_data
@@ -840,7 +859,7 @@ def test_all():
coord_frames = ('head', 'head', 'meg', 'head')
ctcs = (ctc_fname, ctc_fname, ctc_fname, ctc_mgh_fname)
mins = (3.5, 3.5, 1.2, 0.9)
meds = (10.9, 10.4, 3.2, 6.)
meds = (10.8, 10.4, 3.2, 6.)
st_durs = (1., 1., 1., None)
destinations = (None, sample_fname, None, None)
origins = (mf_head_origin,
@@ -857,4 +876,46 @@ def test_all():
sss_mf = Raw(sss_fnames[ii])
assert_meg_snr(sss_py, sss_mf, mins[ii], meds[ii], msg=rf)
@slow_test
@requires_svd_convergence
@testing.requires_testing_data
def test_triux():
"""Test TRIUX system support"""
raw = Raw(tri_fname).crop(0, 0.999)
raw.fix_mag_coil_types()
# standard
sss_py = maxwell_filter(raw, coord_frame='meg', regularize=None)
assert_meg_snr(sss_py, Raw(tri_sss_fname), 37, 700)
# cross-talk
sss_py = maxwell_filter(raw, coord_frame='meg', regularize=None,
cross_talk=tri_ctc_fname)
assert_meg_snr(sss_py, Raw(tri_sss_ctc_fname), 35, 700)
# fine cal
sss_py = maxwell_filter(raw, coord_frame='meg', regularize=None,
calibration=tri_cal_fname)
assert_meg_snr(sss_py, Raw(tri_sss_cal_fname), 31, 360)
# ctc+cal
sss_py = maxwell_filter(raw, coord_frame='meg', regularize=None,
calibration=tri_cal_fname,
cross_talk=tri_ctc_fname)
assert_meg_snr(sss_py, Raw(tri_sss_ctc_cal_fname), 31, 350)
# regularization
sss_py = maxwell_filter(raw, coord_frame='meg', regularize='in')
sss_mf = Raw(tri_sss_reg_fname)
assert_meg_snr(sss_py, sss_mf, 0.6, 9)
_check_reg_match(sss_py, sss_mf, 1)
# all three
sss_py = maxwell_filter(raw, coord_frame='meg', regularize='in',
calibration=tri_cal_fname,
cross_talk=tri_ctc_fname)
sss_mf = Raw(tri_sss_ctc_cal_reg_in_fname)
assert_meg_snr(sss_py, sss_mf, 0.6, 9)
_check_reg_match(sss_py, sss_mf, 1)
# tSSS
raw = Raw(tri_fname).fix_mag_coil_types()
sss_py = maxwell_filter(raw, coord_frame='meg', regularize=None,
st_duration=4., verbose=True)
assert_meg_snr(sss_py, Raw(tri_sss_st4_fname), 700., 1600)
run_tests_if_main()
+1 -1
View File
@@ -149,7 +149,7 @@ def test_volume_stc():
assert_array_almost_equal(img.get_affine(), t1_img.get_affine(),
decimal=5)
except ImportError:
except Exception:
print('Save as nifti test skipped, needs NiBabel')
+3 -1
View File
@@ -13,7 +13,8 @@ from mne import read_surface, write_surface, decimate_surface
from mne.surface import (read_morph_map, _compute_nearest,
fast_cross_3d, get_head_surf, read_curvature,
get_meg_helmet_surf)
from mne.utils import _TempDir, requires_mayavi, run_tests_if_main, slow_test
from mne.utils import (_TempDir, requires_mayavi, run_tests_if_main, slow_test,
requires_tvtk)
from mne.io import read_info
from mne.transforms import _get_trans
@@ -150,6 +151,7 @@ def test_read_curv():
assert_true(np.logical_or(bin_curv == 0, bin_curv == 1).all())
@requires_tvtk
@requires_mayavi
def test_decimate_surface():
"""Test triangular surface decimation
+2 -4
View File
@@ -774,10 +774,8 @@ class AverageTFR(ContainsMixin, UpdateChannelsMixin):
if 'grad' in self:
types.append('grad')
fig = figure_nobar()
fig.suptitle('{:.2f} s - {:.2f} s, {:.2f} Hz - {:.2f} Hz'.format(tmin,
tmax,
fmin,
fmax),
fig.suptitle('{0:.2f} s - {1:.2f} s, '
'{2:.2f} Hz - {3:.2f} Hz'.format(tmin, tmax, fmin, fmax),
y=0.04)
for idx, ch_type in enumerate(types):
ax = plt.subplot(1, len(types), idx + 1)
+1 -1
View File
@@ -682,7 +682,7 @@ def has_nibabel(vox2ras_tkr=False):
'header_class', 0),
'get_vox2ras_tkr', None) is not None)
return out
except ImportError:
except Exception:
return False
+1 -1
View File
@@ -29,4 +29,4 @@ doctest-fixtures = _fixture
[flake8]
exclude = __init__.py,*externals*,constants.py,fixes.py
ignore = E241
ignore = E241,E305
+1 -1
View File
@@ -75,7 +75,7 @@ diff = combine_evoked([evoked, pred_evoked], [1, -1])
plot_params['colorbar'] = True
diff.plot_topomap(time_format='Difference', axes=axes[2], **plot_params)
plt.suptitle('Comparison of measured and predicted fields '
'at {:.0f} ms'.format(best_time * 1000.), fontsize=16)
'at {0:.0f} ms'.format(best_time * 1000.), fontsize=16)
###############################################################################
# Estimate the time course of a single dipole with fixed position and
+1 -1
View File
@@ -34,7 +34,7 @@ print(type(c))
# If you come from a background of matlab, remember that indexing in python
# starts from zero:
a = [1, 2, 3, 4]
print('This is the zeroth value in the list: {}'.format(a[0]))
print('This is the zeroth value in the list: {0}'.format(a[0]))
###############################################################################
# No need to reinvent the wheel. Scipy and Numpy are battle field tested
@@ -70,8 +70,8 @@ print(type(connectivity)) # it's a sparse matrix!
plt.imshow(connectivity.toarray(), cmap='gray', origin='lower',
interpolation='nearest')
plt.xlabel('{} Magnetometers'.format(len(ch_names)))
plt.ylabel('{} Magnetometers'.format(len(ch_names)))
plt.xlabel('{0} Magnetometers'.format(len(ch_names)))
plt.ylabel('{0} Magnetometers'.format(len(ch_names)))
plt.title('Between-sensor adjacency')
###############################################################################