difficulties with run to run alignment, possible solution

Hello AFNI gurus,

I have some extremely noisy partial coverage data, thermal noise in this case, which I am playing with. Unfortunately I am noting that motion correction between runs is less than adequate. Within run, I believe 3dVolreg is doing ok, but when I examine the mean image of each volreg dataset, they are very visibly shifted. Motion in general is very low, but deviation from run to run add up to many voxels of displacement over space. I was intrigued by the -post_vr_allin option, however, this suffered a similar fate - trying to align each noisy vr_base_per_run to the overall vr_base failed.

I was able to modify the proc script to fix this run to run deviation. Namely, I reordered some things, and used the means of within run volreg to drive cross run alignment. Specifically: quick volreg (on last run in this case) to derive a mean_vr_base image, run volreg within run, derive mean of volreg, and then 3dAllineate within run mean to vr_base_mean.

For reference, here are the changes to the script:


# extract volreg registration base
3dbucket -prefix vr_base pb00.$subj.r12.tcat+orig"[86]"

# CHANGE: Quick volreg to create a "better" vr_base
3dvolreg -prefix rm.epi.volreg.temp pb00.$subj.r12.tcat+orig
3dTstat -mean -prefix mean_vr_base+orig rm.epi.volreg.temp+orig

# ================================= volreg =================================
# align each dset to base volume, across runs
foreach run ( $runs )
    # extract volreg base for this run
    3dbucket -prefix vr_base_per_run_r$run pb00.$subj.r$run.tcat+orig'[0]'
    
    # register each volume to the base image
    3dvolreg -verbose -zpad 1 -base vr_base_per_run_r$run+orig  \
             -1Dfile dfile.r$run.1D -prefix rm.epi.volreg.r$run \
             -Fourier                                           \
             -1Dmatrix_save mat.r$run.vr.aff12.1D               \
             pb00.$subj.r$run.tcat+orig
    
    # CHANGE: create a mean image of the volreg data, for cross run alignment.
    3dTstat -mean -prefix mean_vr_base_per_run_r$run rm.epi.volreg.r$run+orig
    
    # and compute xforms for cross-run allin to vr_base
    # CHANGE: reordered, and use the mean for the post VR. 
    3dAllineate -base mean_vr_base+orig                              \
                -source mean_vr_base_per_run_r$run+orig              \
                -prefix al_mean_vr_base_per_run_r$run+orig \
                -1Dfile vr_xrun_allin_dfile.m12.r$run.1D        \
                -1Dmatrix_save mat.vr_xrun_allin.r$run.aff12.1D \
                -autoweight -source_automask                    \
                -warp shr \
                -final wsinc5 \
                -interp quintic \
                -lpa 

    # catenate volreg/post_vr_allin xforms
    cat_matvec -ONELINE                                         \
               mat.vr_xrun_allin.r$run.aff12.1D                 \
               mat.r$run.vr.aff12.1D > mat.r$run.warp.aff12.1D

    # apply catenated xform: volreg/post_vr_allin
    3dAllineate                                                 \
                -input pb00.$subj.r$run.tcat+orig               \
                -1Dmatrix_apply mat.r$run.warp.aff12.1D         \
                -final wsinc5 \
                -prefix pb01.$subj.r$run.volreg
end


and here is part of the original script with post_vr_allin added in is below.


# --------------------------------
# extract volreg registration base
3dbucket -prefix vr_base pb00.$subj.r12.tcat+orig"[86]"

