Back to the main page.

Bug 3103 - ft_sourceanalysis asks for .avg and .trial on same object

Status CLOSED FIXED
Reported 2016-04-02 22:28:00 +0200
Modified 2016-05-06 09:18:27 +0200
Product: FieldTrip
Component: inverse
Version: unspecified
Hardware: PC
Operating System: All
Importance: P5 normal
Assigned to:
URL:
Tags:
Depends on:
Blocks:
See also:

John Richards - 2016-04-02 22:28:16 +0200

I have been using ft_sourceanalysis with ft .avg objects on the data structure. I have just tried "rawtrials", which have a .trial object but not a .avg object. In some of the code it assumes there is a data.avg object, but i can't find it being set and it causes an error. e.g. Nsamples = size(data.avg,2); Nchans = length(data.label); if isfield(data, 'cov') && length(size(data.cov))==3 Ntrials = size(data.cov,1); elseif isfield(data, 'trial') && length(size(data.trial))==3 Ntrials = size(data.trial,1); else Ntrials = 1; end The first Nsamples fails for the rawtrial structure without the .avg. I changed mine to %JER modificiation, if no "avg" but "trial" then get Nsamples from the trial if isfield(data,'avg'); Nsamples = size(data.avg,2); elseif isfield(data,'trial'); Nsamples = size(data.trial,3); end; %Nsamples = size(data.avg,2); similarly, data.avg = data.avg(datchanindx,:); data.cov = data.cov(:,datchanindx,datchanindx); data.trial = data.trial(:,datchanindx,:); to %JER modifications, if get here probably in the raw trials, but may not have data.avg. if isfield(data,'avg'); data.avg = data.avg(datchanindx,:); end data.cov = data.cov(:,datchanindx,datchanindx); if isfield(data,'trial'); data.trial = data.trial(:,datchanindx,:); end;


Robert Oostenveld - 2016-04-12 17:25:00 +0200

Hi John, The trial handling in ft_sourceanalysis dates back >10 years and is regretfully flawed by design. We have been trying to move forward with the code, but at the same trying to keep backward compatible with existing users' matlab scripts. What is it exactly that you are trying to do (from a conceptual point of view)?


John Richards - 2016-04-12 21:06:46 +0200

Conceptually, i have two kinds of FT data. One kind is the "avg" and consists of a single average trial, with n-slices, and n-electrodes. In the FT object representing data this is put in the .avg object of the data structure. The second kind is "trial" data, and consists of several trials, with n-trials, n-slices, and n-electrodes. This is put into the .trial object of the data structure. From what I understand, the data objects in FT either have a avg object or a trial object, but not both. In the code below one place assumes there is a "avg" object in the structure, and the second place assumes there are both "avg" object and "trial" object in the structure. So no matter how one arrives at this particular location on the ft_sourceanalysis procedure, with just one of these objects, the code will fail. My modifications below test of the avg or trial object in the data structure, and acts accordingly. John


Robert Oostenveld - 2016-04-13 12:08:15 +0200

