Help with Registration of Abdominal images

Hi All,

Hoping to find help with strategies in registering a time series of abdomen images. Respiratory motion is a bit tricky since all organs don’t move exactly uniformly. I’m mostly interested in registering just one organ. So willing to use a mask with the base image but wasn’t sure how to do that in 3dAllineate. I tried ‘-source_mask’ but it completely threw off the registration (much worse than without). Below is what I previously tried.


# 2D REGISTER
3dAllineate \
-overwrite \
-prefix $AnimalID/$FolderID/${AnimalID}_${FolderID}.Reg \
-base $AnimalID/$FolderID/${AnimalID}_${FolderID}+orig[0] \
-warp shift_only \
-parfix 3 0 \
$AnimalID/$FolderID/${AnimalID}_${FolderID}+orig

Any help to improve the registration is greatly appreciated. Thank you!

Edwin

I thought it was worth clarifying, the data set is a few non-sequential 2D images. So felt 2D registration was more appropriate than using 3dvolreg. I referenced the discussion below to guide my choice to start this problem but the registration hasn’t come out well at all. I’ve tried a few iterations tampering with the default values in 3dAllineate, but to no avail. My hope/thought is figuring how to source a ROI/mask of voxels in base to register ought to give the best result. I also tried -emask option using an inverted mask but was also worse. Any guidance with this is very much appreciated.

https://afni.nimh.nih.gov/afni/community/board/read.php?1,81467,81468

.

You can try masking the data explicitly to save only that part of the data. If needed, you can apply the transformation to the pre-masked data.

Thanks for the tip. I was just in the middle of doing that. I think it may have improved it a bit. But I am curious how zero values might affect registration in a masked data set (to ensure clarity, by this I mean values inside of mask remain their value and outside of mask becomes zero). So, If a large part of the image is masked (set to zero), then would the registration algorithm try to align the zeroed part of the data set more so than the actual data of interest?

Also, how does one go about applying the transformation to the pre-masked data?

Thank you for your time and help!

I would probably try with align_epi_anat.py which calls 3dAllineate. Datasets are masked and weighted - depending on which is assigned to be the base dataset and which is the source input. You can also do this directly with 3dAllineate. The aea script can apply the affine transformations as “-child_dset1” or “-child_dset2”. You can also choose a -rigid_body alignment if you think the shape doesn’t change. Another way to apply the affine transformation is with “3dAllineate -1Dmatrix_apply”. The affine alignment will be the harder part here. If you get that working, you can then do the nonlinear alignment with 3dQwarp and apply the combination with 3dNwarpApply.

Hi Daniel,

Thank you for your input. I have a follow up question. I also watched your video online as a reference (https://cbmm.mit.edu/video/09-alignment-and-atlases-part-1-2).

Questions pertaining my use: I want to register the EPI data set to say it’s 5th brik. I wasn’t originally trying to register it to an anatomical set. Would the following code be appropriate?


align_epi_anat.py \
-anat $AnimalID/$FolderID/${AnimalID}_${FolderID}+orig  \
-epi $AnimalID/$FolderID/${AnimalID}_${FolderID}+orig \
-rigid_equiv \
-anat_has_skull no \
-epi_strip None \
-epi_base 5

My first attempt with this code produced a registered set ($AnimalID/$FolderID/${AnimalID}_${FolderID}_al+orig) that was completely off. Any feedback or clarity to the source code to use would be greatly appreciated. Thank you.

Edwin

That command uses the sub-brick volume 5, which is the 6th volume because we use a 0-based counting system.

If the data is far off to start, then use -giant_move. You may want to consider premasking the data too. If you’re really stuck, I can help take a look.

Hi Daniel,

Yes I seem to be a bit stuck. I just chose the 5th sub-brik b/c it had good contrast in the time series. Not really because it was off.

I couldn’t get anywhere positive with align_epi_anat. I went back to 3dAllineate. I’ve been methodically using different iterations of parameters. This is what I’ve lately come up with as a set of parameters that improves the registration.


3dAllineate \
-overwrite \
-prefix $AnimalID/$FolderID/${AnimalID}_${FolderID}_Sample.Reg \
-base $AnimalID/$FolderID/${AnimalID}_${FolderID}_Sample+orig[1] \
-warp shift_rotate \
-parfix 3 0 \
-cost ls \
-autoweight^-2 \
-final quintic \
$AnimalID/$FolderID/${AnimalID}_${FolderID}_Sample+orig

  • An autoweight of 2 does an okay job as it (i think I understand) weighs the bright voxels more. But the edges of the organ of interest are dark so I went with a negative value presuming it weighs dark values more(?). It seems to do a slightly better job with negative value.
  • I also manually segmented the area of interest and dilated the mask to get some voxels outside the area of interest to account for motion before registering. It does a slightly better job.

Ultimately I’m left with a data set that has a good portion of it registered, but every 8th time point or so, there remains a large (~3 voxels) jump/sudden translation in one direction which still throws it off. I.e. it doesn’t do a good job of registering that time point back with the rest. Thank you very much for your time and assistance with this issue.

Cheers,
Edwin

You’re not expecting any rotation - only translation?

Sorry, I updated it. I do use the following option:


-warp shift_rotate \

OK, I sent you a PM for uploading data.

Spent some time with this data. This data was pretty “challenging” because it’s only about 5 slices of data, low resolution, spatially and temporally noisy, non-uniform enhancements, and shapes are changing throughout. That’s plenty of trouble. Mostly, your recipe seemed pretty close to what I thought I was best.

restrict data to range

3dcalc -a ‘RA_B017_ZDS3_GEPI2D_Rep1_SampleNOMASK+orig.<30000…100000>’ -expr a -prefix temprange

cluster (interactive or command line)

3dClusterize -nosum -1Dformat -inset /Users/dglen/edwinb/EdwinB/temprange+orig.HEAD
-idat 4 -ithr 0 -NN 2 -clust_nvox 4000 -pref_map Clust_mask

make dataset fit only around a smaller box around the cluster (I used only 1st 100 volumes for testing)

3dAutobox -prefix tempab2 Clust_mask+orig
3dZeropad -master tempab2+orig. -prefix temp100ab RA_B017_ZDS3_GEPI2D_Rep1_SampleNOMASK+orig.‘[0…99]’

alignment with correlation cost

3dAllineate -base temp100ab+orig’[0]’ -prefix temp100ab_al2ls -cost ls -linear -input temp100ab+orig.

Hi Daniel,

Thank you again very much for your time into this. I ran into an error running the part for ‘3dClusterize’:

** FATAL ERROR: Hey, you need to put in threshold type/value!For example, ‘-2sided …’, ‘-1sided …’, etc.

EDIT Based off values in ‘3dcalc’, i used the following and seemed to resolve the error. Would still be interested to hear if you would’ve used something different. Thank you again!


-within_range 30000 100000 \

Cheers,
Edwin

I think that should be fine. I just used the Clusterize plugin for this, and that was the command it showed. The 3dClusterize command apparently needs an additional “-1sided RIGHT_TAIL 0”. The within_range option is probably better, so you can skip the temp_range dataset produced by 3dcalc.