from tifffile import imread
import valis
from valis import registration, valtils
import numpy as np
import sys
import os
import shutil
in_image_path = '/data/image_quadrants/membrane_quadrant1.ome.tiff'
out_folder = '/data/valis_pipeline_out/'
reference_img_fname = 'DAPI_quadrant1.ome.tiff'
image_px = 2000
micro_px = 3000
rigid = True
save = True
verbose = True
in_folder = os.path.dirname(in_image_path) # "/Users/arundas/images/membrane.ome.tiff" --> /Users/arundas/images/
in_file = os.path.basename(in_image_path) # membrane.ome.tiff
img_list = [os.path.join(in_folder, reference_img_fname),
in_image_path]
# Define parameters for registration using the 'Valis' class
registrar = registration.Valis(
in_folder,
out_path,
reference_img_f=reference_img_fname,
crop='reference',
img_list=img_list,
imgs_ordered=True,
align_to_reference=True,
max_processed_image_dim_px=image_px
)
# Perform rigid registration
rigid_registrar, non_rigid_registrar, error_df = registrar.register()
if verbose:
print('==== Rigid Registration Error')
# Split and print error data into multiple columns
num = 4
delta = len(error_df.columns) // num
for _num in range(num-1):
print(error_df[error_df.columns[_num*delta:(_num+1)*delta]])
# Perform micro-registration on higher resolution images, aligning directly to the reference image
non_regid_registrar, error_df = registrar.register_micro(
reference_img_f=reference_img_fname,
align_to_reference=True,
max_non_rigid_registartion_dim_px=micro_px
)
if verbose:
print('==== Micro-Registration Error')
num = 4
delta = len(error_df.columns) // num
for _num in range(num-1):
print(error_df[error_df.columns[_num*delta:(_num+1)*delta]])
print(error_df[error_df.columns[(num-1)*delta:]])
# Save all slides as ome.tiff
# If the non-rigid registration is deemed to have distorted the image too much,
# apply only the rigid transformation by setting non_rigid=False
if save:
print('==== Saving ome.tiff file; Rigid:', rigid)
# Save all slides
# registrar.warp_and_save_slides(
# out_path,
# level=0,
# non_rigid=not args.rigid,
# crop=True,
# interp_method="bicubic",
# tile_wh=1024,
# compression="lzw",
# )
ch_name_f = valtils.get_name(in_image_path)
ch_name_list = ch_name_f.split(" ")
print(ch_name_list)
# Save the object slide
slide_f = os.path.splitext(in_file)[0]
slide_obj = registrar.get_slide(slide_f)
slide_obj.warp_and_save_slide(
out_path,
tile_wh=1024,
level=0
# compression="lzw",
# channel_names = ["Channel:0"]
)
# slide_obj.warp_and_save_slide(
# out_path,
# level=0,
# non_rigid=not rigid,
# crop=True,
# src_f=None,
# channel_names=ch_name_list,
# colormap=None,
# interp_method="bicubic",
# tile_wh=1024,
# compression="lzw"
# )
# Kill the JVM (Java Virtual Machine)
registration.kill_jvm() # Make sure the 'registration' module has a 'kill_jvm' function
Start Image Registration...
/usr/local/src/valis/valtils.py:22: UserWarning: max_image_dim_px is 850 but needs to be less or equal to 2000. Setting max_image_dim_px to 2000
warnings.warn(warning_msg, warning_type)
==== Converting images
Converting images: 0%| | 0/2 [00:00<?, ?image/s]
JVM has been initialized. Be sure to call registration.kill_jvm() or slide_io.kill_jvm() at the end of your script.
Converting images: 100%|███████████████████████████████████████████████████████████████████████████████████| 2/2 [01:53<00:00, 56.97s/image]
==== Processing images
Processing images : 100%|██████████████████████████████████████████████████████████████████████████████████| 2/2 [00:24<00:00, 12.35s/image]
Normalizing images: 100%|██████████████████████████████████████████████████████████████████████████████████| 2/2 [00:01<00:00, 1.81image/s]
Denoising images : 100%|██████████████████████████████████████████████████████████████████████████████████| 2/2 [00:01<00:00, 1.27image/s]
==== Rigid registration
Detecting features : 100%|███████████████████████████████████████████████████████████████████████████████| 2/2 [00:22<00:00, 11.14s/image]
Finding transforms : 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 707.06image/s]
Finalizing : 100%|█████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 7981.55image/s]
======== Rigid registration complete in 32.441 seconds
==== Non-rigid registration
Preparing images for non-rigid registration: 100%|█████████████████████████████████████████████████████████| 2/2 [00:37<00:00, 18.73s/image]
Finding non-rigid transforms: 100%|████████████████████████████████████████████████████████████████████████| 2/2 [00:01<00:00, 1.04image/s]
======== Non-rigid registration complete in 2.591 seconds
/usr/local/src/.venv/lib/python3.10/site-packages/interpolation/splines/eval_splines.py:318: NumbaPendingDeprecationWarning: Code using Numba extension API maybe depending on 'old_style' error-capturing, which is deprecated and will be replaced by 'new_style' in a future release. See details at https://numba.readthedocs.io/en/latest/reference/deprecation.html#deprecation-of-old-style-numba-captured-errors
Exception origin:
File "/usr/local/src/.venv/lib/python3.10/site-packages/interpolation/splines/eval_splines.py", line 116, in __eval_spline
kk = (order).literal_value
return _eval_cubic(*args)
==== Measuring error
Measuring error: 100%|█████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 3.80image/s]
==== Rigid Registration Error
filename from \
0 /data/image_quadrants/DAPI_quadrant1.ome.tiff DAPI_quadrant1
1 /data/image_quadrants/membrane_quadrant1.ome.tiff membrane_quadrant1
to original_D original_rTRE
0 None NaN NaN
1 DAPI_quadrant1 0.049755 0.001782
rigid_D rigid_rTRE non_rigid_D non_rigid_rTRE processed_img_shape
0 NaN NaN NaN NaN (2000, 1949)
1 0.027923 0.001 0.028261 0.001012 (2000, 1949)
shape aligned_shape mean_original_D mean_rigid_D \
0 (21657, 21101) (21668, 21112) 0.049755 0.027923
1 (21657, 21101) (21668, 21112) 0.049755 0.027923
physical_units
0 µm
1 µm
/usr/local/src/valis/valtils.py:22: DeprecationWarning: max_non_rigid_registartion_dim_px is deprecated; use max_non_rigid_registration_dim_px instead
warnings.warn(warning_msg, warning_type)
Preparing images for non-rigid registration: 100%|█████████████████████████████████████████████████████████| 2/2 [00:39<00:00, 19.53s/image]
==== Performing microregistration
Finding non-rigid transforms: 100%|████████████████████████████████████████████████████████████████████████| 2/2 [00:23<00:00, 11.66s/image]
======== Non-rigid registration complete in 24.765 seconds
==== Measuring error
Measuring error: 100%|█████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:01<00:00, 1.62image/s]
==== Micro-Registration Error
filename from \
0 /data/image_quadrants/DAPI_quadrant1.ome.tiff DAPI_quadrant1
1 /data/image_quadrants/membrane_quadrant1.ome.tiff membrane_quadrant1
to original_D original_rTRE
0 None NaN NaN
1 DAPI_quadrant1 0.049755 0.001782
rigid_D rigid_rTRE non_rigid_D non_rigid_rTRE processed_img_shape
0 NaN NaN NaN NaN (2000, 1949)
1 0.027923 0.001 0.024455 0.000876 (2000, 1949)
shape aligned_shape mean_original_D mean_rigid_D \
0 (21657, 21101) (21668, 21112) 0.049755 0.027923
1 (21657, 21101) (21668, 21112) 0.049755 0.027923
physical_units
0 µm
1 µm
resolution name rigid_time_minutes mean_non_rigid_D \
0 0.01 image_quadrants 2.897114 0.024455
1 0.01 image_quadrants 2.897114 0.024455
non_rigid_time_minutes
0 3.775857
1 3.775857
==== Saving ome.tiff file; Rigid: True
['membrane_quadrant1']
/usr/local/src/valis/slide_tools.py:330: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
all_colors = cm.get_cmap(name)(np.linspace(0, 1, n))[..., 0:3]
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[25], line 29
26 slide_f = os.path.splitext(in_file)[0]
27 slide_obj = registrar.get_slide(slide_f)
---> 29 slide_obj.warp_and_save_slide(
30 out_path,
31 tile_wh=1024,
32 level=0
33 # compression="lzw",
34 # channel_names = ["Channel:0"]
35 )
37 # slide_obj.warp_and_save_slide(
38 # out_path,
39 # level=0,
(...)
56 # reference_img_fname = 'DAPI_quadrant1.ome.tiff',
57 # )
File /usr/local/src/valis/valtils.py:30, in deprecated_args.<locals>.deco.<locals>.wrapper(*args, **kwargs)
27 @functools.wraps(f)
28 def wrapper(*args, **kwargs):
29 rename_kwargs(f.__name__, kwargs, aliases)
---> 30 return f(*args, **kwargs)
File /usr/local/src/valis/registration.py:1004, in Slide.warp_and_save_slide(self, dst_f, level, non_rigid, crop, src_f, channel_names, colormap, interp_method, tile_wh, compression, Q)
1002 bf_dtype = slide_io.vips2bf_dtype(warped_slide.format)
1003 out_xyczt = slide_io.get_shape_xyzct((warped_slide.width, warped_slide.height), warped_slide.bands)
-> 1004 ome_xml_obj = slide_io.update_xml_for_new_img(current_ome_xml_str=slide_meta.original_xml,
1005 new_xyzct=out_xyczt,
1006 bf_dtype=bf_dtype,
1007 is_rgb=self.is_rgb,
1008 series=self.series,
1009 pixel_physical_size_xyu=px_phys_size,
1010 channel_names=channel_names,
1011 colormap=colormap
1012 )
1014 ome_xml = ome_xml_obj.to_xml()
1015 if tile_wh is None:
File /usr/local/src/valis/valtils.py:30, in deprecated_args.<locals>.deco.<locals>.wrapper(*args, **kwargs)
27 @functools.wraps(f)
28 def wrapper(*args, **kwargs):
29 rename_kwargs(f.__name__, kwargs, aliases)
---> 30 return f(*args, **kwargs)
File /usr/local/src/valis/slide_io.py:2692, in update_xml_for_new_img(current_ome_xml_str, new_xyzct, bf_dtype, is_rgb, series, pixel_physical_size_xyu, channel_names, colormap)
2689 else:
2690 og_valid_xml = False
-> 2692 temp_new_ome = create_ome_xml(new_xyzct, bf_dtype, is_rgb, pixel_physical_size_xyu, channel_names, colormap=colormap)
2694 if og_valid_xml:
2695 new_ome = og_ome.copy()
File /usr/local/src/valis/valtils.py:30, in deprecated_args.<locals>.deco.<locals>.wrapper(*args, **kwargs)
27 @functools.wraps(f)
28 def wrapper(*args, **kwargs):
29 rename_kwargs(f.__name__, kwargs, aliases)
---> 30 return f(*args, **kwargs)
File /usr/local/src/valis/slide_io.py:2616, in create_ome_xml(shape_xyzct, bf_dtype, is_rgb, pixel_physical_size_xyu, channel_names, colormap)
2613 else:
2614 colormap = default_colormap
-> 2616 channels = [create_channel(i, name=channel_names[i], color=colormap[channel_names[i]]) for i in range(c)]
2617 new_img.pixels.channels = channels
2619 new_ome = ome_types.model.OME()
File /usr/local/src/valis/slide_io.py:2616, in <listcomp>(.0)
2613 else:
2614 colormap = default_colormap
-> 2616 channels = [create_channel(i, name=channel_names[i], color=colormap[channel_names[i]]) for i in range(c)]
2617 new_img.pixels.channels = channels
2619 new_ome = ome_types.model.OME()
KeyError: 'None'
Hello,
I am using
Valis '1.0.2'from the Docker Image to register two single-channelome.tifffiles using the following code. However, I get aKeyError: 'None'error when I attempt to warp and save the image using the warp_and_save_slide method. Could you please help? I'm happy to share/answer any environment or code-related questions.This is the error: