Experimenting with 3dvolreg

AFNI version info (afni -ver): Version AFNI_23.0.07 'Commodus'

Hi, I'm trying to play around with 3dvolreg. Unfortunately it has less parameters to adjust than 3dAllineate.

I don't think 3dvolreg is based on 3dAlineate: I tried using 3dAllineate with a 'ls' cost function and what I thought was correct parameters but it doesn't produce the same results.

  1. Is it possible to adjust parameters in 3dvolreg like one can for 3dAlineate?

or

  1. Any advice on how one would recreate the 3dvolreg function using 3dAlineate or some other function.
code text  # or delete if not needed

Hi-

3dvolreg and 3dAllineate are different programs and written separately. The available parameters for each are listed in the help files. Some overlap, but probably not that many.

If you post the command you are starting with and would like to emulate, as well as provide brief details about the data itself, that would help with making any recommendations.

--pt

Thanks for that confirmation. I have EPI images of a rodent kidney imaged dynamically. Currently I'm using 3dZeropad to crop the original image to reduce the area of interest for registration (as was previously advised to do). I've gotten the registration pretty good. But there are some cases it doesn't work as well. Here are some questions I've had:

  1. It would be cool if I could test different cost functions with 3dvolreg, but I haven't see a way to do that from the help files. 3dvolreg appears much superior to 3dAlineate for our application.
    2A) Is there a more effective way to use the weighting function? i.e. is a binary mask a good way if I'm equally interested to register the entire tissue?
    2B) The kidney has good contrast to a majority of its surrounding (i.e. the edges of it are very distinct and for a good portion of it are bright compared to dark background past the edge). Is there a way to highlight some portion of the edge of the tissue so registration tries to minimize motion of the edge? (if that question makes sense)

Below is what I'm using for 3dvolreg.

3dvolreg \
-overwrite \
-prefix $AnimalID/$FolderID/${AnimalID}_${FolderID}.BoxReg \
-base $AnimalID/$FolderID/${AnimalID}_${FolderID}.Box.Mean+orig[0] \
-weight $AnimalID/$FolderID/MaskFile+orig[0] \
-heptic \
-dfile $AnimalID/$FolderID/dfile_VolReg \
-1Dfile $AnimalID/$FolderID/dfile_VolReg.1D \
-1Dmatrix_save $AnimalID/$FolderID/dfile_VolRegMat.1D \
$AnimalID/$FolderID/${AnimalID}_${FolderID}.DS.Box+orig

  • The weight is just a binary mask of tissue of interest.

Below is an example of what I've tried with 3dAllineate:

3dAllineate \
-overwrite \
-prefix $AnimalID/$FolderID/${AnimalID}_${FolderID}.BoxReg \
-base $AnimalID/$FolderID/${AnimalID}_${FolderID}.Box.Mean+orig \
-warp shift_rotate \
-parfix 3 0 \
-parfix 5 0 \
-parfix 6 0 \
-maxshf 3 \
-twopass \
-twoblur 2 \
-weight $AnimalID/$FolderID/MaskFile+orig \
-cost lpa+ \
-final quintic \
-quiet \
-1Dparam_save $AnimalID/$FolderID/dfile_VolReg \
-1Dmatrix_save $AnimalID/$FolderID/matfile_VolReg \
-input $AnimalID/$FolderID/${AnimalID}_${FolderID}.DS.Box+orig

I would recommend trying align_epi_anat.py which calls 3dAllineate for alignment. It has an -edge option for doing what you suggest. There is also an option to control which program does motion correction via the -volreg_method.

Hi Daniel,

Thank you very much. I tried the following:

align_epi_anat.py \
-dset1 $AnimalID/$FolderID/${AnimalID}_${FolderID}.DS.Box+orig \
-dset2 $AnimalID/$FolderID/${AnimalID}_${FolderID}.Box.Mean+orig \
-dset1to2 \
-volreg_method 3dvolreg \
-anat_has_skull no \
-edge \
-cost ls \
-save_vr

But I get errors (multiple). The very end of this has the initial error after running the command. Altogether, I think the issue comes from this option of the algorithm trying to do 'epi_strip' (or possibly dset1_strip/dset2_strip). I tried adding the options for '-dset1_strip None' and '-dset2_strip None' but it didn't seem to help.

Thank you very much for your time and help.

Initial output plus error:

#++ align_epi_anat version: 1.63
#++ turning off tshift, volume registration, resampling
#++ turning off tshift, volume registration, resampling
#Script is running (command trimmed):
  3dAttribute DELTA ./RE2402_C02/GEPI2D/RE2402_C02_GEPI2D.Box.Mean3+orig
#Script is running (command trimmed):
  3dAttribute DELTA ./RE2402_C02/GEPI2D/RE2402_C02_GEPI2D.Box.Mean3+orig
