Generate design matrices, contrasts, and scripts to set up FSL randomise analyses.
If your project is managed with UV:
# Navigate to your project directory
cd /path/to/your-project
# Add the randomise-prep package from its location
uv add /path/to/randomise-prep
# Sync the environment
uv syncIf you're using a standard virtual environment:
# Navigate to your project directory
cd /path/to/your-project
# Create and activate a virtual environment (example with venv)
python -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate.bat # Windows
# Install randomise-prep in editable mode
pip install -e /path/to/randomise-prepThe -e (editable) flag links directly to the package source, so any changes to randomise-prep are immediately available in your environment.
from randomise_prep import setup_randomise_tfce
import pandas as pd
# 1-sided 1-sample t-test
script_path = setup_randomise_tfce(
input_files=[f"subj{i}_contrast.nii.gz" for i in range(1, 11)],
group_mask="group_mask.nii.gz",
output_directory="output_onesided",
analysis_type="onesample_1sided",
num_perm=1000
)
# 2-sided 1-sample t-test
script_path = setup_randomise_tfce(
input_files=[f"subj{i}_contrast.nii.gz" for i in range(1, 11)],
group_mask="group_mask.nii.gz",
output_directory="output_twosided",
analysis_type="onesample_2sided",
num_perm=1000
)
# GLM analysis with t-tests only
design_matrix = pd.DataFrame({
'age': [25, 30, 35, 28, 32, 27, 29, 31, 26, 33],
'group1': [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
'group2': [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
})
contrast = {
'age_effect': 'age',
'group1_vs_group2': 'group1 - group2'
}
script_path = setup_randomise_tfce(
input_files=[f"subj{i}_contrast.nii.gz" for i in range(1, 11)],
group_mask="group_mask.nii.gz",
output_directory="output_glm",
analysis_type="glm",
num_perm=1000,
design_matrix=design_matrix,
contrast=contrast
)
# GLM analysis with t-tests only *but* renames output files using keys from contrast dictionary instead of ttest1, ttest2, etc.
# AND replaces '_corrp_' with '_1minuspvalue_' in filenames
design_matrix = pd.DataFrame({
'age': [25, 30, 35, 28, 32, 27, 29, 31, 26, 33],
'group1': [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
'group2': [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
})
contrast = {
'age_effect': 'age',
'group1_vs_group2': 'group1 - group2'
}
script_path = setup_randomise_tfce(
input_files=[f"subj{i}_contrast.nii.gz" for i in range(1, 11)],
group_mask="group_mask.nii.gz",
output_directory="output_glm",
analysis_type="glm",
num_perm=1000,
design_matrix=design_matrix,
contrast=contrast,
rename_output=True
)
# GLM analysis with F-tests
ftest = {
'age_effect': ['age_effect'], # F-test for age effect
'group_effect': ['group1_vs_group2'] # F-test for group effect
}
script_path = setup_randomise_tfce(
input_files=[f"subj{i}_contrast.nii.gz" for i in range(1, 11)],
group_mask="group_mask.nii.gz",
output_directory="output_glm_ftest",
analysis_type="glm",
num_perm=1000,
design_matrix=design_matrix,
contrast=contrast,
ftest=ftest
)
# GLM analysis with F-tests using rename option (replaces numbers in file output with key strings)
# AND replaces '_corrp_' with '_1minuspvalue_' in filenames
ftest = {
'age_effect': ['age_effect'], # F-test for age effect
'group_effect': ['group1_vs_group2'] # F-test for group effect
}
script_path = setup_randomise_tfce(
input_files=[f"subj{i}_contrast.nii.gz" for i in range(1, 11)],
group_mask="group_mask.nii.gz",
output_directory="output_glm_ftest",
analysis_type="glm",
num_perm=1000,
design_matrix=design_matrix,
contrast=contrast,
ftest=ftest,
rename_output=True
)
# 1-sided 1-sample t-test with rename option (replaces '_corrp_' with '_1minuspvalue_')
script_path = setup_randomise_tfce(
input_files=[f"subj{i}_contrast.nii.gz" for i in range(1, 11)],
group_mask="group_mask.nii.gz",
output_directory="output_onesided_rename",
analysis_type="onesample_1sided",
num_perm=1000,
rename_output=True
)
# 2-sided 1-sample t-test with rename option (replaces '_corrp_' with '_1minuspvalue_')
script_path = setup_randomise_tfce(
input_files=[f"subj{i}_contrast.nii.gz" for i in range(1, 11)],
group_mask="group_mask.nii.gz",
output_directory="output_twosided_rename",
analysis_type="onesample_2sided",
num_perm=1000,
rename_output=True
)input_files(required): List of 3D nifti files (typically within-subject contrast estimates)group_mask(required): Binary mask indicating voxels where everybody has dataoutput_directory(required): Path to output directoryanalysis_type(required): Type of analysis - 'onesample_1sided', 'onesample_2sided', or 'glm'num_perm(default: 1000): Number of permutationsdesign_matrix(required for 'glm' analysis): pandas DataFrame for GLM analysiscontrast(required for 'glm' analysis): Dictionary mapping contrast names to expressionsftest(optional): List of lists specifying F-tests for 'glm' analysisrename_output(optional): If True, rename output files for better readability:- For 'glm' analysis: rename using contrast/ftest keys AND replace 'corrp' with '1minuspvalue'
- For 'onesample_1sided' and 'onesample_2sided': replace 'corrp' with '1minuspvalue'
- 1-sided 1-sample t-test: Single input file → tests mean > 0
- 2-sided 1-sample t-test: Multiple input files → tests mean ≠ 0
- GLM analysis: Custom design matrix with t-tests and optional F-tests
input_data4d.nii.gz: Concatenated 4D input filedesign.mat: Design matrix file (GLM only)design.con: Contrast file (2-sided and GLM)design.fts: F-test file (2-sided and GLM)randomise_call.sh: Executable shell script
See examples/basic_usage.py for complete working examples.
Run the test suite to verify everything works correctly:
# Install test dependencies
uv sync --extra test
# Run all tests
python run_tests.py
# Or run with pytest directly
uv run pytest tests/ -vThe test suite includes:
- Unit tests for all analysis types and error handling
- Integration tests for file generation and content validation
- Example tests to verify the basic usage examples work
- FSL (for running randomise)
- Python 3.11+
- NumPy, Pandas, Nilearn