Bug with "-Allineate_opts" in align_epi_anat.py?

AFNI version info (afni -ver):

Version AFNI_25.0.00 'Severus Alexander'

Hi afni guys,

I posted a possible bug warning on afni's github (Bug with "-Allineate_opts" in align_epi_anat.py? · Issue #763 · afni/afni · GitHub) but I don't know where it is better to post such things so I am repeating it here. The message is the following:

"When I execute:

align_epi_anat.py -anat2epi -anat 'anat_prewarp.sub-02_ses-01+orig' -suffix _al2epi -epi 'vr_base_min_outlier_noeyes+orig' -epi_base 0 -epi_strip None -anat_has_skull no -cost lpa+ZZ -cmass cmass -prep_off -giant_move -Allineate_opts '-weight_frac 1.0 -maxrot 6 -maxshf 10 -VERB -warp aff -source_mask Cyno162_in_sub-02_ses-01_T1w_brain-mask.cut.der10.nii' -save_script script_aea -volreg off -tshift off

The 3dAllineate part of script_aea accepts my source mask as input but it doesn't remove source_automask (see below), which returns FATAL ERROR: Can't use -source_automask AND -source_mask :-(

3dAllineate -lpa+ZZ -wtprefix ./__tt_anat_prewarp.sub-02_ses-01_al2epi_wtal
-weight ./__tt_vr_base_min_outlier_noeyes_ts_wt+orig -source
./__tt_anat_prewarp.sub-02_ses-01+orig -prefix
./anat_prewarp.sub-02_ses-01_al2epi -base
./__tt_vr_base_min_outlier_noeyes_ts+orig -cmass -1Dmatrix_save
./anat_prewarp.sub-02_ses-01_al2epi_mat.aff12.1D -master BASE -mast_dxyz
0.499999 -weight_frac 1.0 -maxrot 6 -maxshf 10 -VERB -warp aff
-source_mask Cyno162_in_sub-02_ses-01_T1w_brain-mask.cut.der10.nii
-twobest 11 -twopass -VERB -maxrot 45 -maxshf 40 -fineblur 1
-source_automask+2

Is it possibly a bug?"

Best.

Workaround:

  • Add any non-reserverd string such as "break_execution" to -Allineate_opts so that align_epi_anat.py will not return an error and it will create a script of the commands executed (in my case, script_aea)
  • Remove all the files created by align_epi_anat.py
  • Edit script_aea by removing the strings "-source_automask+2" and "break_execution"
  • Run script_aea
align_epi_anat.py \
-anat2epi -anat 'anat_prewarp.sub-02_ses-01+orig' \
-suffix _al2epi \
-epi 'vr_base_min_outlier_noeyes+orig' \
-epi_base 0 \
-epi_strip None\
-anat_has_skull no \
-cost lpa+ZZ \
-cmass cmass \
-prep_off \
-giant_move \
-Allineate_opts '-weight_frac 1.0 -maxrot 6 -maxshf 10 -VERB -warp aff -source_mask Cyno162_in_sub-02_ses-01_T1w_brain-mask.cut.der10.nii break_execution' \
-save_script script_aea \
-volreg off \
-tshift off

rm -rf *_al2epi*
sed -i -e 's/-source_automask+2//g' -e 's/break_execution//g' script_aea
tcsh script_aea

Not beautiful but it works.

Best.

Hello,

This might require some pondering by Daniel, but let me just note that any of these -*_opts options (e.g. afni_proc.py has many) are used to simply add options (blindly) to some other called program. If you need an automatically applied option *changed*, then the main program will generally need a specific option to make such a change.

Regarding your workaround, you can also use align_epi_anat.py -ex_mode dry_run ... to have it output commands, though I am not positive whether all the filenames are resolved there.

-rick

I believe that 3dAllineate overrides options with new options. So while align_epi_anat.py has a "design flaw" (vs a bug) of not replacing specific options, it adds on these Allineate_opts to a basic set. It could parse these options and the defaults to see how to blend them.

The dry_run runs through without executing, but it may not be quite the same as a regular executing run. it assumes oblique datasets, for instance, without verifying if they are oblique, and assumes the minimum voxel size in the dry_run version.

Hi Rick and Daniel,

it's a pleasure to talk to you again! :slight_smile:

@rickr: my first idea was indeed to try the "dry_run" but it's not exactly the same as the "wet(?)_run" as Daniel points out. In fact, the script produced by the dry_run fails with FATAL ERROR: Input -weight is never positive!. I will paste both the dry_run and the normal_run below for the sake of completeness.

@dglen: Unfortunately, in my case, I really need to use a specific mask as input. The alignment doesn't work if I use an automask, probably because my datasets are epi's of cynomolgus monkeys with considerable distortion. After a lot of tinkering, I finally managed to go from (anat is absent because it is far far away)


to
.

Interestingly, of all the costs, hellinger was the one that worked the best. Now I am adapting my afni_proc.py to use my very specific 3dAllineate. The brain stem is still not great though but I still need to optimize my field map correction to see if I gain some.

Coming back to the differences between the dry vs non-dry run:

Align_epi_anat.py with dry_run:

align_epi_anat.py -anat2epi -anat sub-02_ses-01_T1w.cut.ns_der10.nii
-suffix _al2epi
-epi vr_base_min_outlier_noeyes+orig -epi_base 0
-epi_strip None
-anat_has_skull no
-cost hel
-cmass cmass -prep_off -giant_move
-Allineate_opts -weight_frac 1.0 -maxrot 6 -maxshf 10 -VERB -warp aff -source_mask Cyno162_bmask_in_sub-02_ses-01_T1w.cut.der10.nii.gz
-save_script script_epi2anat.tcsh
-volreg off -tshift off -ex_mode dry_run

Script generated by the dry run:

3dAttribute DELTA ./vr_base_min_outlier_noeyes+orig
3dAttribute DELTA ./vr_base_min_outlier_noeyes+orig
3dAttribute DELTA ./sub-02_ses-01_T1w.cut.ns_der10.nii
\rm -f ./__tt_vr_base_min_outlier_noeyes*
\rm -f ./__tt_sub-02_ses-01_T1w.cut.ns_der10*
3dcopy ./sub-02_ses-01_T1w.cut.ns_der10.nii
./__tt_sub-02_ses-01_T1w.cut.ns_der10+orig
3dbucket -prefix ./__tt_vr_base_min_outlier_noeyes_ts
./vr_base_min_outlier_noeyes+orig'[0]'
3dBrickStat -automask -percentile 90.000000 1 90.000000
./__tt_vr_base_min_outlier_noeyes_ts+orig
3dcalc -datum float -prefix ./__tt_vr_base_min_outlier_noeyes_ts_wt -a
./__tt_vr_base_min_outlier_noeyes_ts+orig -expr 'min(1,(a/-999.000000))'
3dAllineate -hel -wtprefix ./__tt_sub-02_ses-01_T1w.cut.ns_der10_al2epi_wtal
-weight ./__tt_vr_base_min_outlier_noeyes_ts_wt+orig -source
./__tt_sub-02_ses-01_T1w.cut.ns_der10+orig -prefix
./sub-02_ses-01_T1w.cut.ns_der10_al2epi -base
./__tt_vr_base_min_outlier_noeyes_ts+orig -cmass -1Dmatrix_save
./sub-02_ses-01_T1w.cut.ns_der10_al2epi_mat.aff12.1D -master BASE
-mast_dxyz 1.234567 -weight_frac 1.0 -maxrot 6 -maxshf 10 -VERB -warp aff
-source_mask Cyno162_bmask_in_sub-02_ses-01_T1w.cut.der10.nii.gz -twobest
11 -twopass -VERB -maxrot 45 -maxshf 40 -fineblur 1 -source_automask+2
3dNotes -h "align_epi_anat.py -anat2epi -anat
sub-02_ses-01_T1w.cut.ns_der10.nii -suffix _al2epi -epi
vr_base_min_outlier_noeyes+orig -epi_base 0 -epi_strip None
-anat_has_skull no -cost hel -cmass cmass -prep_off -giant_move
-Allineate_opts -weight_frac 1.0 -maxrot 6 -maxshf 10 -VERB -warp aff
-source_mask Cyno162_bmask_in_sub-02_ses-01_T1w.cut.der10.nii.gz
-save_script script_epi2anat.tcsh -volreg off -tshift off -ex_mode
dry_run"
./sub-02_ses-01_T1w.cut.ns_der10_al2epi+orig
\rm -f ./__tt_vr_base_min_outlier_noeyes*
\rm -f ./__tt_sub-02_ses-01_T1w.cut.ns_der10*

Script generated by the non-dry run:

3dAttribute DELTA ./vr_base_min_outlier_noeyes+orig
3dAttribute DELTA ./vr_base_min_outlier_noeyes+orig
3dAttribute DELTA ./sub-02_ses-01_T1w.cut.ns_der10.nii
\rm -f ./__tt_vr_base_min_outlier_noeyes*
\rm -f ./__tt_sub-02_ses-01_T1w.cut.ns_der10*
3dcopy ./sub-02_ses-01_T1w.cut.ns_der10.nii
./__tt_sub-02_ses-01_T1w.cut.ns_der10+orig
3dnvals -all ./vr_base_min_outlier_noeyes+orig
3dbucket -prefix ./__tt_vr_base_min_outlier_noeyes_ts
./vr_base_min_outlier_noeyes+orig'[0]'
3dBrickStat -automask -percentile 90.000000 1 90.000000
./__tt_vr_base_min_outlier_noeyes_ts+orig
3dcalc -datum float -prefix ./__tt_vr_base_min_outlier_noeyes_ts_wt -a
./__tt_vr_base_min_outlier_noeyes_ts+orig -expr 'min(1,(a/473.529396))'
3dAllineate -hel -wtprefix ./__tt_sub-02_ses-01_T1w.cut.ns_der10_al2epi_wtal
-weight ./__tt_vr_base_min_outlier_noeyes_ts_wt+orig -source
./__tt_sub-02_ses-01_T1w.cut.ns_der10+orig -prefix
./sub-02_ses-01_T1w.cut.ns_der10_al2epi -base
./__tt_vr_base_min_outlier_noeyes_ts+orig -cmass -1Dmatrix_save
./sub-02_ses-01_T1w.cut.ns_der10_al2epi_mat.aff12.1D -master BASE
-mast_dxyz 0.499999 -weight_frac 1.0 -maxrot 6 -maxshf 10 -VERB -warp aff
-source_mask Cyno162_bmask_in_sub-02_ses-01_T1w.cut.der10.nii.gz -twobest
11 -twopass -VERB -maxrot 45 -maxshf 40 -fineblur 1 -source_automask+2

Best!

Hope all is great. If you wouldn't mind, could you find a way that I could see this data? Maybe, I'll find a simple solution.

Hi Daniel,

The dataset is relatively big and it is from a collaboration so I don't think that I have permission to make it public yet so I sent a sample of it to your email. However, we can continue the discussion here in case it may help someone else.

Best!