├── .github └── workflows │ └── jekyll-gh-pages.yml ├── BOLD-CSF_methods_flowchart.png ├── LICENSE ├── README.md ├── config.yml └── get_BOLD_timeseries_feb24.sh /.github/workflows/jekyll-gh-pages.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a Jekyll site to GitHub Pages 2 | name: Deploy Jekyll with GitHub Pages dependencies preinstalled 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["main"] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 19 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 20 | concurrency: 21 | group: "pages" 22 | cancel-in-progress: false 23 | 24 | jobs: 25 | # Build job 26 | build: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v4 31 | - name: Setup Pages 32 | uses: actions/configure-pages@v4 33 | - name: Build with Jekyll 34 | uses: actions/jekyll-build-pages@v1 35 | with: 36 | source: ./ 37 | destination: ./_site 38 | - name: Upload artifact 39 | uses: actions/upload-pages-artifact@v3 40 | 41 | # Deployment job 42 | deploy: 43 | environment: 44 | name: github-pages 45 | url: ${{ steps.deployment.outputs.page_url }} 46 | runs-on: ubuntu-latest 47 | needs: build 48 | steps: 49 | - name: Deploy to GitHub Pages 50 | id: deployment 51 | uses: actions/deploy-pages@v4 52 | -------------------------------------------------------------------------------- /BOLD-CSF_methods_flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evavanheese/BOLD-CSF/e3103a22f78c3cd4f0b74e80a24165c84f8ed855/BOLD-CSF_methods_flowchart.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Eva van Heese 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BOLD-CSF coupling 2 | 3 | ## The theory 4 | The BOLD-CSF coupling method was proposed by [Fultz and colleagues (2019)](https://www.science.org/doi/full/10.1126/science.aax5440). The coupling monitors a cerebral blood volume-driven CSF inflow at the fourth ventricle, linked to fluctuations of neuronal activity. An anti-correlation is observed between cortical grey matter activity (BOLD signal) and CSF waves, in awake participants, but even stronger during sleep. The coupling between the two signals is explained by the following mechanism: activity fluctuations in the cortex give rise to cerebral blood volume changes, which in turn push CSF out, or allow for CSF inflow, due to the restricted space inside the skull. The BOLD-CSF coupling method has been applied in healthy people during sleep (Fultz et al., 2019), Alzheimer’s Disease during wake (Han et al., 2021) and Cerebral Amyloid Angiopathy during wake (Hirschler et al., in prep). 5 | 6 | ## Overview of general workflow 7 | To retrieve the BOLD-CSF coupling, separate processing of the BOLD and CSF signal is required: 8 | 9 | BOLD signal 10 | - T1w-image processing: segmentation of cortical grey matter 11 | - functional image processing: slice-time and motion correction 12 | - register both images to the same space to retrieve the BOLD signal in the mask 13 | 14 | CSF signal 15 | - functional image processing: NO corrections! 16 | - select ROI location suitable for your dataset and draw manual ROIs on the bottom slice 17 | - retrieve the CSF signal in the manual ROIs 18 | 19 | Both signals are normalised, detrended, and low-pass filtered. The cross-correlation is calculated by taking the peak closest to 0. Calculate the BOLD-CSF correlation and dBOLD-CSF correlation amplitude and lag for statistical analysis. 20 | 21 | 22 | 23 | ## Required software and dependencies 24 | We recommend the use of standardised software pipelines for the image processing steps. In this study, T1w images were processed with FreeSurfer to segment the cortex. The fMRI data were processed using HALFpipe (Waller et al., 2022). Registration was done with ANTs. 25 | 26 | ## Retrieving the BOLD signal 27 | ### HALFpipe 28 | We used [HALFpipe](https://github.com/HALFpipe/HALFpipe) to pre-process the fMRI signal and perform a slice-time and motion correction. HALFpipe can be accessed as a container through Docker/Apptainer on a server. The apptainer command to open the HALFpipe GUI our slurm server looked like this: 29 | ``` 30 | apptainer run /path/to/container/halfpipe-latest.sif --keep none --verbose 31 | ``` 32 | 33 | A GUI will open that allows you to specify settings for preprocessing. You can type as usual, but only use ‘delete’ (not ‘backspace’) to remove text. Use ‘enter’ to confirm an option and the spacebar to select or deselect options in a multiple-choice menu. Go back to the previous question using ctrl + ‘C’. We used the following preprocessing settings: 34 | ``` 35 | Specify working directory: 36 | /path/to/workdir/ 37 | 38 | Is the data available in BIDS format? 39 | yes 40 | 41 | Specify data directory: 42 | /path/to/bidsdir/ 43 | ``` 44 | The GUI now prints how many T1w and BOLD images have been found in that data directory. Confirm the numbers or go back to your data. 45 | ``` 46 | Do slice timing? 47 | yes 48 | 49 | Missing slice acquisition direction values. Specify slice acquisition direction 50 | Inferior to superior 51 | 52 | Check slice timing values. Proceed with these values? 53 | yes 54 | 55 | Remove initial volumes from scans? 56 | [0] 57 | 58 | Specify first-level features? 59 | No 60 | 61 | Output a preprocessed image? 62 | Yes 63 | 64 | Specify image name. 65 | [preproc] 66 | ``` 67 | This name will be used to save your output files, if you choose to run different preprocessing settings at the same time to compare, specify the difference in this name. 68 | ``` 69 | Apply smoothing? 70 | No 71 | 72 | Do grand mean scaling? 73 | No 74 | 75 | Apply a temporal filter? 76 | No 77 | 78 | Remove confounds? 79 | Motion parameters (only) 80 | 81 | Output another preprocessed image? 82 | No 83 | ``` 84 | Preprocessing takes approximately 1-3 hours per subject depending on the available memory and parallel processing options. 85 | 86 | In the specified output folder, data is saved in a ‘reports’, ‘rawdata’, and ‘derivatives’ folder. The output we use for the next steps in this analysis are saved in derivatives/halfpipe/sub-XX/func/sub-XX_task-rest_setting_{your_label}_bold.nii.gz. 87 | 88 | ### Cortical grey matter segmentation 89 | We used [FreeSurfer recon-all](https://freesurfer.net/fswiki/recon-all) for whole-brain segmentation and took the voxels classified as grey matter in the cortical ribbon (ribbon.mgz in {subject}/mri). 90 | 91 | ### Image registration 92 | As the motion- and slice-time corrected functional images generated by HALFpipe are in MNI standard space ([ICBM-152 atlases](https://nist.mni.mcgill.ca/icbm-152-nonlinear-atlases-2009/)), we will register the grey matter mask (currently in T1w image space) to the same MNI space using [ANTs](https://github.com/ANTsX/ANTs)'s antsREgistrationSyN.sh function. 93 | 94 | An example command to register the T1w image of one participant to MNI space: 95 | ``` 96 | antsRegistrationSyN.sh -d 3 -f {MNI_template}.nii.gz -m {sub_T1}.nii.gz -o {T1_MNI_} -n 2 -t s -y 1 -e 2 97 | ``` 98 | 99 | Consequently, to apply the transformations to the grey matter mask: 100 | ``` 101 | antsApplyTransforms \ 102 | -d 3 \ 103 | -i {sub_GM_mask}.nii.gz \ 104 | -r {MNI_template}.nii.gz \ 105 | -t {T1_MNI_}1Warp.nii.gz \ 106 | -t {T1_MNI_}0GenericAffine.mat \ 107 | -n GenericLabel \ 108 | -o {sub_GM_mask_MNI}.nii.gz 109 | ``` 110 | 111 | ### Signal extraction 112 | Before extracting the BOLD signal from the grey matter mask, ensure that: 113 | 1) both images (grey matter mask and functional) are of the same dimensions and orientations. We resampled the grey matter mask to the functional image using AFNI: 114 | ``` 115 | 3dresample -master {sub_func_preprocessed}.nii.gz -input {sub_GM_mask_MNI}.nii.gz -prefix {sub_GM_mask_MNI_resampled}.nii.gz 116 | ``` 117 | 2) you remove voxels from the mask that are outside the functional image (as they will drag the mean signal down). We multiplied the grey matter mask with the functional image using fslmaths and binarised the mask again: 118 | ``` 119 | fslmaths {sub_GM_mask_MNI_resampled}.nii.gz -mul {sub_func_preprocessed}.nii.gz {sub_GM_mask_MNI_resampled_nonzero}.nii.gz 120 | 121 | fslmaths {sub_GM_mask_MNI_resampled_nonzero}.nii.gz -thr 0.5 -bin {sub_GM_mask_MNI_resampled_nonzero_bin}.nii.gz 122 | ``` 123 | 124 | We extracted the BOLD signal using fslmeants (which outputs a .txt file of the timeseries): 125 | ``` 126 | fslmeants -i {sub_func_preprocessed}.nii.gz -m {sub_GM_mask_MNI_resampled_nonzero_bin}.nii.gz -o [sub_output_BOLD_timeseries].txt 127 | ``` 128 | 129 | All previously described steps to retrieve the BOLD signal (except for running HALFpipe) are performed by the [get_BOLD_timeseries.sh script](https://github.com/evavanheese/BOLD-CSF/blob/main/get_BOLD_timeseries_feb24.sh) 130 | 131 | ## Retrieving the CSF signal 132 | The aim of this step is to draw an ROI on a location that shows sufficient CSF signal. In case of an existing dataset: depending on how consistently the field-of-view is planned during fMRI acquisition, this could vary little to greatly between participants. Preferably, the CSF ROI is NOT placed in a larger area, i.e. where CSF moves more isotropically (for example in the middle of the fourth ventricle) but rather at the bottom or top of the fourth ventricle or in the cerebral aqueduct/central canal. It is imperative that the ROI is drawn at the bottom slice (see inflow effect explained in Fultz et al. 2019, [supplementary material](https://www.science.org/doi/full/10.1126/science.aax5440#supplementary-materials)) and that the image is not processsed. 133 | 134 | When drawing the regions of interest: 135 | - Select the bottom slice on the functional image, keep an anatomical scan for reference. 136 | - Scroll through the volumes (i.e. time) and look at the CSF signal in the transverse view. 137 | - Select at least 3 voxels that are generally included in the CSF area, preferably more. 138 | - In case of much motion, select a somewhat larger area to make sure there is always CSF included in the mask over time. 139 | 140 | We extracted the CSF signal using fslmeants (which outputs a .txt file of the timeseries): 141 | ``` 142 | fslmeants -i {sub_func_raw}.nii.gz -m {sub_CSF_manual_mask}.nii.gz -o [sub_output_CSF_timeseries].txt 143 | ``` 144 | 145 | ## Signal processing and cross-correlation 146 | We used Matlab functions for: 147 | - Signal normalisation 148 | - Detrending of the signal (using `spline_detrend` from chronux) 149 | - Low-pass filtering (<0.1 Hz) 150 | - Cross-correlation 151 | 152 | Scripts to perform these steps and make BOLD-CSF output figures with the same layout and formatting as published in the original paper are available upon request. 153 | 154 | ## Recommended checks to perform along the way 155 | - Open T1w images and grey matter masks to confirm accurate segmentation by FreeSurfer (remove mask voxels close to or inside CSF) 156 | - Open T1w and functional images to confirm accurate registration to MNI space 157 | - Plot raw / normalised / detrended / low-pass filtered signal to confirm these processing steps worked well 158 | - Plot TF plots to confirm filtering 159 | - Plot both processed signals and see whether they show any kind of coupling 160 | - Plot cross-correlation (lags over x axis) for some subjects to assess lag (does it make sense) 161 | 162 | ## Sources 163 | Han, F., Chen, J., Belkin-Rosen, A., Gu, Y., Luo, L., Buxton, O. M., Liu, X., & the Alzheimer’s Disease Neuroimaging Initiative. (2021). Reduced coupling between cerebrospinal fluid flow and global brain activity is linked to Alzheimer disease–related pathology. PLoS Biology, 19(6), e3001233. https://doi.org/10.1371/journal.pbio.3001233 164 | 165 | Fultz, N. E., Bonmassar, G., Setsompop, K., Stickgold, R. A., Rosen, B. R., Polimeni, J. R., & Lewis, L. D. (2019). Coupled electrophysiological, hemodynamic, and cerebrospinal fluid oscillations in human sleep. Science, 366(6465), 628–631. https://doi.org/10.1126/science.aax5440 166 | 167 | Waller, L., Erk, S., Pozzi, E., & Toenders, Y. J. (2022). ENIGMA HALFpipe: Interactive, reproducible, and efficient analysis for resting‐state and task‐based fMRI data. Human Brain Mapping. https://onlinelibrary.wiley.com/doi/abs/10.1002/hbm.25829 168 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | name: BOLD CSF documentation 2 | theme: minima 3 | -------------------------------------------------------------------------------- /get_BOLD_timeseries_feb24.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##script to register fMRI to grey matter mask & extract fMRI timeseries based on mask 3 | ##Eva van Heese 4 | ##Feb 2024, version 2.0 5 | ##see steps described on Github page: https://evavanheese.github.io/BOLD-CSF/ 6 | 7 | ##input requirements 8 | #T1w image (.nii.gz) in T1 space 9 | #Grey matter mask of the cortex in T1 space (.nii.gz) 10 | #processed fMRI image in MNI space (.nii.gz) 11 | #MNI template (.nii.gz) best resolution possible (here we use 1mm) 12 | #list of subjects to be processed subj_list.txt (01, 02, 03) in workdir 13 | 14 | ##required adjustments to this script 15 | #change paths under define paths 16 | #change original name t1w image in line 43 to match 17 | #change original name GM mask in line 46 to match 18 | #change original name functional in line 47 to match 19 | #skip step 1 if not relevant 20 | #adjust file names in step 2 and 3 if step 1 was skipped 21 | 22 | ##expected output for each subject 23 | #in output folder: 24 | #T1w image in MNI space 25 | #final GM mask in MNI space 26 | #text file with timeseries extracted from GM mask 27 | 28 | #save terminal output to get_BOLD_timeseries_log.txt 29 | #xxx 30 | 31 | #required software and packages 32 | module load ANTs 33 | 34 | ##define paths 35 | workdir="/home/anw/evanheese/my-scratch/brain_clear_narco/bold-csf/BOLD_signal/test123" 36 | t1dir="/home/anw/evanheese/my-scratch/brain_clear_narco/bold-csf/t1_freesurfer_output" #location T1 scans 37 | GMmaskdir="/home/anw/evanheese/my-scratch/brain_clear_narco/bold-csf/BOLD_signal/GM_masks" 38 | fmridir="/home/anw/evanheese/my-scratch/brain_clear_narco/bold-csf/BOLD_signal/processed_rsfMRI_data" 39 | MNI_template="/home/anw/evanheese/my-scratch/brain_clear_narco/bold-csf/BOLD_signal/mni_icbm152_t1_tal_nlin_asym_09c.nii" 40 | module load FreeSurfer 41 | 42 | mkdir ${workdir}/output 43 | 44 | ##read subjects from subj_list.txt and register T1 to MNI standard space 45 | while read -r sub; do 46 | 47 | echo "__________working on subject ${sub}__________" 48 | mkdir ${workdir}/output/sub-${sub} 49 | 50 | #get all required files in the temporary dir 51 | mkdir ${workdir}/temp 52 | cp ${t1dir}/00${sub}_smri_t1/mri/T1.mgz ${workdir}/temp/sub-${sub}_t1.mgz 53 | 54 | mri_convert ${workdir}/temp/sub-${sub}_t1.mgz ${workdir}/temp/sub-${sub}_t1.nii.gz 55 | cp ${GMmaskdir}/00${sub}_smri_t1_bilat_GM_mask.nii.gz ${workdir}/temp/sub-${sub}_GM_mask_t1space.nii.gz 56 | cp ${fmridir}/sub-${sub}_task-rest_setting-preproc_bold.nii.gz ${workdir}/temp/ 57 | cp ${MNI_template} ${workdir}/temp/ 58 | 59 | cd ${workdir}/temp 60 | 61 | #step 1 [AFNI]: de-oblique t1 and GM mask (specific to our dataset which had oblique images - skip if not relevant) 62 | #echo "***deoblique t1w image and GM mask***" 63 | #apptainer run --writable /mnt/scratch-01/anw/share-np/AFNIr/ 3dWarp -deoblique -prefix ${workdir}/temp/sub-${sub}_t1_deobl.nii.gz ${workdir}/temp/sub-${sub}_t1.nii.gz 64 | #apptainer run --writable /mnt/scratch-01/anw/share-np/AFNIr/ 3dWarp -deoblique -prefix ${workdir}/temp/sub-${sub}_GM_mask_t1space_deobl.nii.gz ${workdir}/temp/sub-${sub}_GM_mask_t1space.nii.gz 65 | 66 | #registration t1 to MNI space 67 | echo "***starting registration to MNI space***" 68 | 69 | #step 2 [ANTs]: 3-stage registration of T1w image to MNI 2009c template 70 | antsRegistrationSyN.sh -d 3 -f ${MNI_template} -m sub-${sub}_t1.nii.gz -o sub-${sub}_t1_MNI_ -n 2 -t s -y 1 -e 2 71 | 72 | #step 3 [ANTs]: apply warp from step 2 to GM mask 73 | antsApplyTransforms \ 74 | -d 3 \ 75 | -i sub-${sub}_GM_mask_t1space.nii.gz \ 76 | -r ${MNI_template} \ 77 | -t sub-${sub}_t1_MNI_1Warp.nii.gz \ 78 | -t sub-${sub}_t1_MNI_0GenericAffine.mat \ 79 | -n GenericLabel \ 80 | -o sub-${sub}_GM_mask_MNIspace.nii.gz 81 | 82 | #step 4 [AFNI]: resample to fMRI (2mm slices) 83 | echo "--resampling image to fmri" 84 | apptainer run --writable /mnt/scratch-01/anw/share-np/AFNIr/ 3dresample -master sub-${sub}_task-rest_setting-preproc_bold.nii.gz -input sub-${sub}_GM_mask_MNIspace.nii.gz -prefix sub-${sub}_GM_mask_MNIspace_resampled2fmri.nii.gz 85 | 86 | #step 5 [FSL]: get rid of GM mask voxels outside fmri FOV -> values are 0 and drag mean signal down (multiply mask with functional image) 87 | echo "----excluding 0 values outside field of view" 88 | fslmaths sub-${sub}_GM_mask_MNIspace_resampled2fmri.nii.gz -mul sub-${sub}_task-rest_setting-preproc_bold.nii.gz sub-${sub}_GM_mask_MNIspace_resampled2fmri_nonzero.nii.gz 89 | 90 | #step 9 [FSL]: binarise again 91 | fslmaths sub-${sub}_GM_mask_MNIspace_resampled2fmri_nonzero.nii.gz -thr 0.5 -bin sub-${sub}_GM_mask_MNIspace_resampled2fmri_nonzero_bin.nii.gz 92 | 93 | #step 10 [FSL]: extract timeseries 94 | echo "------extracting BOLD timeseries" 95 | fslmeants -i ${workdir}/temp/sub-${sub}_task-rest_setting-preproc_bold.nii.gz -m sub-${sub}_GM_mask_MNIspace_resampled2fmri_nonzero_bin.nii.gz -o sub-${sub}_cort_BOLD_signal_in_mask.txt 96 | 97 | #copy useful output to output folder 98 | cp sub-${sub}_t1_MNI_Warped.nii.gz sub-${sub}_GM_mask_MNIspace_resampled2fmri_nonzero_bin.nii.gz sub-${sub}_cort_BOLD_signal_in_mask.txt ${workdir}/output/sub-${sub} 99 | 100 | #comment the next line to avoid removing the temp folder containing output from intermediate steps 101 | #rm -r ${workdir}/temp 102 | 103 | echo "--------done with subject ${sub}" 104 | done < ${workdir}/subj_list.txt 105 | --------------------------------------------------------------------------------