====== Creating and combining masks from VTCs ====== ===== Motivation ===== I wanted to create this page for two reasons: * demonstrate quickly the ease of access on xff objects (in this case BrainVoyager QX types) * give users the ability to create an SPM-comparable mask when running GLMs ===== Requirements ===== You should have all the [[xff - VTC format|VTCs]] you want to combine in a group analysis ([[xff - GLM format|RFX-GLM]]) at hand. In this example, I assume that they are listed in an [[xff - MDM format|MDM]] file, which is BrainVoyager's way of specifying data for a group analysis. ===== Algorithm ===== The algorithm is as follows: * make settings (i.e. required intensity level, either as ratio or fixed value) * load MDM file * load the first (next) VTC file * for first VTC, create a [[xff - MSK format|MSK]] (mask) object with the same spatial layout * for subsequent VTC, check spatial layout * compute the mean over time * clear the VTC * build mask for this VTC (threshold mean) * if first VTC, copy mask to combined mask array * combine mask with combined mask array * continue with step 3 (next VTC) * optionally perform required step for mask thresholding (if not simple binary combination) * store combined mask and save under new filename * clear mask object ==== Code ==== % settings % - intensity threshold: values < 10 are treated as relative threshold! ithresh = 1.5; % - combine as sum or mask summask = true; % - if combine as sum, threshold ? subthresh = 0.75; % load MDM file mdm = xff('*.mdm', 'Please specify the MDM file to create a mask for...'); % loop over VTCS for vc = 1:size(mdm.XTC_RTC, 1) % load first VTC vtc = xff(mdm.XTC_RTC{vc, 1}); if ~isxff(vtc, 'vtc') clearxffobjects({vtc}); error('Not a VTC file!'); end % create mask if vc == 1 msk = xff('new:msk'); msk.Resolution = vtc.Resolution; msk.XStart = vtc.XStart; msk.XEnd = vtc.XEnd; msk.YStart = vtc.YStart; msk.YEnd = vtc.YEnd; msk.ZStart = vtc.ZStart; msk.ZEnd = vtc.ZEnd; % test layout else if msk.Resolution ~= vtc.Resolution || ... msk.XStart ~= vtc.XStart || ... msk.XEnd ~= vtc.XEnd || ... msk.YStart ~= vtc.YStart || ... msk.YEnd ~= vtc.YEnd || ... msk.ZStart ~= vtc.ZStart || ... msk.ZEnd ~= vtc.ZEnd vtc.ClearObject; msk.ClearObject; error(sprintf('VTC %d (%s) mismatches layout!', vc, mdm.XTC_RTC{vc, 1})); end end % compute the mean over time mvtc = squeeze(mean(vtc.VTCData)); % clear VTC vtc.ClearObject; % threshold if ithresh < 10 mask = (mvtc >= (ithresh .* mean(mvtc(:)))); else mask = (mvtc >= ithresh); end % store or combine if vc == 1 combined = mask; else % sum or and mask? if summask combined = combined + mask; else combined = combined & mask; end end end % combine across subjects required (summed mask) if summask % subject threshold combined = (combined >= (subthresh * size(mdm.XTC_RTC, 1))); end % set in mask msk.Mask = uint8(combined); % save mask msk.SaveAs; % clear msk and mdm msk.ClearObject; mdm.ClearObject; ===== Alternative algorithm ===== In case the MSK files/objects have already been created (e.g. as gray matter mask per subject), this is a way to average them. **This will only work if the masks are in the same space, e.g. large TAL box!** * making settings (i.e. percentage threshold for combined mask) * locating all mask files to be averaged * loading all masks and adding the data * thresholding the data * saving new mask ==== Code ==== % settings (80% of masks must have a set voxel) gthresh = 0.8; % locate masks % - this could be enhanced by changing the pattern, e.g. using % 'SK*_TAL*.msk' to locate only masks of subjects beginning with SK in TAL space % - additionally, the startfolder and depth could be altered mskfiles = findfiles(pwd, '*.msk'); % alternative: mskfiles = findfiles([pwd '/SK*/VTC*/RUN*'], 'SK*TAL*.msk', 'depth=1'); % loop over masks msk = []; for mc = 1:numel(mskfiles) % clear old mask if ~isempty(msk) msk.ClearObject; end % load mask msk = xff(mskfiles{mc}); % for first mask if mc == 1 % copy data mask = uint16(msk.Mask); % otherwise else % add data mask = mask + uint16(msk.Mask); end end % threshold mask mask = uint8(mask >= uint16(ceil(gthresh * numel(mskfiles)))); % store msk.Mask = mask; % save msk.SaveAs; % clear object msk.ClearObject;