Partial coverage alignment question

Dear Paul
I have asked our IT to update AFNI and some dependencies according to your advice, and run the command you have provided. Can we work on the data question itself now?
The original post is as follows:

Thanks so much
Congcong

Hi, Congcong-

Great that things are computationally sorted.

Could you please run this command, and show what the two output images look like:

@djunct_overlap_check                                           \
    -ulay    DSET_ANAT                                          \
    -olay    DSET_SLAB                                          \
    -prefix  img_olap

? (This is what set us down the road of updating your computer system to start with, to have Xvfb installed.)

That will show the initial overlap of the 2 datasets, first with obliquity in each ignored, and then the _*DEOB* image will show when obliquity is applied.

Obliquity is a bit of a hassle to navigate for visualization, because typically it will either be ignored (and so the apparent xyz coordinates aren't what they should be) or it can be applied (and some blurring occurs in the dataset, as the data are regridded to show it in cardinal viewing spaces).

Depending on what these look like, we might be able to remove the obliquity in a way that doesn't resample the data. Actually, could you also try running adjunct_deob_around_origin on each dataset, and then show how the overlap looks:

adjunct_deob_around_origin              \
    -input   DSET_ANAT                  \
    -prefix  DSET_ANAT_NEW

adjunct_deob_around_origin              \
    -input   DSET_SLAB                  \
    -prefix  DSET_SLAB_NEW

@djunct_overlap_check                            \
    -ulay    DSET_ANAT_NEW                       \
    -olay    DSET_SLAB_NEW                       \
    -prefix  img_olap_NEW

?

thanks,
pt

Dear Paul

We scanned functional images of four task states for each subject. I selected one of the functional images, and the functional image has undergone slice timing correction and realignment.
The first two images are as follows:



The second command image is as follows:

Thanks so much
Congcong

Hi, Congcong-

OK, how about trying this, then. Take the following script, and replace DSET_ANAT with your anatomical and DSET_SLAB with your slab dset. Then run the script with just tcsh THE_SCRIPT.tcsh.
NB: I'm assuming that the contrasts between them don't match, hence using lpc for cost alignment below.

This script will deoblique each around their origin (without resampling/blurring), and then do alignment between them, mapping the anatomical over to the slab, so the slab is not resampled at all.

One trick of doing this is to use the initial obliquity information to put the anatomical into as good of alignment as the origin dsets have when their obliquities are applied (shown in the img_olap_DEOB image, which has the best alignment initially between them). I tried this with a pair of dsets here, please let me know how that works for you.

--pt

NB: PT edit for future readers---I have updated this script here to have more helpful ending message about which datasets to look at, and below to be more appropriate for a slab "dset_B", where we wouldn't want the default option of trying to skullstrip it being on.

#!/bin/tcsh

# orig
set dset_A = DSET_ANAT
set dset_B = DSET_SLAB

# --------------------------------------------------------------------------

# deob
set aaa = `3dinfo -prefix_noext ${dset_A}`
set bbb = `3dinfo -prefix_noext ${dset_B}`
set dset_A_deob = "${aaa}_DEOB.nii.gz"
set dset_B_deob = "${bbb}_DEOB.nii.gz"

# ==========================================================================
# carry out deobliquing

adjunct_deob_around_origin                \
    -input   "${dset_A}"                  \
    -prefix  "${dset_A_deob}"

adjunct_deob_around_origin                \
    -input   "${dset_B}"                  \
    -prefix  "${dset_B_deob}"

# dset A: useful affine transforms (two formats: aff12.1D and 1D)
cat_matvec                                \
    -ONELINE                              \
    "${dset_A}"::IJK_TO_DICOM_REAL -I     \
    "${dset_A_deob}"::IJK_TO_DICOM_REAL   \
    > mat_A-I_Adeob.aff12.1D
cat_matvec                                \
    "${dset_A}"::IJK_TO_DICOM_REAL -I     \
    "${dset_A_deob}"::IJK_TO_DICOM_REAL   \
    > mat_A-I_Adeob.1D

# dset B: useful transform (just 1D is fine)
cat_matvec                                \
    "${dset_B}"::IJK_TO_DICOM_REAL -I     \
    "${dset_B_deob}"::IJK_TO_DICOM_REAL   \
    > mat_B-I_Bdeob.1D 

# dset A -> B: useful transforms (two formats: aff12.1D and 1D)
cat_matvec                                \
    mat_A-I_Adeob.1D                      \
    mat_B-I_Bdeob.1D -IP                  \
    > mat_A-I_Adeob-B-I_Bdeob-IP.1D
# FINAL pre-matrix
cat_matvec                                \
    mat_A-I_Adeob-B-I_Bdeob-IP.1D -I      \
    > mat_A-I_Adeob-B-I_Bdeob-IP-I.1D 

# =============================================================================
# do alignment, applying pre-matrix

align_epi_anat.py                                                            \
    -anat2epi                                                                \
    -anat             "${dset_A_deob}"                                       \
    -pre_matrix       mat_A-I_Adeob-B-I_Bdeob-IP-I.1D                          \
    -anat_has_skull   no                                                     \
    #-save_skullstrip                                                         \
    -suffix           _al_1to2                                               \
    -epi              "${dset_B_deob}"                                       \
    -epi_base         0                                                      \
    -cost             lpc                                                    \
    #-giant_move                                                              \
    -volreg           off                                                    \
    -tshift           off

cat <<EOF
---------------------------------------------
++ Done. To check alignment, set:

   ulay : ${aaa}_DEOB_al_1to2+orig.HEAD
   olay : ${dset_B_deob}

afni ${aaa}_DEOB_al_1to2+orig.HEAD ${dset_B_deob}

EOF

exit 0

Dear Paul
I run the THE_SCRIPT.tcsh you have provided, an error occurs as follows:

[zhaojing@no-data sub_01]$ tcsh THE_SCRIPT.tcsh
++ Making working directory: ./__workdir_adfo_9jnLAmXmnH2
++ Oblique method in 3drefit is: -oblique_recenter
++ 3dcopy: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ 3drefit: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Authored by: RW Cox
++ Processing AFNI dataset tmp+orig
++ shifting origin by 3.28011 3.07064 6.13429
++ 3drefit processed 1 datasets
++ 3drefit: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Authored by: RW Cox
++ Processing AFNI dataset tmp+orig
 + deoblique
++ 3drefit processed 1 datasets
++ 3dcopy: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Clean working dir

++ DONE. See the output:
   DSET_ANAT_DEOB.nii.gz

+* WARN: input dataset is *not* in orig space.
   That is surprising that it would have obliquity, then.
++ Making working directory: ./__workdir_adfo_t5psfVdzWuK
++ Oblique method in 3drefit is: -oblique_recenter
++ 3dcopy: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ 3drefit: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Authored by: RW Cox
++ Processing AFNI dataset tmp+tlrc
++ shifting origin by 1.35165 -2.51034 -36.7494
++ 3drefit processed 1 datasets
++ 3drefit: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Authored by: RW Cox
++ Processing AFNI dataset tmp+tlrc
 + deoblique
++ 3drefit processed 1 datasets
++ 3dcopy: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Clean working dir

++ DONE. See the output:
   DSET_SLAB_DEOB.nii.gz

*+ WARNING:   If you are performing spatial transformations on an oblique dset,
  such as /data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_ANAT.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:/data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_ANAT.nii is 2.757331 degrees from plumb.
*+ WARNING:   If you are performing spatial transformations on an oblique dset,
  such as /data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_ANAT.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:/data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_ANAT.nii is 2.757331 degrees from plumb.
*+ WARNING:   If you are performing spatial transformations on an oblique dset,
  such as /data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_SLAB.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:/data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_SLAB.nii is 20.208357 degrees from plumb.
#++ align_epi_anat version: 1.63
#++ turning off volume registration
#Script is running:
  3dAttribute DELTA /data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_SLAB_DEOB.nii.gz
#Script is running:
  3dAttribute DELTA /data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_SLAB_DEOB.nii.gz
#Script is running:
  3dAttribute DELTA /data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_ANAT_DEOB.nii.gz
#++ Multi-cost is lpc
#++ Removing all the temporary files
#Script is running:
  \rm -f ./__tt_DSET_SLAB_DEOB*
#Script is running:
  \rm -f ./__tt_DSET_ANAT_DEOB*
#Script is running (command trimmed):
  3dcopy ./DSET_ANAT_DEOB.nii.gz ./__tt_DSET_ANAT_DEOB+orig
++ 3dcopy: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
#Script is running (command trimmed):
  3dinfo ./__tt_DSET_ANAT_DEOB+orig | \grep 'Data Axes Tilt:'|\grep 'Oblique'
#++ Dataset /data/diske48t/7t_test/AFNI_TEST/sub_01/__tt_DSET_ANAT_DEOB+orig is not oblique
#Script is running (command trimmed):
  3dinfo ./DSET_SLAB_DEOB.nii.gz | \grep 'Data Axes Tilt:'|\grep 'Oblique'
#++ Dataset /data/diske48t/7t_test/AFNI_TEST/sub_01/DSET_SLAB_DEOB.nii.gz is not oblique
#Script is running (command trimmed):
  3dAttribute DELTA ./__tt_DSET_ANAT_DEOB+orig
#++ Spacing for anat to oblique epi alignment is 0.700000
#Script is running (command trimmed):
  3dWarp -verb -matvec_in2out ./mat_A-I_Adeob-B-I_Bdeob-IP-I.1D -prefix ./__tt_DSET_ANAT_DEOB_ob -newgrid 0.700000 ./__tt_DSET_ANAT_DEOB+orig 
++ 3dWarp: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Authored by: RW Cox
++ Output dataset ./__tt_DSET_ANAT_DEOB_ob+orig.BRIK
#++ Copying NIFTI EPI input to AFNI format
#Script is running (command trimmed):
  3dcopy ./DSET_SLAB_DEOB.nii.gz ./__tt_DSET_SLAB_DEOB+tlrc
++ 3dcopy: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
#++ Creating representative epi sub-brick
#Script is running (command trimmed):
  3dbucket -prefix ./__tt_DSET_SLAB_DEOB_ts ./__tt_DSET_SLAB_DEOB+tlrc'[0]'
++ 3dbucket: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
#++ resampling epi to match anat data
#Script is running (command trimmed):
  3dresample -master ./__tt_DSET_ANAT_DEOB_ob+orig -prefix ./__tt_DSET_SLAB_DEOB_ts_rs -inset ./__tt_DSET_SLAB_DEOB_ts+tlrc'' -rmode Cu
#++ removing skull or area outside brain
#Script is running (command trimmed):
  3dSkullStrip -orig_vol -input ./__tt_DSET_SLAB_DEOB_ts_rs+orig -prefix ./__tt_DSET_SLAB_DEOB_ts_rs_ns
/bin/sh: 3dSkullStrip: command not found
** ERROR: Could not strip skull

** ERROR - script failed
---------------------------------------------
++ Done. To check alignment, set:

   ulay : DSET_SLAB_DEOB_al_1to2+orig.HEAD
   olay : DSET_SLAB_DEOB.nii.gz

afni DSET_SLAB_DEOB_al_1to2+orig.HEAD DSET_SLAB_DEOB.nii.gz

Therefore, I run afni_system_check.py -check_all, and it is shown as below:

[zhaojing@no-data sub_01]$ afni_system_check.py -check_all
-------------------------------- general ---------------------------------
architecture:         64bit ELF
cpu type:             x86_64
system:               Linux
release:              3.10.0-693.el7.x86_64
version:              #1 SMP Tue Aug 22 21:09:27 UTC 2017
distribution:         CentOS Linux 7.9.2009 Core
number of CPUs:       80
apparent login shell: bash
shell RC file:        .bashrc (exists)

--------------------- AFNI and related program tests ---------------------
which afni           : /opt/fox_cloud/share/app/imaging/afni/afni
afni version         : Precompiled binary linux_centos_7_64: Mar  5 2024 
                     : AFNI_24.0.10 'Caracalla'
AFNI_version.txt     : AFNI_24.0.10, linux_centos_7_64, Mar 05 2024, official
which python         : /bin/python
python version       : 2.7.5
which R              : /opt/fox_cloud/share/app/imaging/R3.6/bin/R
R version            : WARNING: ignoring environment value of R_HOME

instances of various programs found in PATH:
    afni    : 1   (/opt/fox_cloud/share/app/imaging/afni/afni)
    R       : 2 
      /opt/fox_cloud/share/app/imaging/R3.6/bin/R
      /usr/bin/R
    python  : 1   (/usr/bin/python2.7)
    python2 : 1   (/usr/bin/python2.7)
    python3 : 1   (/usr/bin/python3.6)


testing ability to start various programs...
    afni                 : success
    suma                 : FAILURE
        /bin/sh: suma: command not found
    3dSkullStrip         : FAILURE
        /bin/sh: 3dSkullStrip: command not found
    3dAllineate          : success
    3dRSFC               : success
    SurfMesh             : FAILURE
        /bin/sh: SurfMesh: command not found
    3dClustSim           : success
    uber_subject.py      : success
    3dMVM                : success
()
------------------------ dependent program tests -------------------------
checking for dependent programs...

which tcsh           : /bin/tcsh
which Xvfb           : /bin/Xvfb

checking for R packages...
    rPkgsInstall -pkgs ALL -check : success

R RHOME : WARNING: ignoring environment value of R_HOME
/opt/fox_cloud/share/app/imaging/R3.6/lib64/R

------------------------------ python libs -------------------------------

++ module loaded: matplotlib.pyplot
   module file : /usr/lib64/python2.7/site-packages/matplotlib/pyplot.pyc
   matplotlib version : 1.2.0
** need maptplotlib version 2.2+ for APQC


** failed to load module flask
-- flask is not required, but is desirable

** failed to load module flask_cors
-- flask_cors is not required, but is desirable

-------------------------------- env vars --------------------------------
PATH                       = /opt/fox_cloud/share/app/imaging/itksnap-3.6.0/bin:/opt/fox_cloud/share/app/imaging/fsl/bin:/opt/fox_cloud/share/app/imaging/matlab2019/bin:/opt/fox_cloud/share/app/imaging/matlab2019/toolbox/distcomp/bin:/opt/fox_cloud/share/app/imaging/dcm2nii/build/bin:/opt/fox_cloud/share/app/imaging/mricron_lx:/opt/fox_cloud/share/app/imaging/R3.6/bin:/opt/fox_cloud/share/app/imaging/ImageMagick6.4/bin:/opt/fox_cloud/share/app/imaging/caret/bin_linux_intel64:/opt/fox_cloud/share/app/imaging/freesurfer6.0/bin:/opt/fox_cloud/share/app/imaging/freesurfer6.0/fsfast/bin:/opt/fox_cloud/share/app/imaging/freesurfer6.0/tktools:/opt/fox_cloud/share/app/imaging/fsl/bin:/opt/fox_cloud/share/app/imaging/freesurfer6.0/mni/bin:/opt/fox_cloud/share/app/imaging/ants/bin:/opt/fox_cloud/share/app/imaging/afni:/opt/fox_cloud/share/app/imaging/MRIConvert-2.0.7/usr/bin:/opt/fox_cloud/share/app/imaging/go/bin:/opt/fox_cloud/share/app/imaging/pycharm/bin:/opt/fox_cloud/share/app/imaging/Qt5.15/5.15.2/gcc_64/bin:/opt/fox_cloud/share/app/imaging/Qt5.15:/Tools/QtCreator/bin:/opt/fox_cloud/system/evn/jdk1.8/bin:/opt/fox_cloud/system/evn/jdk1.8/jre/bin:/opt/fox_cloud/share/app/imaging/itksnap-3.6.0/bin:/opt/fox_cloud/share/app/imaging/fsl/bin:/opt/fox_cloud/share/app/imaging/matlab2019/bin:/opt/fox_cloud/share/app/imaging/matlab2019/toolbox/distcomp/bin:/opt/fox_cloud/share/app/imaging/dcm2nii/build/bin:/opt/fox_cloud/share/app/imaging/mricron_lx:/opt/fox_cloud/share/app/imaging/R3.6/bin:/opt/fox_cloud/share/app/imaging/ImageMagick6.4/bin:/opt/fox_cloud/share/app/imaging/caret/bin_linux_intel64:/opt/fox_cloud/share/app/imaging/freesurfer6.0/bin:/opt/fox_cloud/share/app/imaging/freesurfer6.0/fsfast/bin:/opt/fox_cloud/share/app/imaging/freesurfer6.0/tktools:/opt/fox_cloud/share/app/imaging/freesurfer6.0/mni/bin:/opt/fox_cloud/share/app/imaging/ants/bin:/opt/fox_cloud/share/app/imaging/afni:/opt/fox_cloud/share/app/imaging/MRIConvert-2.0.7/usr/bin:/opt/fox_cloud/share/app/imaging/go/bin:/opt/fox_cloud/share/app/imaging/pycharm/bin:/opt/fox_cloud/share/app/imaging/Qt5.15/5.15.2/gcc_64/bin:/opt/fox_cloud/share/app/imaging/Qt5.15:/Tools/QtCreator/bin:/opt/fox_cloud/system/evn/jdk1.8/bin:/opt/fox_cloud/system/evn/jdk1.8/jre/bin:/bin:/usr/bin:/opt/thinlinc/bin:/usr/local/bin:/usr/bin/X11:/sbin:/usr/sbin:/usr/local/sbin:/home/zhaojing/.local/bin:/home/zhaojing/bin

PYTHONPATH                 = 
R_LIBS                     = 
LD_LIBRARY_PATH            = /opt/fox_cloud/share/app/imaging/itksnap-3.6.0/lib:/opt/fox_cloud/share/app/imaging/dcm2nii/build/lib:/opt/fox_cloud/share/app/imaging/R3.6/lib64:/opt/fox_cloud/share/app/imaging/R:/opt/fox_cloud/share/app/imaging/ImageMagick6.4/lib:/opt/fox_cloud/share/app/imaging/ants/lib:/opt/fox_cloud/share/app/imaging/MRIConvert-2.0.7/usr/lib:/opt/fox_cloud/share/app/imaging/Qt5.15/5.15.2/gcc_64/lib:/opt/fox_cloud/share/app/imaging/itksnap-3.6.0/lib:/opt/fox_cloud/share/app/imaging/dcm2nii/build/lib:/opt/fox_cloud/share/app/imaging/R3.6/lib64:/opt/fox_cloud/share/app/imaging/R:/opt/fox_cloud/share/app/imaging/ImageMagick6.4/lib:/opt/fox_cloud/share/app/imaging/ants/lib:/opt/fox_cloud/share/app/imaging/MRIConvert-2.0.7/usr/lib:/opt/fox_cloud/share/app/imaging/Qt5.15/5.15.2/gcc_64/lib:/opt/thinlinc/lib64:/opt/thinlinc/lib

DYLD_LIBRARY_PATH          = 
DYLD_FALLBACK_LIBRARY_PATH = 
CONDA_SHLVL                = 0
CONDA_DEFAULT_ENV          = 

----------------------------- eval dot files -----------------------------
()
----------- AFNI $HOME files -----------
()
    .afnirc                   : found
    .sumarc                   : found
    .afni/help/all_progs.COMP : found

--------- shell startup files ----------

   -- no .tcshrc, will create one as a follower of .cshrc
   -- considered operations: path, apsearch
   
   -- note: followers should not need edits, so edit flags should be 0
      (have 1 follower(s), which can be ignored)
   
   dot file test : want 4 modifications across 3 files:
   
      file             path  flatdir  apsearch        follower
      ---------------  ----  -------  --------        --------
      .tcshrc          0     0        0               1     
      .cshrc           1     0        1               0     
      .bashrc          1     0        1               0     
   
------------------------------ data checks -------------------------------
data dir : missing AFNI_data6
data dir : missing AFNI_demos
data dir : missing suma_demo
data dir : missing afni_handouts
atlas    : found TT_N27+tlrc  under /opt/fox_cloud/share/app/imaging/afni

------------------------------ OS specific -------------------------------
which yum            : /bin/yum
yum version          : 3.4.3


=========================  summary, please fix:  =========================
*  just be aware: login shell 'bash', but our code examples use 'tcsh'
*  AFNI programs show FAILURE
*  need maptplotlib version 2.2+ for APQC
*  dot file test : want 4 modifications across 3 files:
*  insufficient data for AFNI bootcamp
   (see "Prepare for Bootcamp" on install pages)

I have asked our IT to solve this matter, and could you also provide some advice why our 3dSkullStrip encountered a failure?

Hi, Congcong-

I think the missing programs might just be bad luck for that version, due to an incomplete build from us. Someone else had noted that there were missing programs on the distributed open_mp_64 binaries for that specific version number, 24.0.10. We fixed that in a subsequent build, and everything seems to be there now. So if you ask the computer folks to update the AFNI binaries, that should be resolved. Sorry about that hassle.

NB: on our HPC, there is a cron job to check for new AFNI versions every day at 4pm, so we always stay uptodate with the latest version. I'm not sure if your local computer folks would like that approach, but we find it useful, esp. for getting the latest updates and any fixes.

Also, here is an updated version of the above script that shouldn't ask for skullstripping at all. In fact, we don't even want the "epi" dataset skullstripped here, because it is a slab---that was an oversight by me, since I was testing on a full-sized epi dataset (=dset_B in the script; NB: PT has updated this script to have better exit message about what datasets to overlay/underlay):

#!/bin/tcsh

# orig
set dset_A = DSET_ANAT
set dset_B = DSET_SLAB

# --------------------------------------------------------------------------

# deob
set aaa = `3dinfo -prefix_noext ${dset_A}`
set bbb = `3dinfo -prefix_noext ${dset_B}`
set dset_A_deob = "${aaa}_DEOB.nii.gz"
set dset_B_deob = "${bbb}_DEOB.nii.gz"

# ==========================================================================
# carry out deobliquing

adjunct_deob_around_origin                \
    -input   "${dset_A}"                  \
    -prefix  "${dset_A_deob}"

adjunct_deob_around_origin                \
    -input   "${dset_B}"                  \
    -prefix  "${dset_B_deob}"

# dset A: useful affine transforms (two formats: aff12.1D and 1D)
cat_matvec                                \
    -ONELINE                              \
    "${dset_A}"::IJK_TO_DICOM_REAL -I     \
    "${dset_A_deob}"::IJK_TO_DICOM_REAL   \
    > mat_A-I_Adeob.aff12.1D
cat_matvec                                \
    "${dset_A}"::IJK_TO_DICOM_REAL -I     \
    "${dset_A_deob}"::IJK_TO_DICOM_REAL   \
    > mat_A-I_Adeob.1D

# dset B: useful transform (just 1D is fine)
cat_matvec                                \
    "${dset_B}"::IJK_TO_DICOM_REAL -I     \
    "${dset_B_deob}"::IJK_TO_DICOM_REAL   \
    > mat_B-I_Bdeob.1D 

# dset A -> B: useful transforms (two formats: aff12.1D and 1D)
cat_matvec                                \
    mat_A-I_Adeob.1D                      \
    mat_B-I_Bdeob.1D -IP                  \
    > mat_A-I_Adeob-B-I_Bdeob-IP.1D
# FINAL pre-matrix
cat_matvec                                \
    mat_A-I_Adeob-B-I_Bdeob-IP.1D -I      \
    > mat_A-I_Adeob-B-I_Bdeob-IP-I.1D 

# =============================================================================
# do alignment, applying pre-matrix

align_epi_anat.py                                                            \
    -anat2epi                                                                \
    -anat             "${dset_A_deob}"                                       \
    -pre_matrix       mat_A-I_Adeob-B-I_Bdeob-IP-I.1D                          \
    -anat_has_skull   no                                                     \
    #-save_skullstrip                                                         \
    -suffix           _al_1to2                                               \
    -epi              "${dset_B_deob}"                                       \
    -epi_base         0                                                      \
    -epi_strip        None                                             \
    -cost             lpc                                                    \
    #-giant_move                                                              \
    -volreg           off                                                    \
    -tshift           off

cat <<EOF
---------------------------------------------
++ Done. To check alignment, set:

   ulay : ${aaa}_DEOB_al_1to2+orig.HEAD
   olay : ${dset_B_deob}

afni ${aaa}_DEOB_al_1to2+orig.HEAD ${dset_B_deob}

EOF

exit 0

Dear Paul
The script has been successfully executed, and I check alignment, set:

ulay : ${bbb}_DEOB_al_1to2+orig.HEAD
olay : ${dset_B_deob}

However, the following command has appeared:

ulay : DSET_SLAB_DEOB_al_1to2+orig.HEAD
   olay : DSET_SLAB_DEOB.nii.gz

The ulay may be DSET_ANAT_DEOB_al_1to2+orig.HEAD? Sorry, I'm not very proficient in this either. If so, ulay: DSET_ANAT_DEOB_al_1to2+orig.HEAD
olay:DSET_SLAB_DEOB.nii.gz
It seems like the functional image has successfully covered the hippocampus, as shown below:


I am a beginner with AFNI, Does this mean the alignment was successful, and If I want to normalize the functional image to the standard MNI space, how should I utilize this linear transformation relationship?
Thanks for your kindness
Congcong

Hi, Congcong-

Sorry, that was a scripting mistake by me---you are right, it should be underlaying DSET_ANAT_DEOB_al_1to2*HEAD and overlaying DSET_SLAB_DEOB.nii.gz. I have updated this in the scripts above, noting the change.

I would probably view that in the AFNI GUI, so I could overlay the DSET_SLAB_DEOB.nii.gz and turn down the opacity, to check the finer structural alignment. I can't quite tell the structural matching, as shown. But if you say the alignmnet is good, that is good. If it weren't, then one would like change the cost function in the align_epi_anat.py command, such as to "lpa" if the tissue contrasts between the two images were similar.

For using this to get to template space, you would want to perform nonlinear alignment between the anatomical and your template of interest---here, MNI space. For standard MPRAGE/T1w volumes, we would recommend using sswarper2 nowadays. However, with these kinds of elevated background images, it might be a bit tricky. I might just guess that you actually have other associated anatomical volumes here---do you have an INV1 and INV2 dataset, from which you created this anatomical? (I have seen this kind of thing with 7T acquisitions, which is why I am guessing).

You could try running sswarper2 on the INV2, first deobliquing in the same way as the MPRAGE here so it aligns exactly, and then running sswarper2, like:

# here, let ${dset_AINV2} be the associated INV2 dset
adjunct_deob_around_origin                             \
    -input   "${dset_AINV2}"                           \
    -prefix  "${dset_AINV2_deob}"

# provide a subject ID, here a variable ${subj}
sswarper2                                              \
    -input  ${dset_AINV2_deob}                         \
    -base   MNI152_2009_template_SSW.nii.gz            \
    -subid  ${subj}                                    \
    -odir   output_dir_${subj}       

Also, in case it is of interest to learn more about alignment in neuroimaging, we have this AFNI Academy: Alignment playlist.

Since your slab is an EPI, I will note that at the end of the day, these pieces being built can all be constructed together within a larger, complete processing pipeline for that EPI, using afni_proc.py:

  • the sswarper2 output: of a nonlinear warp to template space, and a skullstripped anatomical
  • the align_epi_anat.py output: alignment of the template -> EPI (which is reversible)
    ... can each be concatenated, along with motion correction, to send the EPI data to template space.

--pt

hi all, really sorry to barge into this thread but i've spent a lot of time with aligning small FOVs to MP2RAGEs and I know how much of a time sink it can be (and Congcong your screenshot does not look like successful alignment to me) so here are my tips:

first suppress the background noise of the MP2RAGE "UNI" image. there's a long thread here with many ways to do this. The pure AFNI way that I ("stbmtx") suggested only needs 2 of those 4 images, and note it's not my original method.

de-obliquing is a good idea, and i would follow Paul's steps for that. note that the normal AFNI gui doesn't handle obliquity well but the SUMA interface does. but that's a little tricky in itself so better to just deoblique and use the normal AFNI gui. if you want to skull-strip and simultaneously warp to a standardized template I agree that sswarper2 is good.

even after all this the alignment still runs the risk of throwing the FOV off. I've found that it's helpful to constrain how much it can move if the images start out with decent alignment. in the afni_proc context this looks like direct control of 3dAllineate via options that control it through the align_epi_anat.py "wrapper". so in your afni_proc script, for example, you could first try:

-align_opts_aea
-cost lpc+ZZ
-Allineate_opts
-warp shift_rotate
-maxshf 15 -maxrot 20
-twoblur 5 -twopass \

it's like 2 nested levels but it gives you more control and can work well. i'd also watch those videos that Paul linked to and get savvy at using AFNI's GUI to carefully assess alignments, zooming and panning and using keystrokes "4", "5", "6", and "o" and "u"

hope this can help others who read this too. note that if any of your data is missing header information then this process becomes even more of a nightmare. it looks like you have standard pulse sequences, however, so you're probably not dealing with that.

Ciao, @storrisi ! Thanks for all the useful suggestions, which I know are based on lots of experience with these issues.

That is good to know about the background noise suppression! I had missed that in the thread.

Re. obliquity: It's perhaps a little more subtle about good/bad with obliquity. There is linked functionality for time series displays in the AFNI GUI (overlaying time series of different datasets), and so we make the choice to ignore obliquity to preserve this as well as to not blur the data in the viewer. SUMA is less constrained to view planes, so it can more freely apply obliquity. The approach here removed obliquity from the datasets themselves but preserved the knowledge of the relative rotation, so they could be aligned from a good starting point still if well-aligned.

Those are helpful points about align_epi_anat.py options, thanks.

--pt

1 Like

Hi storrisi
Thanks for your advice, but I have really no idea why you say it is not a successful alignment to you? The functional image truly covered the hippocampus? could you provide a more detailed explanation?
Thanks so much
Congcong

Maybe checking the alignment image in AFNI with opacity turned down would help? I don't know the best range for overlay values, but what do these images look like:

@chauffeur_afni                                                              \
    -ulay              DSET_ANAT_DEOB_al_1to2*HEAD         \
    -olay              DSET_SLAB_DEOB.nii.gz'[0]'                  \
    -box_focus_slices  DSET_SLAB_DEOB.nii.gz'[0]'          \
    -montx             4                                                     \
    -monty             2                                                     \
    -opacity           5                                                     \
    -pbar_posonly                                                            \
    -cbar              Reds_and_Blues_Inv                                    \
    -prefix            img_final

?

--pt

Hi Paul
The images are as below:



Umm, I don't know why I can't see the underlay. Hmm. Was the correct underlay name for your data used---the same one you used in your image above?

--pt

the sagittal in your screenshot looks off

I haven't made any changes to the data. The command is as follows:

[zhaojing@no-data sub_01]$ @chauffeur_afni                                                              \
>     -ulay              DSET_ANAT_DEOB_al_1to2*HEAD         \
>     -olay              DSET_SLAB_DEOB.nii.gz'[0]'                  \
>     -box_focus_slices  DSET_SLAB_DEOB.nii.gz'[0]'          \
>     -montx             4                                                     \
>     -monty             2                                                     \
>     -opacity           5                                                     \
>     -pbar_posonly                                                            \
>     -cbar              Reds_and_Blues_Inv                                    \
>     -prefix            img_final
++ My command:
   @chauffeur_afni -ulay DSET_ANAT_DEOB_al_1to2+orig.HEAD -olay DSET_SLAB_DEOB.nii.gz[0] -box_focus_slices DSET_SLAB_DEOB.nii.gz[0] -montx 4 -monty 2 -opacity 5 -pbar_posonly -cbar Reds_and_Blues_Inv -prefix img_final

++ Using AFNI ver : AFNI_24.0.10
++ chauffeur ver  : 6.61

------------------ start of optionizing ------------------

++ Found input file:   DSET_ANAT_DEOB_al_1to2+orig.HEAD
++ Found input file:   DSET_SLAB_DEOB.nii.gz[0]
++ Found focus refbox file:   DSET_SLAB_DEOB.nii.gz[0]
++ Using blowup factor: 2
++ Using opacity:  5
++ Making temporary work directory to copy vis files: ./__tmp_chauf_iztrjpqeIzB
++ Converted 0 to labels
++ Final subbrick indices: -1 -1 -1
++ Copy ulay to visualize (volumetric) within user's range:
++ Ulay to be visualized within user range:
  [0%, 98%] -> [0.000000, 3744.000000]
++ 3dcalc: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Authored by: A cast of thousands
++ Output dataset ././__tmp_chauf_iztrjpqeIzB/tmp_ulay.nii
++ 3dcalc: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Authored by: A cast of thousands
++ Output dataset ././__tmp_chauf_iztrjpqeIzB/tmp_olay.nii
++ For olay, the 100%ile value leads to
   --> upper range value: 2390.351807
++ Dimensions (xyzt): 240 280 280 1
++ (initial) Slice spacing ordered (x,y,z) is:  30 35 35
++ Resample refbox to match ulay
++ 3dAutobox: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Auto bbox: x=0..239  y=18..279  z=87..129
++ 3dAutobox: output dataset = ./__tmp_chauf_iztrjpqeIzB/ulay_box_0.nii
++ 3dmaskdump: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Executing 3dcalc()
 argv[0]=3dcalc argv[1]=-a argv[2]=./__tmp_chauf_iztrjpqeIzB/ulay_box_0.nii[0] argv[3]=-expr argv[4]=a argv[5]=-byte argv[6]=-session argv[7]=/tmp argv[8]=-prefix argv[9]=3dcalc_AFN_kjDCJPYSTPSOxJFhueShOQ argv[10]=-verbose
++ 3dcalc: AFNI version=AFNI_24.0.10 (Mar  5 2024) [64-bit]
++ Authored by: A cast of thousands
++ Computing sub-brick 0
++ Scaling output to type byte brick(s)
++ Sub-brick 0 scale factor = 0.106679
++ Computing output statistics
++ Output dataset /tmp/3dcalc_AFN_kjDCJPYSTPSOxJFhueShOQ+tlrc.BRIK
++ 2703840 voxels in the entire dataset (no mask)
++ 1 voxels in the boxes and/or balls
++ Using only the boxes+balls mask
++ How many coors? 3
++ Will have the ref box central coors : SET_DICOM_XYZ -53.20006 55.3 -5.60001
++ Will have the ref box central gapord: 30 32 5

------------------- end of optionizing -------------------

 -- trying to start Xvfb :859 
[1] 112669

+++ Command Echo:
   afni -q -no1D -noplugins -no_detach -com SWITCH_UNDERLAY tmp_ulay.nii -com SWITCH_OVERLAY  tmp_olay.nii -com SEE_OVERLAY     + -com OPEN_WINDOW sagittalimage opacity=5 mont=4x2:30:0:black crop=0:0,0:0  -com OPEN_WINDOW coronalimage  opacity=5 mont=4x2:32:0:black crop=0:0,0:0  -com OPEN_WINDOW axialimage    opacity=5 mont=4x2:5:0:black crop=0:0,0:0  -com SET_PBAR_ALL    +99 1 Reds_and_Blues_Inv -com DO_NOTHING -com SET_SUBBRICKS   -1 -1 -1 -com SET_ULAY_RANGE A.all 0.000000 3744.000000 -com SET_FUNC_RANGE  2390.351807 -com SET_THRESHNEW   0 * -com SET_FUNC_ALPHA  No -com SET_FUNC_BOXED  No -com SET_FUNC_RESAM  NN.NN -com SET_XHAIRS      OFF -com SET_XHAIR_GAP   -1 -com SET_DICOM_XYZ -53.20006 55.3 -5.60001 -com SAVE_PNG axialimage    ./img_final.axi blowup=2 -com SAVE_PNG sagittalimage ./img_final.sag blowup=2 -com SAVE_PNG coronalimage  ./img_final.cor blowup=2 -com QUITT ./__tmp_chauf_iztrjpqeIzB 

+/data/diske48t/7t_test/AFNI_TEST/sub_01/__tmp_chauf_iztrjpqeIzB*+ WARNING: Forced switch from 'Original View' to 'Talairach View' [#1]
++ Writing one 1920x1120 image to filter '/bin/pnmtopng -compression 9 > ./img_final.axi.png'
++ Writing one 2240x1120 image to filter '/bin/pnmtopng -compression 9 > ./img_final.sag.png'
++ Writing one 1920x1120 image to filter '/bin/pnmtopng -compression 9 > ./img_final.cor.png'

AFNI QUITTs!

+* Removing temporary image directory './__tmp_chauf_iztrjpqeIzB'.

[1]  + Done                          Xvfb :859 -screen 0 1024x768x24

++ DONE (good exit)
   see: ./img_final*

I previously attempted to visualize olay and ulay using AFNI, however, I found that it's not possible to display both images simultaneously. I used MRIcron to display olay and ulay, and adjusted the transparency as below:


May be easier to check? or it's convenient to send you the data to take a look?

Hi, Congcong-

What is the output of

nifti_tool -disp_hdr -field qform_code -form_sform code -infiles DSET1 DSET2

3dinfo -space -av_space DSET1 DSET2

for your DEOB* datasets that you are overlaying underlaying? Does one of them have an ambiguous sform or qform code?

--pt

Hi Paul
It may be:nifti_tool -disp_hdr -field qform_code -field sform_code -infiles ? If so, the command was below:

[zhaojing@no-data sub_01]$ nifti_tool -disp_hdr -field qform_code -field sform_code -infiles DSET_ANAT_DEOB_al_1to2*HEAD DSET_SLAB_DEOB.nii.gz
** ERROR (nifti_read_header): failed to find header file for 'DSET_ANAT_DEOB_al_1to2+orig.HEAD'
[zhaojing@no-data sub_01]$ nifti_tool -disp_hdr -field qform_code -field sform_code -infiles DSET_SLAB_DEOB.nii.gz

N-1 header file 'DSET_SLAB_DEOB.nii.gz', num_fields = 2
  name                offset  nvals  values
  ------------------- ------  -----  ------
  qform_code           252      1    3
  sform_code           254      1    3

failed to find header file for ulay. and second command was below:

[zhaojing@no-data sub_01]$ 3dinfo -space -av_space DSET_ANAT_DEOB_al_1to2*HEAD DSET_SLAB_DEOB.nii.gz
ORIG	+orig
TLRC	+tlrc

Hi, Congcong-

Ah, right, nifti_tool will only work on the NIFTI dataset, not on the BRIK/HEAD one.

But those outputs do show that the second dataset has +tlrc AFNI view space, and that its qform_code and sform_code are both 3. That information means its header says that it is in standard space. It should not be so---it has just been deobliqued.

My guess is that in your original slab dataset, the qform_code and sform_code are either 0 and 2, respectively, or 2 and 2, respectively. The qform_code and sform_code values encode in NIFTI whether the dataset is in native/original space (value=1), or whether it is in a template space (value=3, 4, or 5). Unfortunatley, for historical reasons in some other software, a value of "2" was included, which is ambiguous (could be original/native or standard space). There is an AFNI environment variable to control whether "2" should be interpreted as original space ("+orig") or some standard one ("+tlrc"), called AFNI_NIFTI_VIEW. By current default it is set to "tlrc", but we plan to change it to be "orig" as that seems to be the more common appropriate interpretation nowadays; you can set it in your ~/.afnirc to be "orig", by putting this line at the bottom of the file:

AFNI_NIFTI_VIEW = orig

The reason this affects the visualization is that the AFNI GUI won't overlay/underlay datasets that are in different view spaces. So, a "+orig" and a "+tlrc" dataset won't be viewed together.

Anyways, assuming this is the case, you should probably change the qform_code and sform_code values in your slab dataset from the beginning, since they are in original space; here, you can also change those values in the output dataset. You can do this by:

# make a copy to adjust, because we are going to change the header
3dcopy DSET_SLAB_NEW DSET_SLAB_NEW2
# reset 2 properties (NB: "ORIG" here is a keyword to be typed as written)
3drefit -space ORIG -view orig DSET_SLAB_NEW2

After that, you should be able to view DSET_SLAB_NEW2 with DSET_ANAT_DEOB_al_1to2*HEAD fine, and you can try the @chauffeur_afni command with it.

This is a pretty small technical thing and an annoyance. But at least you can add this copy+refit to the start of your processing pipeline for your datasets.

--pt

Hi Paul

I finally can view olay and ulay fine now using your method as below:




Is it a successful alignment? It is truly cover the hippocampus.
Thanks so much
Congcong