Back to the main page.

Bug 3369 - implement a elekta neuromag fif log file reader

Reported 2017-11-14 10:05:00 +0100
Modified 2019-08-10 12:40:23 +0200
Product: FieldTrip
Component: fileio
Version: unspecified
Hardware: PC
Operating System: Mac OS
Importance: P5 normal
Assigned to: Mikkel Vinding
Depends on:
See also:

Robert Oostenveld - 2017-11-14 10:05:43 +0100

the maxfilter(tm) software can produce an ascii log file that contains the head movements. It would be relevant to read and display all (temporal) parameters in that log file.

Robert Oostenveld - 2017-11-14 14:31:11 +0100

mac011> git commit -a [bug3369 fbd9347] ENH - implemented log file reader for Neuromag Maxfilter log files, see 4 files changed, 132 insertions(+) create mode 100644 fileio/private/read_neuromag_maxfilterlog.m

Robert Oostenveld - 2017-11-14 14:35:11 +0100

I have merged the first implementation of this. You can use it as cfg.dataset = 'some recording.fif.log' data = ft_preprocessing(cfg) but you might also want to look into fieldtrip/fileio/private/read_neuromag_maxfilterlog.m Note that the channel labels still need refinement. Also the offset of the recording is not consistent with the time indicated in seconds inside the log file. The first sample is now (by construct) at t=0.

Robert Oostenveld - 2017-11-14 14:35:53 +0100

@Mikkel, can you now have a look at it and perhaps come with suggestions for improvement?

Mikkel Vinding - 2017-11-14 18:38:47 +0100

(In reply to Robert Oostenveld from comment #3) I run an older version of Matlab (R2016a) which does not have the build-in function "contains" - replacing it with any(strfind( ... )) fixed this. I am not entirely sure what I get in the output from ft_preprocessing( ) when calling to a log file? The structure contains 50 channels named HPI or single letters, which are sampled every second.

Robert Oostenveld - 2017-11-15 09:21:15 +0100

(In reply to Mikkel Vinding from comment #4) Contains was introduced in 2016b. I have added a drop-in replacement for "contains" in fieldtrip/compat/matlablt2016b. It will be automatically added to the path. Regarding the output, that indeed still needs some work where you should help and where the documentation might be needed. Please have a look in the code. The single letters come from the last line (of the 4 lines), the hpiN_M channels contain the Mth value of the line for the Nth hpi coil. I suspect that the first 6 values are the (fixed) polhemus and the estimated position of each coil. For the 7th and 8th value: it mentions g and hence hpi1_7 should be renamed into something like gof1 (probably g is "goodness of fit") and the error ("err") could be err1 instead of hpi1_8. The last 4x3 block needs to be named differently as well. % Hpi fit OK, movements [mm/s] = 55.8 / 48.1 / 42.7 / 52.3 / % 79.5 0.0 0.0 / 79.2 -0.3 0.2 / g = 0.999 err = 0.5 mm / 0.998 -0.056 -0.011 % 0.0 79.5 0.0 / 0.1 80.0 -0.2 / g = 1.000 err = 0.5 mm / 0.057 0.989 0.137 % -79.5 0.0 0.0 / -78.8 -1.0 0.2 / g = 0.994 err = 1.2 mm / 0.003 -0.138 0.990 % 0.0 -79.5 0.0 / -0.6 -78.6 -0.2 / g = 0.999 err = 1.0 mm / -0.2 1.4 5.8 % #t = 170.510, #e = 0.08 cm, #g = 0.998, #v = 0.75 cm/s, #r = 0.61 rad/s, #d = 0.26 cm

Mikkel Vinding - 2017-11-17 15:47:26 +0100

We had it mostly figured out. I got this reply from Elektra: Line 1 (Hpi fit OK) tells the coil movement speeds from the previous fit point. Lines 2-5: first 3 numbers are the digitized x,y,z, and the next 3 numbers give the fitted locations after transforming to the head coordinate system. g is goodness of fit between measured and modeled HPI data. Err indicates the distance between fitted and digitized locations. The last part shows the transformation, first 3x3 rotation and then the translation from the device to the head coordinates. On line 6, #t is the time, #e and #g are the mean err and g-values, and #v and #r are the mean translation and rotation velocities. The last value #d indicates how much has the origin moved (drifted) from the initial locations. Maybe it would make sense to separate the translation matrix from the rest in the "trial" struct. Should we move it to another field in the output called "transform" or something similar?

Robert Oostenveld - 2017-11-22 11:25:04 +0100

(In reply to Mikkel Vinding from comment #6) I discussed this with Mikkel and learned quite a bit. Relevant documentation is and

Robert Oostenveld - 2017-11-22 11:35:58 +0100

Since the maxfilter "pos" file has 6 quaternion parameters, I added support for that as well. mac011> git commit -a [bug3369 82d835b] ENH - support unit quarternion with 6 parameters, see 1 file changed, 11 insertions(+), 3 deletions(-)

Robert Oostenveld - 2017-12-11 15:34:04 +0100

I think this is good enough for now, so let's close this issue. If there is need for further improvements, they can still be made.

Robert Oostenveld - 2019-08-10 12:34:13 +0200

This closes a whole series of bugs that have been resolved (either FIXED/WONTFIX/INVALID) for quite some time. If you disagree, please file a new issue on

Robert Oostenveld - 2019-08-10 12:40:23 +0200

This closes a whole series of bugs that have been resolved (either FIXED/WONTFIX/INVALID) for quite some time. If you disagree, please file a new issue on