Move voxel values in one hemisphere to the other

I’m trying to write a function that moves the values of all the voxels in the left hemisphere to the right hemisphere.
nilearn has a swap_img_hemispheres function which swaps the left hemisphere voxels to the right hemisphere, but also moves the right hemisphere voxels to the left hemisphere.
Is there a way to move just the voxel values in one of the hemispheres?

If what you want is to mirror the left hemisphere you could try concatenating your image (Ll,Rr) with its swapped version (Rl,Lr), such that you’d have (Rl, Lr, Ll, Rr), then extracting the middle image (Lr, Ll) and cirshifting it (Ll, Lr). Not the most computationally efficient solution, but requires 0 effort.

from nilearn import image
import numpy as np

# Load image
img = image.load_img("data3d.nii.gz")

# Reorder is called implicitly by swap_img_hemispheres, so we want to do the same.
data_rllr = np.stack([image.swap_img_hemispheres(img).get_data(),
                      image.reorder_img(img).get_data()], 0)

# Get the ll data and circshift it to account for positioning in the FOV.
data_ll = data_rllr[data_rllr.shape[0]//4:data_rllr.shape[0]//4+img.shape[0], :, :]
data_ll = np.roll(data_ll, data_ll.shape[0]//2, 0)

# Place it into a new NifTI object
img_ll = image.new_img_like(img, data_ll, img.affine, copy_header=True)

I suppose this should be robust to even/odd number of voxels, but haven’t tested.

Thanks @dangom, your code did not give any errors, but the final image looks exactly the same as the original image. Maybe I’m wrong but it seems that there is something missing in this command, isn’t there?:

data_ll = data_rllr[data_rllr.shape[0]//4:data_rllr.shape[0]//4+img.shape[0], :, :]

yes, it should’ve been np.concatenate instead of np.stack.
Again, I did not test this, so if you use this in real applications make sure to test it on some toy data with 1s and 0s.

from nilearn import image
import numpy as np


def duplicate_img_left_hemisphere(path):
    # Load image
    img = image.load_img(path)

    # Reorder is called implicitly by swap_img_hemispheres, so we want to do the same.
    data_rllr = np.concatenate(
        [image.swap_img_hemispheres(img).get_data(), 
         image.reorder_img(img).get_data()],
        0,
    )

    # Get the ll data and circshift it to account for positioning in the FOV.
    data_ll = data_rllr[
        data_rllr.shape[0] // 4 : data_rllr.shape[0] // 4 + img.shape[0], :, :
    ]
    data_ll = np.roll(data_ll, data_ll.shape[0] // 2, 0)

    # Place it into a new NifTI object
    img_ll = image.new_img_like(img, data_ll, img.affine, copy_header=True)

    return img_ll

1 Like

Did this work for you @mri ?

Yes - thanks @dangom I just tried your solution with binary images and it works! It copies all the 1s in the left hemisphere to the right hemisphere. However how can I change the values in the left hemisphere to 0 after they have been copied to the right hemisphere, so that only the right hemisphere has 1s?
Thanks!

I don’t see how this would differ from swap_img_hemispheres.

@dangom, say my binary image looks like this:

Right      Left
1 0 0 1    0 0 0 1
0 0 1 0    0 1 0 0
0 0 0 0    0 1 1 1

swap_img_hemispheres does this:

Right      Left
0 0 0 1    1 0 0 1        
0 1 0 0    0 0 1 0    
0 1 1 1    0 0 0 0 

your code does this:

Right      Left
1 0 0 1    0 0 0 1
0 1 1 0    0 1 0 0
0 1 1 1    0 1 1 1

and I’m looking for a way to do this:

Right      Left
1 0 0 1    0 0 0 0
0 1 1 0    0 0 0 0
0 1 1 1    0 0 0 0

Sorry I misunderstood @dangom’s code. What it does is it creates a mirror image of the left hemisphere in the right hemisphere.

So if this is the original data:

Right      Left
1 0 0 1    0 0 0 1
0 0 1 0    0 1 0 0
0 0 0 0    0 1 1 1

dangom’s code does this:

  Right      Left
  1 0 0 0    0 0 0 1
  0 0 1 0    0 1 0 0
  1 1 1 0    0 1 1 1

How can I change the duplicate_img_left_hemisphere function above such that all left voxels equal zero?, like this:

Right      Left
1 0 0 0    0 0 0 0
0 0 1 0    0 0 0 0
1 1 1 0    0 0 0 0