Frequently Asked Questions
BIDS: What is a BIDS way to name and store Regions of Interest (ROIs)?
General: How can I know that things are set up properly before I run an analysis?
General: How can I prevent from having SPM windows pop up all the time?
General: How can I run bidspm only certain files, like just the session
02
for example?Results: How can I change which slices are shown in a montage?
SPM: How can get the data from some specific voxel in a nifti image?
SPM: How can I use SPM image calculator (
imcalc
) to create a ROI?SPM: How can set the value of a specific voxel in a nifti image?
SPM: How do I know which matlab function performs a given SPM process?
Statistics: How can change the name of the folder of the subject level analysis?
Statistics: How can I see what the transformation in the BIDS stats model will do to my events.tsv?
Statistics: How should I name my conditions in my events.tsv?
Statistics: How should I structure my data to run my statistical analysis?
BIDS: What is a BIDS way to name and store Regions of Interest (ROIs)?
There is no “official” way to name ROI in BIDS, but you can apply BIDS naming principles to name those.
The closest things to ROI naming are the masks
for the
BIDS derivatives.
Here is an example from the :ref:face repetition demo
::
bidspm-roi
├── group
│ ├── hemi-L_space-MNI_label-V1d_desc-wang_mask.json
│ ├── hemi-L_space-MNI_label-V1d_desc-wang_mask.nii
│ ├── hemi-L_space-MNI_label-V1v_desc-wang_mask.json
│ ├── hemi-L_space-MNI_label-V1v_desc-wang_mask.nii
│ ├── hemi-R_space-MNI_label-V1d_desc-wang_mask.json
│ ├── hemi-R_space-MNI_label-V1d_desc-wang_mask.nii
│ ├── hemi-R_space-MNI_label-V1v_desc-wang_mask.json
│ └── hemi-R_space-MNI_label-V1v_desc-wang_mask.nii
└── sub-01
└── roi
├── sub-01_hemi-L_space-individual_label-V1d_desc-wang_mask.nii
├── sub-01_hemi-L_space-individual_label-V1v_desc-wang_mask.nii
├── sub-01_hemi-R_space-individual_label-V1d_desc-wang_mask.nii
└── sub-01_hemi-R_space-individual_label-V1v_desc-wang_mask.nii
ROIs that are defined in some MNI space are going to be the same across subjects, so you could store a “group” folder (this is not BIDSy but is less redundant than having a copy of the same file for each subject).
The desc
entity (description) here is used to denotate the atlas the ROI taken
from, so if you are building yours from a localizer you might not need to use
it.
Ideally you would want to add a JSON file to add metadata about those ROIs.
You can use bids-matlab to help you create BIDS valid filenames.
>> name_spec.ext = '.nii';
>> name_spec.suffix = 'mask';
>> name_spec.entities = struct( ...
'hemi', 'R', ...
'space', 'MNI', ...
'label', 'V1v', ...
'desc', 'wang');
>> file = bids.File(name_spec);
>> file.filename
hemi-R_space-MNI_label-V1v_desc-wang_mask.nii
General: Can I use parallelization with bidspm?
You can use parallelization with bidspm.
The main way to do so is to use parfor
loops in your code
when running the preprocess
, smooth
or stats
actions.
For example, if you want to run the preprocess
action on a list of subjects,
subjects = {'01', '02', '03', '04', '05'};
parfor i = 1:length(subjects)
bidspm(bids_dir, output_dir, ...
'participant_label', subjects(i), ...
'action', 'preprocess', ...
'task', {'tasnName'}, ...
'space', {'IXI549Space'});
end
General: How can I know that things are set up properly before I run an analysis?
If you want to set things up but not let SPM actually run the batches you can use the option:
opt.dryRun = true()
This can be useful when debugging. You may still run into errors when SPM jobman takes over and starts running the batches, but you can at least see if the batches will be constructed without error and then inspect with the SPM GUI to make sure everything is fine.
General: How can I prevent from having SPM windows pop up all the time?
Running large number of batches when the GUI of MATLAB is active can be annoying, as SPM windows will always pop up and become active instead of running in the background like most users would prefer to.
One easy solution is to add a spm_my_defaults
function with the following
content in the MATLAB path, or in the directory where you are running your
scripts or command from.
function spm_my_defaults
global defaults
defaults.cmdline = true;
end
This should be picked up by bidspm and SPM upon initialization and ensure that SPM runs in command line mode.
General: How can I run bidspm from the command line?
You can use the Python CLI of bidspm to run many functionalities from the terminal.
See the README to see how to install it.
You can also run your matlab script from within your terminal without starting the MATLAB graphic interface.
For this you first need to know where is the MATLAB application. Here are the
typical location depending on your operating system (where XXx
corresponds to
the version you use).
Windows:
C:\Program Files\MATLAB\R20XXx\bin\matlab.exe
Mac:
/Applications/Matlab_R20XXx.app/bin/matlab
Linux:
/usr/local/MATLAB/R20XXx/bin/matlab
You can then launch MATLAB from a terminal in a command line only with the
following arguments: -nodisplay -nosplash -nodesktop
So on Linux for example:
/usr/local/MATLAB/R2017a/bin/matlab -nodisplay -nosplash -nodesktop
If you are on Mac or Linux, we would recommend adding those aliases to your
.bashrc
or wherever else you keep your aliases.
matlab=/usr/local/MATLAB/R20XXx/bin/matlab
matlabcli='/usr/local/MATLAB/R20XXx/bin/matlab -nodisplay -nosplash -nodesktop'
General: How can I run bidspm only certain files, like just the session 02
for example?
Currently there are 2 ways of doing this.
using the
bids_filter_file
parameter or an equivalentbids_filter_file.json
file or its counterpart fieldopt.bidsFilterFile
using the
opt.query
option field.
On the long run the plan is to use only the bids_filter_file
, but for now both
possibilities should work.
bids filter file
This is similar to the way you can “select” only certain files to preprocess with fmriprep.
You can use a opt.bidsFilterFile
field in your options to define a typical
images “bold”, “T1w” in terms of their BIDS entities. The default value is:
struct('fmap', struct('modality', 'fmap'), ...
'bold', struct('modality', 'func', 'suffix', 'bold'), ...
't2w', struct('modality', 'anat', 'suffix', 'T2w'), ...
't1w', struct('modality', 'anat', 'space', '', 'suffix', 'T1w'), ...
'roi', struct('modality', 'roi', 'suffix', 'mask'));
Similarly when using the bidspm you can use the argument bids_filter_file
to
pass a structure or point to a JSON file that would also define typical images
“bold”, “T1w”…
The default content in this case would be:
{
"fmap": { "datatype": "fmap" },
"bold": { "datatype": "func", "suffix": "bold" },
"t2w": { "datatype": "anat", "suffix": "T2w" },
"t1w": { "datatype": "anat", "space": "", "suffix": "T1w" },
"roi": { "datatype": "roi", "suffix": "mask" }
}
So if you wanted to run your analysis on say run 02
and 05
of session 02
,
you would define a json file this file like this:
{
"fmap": { "datatype": "fmap" },
"bold": {
"datatype": "func",
"suffix": "bold",
"ses": "02",
"run": ["02", "05"]
},
"t2w": { "datatype": "anat", "suffix": "T2w" },
"t1w": { "datatype": "anat", "space": "", "suffix": "T1w" },
"roi": { "datatype": "roi", "suffix": "mask" }
}
opt.query
You can select a subset of your data by using the opt.query
.
This will create a “filter” that bids-matlab will use to only “query” and retrieve the subset of files that match the requirement of that filter
In “pure” bids-matlab it would look like:
BIDS = bids.layout(path_to_my_dataset)
bids.query(BIDS, 'data', opt.query)
So if you wanted to run your analysis on say run 02
and 05
of session 02
,
you would define your filter like this:
opt.query.ses = '02'
opt.query.run = {'02', '05'}
General: What happens if we run same code twice?
In the vast majority of cases, if you have not touched anything to your options, you will overwrite the output.
Two exceptions that actually have time stamps and are not over-written:
The
matlabbatches
saved in thejobs
folders as.m
and.json
files.If you have saved your options with
saveOptions
(which is the case for most of bidspm actions), then the output.json
file is saved with a time stamp too.
In most of other cases if you don’t want to overwrite previous output, you will have to change the output directory.
For the preprocess action, in general you would have to specify a different
output_dir
.
For the statistics workflows, you have a few more choices as the name of the output folders includes information that comes from the options and / or the BIDS stats model.
The output folder name (generated by getFFXdir()
for the subject level and by
getRFXdir()
for the dataset level) should include:
the FWHM used on the BOLD images
info specified in the
Inputs
section of the BIDS stats model JSON file (like the name of the task or the MNI space of the input images)the name of the run level node if it is not one of the default one (like
"run level"
).
$ ls demos/MoAE/outputs/derivatives/bidspm-stats/sub-01/stats
# Folder name for a model on the auditory task in SPM's MNI space
# on data smoothed with a 6mm kernel
task-auditory_space-IXI549Space_FWHM-6
Results: How can I change which slices are shown in a montage?
In
bidsspm(..., 'action', 'results', ...)
I get an image with the overlay of different slices. How can I change which slices are shown?
When you define your options the range of slices that are to be shown can be
changed like this (see bidsResults
help section for more information):
% slices position in mm [a scalar or a vector]
opt.results(1).montage.slices = -12:4:60;
% slices orientation: can be 'axial' 'sagittal' or 'coronal'
% axial is default
opt.results(1).montage.orientation = 'axial';
SPM: How can get the data from some specific voxel in a nifti image?
spm_read_vols
This can be done with the spm_read_vols
function.
% get header of Nifti images
header = spm_vol(path_to_image);
% get the data
data = spm_read_vols(header);
data
is an array of size (x, y, z, t) with x, y and z being the spatial dimensions
and t being the temporal dimension.
You can access the data in any voxel by using the proper index.
spm_get_data
% get header of Nifti images
header = spm_vol(path_to_image);
% define voxels to return
XYZ = [10 20; ...
20 25; ...
39 10];
% get the data
data = spm_get_data(header, XYZ)
header
- [1 x n] structure array of file headers withn
being the number of volumesXYZ
- [3 x m] or [4 x m] location matrix {voxel}data
- [n x m] double values
SPM: How can I use SPM image calculator (imcalc
) to create a ROI?
The image calculator utility is accessible in the SPM batch GUI:
Batch --> SPM --> Util --> Image Calculator
You can select the input image you want to use to create a ROI (like an atlas for example), and then set the expression you want to use to only keep certain voxels as part of the binary mask that will define your ROI.
If you want to keep voxels for your ROI that have a value of 51 or 52 or 53, you would use the following expression:
i1==51 || i1==52 || i1 == 53
If you save the batch and its job you will get an .m file that may contain something like this.
matlabbatch{1}.spm.util.imcalc.input = fullpath_to_the_image;
matlabbatch{1}.spm.util.imcalc.output = 'output';
matlabbatch{1}.spm.util.imcalc.outdir = {''};
matlabbatch{1}.spm.util.imcalc.expression = 'i1==51 || i1==52 || i1 == 53';
matlabbatch{1}.spm.util.imcalc.var = struct('name', {}, 'value', {});
matlabbatch{1}.spm.util.imcalc.options.dmtx = 0;
matlabbatch{1}.spm.util.imcalc.options.mask = 0;
matlabbatch{1}.spm.util.imcalc.options.interp = 1;
matlabbatch{1}.spm.util.imcalc.options.dtype = 4;
SPM: How can set the value of a specific voxel in a nifti image?
This can be done with the spm_write_vols
function.
% get nifti header
header = spm_vol(path_to_image);
% get atlas content
content = spm_read_vols(header);
% set the voxel (1,1,1) to 0
x = 1;
y = 1;
z = 1;
content(x,y, z) = 0;
% prepare header for the output
new_header = header;
new_header.fname = 'changed_nifti.nii';
% write mask
spm_write_vol(new_header, content);
SPM: How do I get the header of a nifti image?
Getting the header
This can be done with the spm_vol
function.
% get header of Nifti images
header = spm_vol(path_to_image);
If the input image is a 4D nifti file, the structure header
returned will have as many elements
as they are volumes in the file.
The fields of the structures are:
header.fname
- the filename of the image.header.dim
- the x, y and z dimensions of the volumeheader.dt
- A 1x2 array. First element is datatype (see spm_type). The second is 1 or 0 depending on the endian-ness.header.pinfo
- plane info for each plane of the volume.header.pinfo(1,:)
- scale for each planeheader.pinfo((2,:)
- offset for each plane The true voxel intensities of the jth image are given by:val*header.pinfo(1,j) + header.pinfo(2,j)
header.pinfo((3,:)
- offset into image (in bytes). If the size of pinfo is 3x1, then the volume is assumed to be contiguous and each plane has the same scalefactor and offset.
header.mat
- a 4x4 affine transformation matrix mapping from voxel coordinates to real world coordinates. This can also be directly accessed byspm_get_space
.
Voxel size
The voxel size are the 3 first values of the main diagonal of header.mat
.
Get the value along the main diagonal of the matrix and stores it in a
temporary variable.
temp = diag(header.mat);
Then we only keep the 3 first values of this diagonal to get the x, y, z dimension of each voxel (in mm) of this image.
% the "abs" is there to have the absolute value
VoxelsDimension = abs(temp(1:3));
Getting the voxel subscripts of a given set of world space coordinates
% world coordinate in mm
x = 0;
y = 0;
z = 0;
world_space_coordinates = [x; y; z; 1];
% Remember that if a matrix A performs a certain transformation,
% the matrix inv(A) will perform the reverse transformation
voxel_subscripts = inv(header.mat) * world_space_coordinates;
% we need to use 'round' to get a value that is not in between 2 voxels.
voxel_subscripts = round(voxel_subscripts(1:3));
Getting the world space coordinate of a given voxel
x = 1;
y = 1;
z = 1;
% We have to pad with an extra one to be able
% to multiply it with the transformation matrix.
voxel_subscripts = [x; y; z; 1];
world_space_coordinates = header.mat * voxel_subscripts;
% Only the three first value of this vector are of interest to us
world_space_coordinates = world_space_coordinates(1:3);
SPM: How do I know which matlab function performs a given SPM process?
If you are looking for which SPM function does task X, click on the help
button in the main SPM menu window, then on the task X (e.g Results): the new
window will tell you the name of the function that performs the task you are
interested in (spm_results_ui.m
in this case).
Another tip is that usually when you run a given process in SPM, the command line will display the main function called.
For example clicking on the Check Reg
button and selecting an image to view
display:
SPM12: spm_check_registration (v6245) 13:42:08 - 30/10/2018
========================================================================
Display D:\SPM\spm12\canonical\avg305T1.nii,1
This tells you that this called the spm_check_registration.m
matlab function.
You can also find other interesting suggestions in this discussion of the SPM mailing list: SPM: Peeking under the hood – how?.
Once you have identified the you can then type either type help function_name
if you want some more information about this function or edit function_name
if
you want to see the code and figure out how the function works.
SPM: How do I merge 2 masks with SPM?
Here is a code snippet to merge 2 masks:
path_to_mask_1 = 'FIX_ME';
path_to_mask_2 = 'FIX_ME';
% get header of Nifti images
header_1 = spm_vol(path_to_mask_1);
header_2 = spm_vol(path_to_mask_2);
% if you want to make sure that images are in the same space
% and have same resolution
masks = char({path_to_mask_1; path_to_mask_2});
spm_check_orientations(spm_vol(masks));
% get data of Nifti images
mask_1 = spm_read_vols(header_1);
mask_2 = spm_read_vols(header_2);
% concatenate data along the 4th dimension
merged_mask = cat(4, mask_1, mask_2);
% keep any voxel that has some value along the 4th dimension
merged_mask = any(merged_mask, 4);
% create a new header of the final mask
merged_mask_header = header_1;
merged_mask_header.fname = 'new_mask.nii';
spm_write_vol(merged_mask_header, merged_mask);
Also good way to learn about some basic low level functions of SPM.
spm_vol
: reads the header of a 3D or 4D Nifti imagesspm_read_vols
: given a header it will get the data of Nifti imagespm_write_vol
: given a header and a 3D matrix, it will write a Nifti image
For more info about basic files, check the SPM wikibooks.
SPM: What is the content of the SPM.mat file?
This is here because SPM has the sad (and bad) Matlabic tradition of using variable names
that have often attempted to replicate the notation in the papers to make engineers
and the generally math enclined happy,
rather than the TypicalLongVariableNames
that many programmers and new comers
would prefer to see to help with code readability.
Adapted from: http://andysbrainblog.blogspot.com/2013/10/whats-in-spmmat-file.html
details on experiment
SPM.xY.RT
- TR length (RT =”repeat time”)SPM.xY.P
- matrix of file namesSPM.xY.VY
- (number of runs x 1) struct array of mapped image volumes (.nii file info)SPM.modality
- the data you’re using (PET, FMRI, EEG)SPM.stats.[modality].UFp
- critical F-threshold for selecting voxels over which the non-sphericity is estimated (if required) [default:0.001
]SPM.stats.maxres
- maximum number of residual images for smoothness estimationSPM.stats.maxmem
- maximum amount of data processed at a time (in bytes)SPM.SPMid
- version of SPM usedSPM.swd
- directory for SPM.mat and nii files. default ispwd
basis function
SPM.xBF.name
- name of basis functionSPM.xBF.length
- length in seconds of basisSPM.xBF.order
- order of basis setSPM.xBF.T
- number of subdivisions of TRSPM.xBF.T0
- first time bin (see slice timing)SPM.xBF.UNITS
- options:'scans'
or'secs'
for onsetsSPM.xBF.Volterra
- order of convolutionSPM.xBF.dt
- length of time bin in secondsSPM.xBF.bf
- basis set matrix
Session structure
Note that in SPM lingo sessions are equivalent to a runs in BIDS.
user-specified covariates/regressors
e.g. motion
SPM.Sess([session]).C.C
- (n x c) double regressor (c
is number of covariates,n
is number of sessions)SPM.Sess([session]).C.name
- names of covariates
conditions & modulators specified
i.e. input structure array
SPM.Sess([session]).U(condition).dt
: - time bin length (seconds)SPM.Sess([session]).U(condition).name
- names of conditionsSPM.Sess([session]).U(condition).ons
- onset for condition’s trialsSPM.Sess([session]).U(condition).dur
- duration for condition’s trialsSPM.Sess([session]).U(condition).u
- (t x j) inputs or stimulus function matrixSPM.Sess([session]).U(condition).pst
- (1 x k) peri-stimulus times (seconds)
parameters/modulators specified
SPM.Sess([session]).U(condition).P
- parameter structure/matrixSPM.Sess([session]).U(condition).P.name
- names of modulators/parametersSPM.Sess([session]).U(condition).P.h
- polynomial order of modulating parameter (order of polynomial expansion where 0 is none)SPM.Sess([session]).U(condition).P.P
- vector of modulating valuesSPM.Sess([session]).U(condition).P.P.i
- sub-indices ofU(i).u
for plotting
scan indices for sessions
SPM.Sess([session]).row
effect indices for sessions
SPM.Sess([session]).col
F Contrast information for input-specific effects
SPM.Sess([session]).Fc
SPM.Sess([session]).Fc.i
- F Contrast columns for input-specific effectsSPM.Sess([session]).Fc.name
- F Contrast names for input-specific effectsSPM.nscan([session])
- number of scans per session (or if e.g. a t-test, total number of con*.nii files)
global variate/normalization details
SPM.xGX.iGXcalc
- either'none'
or'scaling'
For fMRI usually is none
(no global normalization).
If global normalization is scaling
, see spm_fmri_spm_ui
for parameters that will then appear under SPM.xGX
.
design matrix information
SPM.xX.X
- design matrix (raw, not temporally smoothed)SPM.xX.name
- cellstr of parameter names corresponding to columns of design matrixSPM.xX.I
- (nScan x 4) matrix of factor level indicators. first column is the replication number. Other columns are the levels of each experimental factor.SPM.xX.iH
- vector of H partition (indicator variables) indicesSPM.xX.iC
- vector of C partition (covariates) indicesSPM.xX.iB
- vector of B partition (block effects) indicesSPM.xX.iG
- vector of G partition (nuisance variables) indicesSPM.xX.K
- cell. low frequency confound: high-pass cutoff (seconds)SPM.xX.K.HParam
- low frequency cutoff valueSPM.xX.K.X0
- cosines (high-pass filter)SPM.xX.W
- Optional whitening/weighting matrix used to give weighted least squares estimates (WLS). If not specifiedspm_spm
will set this to whiten the data and render the OLS estimates maximum likelihood i.e.W*W' inv(xVi.V)
.SPM.xX.xKXs
- space structure for KWX, the ‘filtered and whitened’ design matrixSPM.xX.xKXs.X
- matrix of trials and betas (columns) in each trialSPM.xX.xKXs.tol
- toleranceSPM.xX.xKXs.ds
- vectors of singular valuesSPM.xX.xKXs.u
- u as in X u*diag(ds)*v’SPM.xX.xKXs.v
- v as in X u*diag(ds)*v’SPM.xX.xKXs.rk
- rankSPM.xX.xKXs.oP
- orthogonal projector on XSPM.xX.xKXs.oPp
- orthogonal projector on X’SPM.xX.xKXs.ups
- space in which this one is embeddedSPM.xX.xKXs.sus
- subspace
SPM.xX.pKX
- pseudoinverse of KWX, computed byspm_sp
SPM.xX.Bcov
- xX.pKXxX.VxX.pKX - variance-covariance matrix of parameter estimates (when multiplied by the voxel-specific hyperparameter ResMS of the parameter estimates (ResSS/xX.trRV ResMS) )SPM.xX.trRV
- trace of R*VSPM.xX.trRVRV
- trace of RVRVSPM.xX.erdf
- effective residual degrees of freedom (trRV^2/trRVRV
)SPM.xX.nKX
- design matrix (xX.xKXs.X
) scaled for display (seespm_DesMtx('sca',...
for details)SPM.xX.sF
- cellstr of factor names (columns inSPM.xX.I
, i think)SPM.xX.D
- struct, design definitionSPM.xX.xVi
- correlation constraints (see non-sphericity below)SPM.xC
- struct. array of covariate info
header info
SPM.P
- a matrix of filenamesSPM.V
- a vector of structures containing image volume information.SPM.V.fname
- the filename of the image.SPM.V.dim
- the x, y and z dimensions of the volumeSPM.V.dt
- a (1 x 2) array. First element is datatype (seespm_type
). The second is 1 or 0 depending on the endian-ness.SPM.V.mat
- a (4 x 4) affine transformation matrix mapping from voxel coordinates to real world coordinates.SPM.V.pinfo
- plane info for each plane of the volume.SPM.V.pinfo(1,:)
- scale for each planeSPM.V.pinfo(2,:)
- offset for each plane The true voxel intensities of the jth
image are given by:val*V.pinfo(1,j) + V.pinfo(2,j
)SPM.V.pinfo(3,:)
- offset into image (in bytes). If the size of pinfo is 3x1, then the volume is assumed to be contiguous and each plane has the same scale factor and offset.
structure describing intrinsic temporal non-sphericity
SPM.xVi.I
- typically the same asSPM.xX.I
SPM.xVi.h
- hyperparametersSPM.xVi.V
- xVi.h(1)*xVi.Vi{1} + …SPM.xVi.Cy
- spatially whitened (used by ReML to estimate h)SPM.xVi.CY
-<(Y - )*(Y - )'>
(used byspm_spm_Bayes
)SPM.xVi.Vi
- array of non-sphericity componentsdefaults to
{speye(size(xX.X,1))}
- i.i.d.specifying a cell array of constraints ((Qi)
These constraints invoke
spm_reml
to estimate hyperparameters assuming V is constant over voxels that provide a high precise estimate of xX.V
SPM.xVi.form
- form of non-sphericity (either'none'
or'AR(1)'
or'FAST'
)SPM.xX.V
- Optional non-sphericity matrix.CCov(e)sigma^2*V
. If not specifiedspm_spm
will compute this using a 1st pass to identify significant voxels over which to estimate V. A 2nd pass is then used to re-estimate the parameters with WLS and save the ML estimates (unless xX.W is already specified).
filtering information
SPM.K
- filter matrix or filtered structureSPM.K(s)
- structure array containing partition-specific specificationsSPM.K(s).RT
- observation interval in secondsSPM.K(s).row
- row of Y constituting block/partitionsSPM.K(s).HParam
- cut-off period in secondsSPM.K(s).X0
- low frequencies to be removed (DCT)
SPM.Y
- filtered data matrix
masking information
SPM.xM
- Structure containing masking information, or a simple column vector of thresholds corresponding to the images in VY.SPM.xM.T
- (n x 1) double - Masking indexSPM.xM.TH
- (nVar x nScan) matrix of analysis thresholds, one per imageSPM.xM.I
- Implicit masking (0
–> none;1
–> implicit zero/NaN mask)SPM.xM.VM
- struct array of mapped explicit mask image volumesSPM.xM.xs
- (1 x 1) struct ; cellstr description
design information
self-explanatory names, for once
SPM.xsDes.Basis_functions
- type of basis functionSPM.xsDes.Number_of_sessions
SPM.xsDes.Trials_per_session
SPM.xsDes.Interscan_interval
SPM.xsDes.High_pass_Filter
SPM.xsDes.Global_calculation
SPM.xsDes.Grand_mean_scaling
SPM.xsDes.Global_normalisation
details on scanner data
e.g. smoothness
SPM.xVol
- structure containing details of volume analyzedSPM.xVol.M
- (4 x 4) voxel –> mm transformation matrixSPM.xVol.iM
- (4 x 4) mm –> voxel transformation matrixSPM.xVol.DIM
- image dimensions - column vector (in voxels)SPM.xVol.XYZ
- (3 x S) vector of in-mask voxel coordinatesSPM.xVol.S
- Lebesgue measure or volume (in voxels)SPM.xVol.R
- vector of resel counts (in resels)SPM.xVol.FWHM
- Smoothness of components - FWHM, (in voxels)
info on beta files
SPM.Vbeta
- struct array of beta image handlesSPM.Vbeta.fname
- beta nii file namesSPM.Vbeta.descrip
- names for each beta file
info on variance of the error
SPM.VResMS
- file struct of ResMS image handleSPM.VResMS.fname
- variance of error file name
info on mask
SPM.VM
- file struct of Mask image handleSPM.VM.fname
- name of mask nii file
contrast details
added after running contrasts
SPM.xCon
- Contrast definitions structure array. See alsospm_FcUtil.m
for structure, rules & handling.SPM.xCon.name
- Contrast nameSPM.xCon.STAT
- Statistic indicator character ('T'
,'F'
or'P'
)SPM.xCon.c
- Contrast weights (column vector contrasts)SPM.xCon.X0
- Reduced design matrix data (spans design space under Ho)Stored as coordinates in the orthogonal basis of xX.X from spm_sp (Matrix in SPM99b)
Extract using X0
spm_FcUtil('X0', ...
SPM.xCon.iX0
- Indicates how contrast was specified:If by columns for reduced design matrix then iX0 contains the column indices.
Otherwise, it’s a string containing the
spm_FcUtil
‘Set’ action: Usually one of{'c','c+','X0'}
defines the indices of the columns that will not be tested. Can be empty.
SPM.xCon.X1o
- Remaining design space data (X1o is orthogonal to X0)Stored as coordinates in the orthogonal basis of xX.X from
spm_sp
(Matrix in SPM99b)Extract using X1o
spm_FcUtil('X1o', ...
SPM.xCon.eidf
- Effective interest degrees of freedom (numerator df)Or effect-size threshold for Posterior probability
SPM.xCon.Vcon
- Name of contrast (for ‘T’s) or ESS (for ‘F’s) imageSPM.xCon.Vspm
- Name of SPM image
Statistics: How can change the name of the folder of the subject level analysis?
This can be done by changing the Name
of the run level Nodes
in the BIDS stats model.
If your Nodes.Name
is one of the “default” values:
"run"
"run level"
"run_level"
"run-level"
…
like in the example below
"Nodes": [
{
"Level": "Run",
"Name": "run_level",
...
then src.stats.subject_level.getFFXdir.m()
will set the subject level folder to be named as follow:
sub-subLabel
└── task-taskLabel_space-spaceLabel_FWHM-FWHMValue
However if your Nodes.Name
is not one of the “default” values, like this
"Nodes": [
{
"Level": "Run",
"Name": "parametric",
...
then the subject level folder to be named as follow:
sub-subLabel
└── task-taskLabel_space-spaceLabel_FWHM-FWHMValue_node-parametric
Statistics: How can I see what the transformation in the BIDS stats model will do to my events.tsv?
You can use the bids.util.plot_events
function to help you visualize what events will be used in your GLM.
If you want to vivualize the events file:
bids.util.plot_events(path_to_events_files);
This assumes the events are listed in the trial_type
column (though this can be
changed by the trial_type_col
parameter).
If you want to see what events will be included in your GLM after the transformations are applied:
bids.util.plot_events(path_to_events_files, 'model_file', path_to_bids_stats_model_file);
This assumes the transformations to apply are in the root node eof the model.
In case you want to save the output after the transformation:
% load the events and the stats model
data = bids.util.tsvread(path_to_events_files);
model = BidsModel('file', path_to_bids_stats_model_file);
% apply the transformation
transformers = model.Nodes{1}.Transformations.Instructions;
[new_content, json] = bids.transformers(transformers, data);
% save the new TSV for inspection to make sure it looks like what we expect
bids.util.tsvwrite(fullfile(pwd, 'new_events.tsv'), new_content);
Statistics: How should I name my conditions in my events.tsv?
In BIDS format, conditions should be named in the trial_type
column of the events.tsv
file.
Some good practices for naming “things” can probably be applied here.
use only alphanumeric characters, underscores and hyphens, avoid spaces in the condition names
For example: foo_bar
is ok, but f$o}o b^a*r
is not.
the condition names should be short AND descriptive AND human readable
For example: 1
or one
or condition1
are short but not descriptive.
An extra requirement to have condition names that can work with bidspm is that condition names ending with an underscore followed by one or more digits may lead to unwanted behavior (error or nothing happening
see issue) when computing results of a GLM.
So for example:
happy_face1
and house123
are ok, but happy_face_1
and house_123
are not.
If your BIDS dataset has conditions that do not follow this rule,
then you can use
the Replace
variable transform
in your BIDS statistical model
to rename them on the fly without having to manually edit potentially dozens of files.
See also example below.
Say one of your events.tsv files looks like this:
onset |
duration |
trial_type |
---|---|---|
2 |
2 |
happy_face_1 |
4 |
2 |
house_2 |
5 |
2 |
happy_face_2 |
8 |
2 |
house_4 |
You can add the following transformation to the first node (usually the run level node) of your BIDS stats model.
{
"Nodes": [
{
"Level": "Run",
"Name": "run_level",
"GroupBy": [
"run",
"subject"
],
"Transformations": {
"Description": "Replace",
"Instruction": [
{
"Name": "Replace",
"Input": "trial_type",
"Replace": [
{
"key": "happy_face_1",
"value": "happy_face1"
},
{
"key": "house_2",
"value": "house2"
},
{
"key": "happy_face_2",
"value": "happy_face2"
},
{
"key": "house_4",
"value": "house4"
}
]
}
]
},
"Model": {
"X": [
"trial_type.happy_face*",
"trial_type.house*"
],
"Description": "the rest of the bids stats model would go below this as usual."
}
}
]
}
Related issue: https://github.com/cpp-lln-lab/bidspm/issues/973
Statistics: How should I structure my data to run my statistical analysis?
The main thing to remember is that bidspm will read the events.tsv files from
your raw BIDS data set and will read the bold images from a bidspm-preproc
folder.
If your data was preprocessed with fmriprep, bidspm will first need to copy,
unzip and smooth the data into a bidspm-preproc
folder
Here is an example of how the data is organized for the MoAE fmriprep demo and
what the bidspm
BIDS call would look like.
├── inputs
│ ├── fmriprep # fmriprep preprocessed BIDS dataset
│ | ├── dataset_description.json
│ │ └── sub-01
│ │ ├── anat
│ │ ├── figures
│ │ └── func
│ │ ├── sub-01_task-auditory_desc-confounds_timeseries.json
│ │ ├── sub-01_task-auditory_desc-confounds_timeseries.tsv
│ │ ├── sub-01_task-auditory_space-MNI152NLin6Asym_desc-brain_mask.json
│ │ ├── sub-01_task-auditory_space-MNI152NLin6Asym_desc-brain_mask.nii.gz
│ │ ├── sub-01_task-auditory_space-MNI152NLin6Asym_desc-preproc_bold.json
│ │ └── sub-01_task-auditory_space-MNI152NLin6Asym_desc-preproc_bold.nii.gz
│ └── raw # raw BIDS dataset
│ ├── dataset_description.json
│ ├── README
│ ├── sub-01
│ │ ├── anat
│ │ │ └── sub-01_T1w.nii
│ │ └── func
│ │ ├── sub-01_task-auditory_bold.nii
│ │ └── sub-01_task-auditory_events.tsv
│ └── task-auditory_bold.json
├── models # models used to run the GLM
│ ├── model-MoAEfmriprep_smdl.json
│ ├── model-MoAEindividual_smdl.json
│ └── model-MoAE_smdl.json
├── options
└── outputs
└── derivatives
└── bidspm-preproc # contains data taken from fmriprep and smoothed
├── dataset_description.json
├── README
├── jobs
│ └── auditory
│ └── sub-01
└── sub-01
├── anat
└── func
├── sub-01_task-auditory_desc-confounds_timeseries.json
├── sub-01_task-auditory_desc-confounds_timeseries.tsv
├── sub-01_task-auditory_space-MNI152NLin6Asym_desc-brain_mask.json
├── sub-01_task-auditory_space-MNI152NLin6Asym_desc-brain_mask.nii
├── sub-01_task-auditory_space-MNI152NLin6Asym_desc-preproc_bold.json
├── sub-01_task-auditory_space-MNI152NLin6Asym_desc-preproc_bold.nii
├── sub-01_task-auditory_space-MNI152NLin6Asym_desc-smth8_bold.json
└── sub-01_task-auditory_space-MNI152NLin6Asym_desc-smth8_bold.nii
WD = fileparts(mfilename('fullpath'));
subject_label = '01';
bids_dir = fullfile(WD, 'inputs', 'raw');
output_dir = fullfile(WD, 'outputs', 'derivatives');
preproc_dir = fullfile(output_dir, 'bidspm-preproc');
model_file = fullfile(pwd, 'models', 'model-MoAEfmriprep_smdl.json');
bidspm(bids_dir, output_dir, 'subject', ...
'participant_label', {subject_label}, ...
'action', 'stats', ...
'preproc_dir', preproc_dir, ...
'model_file', model_file, ...
'fwhm', 8, ...
'options', opt);
Generated by FAQtory