Back to the main page.

Bug 1914 - implement support for the babySQUID MEG system in Boston

Status CLOSED FIXED
Reported 2012-12-28 12:38:00 +0100
Modified 2019-08-10 12:31:11 +0200
Product: FieldTrip
Component: fileio
Version: unspecified
Hardware: PC
Operating System: Mac OS
Importance: P3 normal
Assigned to: Chiran Doshi
URL:
Tags:
Depends on:
Blocks:
See also:

Robert Oostenveld - 2012-12-28 12:38:29 +0100

Chiran Doshi contacted me with the request to support the babySQUID MEG system. The file format is fif, so should be easy to work with. TODO: 1) get some test datasets 2) get some documentation on the geometry and triggering, preferably put it on http://fieldtrip.fcdonders.nl/getting_started/babysquid 3) write test script 4) define new senstype (see fileio/ft_senstype.m) 5) extend fileio/private/mne2grad.m


Chiran Doshi - 2012-12-28 17:12:45 +0100

(In reply to comment #0) Hi, I have sent a link to Robert with few fiff files and their corresponding *.eve files 1) Only MEG with no triggers. 2) Only MEG with triggers 3) MEG and EEG peripheral 4) MEG and EEG simultaneously In addition, I have sent BabySQUID.lout file containing coil geometries. Thanks, Chiran


Chiran Doshi - 2013-01-14 21:25:16 +0100

(In reply to comment #1) Hi Robert, Any updates on the progress with the incorporation? Thank you, Chiran


Johanna - 2013-01-17 16:15:46 +0100

Chiran has also contacted Sarang for requesting the babySQUID to be read into Nutmeg, to which Sarang responded that Nutmeg will let FT do the fileio and then convert to Nutmeg format from there. To move this bug along, to whom shall it be assigned?


Robert Oostenveld - 2013-01-17 16:55:44 +0100

good point, we should indeed plan some concrete actions as it should not be too much work.


Robert Oostenveld - 2013-01-17 16:56:29 +0100

I copied the test data to /home/common/matlab/fieldtrip/data/test/bug1914 it consists of -rw-r--r-- 1 roboos staff 3589 Dec 6 01:01 BabySQUID.lout -rw-r--r-- 1 roboos staff 38 Oct 17 12:03 conversion_testing_MEGEEG_raw.eve -rw-r--r-- 1 roboos staff 202442944 Oct 17 12:03 conversion_testing_MEGEEG_raw.fif -rw-r--r-- 1 roboos staff 1228 Oct 17 11:31 conversion_testing_MEGandperipheral_raw.eve -rw-r--r-- 1 roboos staff 40000232 Oct 17 11:31 conversion_testing_MEGandperipheral_raw.fif -rw-r--r-- 1 roboos staff 36277552 Oct 17 11:23 conversion_testing_OnlyMEG_no_triggers_raw.fif -rw-r--r-- 1 roboos staff 52453 Oct 17 11:28 conversion_testing_OnlyMEG_with_triggers_raw.eve -rw-r--r-- 1 roboos staff 194150720 Oct 17 11:28 conversion_testing_OnlyMEG_with_triggers_raw.fif


Robert Oostenveld - 2013-01-17 16:59:30 +0100

(In reply to comment #5) ouch, ugly layout of the directory list. I made a test script, sofar just using ft_read_header, data and event mac001> svn commit test_bug1914.m Adding test_bug1914.m Transmitting file data . Committed revision 7345. See http://code.google.com/p/fieldtrip/source/browse/trunk/test/test_bug1914.m or do an svn update to get a local copy.


Robert Oostenveld - 2013-01-17 17:01:59 +0100

(In reply to comment #6) I ran the test script and get (more or less) the following output for disp(filename) disp(hdr) disp(event) Note that the events are empty in all 4 cases. %% conversion_testing_MEGEEG_raw.fif label: {83x1 cell} nChans: 83 Fs: 1024 grad: [1x1 struct] elec: [1x1 struct] nSamples: 609592 nSamplesPre: 0 nTrials: 1 orig: [1x1 struct] chantype: {83x1 cell} chanunit: {83x1 cell} %% conversion_testing_MEGandperipheral_raw.fif label: {79x1 cell} nChans: 79 Fs: 1024 grad: [1x1 struct] nSamples: 126402 nSamplesPre: 0 nTrials: 1 orig: [1x1 struct] chantype: {79x1 cell} chanunit: {79x1 cell} %% conversion_testing_OnlyMEG_no_triggers_raw.fif label: {74x1 cell} nChans: 74 Fs: 1024 grad: [1x1 struct] nSamples: 122368 nSamplesPre: 0 nTrials: 1 orig: [1x1 struct] chantype: {74x1 cell} chanunit: {74x1 cell} %% conversion_testing_OnlyMEG_with_triggers_raw.fif label: {76x1 cell} nChans: 76 Fs: 1024 grad: [1x1 struct] nSamples: 638464 nSamplesPre: 0 nTrials: 1 orig: [1x1 struct] chantype: {76x1 cell} chanunit: {76x1 cell}


Chiran Doshi - 2013-01-17 17:10:23 +0100

(In reply to comment #7) Hi Robert, The events cells are empty on purpose. When I convert BabySQUID data to fiff file, I generate a *.eve file. Does FieldTrip support *.eve file? Thanks, Chiran


Robert Oostenveld - 2013-01-17 17:11:35 +0100

furthermore >> hdr.grad ans = chanori: [0x3 double] chanpos: [0x3 double] chantype: {0x1 cell} chanunit: {0x1 cell} coilori: [0x3 double] coilpos: [0x3 double] label: {0x1 cell} tra: [] unit: 'cm' which suggests that the channel details are not defined in the fif file. However, inside fieldtrip/fileio/private/mne2grad (which deals with the gradiometer definition), I see around the following section at line 60 % how many Planar gradiometers? nPlaGrad = 0; for i = 1:orig.nchan; nPlaGrad = nPlaGrad +(orig.chs(i).coil_type==3012 | orig.chs(i).coil_type==3013 | orig.chs(i).coil_type==3014 | orig.chs(i).coil_type==2) ; end whereas K>> orig.chs(1) ans = scanno: 1 logno: 1 kind: 1 range: 1 cal: 1 coil_type: 7001 loc: [12x1 double] coil_trans: [4x4 double] eeg_loc: [] coord_frame: 4 unit: 112 unit_mul: 0 Note the 7001 coil type that mne2grad is not able to deal with. TODO => extend mne2grad with the 7001 coil type.


Robert Oostenveld - 2013-01-17 17:16:38 +0100

(In reply to comment #8) no, not yet. Since the event representation in neuromag data is rather messy due to the various incarnations of the scanners with analog and digital channels, I suggest to add support for the eve format. It is a simple format like 9922 9.689453 0 5 11127 10.866211 0 1 12143 11.858398 0 1 12971 12.666992 0 1 13979 13.651367 0 1 15121 14.766602 0 1 32803 32.034180 0 1 ... What do the numbers mean on the first line, and on the subsequent lines? In ft_read_event this would have to be extended so that the joint occurrence of a fif and an eve file causes the (to be made) read_babysquid_eve function to be called. TODO => implement read_babysquid_eve TODO => change ft_filetype such that eve+fif together are detected as 'babysquid_fif' and 'babysquid_eve'. In ft_read_header and ft_read_data those should cause the normal mne code to be called, in ft_read_event it should call read_babysquid_eve


Robert Oostenveld - 2013-01-17 17:21:33 +0100

Created attachment 407 BabySQUID.lout -> lay in the testing directory there is also a BabySQUID.lout which contains this -24.39 25.73 -23.32 25.39 001 1.63 1.93 4.00 3.00 MEG001 002 1.11 -2.46 4.00 3.00 MEG002 003 -2.45 2.51 4.00 3.00 MEG003 004 -3.03 -2.28 4.00 3.00 MEG004 005 11.85 1.80 4.00 3.00 MEG005 006 11.73 -2.88 4.00 3.00 MEG006 007 6.96 1.62 4.00 3.00 MEG007 008 6.79 -2.87 4.00 3.00 MEG008 ... This is almost like the fieldtrip layout format (once introduced by Ole, who spent time in Helsinki, so might be affected by a neuromag file format). See http://fieldtrip.fcdonders.nl/tutorial/layout What is the significance of the first deviant line? If I remove it and rename it to *.lay, I get with the following code >> cfg = []; >> cfg.layout = 'BabySQUID.lay' >> ft_layoutplot(cfg) the attached figure. Not bad, but also not ideal. TODO => make good template layout for inclusion in fieldtrip


Robert Oostenveld - 2013-01-17 17:24:04 +0100

Chiran, could you have a look at fieldtrip/fileio/private/mne2grad? e.g. from here http://code.google.com/p/fieldtrip/source/browse/trunk/fileio/private/mne2grad.m or following an SVN checkout. Please make the changes needed to support the 7001 sensor type.


Robert Oostenveld - 2013-01-17 17:39:43 +0100

(In reply to comment #10) mac001> svn add read_babysquid_eve.m A read_babysquid_eve.m mac001> svn commit Adding private/read_babysquid_eve.m Transmitting file data . Committed revision 7346. @Chiran, do the sample numbers in the eve file start at 1 (MATLAB-style) or 0 (C-style)? FieldTrip expects them to start at 1, that is what I now assumed in the code.


Chiran Doshi - 2013-01-17 17:41:49 +0100

(In reply to comment #13) It starts at 1


Robert Oostenveld - 2013-01-17 17:51:56 +0100

mac001> svn commit Sending fileio/ft_filetype.m Sending fileio/ft_read_data.m Sending fileio/ft_read_event.m Sending fileio/ft_read_header.m Transmitting file data .... Committed revision 7347. This results in >> ft_filetype('conversion_testing_OnlyMEG_with_triggers_raw.fif') ans = babysquid_fif and >> ft_filetype('conversion_testing_OnlyMEG_with_triggers_raw.eve') ans = babysquid_eve reading header and data are still ok, the events need to be completed. What are column 3 and 4 in the eve file?


Chiran Doshi - 2013-01-17 17:57:53 +0100

(In reply to comment #15) Column three is is most cases always zero. (I believe it is useful when you need to mark a segment rather than a time point). Column four value is the event type you assign. For example 5 in the first line of the eve file is assigned as a Sync_pulse by us.


Robert Oostenveld - 2013-01-17 18:01:05 +0100

(In reply to comment #16) ft_read_event function returns an event structure with the following fields event.type = string event.sample = expressed in samples, the first sample of a recording is 1 event.value = number or string event.offset = expressed in samples event.duration = expressed in samples Should the 3rd column then be mapped to event.duration? What is the unit of the duration?


Chiran Doshi - 2013-01-17 18:14:57 +0100

(In reply to comment #17) So I looked into the format of the eve file (MNE manual). It is supposed to be the value of the trigger channel at that sample. So keep it at 0. It has worked fine for both brainstorm and MNE so I do not expect any surprises.


Robert Oostenveld - 2013-01-17 20:12:21 +0100

(In reply to comment #18) So the first out of 9922 9.689453 0 5 11127 10.866211 0 1 12143 11.858398 0 1 12971 12.666992 0 1 13979 13.651367 0 1 15121 14.766602 0 1 32803 32.034180 0 1 ... should be represented as event(1).sample = 9922 event(1).type = 'Sync_pulse'; event(1).value = 0; event(1).offset = 0; event(1).duration = []; right? What possible values can the last column take and how should they be mapped on the event.type (which should be a string)?


Chiran Doshi - 2013-01-17 20:17:42 +0100

(In reply to comment #19) Is it not possible to keep the event(1).type = '5' or 5 (if possible)? Practically, event type can be any number (lets say 1000 for spike or 999 for artifact). This would keep it flexible as to what event names we assign. We keep a log as to what events correspond to what. Is it that FieldTrip needs to have predefined event names?


Robert Oostenveld - 2013-01-17 20:37:07 +0100

(In reply to comment #20) event.type needs to be a string, event.value can be a sting or number. So event(1).sample = 9922 event(1).type = '5'; event(1).value = 0; event(1).offset = 0; event(1).duration = []; would do just fine and I implemented it like this. mbp> svn commit Sending fileio/ft_read_event.m Transmitting file data . Committed revision 7349.


Chiran Doshi - 2013-01-18 16:12:57 +0100

(In reply to comment #12) Hi Robert, I looked into the mne2grad function. Actually, I do not know exactly how will it translate to our coil type (axial gradiometer) since I have not done this before. I do have the coil dimensions with the integration points. If you can explain to me how to determine the coil positions for axial gradiometer, it would be perfect or I could provide you with the values. Either one works for me. I want to make sure we get this right. Let me know, Chiran


Robert Oostenveld - 2013-01-21 13:01:54 +0100

(In reply to comment #22) around line 101 there is for n = 1:orig.nchan if (orig.chs(n).coil_type==3022 ...) % magnetometer elseif (orig.chs(n).coil_type==3022 ...) % planar gradiometer you can add elseif (orig.chs(n).coil_type== 7001) % babysquid axial gradiometer and supply the coilpos = Nx3 coilori = Nx3 arrays, where each of the M channels consists of two coils, so N=2*M. Besides each coil, the way that they combine into channels has to be coded in tra = MxN, i.e. Mx(2*M). The idea is that the leadfield gets computed for all coils, and then multiplied with the tra matrix to linearly combine the two coils into one channel. So lf_chan = tra * lf_coil. The most convenient to explain is to do all bottom coils first and then all top coils, so coilpos(1,:) = chan1_bottom_xyz; coilpos(2,:) = chan2_bottom_xyz; coilpos(3,:) = chan3_bottom_xyz; ... and coilpos(M+1,:) = chan1_top_xyz; coilpos(M+2,:) = chan2_top_xyz; coilpos(M+3,:) = chan3_top_xyz; ... If you then give the bottom coil an upward orientation and the top coil a downward orientation, tra is then simply [eye(M) eye(M)]. If you give both bottom and top coil the same orientation, tra becomes [eye(M) -eye(M)]. For the axial magnetometers the chanpos should be specified as the position of the bottom coil, chanori should be the orientation of the bottom coil. I hope that this clarifies all. If not, give it a try, send it to me and I'll complete it. Robert


Chiran Doshi - 2013-01-23 16:19:59 +0100

Created attachment 413 mne2grad function


Chiran Doshi - 2013-01-23 16:33:00 +0100

Created attachment 414 coil definitions used in mne Hi Robert, I have attached the mne2grad function and the coil_def.dat used in MNE. You will find the integration points and the geometry of the coils used by MNE and brainstorm in the coil_def.dat For the mne2grad function, I have assumed the bottom coil to be equivalent to magnetometer. For the top coil, I do not know how mne or brainstorm handles it. Does it calculate the location of the top coil on the fly using its geometry. Also I have made some changes to the code by adding nAxGrad at several places. Sorry could not be of much help with this. Let me know, how do you go about it. Chiran


Robert Oostenveld - 2013-02-04 14:00:14 +0100

Created attachment 418 babySQUID channel and coil positions I have taken some pieces from your code and merged them with the latest fieldtrip version. I also added the 2nd coil to the definition, assuming a 50mm baseline (which I got from the documentation). mac001> svn commit Sending fileio/ft_chantype.m Sending fileio/ft_read_header.m Sending fileio/ft_read_sens.m Sending fileio/private/channelposition.m Sending fileio/private/mne2grad.m Transmitting file data ..... Committed revision 7435. Please download the fieldtrip version from today from ftp.fcdonders.nl (i.e. you can download todays version it after 22.00 CET). You should them be able to do >> grad = ft_read_sens('conversion_testing_MEGandperipheral_raw.fif') grad = chanpos: [74x3 double] chantype: {74x1 cell} coilori: [148x3 double] coilpos: [148x3 double] label: {74x1 cell} tra: [74x148 double] type: 'babysquid74' unit: 'cm' and then >> plot3(grad.chanpos(:,1), grad.chanpos(:,2), grad.chanpos(:,3), 'bo') >> hold on >> plot3(grad.coilpos(:,1), grad.coilpos(:,2), grad.coilpos(:,3), 'k.') >> axis vis3d >> grid on >> xlabel('x (cm)'); ylabel('y (cm)'); zlabel('z (cm)') to get attached screen shot


Robert Oostenveld - 2013-02-04 14:07:37 +0100

TODO: 1) get some test datasets -> DONE 2) get some documentation on the geometry and triggering 3) write test script -> DONE 4) define new senstype (see fileio/ft_senstype.m) -> DONE 5) extend fileio/private/mne2grad.m -> DONE The only thing that remains is 2: to compile some documentation and put that on the wiki under http://fieldtrip.fcdonders.nl/getting_started as http://fieldtrip.fcdonders.nl/getting_started/babysquid. Please provide some information about the babysquid system. It can be as elaborate as you want, but I suggest to at least describe how triggers work, and how the coordinate system should be interpreted. Where is position [0 0 0] in relation to the baby and what are the x, y, and z-directions? When I looked at the 3D plot of the channel positions, I was not able to deduce how the head would have been. Have a look at the getting started for ctf, yokogawa, neuromag and bti to get some inspiration.


Chiran Doshi - 2013-02-04 16:55:36 +0100

Created attachment 419 babySQUID setup Hi Robert, Thanks for implementing babySQUID with FieldTrip. I will download the latest version and try to analyze one dataset (evoked field response)and try to go from the beginning to the end. I will let you know if I face any difficulty. From the screenshot you sent, the sensor plot looks reasonable. BabySQUID is a prototype system that has partial coverage of the head.Attached screenshot would help understand the setup better. I will update the wiki as and when time permits. Thank you so much for looking into this. Chiran


Robert Oostenveld - 2013-02-04 17:35:39 +0100

(In reply to comment #28) thanks, that figure puts it in perspective. I did not really have a feeling for the coverage of the array. Please give it a try with a full analysis.


Chiran Doshi - 2013-02-28 03:01:53 +0100

(In reply to comment #29) Hi Robert, I have started to look into the FieldTrip toolbox and I noticed a few things that are causing potential issues with our system. 1) I looked in the ft_filetype script and noticed that FieldTrip expects the fif and eve file to exist and should have the same name else it cannot determine eve file type and wrongly guesses babysquid fif file as neuromag_fif. This is a issue in case of spontaneous MEG recordings where there is no associated eve file. Is it possible to remove this dependency? 2) I was trying to get ft_define_trial to work normally and it could not due to following reasons a) By default ft_define_trial executes ft_trialfun_general for reading events and in the line where it calls ft_read_event, it expects that cfg.headerfile (my data file) contains the events. But it is not true in my case as I have a separate file. I looked into the documentation and it mentions that I can change the cfg.trialfun to execute ft_read_event instead of *_general but I could not figure out how to use it. Instead I added field cfg.readev (file name of my event file) and also created cfg.eventformat='babysquid_eve'. I edited a couple of lines in ft_trialfun_general to execute differently in case cfg.eventformat is babysquid_eve. Here are lines of code I edited and it fixed the issue try if strcmp(cfg.eventformat,'babysquid_eve') event = ft_read_event(cfg.readev, 'eventformat',cfg.eventformat); else fprintf('reading the events from ''%s''\n', cfg.headerfile); event = ft_read_event(cfg.headerfile, 'headerformat', cfg.headerformat, 'eventformat', cfg.eventformat, 'dataformat', cfg.dataformat); end b) For ft_define_trial to execute, it needs non-empty trl field. trl field in *_general depends on the event(i).value which is set to equal third column in read_babysquid_eve.m file. Generally that value is zero. Probably the concept of value in FieldTrip is different than the value in eve file. I changed line 43 : val3 = a(4,:)'; and it works. I got the function ft_define_trial to work in the end but if you feel there is a better way to fix the issue, let me know. Thanks, Chiran


Chiran Doshi - 2013-02-28 15:00:21 +0100

(In reply to comment #29) Just to add to that, Apparently, the MEG trigger lines labelled MEG_trg1 and MEG_trg2 are being classified as MEG channels and are being extracted along with rest Of MEG channels for trial averaging. Is this normal? In the header of the fiff file, data.hdr.org.raw.info.chs.kind field for these two channels have been labelled as 502 (Misc channels). Thanks, Chiran


Robert Oostenveld - 2013-12-02 10:18:53 +0100

I received a fif dataset from Leipzig that included a fif and an eve file (see bug 2170 for some details). Using that dataset, I have been able to sofrt out how the columns in the eve file are actually to be interpreted (0-offset, not corrected for recording start, last column is event value rather than type). With this information I have updated the code to improve the general eve/fif handling. I have removed the specific babysquid_fif and babysquid_eve identifiers as fileformat, since it now works fine with the normal neuromag_mne (default).


Robert Oostenveld - 2013-12-02 10:35:20 +0100

(In reply to comment #32) consistently deal with neuromag fif and eve file, also used for Tristan BabySQUID datasets. See http://bugzilla.fcdonders.nl/show_bug.cgi?id=1914 and http://bugzilla.fcdonders.nl/show_bug.cgi?id=2170 mac001> svn commit ft_read_event.m ft_filetype.m private/ Sending ft_filetype.m Sending ft_read_event.m Deleting private/read_babysquid_eve.m Adding private/read_neuromag_eve.m Transmitting file data ... Committed revision 8930.


Robert Oostenveld - 2013-12-02 11:02:02 +0100

I updated the deterction of the channel type and of the channel units mac001> svn commit ft_read_sens.m ft_read_data.m ft_chanunit.m ft_chantype.m ft_read_header.m private/ Sending ft_chantype.m Sending ft_chanunit.m Sending ft_read_data.m Sending ft_read_header.m Sending ft_read_sens.m Sending private/ft_senstype.m Transmitting file data ...... Committed revision 8932.


Robert Oostenveld - 2015-10-19 10:44:58 +0200

I noticed this paper in Frontiers http://journal.frontiersin.org/article/10.3389/fnhum.2014.00099/abstract This triggered me to write the wiki page http://www.fieldtriptoolbox.org/getting_started/babysquid I also made some minor code updates mac011> svn commit forward/ft_senstype.m test/test_bug1914.m Sending forward/ft_senstype.m Sending test/test_bug1914.m Transmitting file data .. Committed revision 10788. @Chiran, could you explain what the babysquid74 system is in relation to the artemis123 and the magview system, which both have more channels? That documentation should go on the http://www.fieldtriptoolbox.org/getting_started/babysquid wiki page.


Robert Oostenveld - 2015-10-19 10:49:45 +0200

(In reply to Robert Oostenveld from comment #35) To partially answer my own question: I suspect the babysquid74 system to be this one: http://www.tristantech.com/pdf/babySQUID_v1.1.pdf The sensor layout in the test files that I have resembles the figure on that poster. Has it been installed somewhere? Does anyone have (test) data from the artemis123 and the magview systems which I could add to the baby squid test script? I suspect that at this moment the mne2grad function will not add the respective grad.type field for data from those systems.


Robert Oostenveld - 2019-08-10 12:31:11 +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 https://github.com/fieldtrip/fieldtrip/issues.