MathOnco / valis

Virtual Alignment of pathoLogy Image Series
https://valis.readthedocs.io/en/latest/
MIT License
117 stars 29 forks source link

Learn transformation on one image pair and apply to the rest. #51

Closed myylee closed 1 year ago

myylee commented 1 year ago

Hi VALIS developers,

Thanks for the great package. I have a specific situation that I'd like to get your guidance on.

I have one H&E image and a stack of IF images that have been aligned already. I'd like to use the H&E and the DAPI image(one channel in the stack of IF images) to learn the transformation (non-rigid), and then apply the transformation on the rest of the IF images, because they are basically measuring the same location as the DAPI image.

The current tutorial requires all input images to be saved in one directory and the transformation is learned to either register all images to one reference, or perform a serial transformation. Could you provide any guidance on how I could learn the transformation using only two images and apply the same thing on the rest?

Thank you very much.

Best regards, Michelle

cdgatenbee commented 1 year ago

Hi @myylee,

Glad to hear you're liking valis :) To answer your question, you can specify a subset of images you would like to align by passing a list of their paths to img_list when you initialize the Valis object. After that, you can use the Slide associated with your DAPI image to warp and save the rest of the IF slides. Also, since you're registering DAPI to H&E, you may want to try the H&E deconvolver Image Processor. All together, it would look something like this, with the warped slides being saved in "aligned_slides_dir":

from valis import registration, valtils, preprocessing

img_list = [he_f, dapi_f]

registrar = registration.Valis(src_dir, dst_dir, img_list=img_list, reference_img_f=he_f)
rigid_registrar, non_rigid_registrar, error_df = registrar.register(brightfield_processing_cls=preprocessing.HEDeconvolution, brightfield_processing_kwargs={})

all_imgs = [os.path.join(src_dir, f) for f in os.listdir(src_dir)]
dapi_slide = registrar.get_slide(dapi_f)
for f in all_imgs:
    if f in img_list:
        slide_warper = registrar.get_slide(f)
    else:
        # Use DAPI Slide to warp other IF images
        slide_warper = dapi_slide

    slide_name = valtils.get_name(f)
    dst_f = os.path.join(aligned_slides_dir, f"{slide_name}.ome.tiff")
    slide_warper.warp_and_save_slide(dst_f=dst_f, src_f=f)

Please try the above and let me know how it goes.

Best, -Chandler

myylee commented 1 year ago

Hi Chandler,

Thank you very much for the detailed instruction.

I tried your codes and ran without error. However, I realized is that all the output files are exactly the same.

Let's say I have another channel, E-cadherin. It is warped using the dapi_warper and saved into the aligned_slides_dir.

If I check the saved images, it looks exactly the same as the DAPI image, and I know there are certain features exclusive to the E-cadherin image.

If I check the element-wise value between the DAPI and E-cadherin image, by running

dapi = skio.imread(aligned_slides_dir+"DNA.ome.tiff", plugin="tifffile")
ecad = skio.imread(aligned_slides_dir+"E-cadherin.ome.tiff", plugin="tifffile")
np.sum(dapi == ecad) == (dapi.shape[0]*dapi.shape[1])

this returns true.

I'm not exactly sure which step caused this, so would greatly appreciate it if you have any suggestions.

Here is the code I ran:

from valis import registration, valtils, preprocessing
src_dir = "/home/myylee/crc_atlas/prediction_096-097/valis_input_cycif/"
dst_dir = "/home/myylee/crc_atlas/prediction_096-097/valis_output_cycif/"
aligned_slides_dir = dst_dir+"registered_slides"

he_f = "/home/myylee/crc_atlas/prediction_096-097/valis_input_cycif/0_he096.png"
dapi_f = "/home/myylee/crc_atlas/prediction_096-097/valis_input_cycif/DNA.png"
img_list = [he_f, dapi_f]

registrar = registration.Valis(src_dir, dst_dir, img_list=img_list, reference_img_f=he_f)
rigid_registrar, non_rigid_registrar, error_df = registrar.register()

all_imgs = [os.path.join(src_dir, f) for f in os.listdir(src_dir)]
dapi_slide = registrar.get_slide(dapi_f)
for f in all_imgs:
    if f in img_list:
        slide_warper = registrar.get_slide(f)
    else:
        # Use DAPI Slide to warp other IF images
        slide_warper = dapi_slide

    slide_name = valtils.get_name(f)
    dst_f = os.path.join(aligned_slides_dir, f"{slide_name}.ome.tiff")
    slide_warper.warp_and_save_slide(dst_f=dst_f, 
                                     src_f=f,
                                     colormap=valis.viz.cam16ucs_cmap())

Thanks, Michelle

cdgatenbee commented 1 year ago

Hi @myylee, So sorry about this. Could you please check which version on valis you are using? I thought I had addressed this issue in the most recent version (1.0.0rc15), which just got pushed last week. If you are using that version, please let me know and I'lll see if I can figure what is going on.

Best, -Chandler

myylee commented 1 year ago

Hi @cdgatenbee,

I was using an older version (1.0.0rc14). It works now! Thank you very much.

Best regards, Michelle

cdgatenbee commented 1 year ago

Great! Glad to hear it's working now :) I'll go ahead and close the issue then.

Best. -Chandler