#Script is running (command trimmed):
  3dAttribute DELTA ./RE2402_C02/GEPI2D/RE2402_C02_GEPI2D.DS.BoxReg1D+orig
#++ Multi-cost is ls
#++ Removing all the temporary files
#Script is running:
  \rm -f ./__tt_RE2402_C02_GEPI2D.Box.Mean3*
#Script is running:
  \rm -f ./__tt_RE2402_C02_GEPI2D.DS.BoxReg1D*
#Script is running (command trimmed):
  3dcopy ./RE2402_C02/GEPI2D/RE2402_C02_GEPI2D.DS.BoxReg1D+orig ./__tt_RE2402_C02_GEPI2D.DS.BoxReg1D+orig
++ 3dcopy: AFNI version=AFNI_23.0.07 (Mar  1 2023) [64-bit]
#Script is running (command trimmed):
  3dinfo ./__tt_RE2402_C02_GEPI2D.DS.BoxReg1D+orig | \grep 'Data Axes Tilt:'|\grep 'Oblique'
#++ Dataset /Users/ebaldelo/Documents/Bash/SNGFR/Rat/__tt_RE2402_C02_GEPI2D.DS.BoxReg1D+orig is not oblique
#Script is running (command trimmed):
  3dinfo ./RE2402_C02/GEPI2D/RE2402_C02_GEPI2D.Box.Mean3+orig | \grep 'Data Axes Tilt:'|\grep 'Oblique'
#++ Dataset /Users/ebaldelo/Documents/Bash/SNGFR/Rat/RE2402_C02/GEPI2D/RE2402_C02_GEPI2D.Box.Mean3+orig is not oblique
#++ Creating edge dataset
#Script is running (command trimmed):
  3dAutomask -overwrite -erode 5 -prefix __tt_RE2402_C02_GEPI2D.DS.BoxReg1D_edge_edge_mask ./__tt_RE2402_C02_GEPI2D.DS.BoxReg1D+orig
++ 3dAutomask: AFNI version=AFNI_23.0.07 (Mar  1 2023) [64-bit]
++ Authored by: Emperor Zhark
++ Loading dataset ./__tt_RE2402_C02_GEPI2D.DS.BoxReg1D+orig
++ Forming automask
 + Fixed clip level = 66.822609
 + Used gradual clip level = 53.603554 .. 122.897804
 + Number voxels above clip level = 5404
 + Clustering voxels ...
 + Largest cluster has 5338 voxels
 + Clustering voxels ...
 + Largest cluster has 5104 voxels
 + Filled   130 voxels in small holes; now have 5234 voxels
 + Clustering voxels ...
 + Largest cluster has 5232 voxels
 + Clustering non-brain voxels ...
 + Clustering voxels ...
 + Largest cluster has 3262 voxels
 + Mask now has 5238 voxels
++ Eroding automask
 + Eroded   2958 voxels
 + Eroded   1818 voxels
 + Eroded   486 voxels
 + Clustering voxels ...
 + Largest cluster has 8500 voxels
++ 0 voxels in the mask [out of 8500: 0.00%]
** FATAL ERROR: No voxels? Quitting without saving mask
** Program compile date = Mar  1 2023
#Script is running (command trimmed):
  3dLocalstat -overwrite -mask ./__tt_RE2402_C02_GEPI2D.DS.BoxReg1D_edge_edge_mask+orig -nbhd 'RECT(-2,-2,-1)' -stat cvar -prefix __tt_RE2402_C02_GEPI2D.DS.BoxReg1D_edge ./__tt_RE2402_C02_GEPI2D.DS.BoxReg1D+orig
++ 3dLocalstat: AFNI version=AFNI_23.0.07 (Mar  1 2023) [64-bit]
++ Authored by: Emperor Zhark
** FATAL ERROR: Can't open dataset './__tt_RE2402_C02_GEPI2D.DS.BoxReg1D_edge_edge_mask+orig'
** Program compile date = Mar  1 2023
** ERROR: Could not create edge dataset /Users/ebaldelo/Documents/Bash/SNGFR/Rat/__tt_RE2402_C02_GEPI2D.DS.BoxReg1D_edge+orig
#++ using 0th sub-brick because only one found
#Script is running (command trimmed):
  3dbucket -prefix ./__tt_RE2402_C02_GEPI2D.Box.Mean3_ts ./RE2402_C02/GEPI2D/RE2402_C02_GEPI2D.Box.Mean3+orig'[0]'
++ 3dbucket: AFNI version=AFNI_23.0.07 (Mar  1 2023) [64-bit]
...

Strange. It fails on a 3dAutomask step. You can investigate that by itself on the command line, or skip the epi masking step with "-epi_strip None"

I got it to run successfully. But there seems to be an issue with the 'edge' portion of it. I get the following error

