FDR "corrected" vs "adjusted" p-values
Demonstration of the difference, following a query about the different results from SPM's spm_P_FDR and FSL's fdr.
See http://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind0704&L=fsl&P=22195
Contents
p-values, from random t-values
rand('state', 0); randn('state', 0); % (both used by trnd) df = 20; % arbitrary (smallish) degrees of freedom % t non-centrality parameter, 50 null voxels, 50 activated: delta = [zeros(50,1); ones(50,1)]; t = nctrnd(df, delta); hist(t) p = tcdf(-t, df); % right-sided p-values, as SPM

"Corrected" p-values
[Ps Is] = sort(p(:)); S = length(Ps); cV = 1; Qs = Ps*S./(1:S)'*cV; [I Iu] = sort(Is); % indexing to from sorted to original unsorted clear I; if ~all(p == Ps(Iu)), error('inverse sorting not successful'), end Q = Qs(Iu); plot(Ps, Qs, 'bx-')

"Adjusted" p-values
Code adapted slightly from spm_P_FDR.
Ensures monotonicity of relationship between pUnc and pFDR, see http://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind0704&L=fsl&P=22195
P = zeros(size(p)); for i = 1:length(p) % Find PZ(i) in Ps, or smallest Ps(j) s.t. Ps(j) >= PZ(i) %--------------------------------------------------------------- I = min(find(Ps>=p(i))); % -"Adjusted" p-values %--------------------------------------------------------------- if isempty(I) P(i) = 1; else P(i) = min(Qs(I:S)); end end plot(Ps, P(Is), 'bx-')

Critical p-value
Pc = spm_uc_FDR(0.5, [1 df], 'P', 1, Ps)
Pc = 0.2643
Write results
dim = [5 5 4]; V = struct('fname', 'fdr_query_p.nii',... 'dim', dim,... 'mat', eye(4),... 'pinfo', [1;0;0],... 'dt', [spm_type('float32') spm_platform('BigEnd')],... 'n', [1 1]... ); spm_write_vol(V, reshape(p, dim)); V.fname = 'fdr_query_P.nii'; spm_write_vol(V, reshape(P, dim)); V.fname = 'fdr_query_Q.nii'; spm_write_vol(V, reshape(Q, dim)); V.fname = 'fdr_query_mask.nii'; spm_write_vol(V, ones(dim));
Use FSL's fdr
[status stdout] = system('fsl'); % (ignore me...) if status ~= 0, error('FSL not working'), end cmd = 'setenv FSLOUTPUTTYPE NIFTI; '; cmd = [cmd 'fdr -i fdr_query_p.nii -m fdr_query_mask.nii -o fdr_query_fslQ -q 0.5']; [status stdout] = system(cmd); fslPc = str2double(regexp(stdout, '0\.\d+', 'match')) fslQ = spm_read_vols(spm_vol('fdr_query_fslQ.nii')); fslQ = fslQ(:);
fslPc = 0.2643
Compare
errPc = abs(Pc - fslPc) maxQerr = max(abs(Q-fslQ)) % FSL's fdr p-values (q-rate) correspond to Q plot(1:100,p, 1:100,P, 1:100,fslQ); legend('Uncorrected', 'SPM P', 'FSL Q')
errPc = 3.4523e-07 maxQerr = 5.7571e-08

Note Q is conservative in the following sense:
all(Q >= P)
ans = 1
Ged Ridgway (drc.spm@gmail.com), with thanks to Tom Nichols.