Back to the main page.

Bug 3342 - why does ft_freqbaseline normalize trials using the trial-specific baseline instead of the average baseline?

Reported 2017-08-31 02:08:00 +0200
Modified 2019-08-10 12:43:41 +0200
Product: FieldTrip
Component: core
Version: unspecified
Hardware: PC
Operating System: Mac OS
Importance: P5 normal
Assigned to: Eelke Spaak
Depends on:
See also:

Arjen Stolk - 2017-08-31 02:08:13 +0200

I couldn't find any bug report related to this, but am pretty sure it used to be the other way around and wondered about the rationale behind his change. Looking back in history, the following code clean-up might have introduced it: @Eelke, did you intentionally make it perform the normalization per trial? As far as I know, baseline-correcting per trial can be noisier since the baseline is estimated less robustly, namely, an average over just a few samples corresponding to the trial-specific baseline. In contrast, taking an average across all trials as a baseline generally uses many more samples. This is all theoretical and I'm not asking because of experiencing any issues. Just wondering.

Arjen Stolk - 2017-08-31 02:24:28 +0200

Just briefly for a point in case: 3 trials, where the trial-specific activation is identical across the two situations below. All that differs is how the baseline is calculated (per trial in situation #1, or across trials in situation #2). > situation #1: normalization using trial-specific baseline (using a baseline that averages to 2 across the 3 trials, i.e. (2+3+1)/3=2) ((2-1.5)/1.5 + (3-1)/1 + (1-.5)/.5) /3 ans = 1.1111 > situation #2: normalization using across-trial average baseline (the average is 2) ((2-1.5)/1.5 + (2-1)/1 + (2-.5)/.5) /3 ans = 1.4444 On average there was a (2-1)/1 = 100% increase. So situation #1 is closer to the average, which doesn't really illustrate my point hehe. The main problem is that a trial-specific baseline increases the risk for disproportionally blowing up activity modulations because of a noisy baseline in a given trial. But perhaps I'm missing something here?

Arjen Stolk - 2017-09-14 07:21:11 +0200

Hope you don't mind me 'assigning' this one to you to avoid it getting lost in the ever-ongoing stream of notifications.

Arjen Stolk - 2017-12-30 06:20:06 +0100

Still getting wildly different results with the current implementation of baseline-correction, as compared to the old version where the baseline is based on the average across baseline intervals. The current implementation does the baseline-correction using the trial-specific baseline interval. I'm uploading a plot of old vs. current style, left and right respectively. It seems to me the current implementation has a strong bias towards positive changes (in all channels). I feel it renders the current implementation of ft_freqbaseline useless, unless people average across trials prior to baselinecorrection, but I presume this is not intended behavior?

Arjen Stolk - 2017-12-30 06:21:28 +0100

Created attachment 853 old vs new/current implementation simulated the old style by averaging across trials prior to baselinecorrection. anything else is identical: cfg = []; cfg.baseline = [-.3 -.1]; cfg.baselinetype = 'relchange'; freq_blc = ft_freqbaseline(cfg, freq);

Arjen Stolk - 2019-04-01 09:12:29 +0200

Bumping this, as I don't know if it's (still) an issue or design choice.

Jan-Mathijs Schoffelen - 2019-04-01 09:33:50 +0200

heb ik op de 'aan' knop gedrukt?

Robert Oostenveld - 2019-04-01 10:13:31 +0200

The bug report has a question as the title. The answer to the question could for example be "just because". It is unclear to me what the issue is that is to be solved. Is it that the baseline computation is now done differently than it used to in the past? And is the requested action to revert to the past behaviour? I used the following code, going back year after year. --------- restoredefaultpath addpath('/home/common/matlab/fieldtrip-20091231'); try ft_defaults catch fieldtripdefs end %% freq = []; freq.dimord = 'rpt_chan_freq_time'; freq.label = {'1', '2'}; freq.freq = linspace(1, 30, 30); freq.time = linspace(-0.5, 1, 100); freq.powspctrm(1,:,:,:) = 1*ones(1, 30, 100); freq.powspctrm(2,:,:,:) = 2*ones(1, 30, 100); %% cfg= []; cfg.baselinetype = 'absolute'; cfg.baseline = [-inf 0]; ft_freqbaselinefreqbl = freqbaseline(cfg, freq); if all(freqbl.powspctrm(:,1,1,1)==0) fprintf('correction was done with individual trial baselines\n'); else fprintf('correction was done using average baseline\n'); end --------- Going back further than 2009 failed (could be solved, but this is far enough back if you ask me). And some of the older FieldTrip versions are incompatible with R2018b. But all FT versions that worked showed that correction was done with individual trial baselines. So it seems to me that there is no issue. You still might want the baseline correction to be done using the average over trials, but that would be new functionality.

Arjen Stolk - 2019-04-02 04:16:41 +0200

Thanks for looking into this. I checked the git commit linked to above and it seems freqbaseline was initially taking the average across the baseline interval rather than across trials as I thought. This means that freqbaseline was already altered before that commit or that it never computed the average baseline in the first place as your check suggests. Guess I'm losing my marbles then, and that this gnarly per-trial-normalization was a design choice all along ...

Robert Oostenveld - 2019-04-02 10:07:32 +0200

(In reply to Arjen Stolk from comment #8) I don't think it was a design choice per see. I guess the function was initially written with averaged TFRs in mind, and only later extended for trials by simply adding a for-loop. I see the use case (actually multiple) to extend the functionality, e.g. like this cfg.averageover = 'individual' freq_bl = ft_freqbaseline(cfg, freq); cfg.averageover = 'trials' freq_bl = ft_freqbaseline(cfg, freq); cfg.averageover = 'conditions' freq_bl = ft_freqbaseline(cfg, freqC1, freqC2, ...); This would be new functionality, so better dealt with in a separate issue (on github).

Robert Oostenveld - 2019-08-10 12:43:41 +0200

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