** FATAL ERROR: Can't open dataset './__tt_RE2402_C02_GEPI2D.Box.Mean_edge_edge_mask+orig'

But I do see a file generated:

'./_tt_RE2402_C02_GEPI2D.Box.Mean_edge_edge_mask+orig'

Note the two under-scores in the file it's attempting to find versus a single underscore in the file actually generated.

This is the command I used to run:

align_epi_anat.py \
-overwrite \
-epi $AnimalID/$FolderID/${AnimalID}_${FolderID}.DS.BoxReg1D+orig \
-anat $AnimalID/$FolderID/${AnimalID}_${FolderID}.Box.Mean3+orig \
-epi2anat \
-epi_base 0 \
-epi_strip None \
-volreg_method 3dvolreg \
-volreg_base median \
-volreg_opts  '-heptic' \
-anat_has_skull no \
-output_dir "$AnimalID/$FolderID/" \
-edge \
-cost ls \
-save_vr

p.s. I'd also be curious to test if using a mask for weighting purposes would be helpful for 'align_epi_anat'. I tried the following:

-volreg_opts  "-weight MaskFile+orig"

But i get the following error:

** Illegal weight dataset after -weight
#**ERROR Could not do volume registration

This name/format works when just using the '3dvolreg' function alone. But not with 'align_epi_anat'.

That command works for me though there is something odd in the copy/paste from the browser that includes a backspace after the "median". The 3dvolreg option should work too, but that requires a '[0]' in the weight option dataset sub-brick (not sure why).

I recommend simplifying the options here to start and then add on as you see fit. Then you can see what makes it fail.

I have been trying and I can't seem to get it working at all with edge. I get the following error. It looks like something with the Automask that is calculated...

#++ Creating edge dataset
#Script is running (command trimmed):
  3dAutomask -overwrite -erode 5 -prefix __tt_HB001_J23_GRE2D.Box.Mean2_edge_edge_mask ./__tt_HB001_J23_GRE2D.Box.Mean2+orig
++ 3dAutomask: AFNI version=AFNI_24.2.01 (Jul 16 2024) [64-bit]
++ Authored by: Emperor Zhark
++ Loading dataset ./__tt_HB001_J23_GRE2D.Box.Mean2+orig
++ Forming automask
++ Eroding automask
 + Eroded   2016 voxels
 + Clustering voxels ...
 + Largest cluster has 2016 voxels
++ 0 voxels in the mask [out of 2016: 0.00%]
** FATAL ERROR: No voxels? Quitting without saving mask
** Program compile date = Jul 16 2024
#Script is running (command trimmed):
  3dLocalstat -overwrite -mask ./__tt_HB001_J23_GRE2D.Box.Mean2_edge_edge_mask+orig -nbhd 'RECT(-2,-2,-1)' -stat cvar -prefix __tt_HB001_J23_GRE2D.Box.Mean2_edge ./__tt_HB001_J23_GRE2D.Box.Mean2+orig
++ 3dLocalstat: AFNI version=AFNI_24.2.01 (Jul 16 2024) [64-bit]
++ Authored by: Emperor Zhark
** FATAL ERROR: Can't open dataset './__tt_HB001_J23_GRE2D.Box.Mean2_edge_edge_mask+orig'

Here is the Code I used to run:

align_epi_anat.py \
-overwrite \
-epi $AnimalID/$FolderID/${AnimalID}_${FolderID}.DS.BoxReg+orig \
-anat $AnimalID/$FolderID/${AnimalID}_${FolderID}.Box.Mean2+orig \
-epi2anat \
-epi_base 0 \
-epi_strip None \
-edge \
-volreg off \
-tshift off \
-anat_has_skull no \
-output_dir "$AnimalID/$FolderID/" \
-cost ls

It looks like there are not too many voxels left in the automask, and then the default erosion takes all the remaining voxels away. Try the option "-edge_erodelevel 1", but also look at the results of 3dAutomask with this data by itself.

Thanks. That did help, but had to use '-edge_erodelevel 0'. The co-registered volume seems to be distorted. Not sure what else to do but use what I was doing.

While I don't have specific experience with kidney alignment, I do have a few general pointers.

  1. 3dvolreg assumes the same grid - exactly - including the origin, so ones with different origins won't work even if the number of voxels in all dimensions are the same. If they come from a single dataset, that should be okay. If they are acquired as a series of individual scans, then you might have some problems.
  2. For dynamic alignment/motion correction, you might try separating the kidneys to either the left or the right.
  3. The automasking done in align_epi_anat.py won't work for two objects at the same time. It looks for one large central cluster. Try 3dAutomask by itself to see the results. Turn off automasking/skullstripping for both inputs in aea with -dset1_strip None -dset2_strip None
  4. For simple blobby shapes that don't change too much over time, try the nmi cost function.

Showing images and commands you try can help here.