# ================================= volreg =================================
# align each dset to base volume, across runs
foreach run ( $runs )
    # extract volreg base for this run
    3dbucket -prefix vr_base_per_run_r$run pb00.$subj.r$run.tcat+orig'[0]'
    
    # and compute xforms for cross-run allin to vr_base
    3dAllineate -base vr_base+orig                              \
                -source vr_base_per_run_r$run+orig              \
                -1Dfile vr_xrun_allin_dfile.m12.r$run.1D        \
                -1Dmatrix_save mat.vr_xrun_allin.r$run.aff12.1D \
                -autoweight -source_automask                    \
                -lpa -cubic

    # register each volume to the base image
    3dvolreg -verbose -zpad 1 -base vr_base_per_run_r$run+orig  \
             -1Dfile dfile.r$run.1D -prefix rm.epi.volreg.r$run \
             -Fourier                                           \
             -1Dmatrix_save mat.r$run.vr.aff12.1D               \
             pb00.$subj.r$run.tcat+orig

    # catenate volreg/post_vr_allin xforms
    cat_matvec -ONELINE                                         \
               mat.vr_xrun_allin.r$run.aff12.1D                 \
               mat.r$run.vr.aff12.1D > mat.r$run.warp.aff12.1D

    # apply catenated xform: volreg/post_vr_allin
    3dAllineate                                                 \
                -input pb00.$subj.r$run.tcat+orig               \
                -1Dmatrix_apply mat.r$run.warp.aff12.1D         \
                -prefix pb01.$subj.r$run.volreg
end

Perhaps this will prove useful for others, or maybe afni_proc could benefit from something like: - -volreg_pvra_base_index MEAN.

Hi, Logan-

My favorite kind of MB posts are those with “possible solution” in the title. Esp. on a Friday afternoon.

Can I ask what your data looks like? Could you share a sagittal image of each of your runs, to see just how different things are? Based on this description:
“extremely noisy partial coverage data, thermal noise in this case”
I am curious how different the runs are.

If you can’t post an image here, I’d be happy to share a Box link or something.

thanks,
pt

Hello,

While I have not gone through the entire script so well yet, it jumped out that you originally aligning each run to volume index 0 for that run. The MIN_OUTLIER volume is generally a much better base volume, as it is expected to have very little motion artifact. Consider this set of options (part of Example 13):

-align_opts_aea -cost lpc+ZZ -giant_move                \
                 -volreg_align_to MIN_OUTLIER                            \
                 -volreg_post_vr_allin yes                               \
                 -volreg_pvra_base_index MIN_OUTLIER                     \
                 -volreg_warp_final_interp wsinc5                        \

I hope that works a little better, though for noisy data, I could see averaging being better.

But you have index 86 above. What does that index imply?

  • rick

I’ll get in touch - but imagine data that is nearly just a noise field, with only small areas of larger values, corresponding to csf.

That index is the last run.

And yes, for typical fmri in which motion can produce bad alignment targets I believe MIN OUTLIER is a great choice. However, for this data the subject is experienced and within run, within volume motion is quite low. 3dvolreg suggest avg 0.03~0.04mm of the volumes in the enorm output.

The mean image, after within run volreg, is quite pretty and has meaningful features and good contrast. That said, I’ll probably test this MIN_OUTLIER option to verify my intuitions here.

This also raises another alignment spector. I can imagine, that for this data, I would need to use the mean (perhaps my already calculated mean_vr_base) to align to anatomy, which would require a bit more hacking. This conceptual approach may also prove useful for those folks that have fought with partial coverage data in the past. Maybe median though?

OK, cool. That makes me thing that 3dvolreg is almost not appropriate: it’s really for aligning “like” with “like”. Having very different looking volumes is not an intended purpose with the “ls” cost function. I wonder about trying a different cost like MI or something. Perhaps via one of these AP options:


        -volreg_allin_cost COST : specify the cost function used in 3dAllineate
        -volreg_opts_vr OPTS ... : specify extra options for 3dvolreg

–pt

That is a good idea, that I had not considered - altering the cost function. (not cost functional? :wink: ) and using 3dAllineate. I really think that 3dvolreg is handling within run motion ok - the image are certainly alike…ish. Just an extra helping of noise on top.

I may get a chance to try this, but I am quite happy with the results obtained by using 3dvolreg (within run sucess) + mean for across run 3dAllineate so I’m not sure how much more I will explore.

An update:

MIN_OUTLIER, as a vr_base (and further as a by_run_vr_base) works incredibly well. Rick and Paul win this one. The noise is high, but MIN_OUTLIER also succeeds in finding a reasonable target nevertheless.

The edits I made, to use mean images does work well and makes nice clean images to inspect however its not as beneficial as I had hoped.

I have concerns that alignment to anatomy would benefit from a mean image (after volume registration) but thats a separate issue. I am also curious how even noisier data would work - perhaps the editing would be needed - but for now, AFNI and the AFNI crew claim another victory.