(In reply to John Richards from comment #2) Both are contained within one FieldTrip data structure that is "time-locked" to the event onset at t=0. The data structure is the result of ft_timelockanalysis with cfg.keeptrials=yes. You should not consider the "avg" and the "trial" subfield separate from the remainder of the data structure. See http://www.fieldtriptoolbox.org/reference/ft_datatype_timelock Compared to raw data (see http://www.fieldtriptoolbox.org/reference/ft_datatype_raw) the important difference in the trial field is that it is a 3D array, rather than a cell array of 2D matrices. The "time-locked" data structure will most likely also have single trial or an average channel covariance matrix. Do you want to source reconstruct the average (1), or do you want to source reconstruct individual trials (2)? In the latter case, you can construct the inverse operator either on the average (2a), or also on the individual trials (2b). With case 2b you should be aware that if the inverse operator is data dependent (like with a beamformer), the covariance will be used. The single trial covariance is a poor estimator of the signal and noise structure and hence the single trial estimates using single trial inverse operator are usually very poor. Case 2a is relevant if you want to do within-subject statistics, comparing different types of trials under the H0 that the cortical activity is the same in the two types of trials. Under that H0, all trials can (and should) have the same inverse operator, which is therefore based on the averaged covariance over all trials (regardless the condition). You can also contrast the average between two conditions (i.e. 1b), following the approach outlined on http://www.fieldtriptoolbox.org/tutorial/beamformer#source_analysiscontrast_activity_to_another_interval If the problem persists, please send me the input cfg and data that you pass to the ft_sourceanalysis function (see http://www.fieldtriptoolbox.org/faq/how_should_i_send_example_data_to_the_developers).


John Richards - 2016-04-13 16:19:21 +0200

http://www.fieldtriptoolbox.org/reference/ft_datatype_timelock http://www.fieldtriptoolbox.org/reference/ft_datatype_raw the "timelock" structure carries the data in ".avg", n-chanels x n-slice The "raw" structure carries the data in ".trial', n-channels x n-slice x n-trials. The code in ft_sourceanalysis, apparently, expects that BOTH the ".avg" and the ".trial" will exist in the structure. % determine the size of the data Nsamples = size(data.avg,2); Nchans = length(data.label); if isfield(data, 'cov') && length(size(data.cov))==3 Ntrials = size(data.cov,1); elseif isfield(data, 'trial') && length(size(data.trial))==3 Ntrials = size(data.trial,1); else Ntrials = 1; end This also else data.avg = data.avg(datchanindx,:); data.cov = data.cov(:,datchanindx,datchanindx); data.trial = data.trial(:,datchanindx,:); end So no matter how I am arriving there, my understanding of the exclusive nature of the .avg and .trial is either wrong (there CAN be .avg and .trial objects in a data structure), or this code is wrong. I arrived to this section of the code with a cfg.rawtrial = 'yes' and the data structure listed below. The ft_sourceanalysis that has "jackknife" "permutation" "bootstrap" cfg.rawtrial, uses the .trial rather than the .avg. So the code above the assumes the existence of both .avg and .trial on the data object would fail. I understand the pitfalls of doing single trial source analysis. The work i was doing with this was experimental programming, and now I am not trying to do it, so I don't have the full cfg. I was using cfg.rawtrial = 'yes', and the data listed below, which got me into the section of ft_sourceanalysis where it assumed both the .avg and .trial was set. I was trying to analyze raw trials, with cfg.rawtrials set, the data are label: {1x126 cell} fsample: 250 elec: [1x1 struct] trial: {1x65 cell} time: {1x65 cell} cfg: [1x1 struct] dimord: 'rpt_chan_time' trialinfo: [65x1 double] cov: [65x126x126 double] sampleinfo: [65x2 double]


Robert Oostenveld - 2016-04-13 18:12:51 +0200

(In reply to John Richards from comment #4) You wrote > The "timelock" structure carries the data in ".avg", n-chanels x n-slice > The "raw" structure carries the data in ".trial', n-channels x n-slice x n-trials. Statement 2 is incorrect. In the raw structure the data in ".trial" is a cell array, and trial is 1*Ntrials. Each trial in turn is Nchan*Ntime matrix, where Ntime can differ over trials. Furthermore, the trials (better would be to call them "data segments") don't even have to overlap in time. Although usually they are expressed relative to the stimulus and will overlap. In the time-locked data representation the average is indeed locked to the event (at t=0). The individual trials can also be represented, but only if they are aligned to each other. The .avg field is nchan*ntime, the .trial field (if present) is trial*nchan*ntime. ft_sourceanalysis does not accept raw data as input, only time locked (or frequency decomposed) data. Some of the algorithms in ft_sourceanalysis also require that the time locked structure contains the covariance. On another note: Although for you it does not matter how you ended up with an error, for me it does, as it helps me in trying to figure how you get you out of the problematic situation. The data structure you describe is not a FieldTrip data structure and violates the requirements of ft_sourceanalysis (and other FT functions). It appears to be a hybrid raw/timelock structure. Please structure it according to ft_datatype_timelock.


John Richards - 2016-04-13 18:34:16 +0200

Thanks for the information, that was very helpful. The data structure was indeed a hybrid structure constructed from EEGLab/ERPLab data and did not conform to the type of data needed for the ft_sourceanalysis.


Jan-Mathijs Schoffelen - 2016-05-05 09:48:07 +0200

It looks as if this has been resolved (up until the point that it can be resolved). Can we close this? John, if this is the case, please do so.


John Richards - 2016-05-05 21:52:45 +0200

This is resolved