Comments (5)
Current code proposition (also include in the .zip above):
% Trying to rebuild missing from the HCP pre-processed files.
% We want to reconstruct separate matrices from the .tra matrix, with the help of the .balance field:
% - the sparse coil-channel correspondance matrix
% - the noise-compensation matrix applied by 4D acquisition system
% - the PCA/ICA cleaning procedures
%
% Authors: Francois Tadel, 2017
% Load example structure: Subject HCP/891667, resting state recordings pre-processed with FieldTrip
ftMat = load('891667_MEG_3-Restin_rmegpreproc_5trials.mat');
ftMat = ftMat.data;
grad = ftMat.grad;
% === FIX STRUCTURE ===
% Suggestion from JM: Fix glitches in the grad structure with ft_datatype_sens
% Reference: http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=3298#c6
% Problem: does not fix retroactively the history in the .balance field
grad = ft_datatype_sens(grad);
% === REVERT TO THE ORIGINAL .TRA MATRIX ===
% Suggestion from JM: Use ft_apply_montage to revert to the original .tra matrix
% Reference: http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=3298#c3
%
% Problems: There are lots of inconsistencies in the .balance fields of the HCP files:
% 1) The output channel units and types in transformation "pca" are set to "unknown"
% 2) Random naming chanunitorg/chanunitold fields
% 3) Channel types change randomly between "meg" (eg. pca) and "megmag" (eg. invcomp)
% Reference: http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=3298#c5
% Get the list of montages to undo
montageList = {grad.balance.current};
if ~isempty(grad.balance.previous)
montageList = cat(2, montageList, grad.balance.previous{:});
end
% Undo montages one by one
for iMontage = 1:length(montageList)
% Make sure the montage is defined in the structure
mont = montageList{iMontage};
if ~isfield(grad.balance, mont)
continue;
end
% ISSUE #1: Trying to fix units and types (with randomness of issue #2)
if isfield(grad.balance.(mont), 'chanunitnew') && strcmpi(grad.balance.(mont).chanunitnew{1}, 'unknown')
if isfield(grad.balance.(mont), 'chanunitorg')
grad.balance.(mont).chanunitnew = grad.balance.(mont).chanunitorg;
elseif isfield(grad.balance.(mont), 'chanunitold')
grad.balance.(mont).chanunitnew = grad.balance.(mont).chanunitold;
end
end
if isfield(grad.balance.(mont), 'chantypenew') && strcmpi(grad.balance.(mont).chantypenew{1}, 'unknown')
if isfield(grad.balance.(mont), 'chantypeorg')
grad.balance.(mont).chantypenew = grad.balance.(mont).chantypeorg;
elseif isfield(grad.balance.(mont), 'chantypeold')
grad.balance.(mont).chantypenew = grad.balance.(mont).chantypeold;
end
end
% % ISSUE #3: Trying to fix the channel types
% % DOES NOT WORK BECAUSE THE ORDER OF THE CHANNELS CHANGE
% if isfield(grad.balance.(mont), 'chantypenew') && (length(grad.balance.(mont).chantypenew) == length(grad.chantype))
% grad.balance.(mont).chantypenew = grad.chantype;
% end
% if isfield(grad.balance.(mont), 'chantypeorg') && (length(grad.balance.(mont).chantypeorg) == length(grad.chantype))
% grad.balance.(mont).chantypeorg = grad.chantype;
% end
% if isfield(grad.balance.(mont), 'chantypeold') && (length(grad.balance.(mont).chantypeold) == length(grad.chantype))
% grad.balance.(mont).chantypeold = grad.chantype;
% end
% Reverse transformation
grad = ft_apply_montage(grad, grad.balance.(mont), 'inverse', 'yes', 'keepunused', 'yes');
end
% === REBUILD ORIGINAL COIL-CHANNEL MATRIX ===
% Remove small values (probably due to the multiple matrix inversions) to keep only the ones
grad.tra(abs(grad.tra) < 0.1) = 0;
% For each channel
for i = 1:length(ftMat.label)
% MEG sensors
if isfield(ftMat, 'grad') && ~isempty(ftMat.grad) && isfield(ftMat.grad, 'tra') && isfield(ftMat.grad, 'label') && ~isempty(ftMat.grad.label) && ismember(ftMat.label{i}, ftMat.grad.label)
% Find channel index
ichan = find(strcmpi(ftMat.label{i}, grad.label));
% Find corresponding coils
icoils = find(grad.tra(ichan,:));
% Error: Two many coils
if (length(icoils) > 2)
error(['Wrong number of coils for channel ', ftMat.label{i}, ': Cannot import this file correctly...']);
end
% Get sensor properties
Loc = ftMat.grad.coilpos(icoils,:)';
Orient = ftMat.grad.coilori(icoils,:)';
Weight = ftMat.grad.tra(ichan,icoils);
end
end
from fieldtrip.
I agree that it's a mess
what seems to work for me (that is, it produces a tra matrix that can be used for channel/coil mapping), when I remove the chanunitNEW/OLD/ORG and chantypeNEW/OLD/ORG from the montage prior to using it in ft_apply_montage, i.e.
montage = somegrad.balance.(somename);
montage = removefields(montage, {'chanunitnew' 'chanunitold' 'chanunitorg' 'chantypenew' 'chantypeold' 'chantypeorg'}); % this is a fieldtrip function that behaves the same as rmfield, apart from that it does not throw an error if a field is missing
somenewgrad = ft_apply_montage(somegrad, montage, 'keepunused', 'yes', 'inverse', 'yes');
from fieldtrip.
Some additional comments: I recall that we had quite some discussions in the HCP MEG team about how to handle the Supine weights, and I believe that we settled on removing this from the grad.tra matrix prior to further processing. Note that we did not 'undo' the same balancing on the sensor data. The reason we decided to do this I don't fully remember, but I think that applying the Supine weights to the leadfields caused strangely distorted topographies, which we did not trust in the end. Another observation, albeit anecdotally, was that the source reconstructed resting state maps made more 'sense' to the Chieti team, when using unbalanced (by Supine weights) gradiometer arrays.
Perhaps @gmichalareas or @robertoostenveld can confirm this.
Anyway, the resulting tra matrix is not fully sparse (containing only 0's and 1's, which could be due to the fact that this appears to be data from the resting state condition (data.cfg.previous.previous.previous{1}.previous.previous.previous.previous.previous.previous.datafile) tells me this, and it could well be that it's due to the 'invcomp' step being not full rank due to discarded channels
from fieldtrip.
Thanks for the suggestion, now I can rebuild the coil-channel matrix.
From what I understand from your second message: the first step of processing of the continuous 4D recordings was to undo the 4D noise compensation. But what do you mean with "Note that we did not 'undo' the same balancing on the sensor data"? Did you just remove it from the .tra matrix without applying the corresponding inverse transform to the MEG recordings?
Are we supposed to use this "invcomp" projector in the computation of the forward operator?
Is this formally documented somewhere? Do you have any written trace of why you decided to cancel the 4D noise compensation? This would be worth sharing with the users of the HCP-MEG data.
Do you know if there any published study of the impact of the 4D noise compensation on the source modeling?
from fieldtrip.
This seems to be HCP specific, not related to the FieldTrip code. So let me close it here.
from fieldtrip.
Related Issues (20)
- function ft_singleplotTFR output HOT 1
- Document and implement OPM coregistration on basis of only Polhemus 3D tracker. HOT 4
- deal with FieldLine smart helmet sensor localization errors HOT 3
- Problem with importing MEG datasets ds003352 & ds003922 with File-IO HOT 8
- Maxfilter issue when importing MEG datasets ds004276 & ds004483 with File-IO HOT 5
- Deal with FieldLine v3 recordings in which the sensor localization was not successful and the channel names are not unique. HOT 1
- Fieldtrip-SimBio pipeline on macOS with Apple silicon - calc_stiff_matrix_val.mexmaca64 is missing HOT 5
- FIF import issue HOT 2
- CTF data in BIDS format results in inconsistent channel names HOT 11
- Consider reducing the .git history size by removing large binary blobs HOT 1
- Iso2Mesh External Toolbox missing cork.exe HOT 2
- The `ft_read_event` function doesn't work for '.nirs' files due to a repeat key-value pair in function code. HOT 1
- Inconsistency between stat.mask and p-values in ft_freqstatistics HOT 2
- Inconsistency between stat.mask and p-values in ft_freqstatistics HOT 5
- Source localization now require optimization toolbox HOT 4
- ft_selectdata failure HOT 4
- Beamforming oscillatory responses in combined MEG/EEG data HOT 3
- Dipole fitting of combined MEG/EEG data
- EEG inverse mode; HOT 3
- ft_rejectvisual failure HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fieldtrip.