Contents
- Processing Parameters
- Load DICOMs
- Checking Rx
- Regridding data
- ======================= Processing TOF ===========================
- GUI for Defining 3D Vessel Mask from TOF
- Getting skeleton.
- Getting endpoints.
- Get the farthest two endpoints.
- Pruning skeleton.
- Compute distance transforms of voxels to the CCA-ICA skeleton.
- Compute typical radius of vessel, then extract CCA/ICA carotids mask.
- Computing distance along skeleton
- Identify CCA and ICA skeletons and masks.
- Assigning every CCA/ICA voxel a distance
- Saving off TOF processing outputs.
- ===================== Processing OSPCMRI =========================
- Retrieve the OSPCMRI data and OSPCMRI mask for further processing.
- Interpolate missing/outlier timepoints
- Smooth waveforms (Optional)
- Retricting mask to significantly positive OSPCMRI values
- Use the mask to extract voxels
- Update mask by correlation filter (Optional)
- Compute distance values in OSPCMRI mask.
- Averaging at axial locations along vessel
- Creating masks for CCA/ICA along axial locations
- Normalize all waveforms between 0 and 1
- Compute Pulse Wave Velocity (PWV)!
- Compute PI and RI at every location
- Generate waves figure
- Writing results to file
===============================================================
=================== CFMRI OSPCMRI Pipeline ====================
Pipeline Version: 1.0.0 (2025/09/25).
For any questions, please contact Conan Chen.
===============================================================
Processing Parameters
Showing the processing flags used.
==================== Processing parameters ==================== tofdir = '/Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0007_tof_fl3d_tra_p2_Slabs4_PF66' ospcmridir = '/Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P' procdir = '/Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/' locdir = '/Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0002_localizer_64ch/' flag_WLS = 0 flag_upsample = 1 flag_smooth = 1 flag_robust = 1 flag_reuseTOFmask = 0 flag_publishopen = 1 flag_publishcode = 0 flag_publish = 1 flag_padnslices = 5 flag_overwrite = 1 flag_manualBP = 0 flag_makefigs = 1 flag_distbinwidthmm = 2 flag_debug = 0 flag_corrmaskthresh = 0.8 flag_corrmask = 1 flag_corritermask = 0 flag_checkRx = 1 flag_censoriter = 1 flag_censor = 1 ===============================================================
Load DICOMs
Loading DICOMs and displaying basic subject information.
dcm2niix -w 1 -f %s_%d -o /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/ /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P
dcm2niix -w 1 -f %s_%d -o /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/ /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0007_tof_fl3d_tra_p2_Slabs4_PF66
Processing Subject SubjectID:
dataset.patientInfo =
ID: 'SubjectID'
age: 100
sex: 'M/F/O'
height: 1.7526
weight: 72.5748
dataset.scanInfo =
name: 'OSPCMRI_sag_in-plane_FA10_Venc100_left'
side: 'left'
Checking Rx
The figure below provides a low-resolution, sagittal view of the prescriptions for the localizer (grayscale), TOF (blue-green-yellow) and OSPCMRI (red-orange-white) scans. For proper positioning, the top of the TOF Rx should be roughly aligned with the bottom of the cerebellum, and the OSPCMRI Rx up-down (superior-inferior) positioning should track closely with the TOF. Significant deviations may indicate improper scan positioning, and potentially mean the OSPCMRI scans do NOT cover the CCA/ICA segment of interest.
dcm2niix -w 1 -f %s_%d -o /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/ /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0002_localizer_64ch/
3dresample -overwrite -input 2_localizer_64ch_i00001.nii -orient RAI -overwrite -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_LocSag_lowres.nii -dxyz 21 5 5
3dwarp -overwrite -deoblique -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_OSPCMRI_dbq.nii 19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii'[0]'
++ 3dWarp: AFNI version=AFNI_23.1.00 (Apr 7 2023) [64-bit]
++ Authored by: RW Cox
** AFNI converts NIFTI_datatype=4 (INT16) in file /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii to FLOAT32
Warnings of this type will be muted for this session.
Set AFNI_NIFTI_TYPE_WARN to YES to see them all, NO to see none.
# mat44 Obliquity Transformation ::
0.745690 0.662844 0.067706 64.207626
-0.666044 0.738774 0.102952 -10.895149
0.018222 -0.121865 0.992379 -11.268112
++ Using minimum spacing of 1.000000 mm for new grid spacing
3dresample -overwrite -rmode Cu -input /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_OSPCMRI_dbq.nii -dxyz 21 5 5 -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_OSPCMRI_dbq_RAI.nii
3dZeropad -overwrite -I 23 -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_LocSag_lowres_pad2TOF.nii /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_LocSag_lowres.nii
++ 3dZeropad: AFNI version=AFNI_23.1.00 (Apr 7 2023) [64-bit]
++ output dataset: /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_LocSag_lowres_pad2TOF.nii
3dresample -overwrite -input 7_tof_fl3d_tra_p2_Slabs4_PF66.nii -master /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_LocSag_lowres_pad2TOF.nii -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_TOF_resampled.nii
3dwarp -overwrite -deoblique -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_OSPCMRI_dbq.nii 19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii
++ 3dWarp: AFNI version=AFNI_23.1.00 (Apr 7 2023) [64-bit]
++ Authored by: RW Cox
** AFNI converts NIFTI_datatype=4 (INT16) in file /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii to FLOAT32
Warnings of this type will be muted for this session.
Set AFNI_NIFTI_TYPE_WARN to YES to see them all, NO to see none.
# mat44 Obliquity Transformation ::
0.745690 0.662844 0.067706 64.207626
-0.666044 0.738774 0.102952 -10.895149
0.018222 -0.121865 0.992379 -11.268112
++ Using minimum spacing of 1.000000 mm for new grid spacing
3dresample -overwrite -rmode NN -input /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_OSPCMRI_dbq.nii -master /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_LocSag_lowres_pad2TOF.nii -dxyz 1 5 5 -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//CheckRx_OSPCMRI_dbq_resampled.nii
Regridding data
Zero-pads the OSPCMRI data in the slice direction, i.e. increasing the width of the OSPCMRI Rx slab. Then, warps the TOF data (cardinal) to the zero-padded OSPCMRI grid (oblique), and resampled both TOF and OSPCMRI to a 1mm isotropic resolution. This yields a modified TOF dataset in the same grid/resolution as the OSPCMRI. In subsequent steps, the user (with automated help from the script for some aspects) will act on this modified TOF dataset to define the vessel mask for subsequent OSPCMRI processing.
sending incremental file list
sent 104 bytes received 12 bytes 232.00 bytes/sec
total size is 3,492,192 speedup is 30,105.10
sending incremental file list
sent 86 bytes received 12 bytes 196.00 bytes/sec
total size is 8,008,032 speedup is 81,714.61
** AFNI converts NIFTI_datatype=4 (INT16) in file /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii to FLOAT32
Warnings of this type will be muted for this session.
Set AFNI_NIFTI_TYPE_WARN to YES to see them all, NO to see none.
[7m*+ WARNING: [0m If you are performing spatial transformations on an oblique dset,
such as /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii,
or viewing/combining it with volumes of differing obliquity,
you should consider running:
3dWarp -deoblique
on this and other oblique datasets in the same session.
See 3dWarp -help for details.
++ Oblique dataset:/Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii is 42.372952 degrees from plumb.
++ 3dinfo: AFNI version=AFNI_23.1.00 (Apr 7 2023) [64-bit]
Dataset File: /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph_RAI.nii
Identifier Code: AFN_3OJ_wmZgAVKXnvKjEcun0A Creation Date: Tue Sep 23 16:02:19 2025
Template Space: ORIG
Dataset Type: Echo Planar (-epan)
Byte Order: LSB_FIRST {assumed} [this CPU native = LSB_FIRST]
Storage Mode: NIFTI
Storage Space: 6,983,680 (7.0 million) bytes
Geometry String: "MATRIX(4,0,0,-19.24884,0,1,0,-81.27656,0,0,1,-224.9308):1,124,176"
Data Axes Tilt: Plumb
Data Axes Orientation:
first (x) = Right-to-Left
second (y) = Anterior-to-Posterior
third (z) = Inferior-to-Superior [-orient RAI]
R-to-L extent: -19.249 [R] -to- -19.249 [R] -step- 4.000 mm [ 1 voxels]
A-to-P extent: -81.277 [A] -to- 41.723 [P] -step- 1.000 mm [124 voxels]
I-to-S extent: -224.931 [I] -to- -49.931 [I] -step- 1.000 mm [176 voxels]
Number of time steps = 80 Time step = 0.01406s Origin = 0.00000s
-- At sub-brick #0 '?' datum type is float: -4096 to 4088
-- At sub-brick #1 '?' datum type is float: -4094 to 4092
-- At sub-brick #2 '?' datum type is float: -4096 to 4088
** For info on all 80 sub-bricks, use '3dinfo -verb' **
----- HISTORY -----
[username@cfmriconan.ucsd.edu: Tue Sep 23 16:02:19 2025] {AFNI_23.1.00:macos_10.12_local} 3dresample -orient RAI -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph_RAI.nii -input /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii
Dimension: R-to-L Thickness: 4 mm
Dimension: A-to-P Thickness: 1 mm
Dimension: I-to-S Thickness: 1 mm
3dZeropad -R 5 -L 5 -prefix /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph_RAI_pad.nii /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph_RAI.nii'[0]'++ 3dZeropad: AFNI version=AFNI_23.1.00 (Apr 7 2023) [64-bit]
++ output dataset: /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed//19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph_RAI_pad.nii
++ 3dWarp: AFNI version=AFNI_23.1.00 (Apr 7 2023) [64-bit]
++ Authored by: RW Cox
** AFNI converts NIFTI_datatype=4 (INT16) in file /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/19_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_ph.nii to FLOAT32
Warnings of this type will be muted for this session.
Set AFNI_NIFTI_TYPE_WARN to YES to see them all, NO to see none.
# mat44 Obliquity Transformation ::
0.745690 -0.666044 0.018222 -54.930298
0.662844 0.738774 -0.121865 -35.883797
0.067706 0.102952 0.992379 7.956694
++ Using minimum spacing of 0.781250 mm for new grid spacing
======================= Processing TOF ===========================
The 'hidden' flag also closes figures with hidden handles, such as volshow windows.
GUI for Defining 3D Vessel Mask from TOF
This section generates a GUI that allows the user to set a TOF intensity threshold to binarize the TOF, and automatically and/or manually refine the binarized mask to produce a 3D binary dataset representing a vessel mask.
Getting skeleton.
Skeletonizing the 3D vessel mask.
Getting endpoints.
Detecting the endpoints of the 3D vessel mask.
Get the farthest two endpoints.
The skeleton connecting the farthest two endpoints is assumed to represent the CCA/ICA segment of interest. Intermediate endpoints are assumed to be the ECA or potentially spurious branches arising from minor imperfections of the binarized TOF data.
Pruning skeleton.
Prune all minor skeleton voxels/branches until we are left with only the skeleton component that connects the two farthest endpoints (the main CCA/ICA branch). The longest pruned branch is assumed to be the ECA, and this will be considered when automatically identifying the carotids branch point. All other pruned branches are assumed to be spurious branches.
Compute distance transforms of voxels to the CCA-ICA skeleton.
Compute distance transform to the CCA-ICA skeleton. Also compute the distance transform to non-CCA-ICA skeleton voxels. These distance maps help define which voxels we attribute to the CCA-ICA mask.
Compute typical radius of vessel, then extract CCA/ICA carotids mask.
Compute the typical radius of the vessel, which helps assign voxels in the carotids branching area to either the CCA/ICA segments of interest, or to the ECA segment that will be pruned.
Computing distance along skeleton
Starting from the lower endpoint (the CCA), compute the distance along the CCA/ICA sketlon up to the upper endpoint (the ICA).
Identify CCA and ICA skeletons and masks.
The largest pruned branch is assumed to be the ECA. The point where the ECA connects to the rest of the skeleton is the carotids branchpoint, i.e. where CCA branches into ICA and ECA.
Assigning every CCA/ICA voxel a distance
Starting from the lower endpoint (the CCA), computing the distance along the CCA/ICA sketlon.
Saving off TOF processing outputs.
Saving off TOF processing outputs into the dataset.TOFproc field.
===================== Processing OSPCMRI =========================
Cleaning up workspace and loading saved outputs from TOF processing.
Retrieve the OSPCMRI data and OSPCMRI mask for further processing.
Retrieving OSPCMRI data and mask for further processing. The initial OPSCMRI mask is simply the MIP (in the slice-direction) of the TOF-derived CCA-ICA mask! This mask gives a good estimate of where the vessel voxels are located in the OSPCMRI data, and will be refined through subsequent processing steps.
Interpolate missing/outlier timepoints
Interpolate any missing cardiac phases (e.g. if we expect 80 cardiac phases but the scanner only outputted 78 DICOM images), or non-physiological outlier cardiac phases (which come from dcm2niix trying to do some undisclosed estimation of missing cardiac phases - only seems to do so for certain dcm2niix versions).
Warning: Ignoring extra legend entries.
Smooth waveforms (Optional)
Applies a third-order Savitsky-Golay filter of frame-length 17 to smooth the waveforms in the cardiac phase dimension.
Retricting mask to significantly positive OSPCMRI values
Only keeps OSPCMRI voxels that pass a right-tail Signed-Rank test with a threshold of p < 0.01. Excluded voxels will generally represent noise or venous voxels.
Use the mask to extract voxels
Use the current OSPCMRI mask to extract OSPCMRI voxel waveforms.
Update mask by correlation filter (Optional)
Within the OSPCMRI mask resulting from the sign-rank step, further exclude any voxels that are poorly correlated with the mean waveform. This tends to remove any remaining voxels that are noisy and/or exhibit a non-physiological waveform.
Compute distance values in OSPCMRI mask.
Using the path-length distance information from the 3D (TOF-derived) vessel mask, flatten that distance information into the 2D OSPCMRI plane. This effectively assigns each OSPCMRI voxel a value for distance along the vessel.
Averaging at axial locations along vessel
Bin OSPCMRI voxels by their along-path distance. This produces voxel waveforms at the newly-averaged axial locations.
Creating masks for CCA/ICA along axial locations
For each axial location (i.e. location along the vessel), assign it to either the CCA or ICA. This is used for computing PI and RI for the CCA and ICA later.
Normalize all waveforms between 0 and 1
Normalize all axially-averaged OSPCMRI waveforms to span a range (min-to-max) of 0 to 1. See Figure 1D of OSPCMRI paper.
Compute Pulse Wave Velocity (PWV)!
Compute Pulse Wave Velocity using Middle UpStroke Area (MUSA), Time-To-Foot (TTF), and Circular Cross-Correlation (CXCORR) methods to estimate the time delays of each waveform relative to the reference waveform. By then considering the distance along the vessel, PWV can be computed.
Compute PI and RI at every location
Compute PI and RI for each axially-averaged waveform.
Generate waves figure
Generate a waveforms figure, just for visual quality assurance purposes.
Writing results to file
Writing results to results.txt, results.json, and results.mat.
Processing complete!
Results saved to: /Users/username/Documents/20220706_2DVSASL_Pulsatility/20221209__SubjectFolder/0019_OSPCMRI_sag_in-plane_FA10_Venc100_left_P_processed/results.mat
results_struct =
struct with fields:
patient_ID: {'SubjectID'}
patient_age_Y: 100
patient_sex: 'M/F/O'
patient_height_m: 1.7526
patient_weight_lbs: 72.5748
RR_mean_ms: 993
RR_stdv_ms: 23
PWV_MUSA_mps: 12.0659
PWVpval_MUSA: 1.3762e-06
PWV_TTF_mps: 15.3053
PWVpval_TTF: 2.2419e-06
PWV_CXCORR_mps: 5.9050
PWVpval_CXCORR: 4.9664e-15
PI_CCA: 2.3947
PI_ICA: 1.2404
RI_CCA: 7.4043
RI_ICA: 2.2867
scan_name: {'OSPCMRI_sag_in-plane_FA10_Venc100_left'}
scan_side: {'left'}