1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 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='read', 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'))
|