diff --git a/examples/acrobat_2023/valis/affine_optimizer.py b/examples/acrobat_2023/valis/affine_optimizer.py index bede3e79..9762db09 100644 --- a/examples/acrobat_2023/valis/affine_optimizer.py +++ b/examples/acrobat_2023/valis/affine_optimizer.py @@ -1,10 +1,10 @@ """Optimize rigid alignment Contains functions related to optimization, as well as the AffineOptimizer -class that performs the optimzation. This class can be subclassed to implement +class that performs the optimization. This class can be subclassed to implement custom optimization methods. -There are several subclasses, but AffineOptimizerMattesMI is the +There are several subclasses, but AffineOptimizerMattesMI is the fastest and most accurate, and so is default affine optimizer in VALIS. It's not recommended that the other subclasses be used, but they are kept to provide examples on how to subclass AffineOptimizer. @@ -348,7 +348,7 @@ def build_P(A, B, r, mask): @nba.njit() def entropy(x): """ - Caclulate Shannon's entropy for array x + Calculate Shannon's entropy for array x Parameters ---------- @@ -473,7 +473,7 @@ def MI(fixed, moving, nb, spacing): class AffineOptimizer(object): - """Class that optimizes ridid registration + """Class that optimizes rigid registration Attributes ---------- @@ -492,10 +492,10 @@ class AffineOptimizer(object): Type of transformation, "EuclideanTransform" or "SimilarityTransform" current_level : int - Current level of the Guassian pyramid that is being registered + Current level of the Gaussian pyramid that is being registered accepts_xy : bool - Bool declaring whether or not the optimizer will use corresponding points to optimize the registration + Boolean indicating whether the optimizer uses corresponding points to optimize registration. Methods ------- @@ -521,9 +521,9 @@ class AffineOptimizer(object): to have a new cost_fxn method. See AffineOptimizerDisplacement for an example implementing a new cost function Major overhauls are possible too. See AffineOptimizerMattesMI for an example on using SimpleITK's - optimization methods inside of an AffineOptimizer subclass + optimization methods inside an AffineOptimizer subclass - If the optimizer uses corressponding points, then the class attribute + If the optimizer uses corresponding points, then the class attribute accepts_xy needs to be set to True. The default is False. """ @@ -567,7 +567,7 @@ def setup(self, moving, fixed, mask, initial_M=None): Image moving is warped to align to mask : ndarray - 2D array having non-zero pixel values, where values of 0 are ignnored during registration + 2D array having non-zero pixel values, where values of 0 are ignored during registration initial_M : (3x3) array Initial transformation matrix @@ -628,7 +628,7 @@ def align(self, moving, fixed, mask, initial_M=None, moving_xy=None, fixed_xy=No Image moving is warped to align with mask : ndarray - 2D array having non-zero pixel values, where values of 0 are ignnored during registration + 2D array having non-zero pixel values, where values of 0 are ignored during registration initial_M : (3x3) array Initial transformation matrix @@ -813,7 +813,7 @@ def setup(self, moving, fixed, mask, initial_M=None, moving_xy=None, fixed_xy=No Image moving is warped to align to mask : ndarray - 2D array having non-zero pixel values, where values of 0 are ignnored during registration + 2D array having non-zero pixel values, where values of 0 are ignored during registration initial_M : (3x3) array Initial transformation matrix @@ -880,7 +880,7 @@ def align(self, moving, fixed, mask, initial_M=None, Image moving is warped to align with mask : ndarray - 2D array having non-zero pixel values, where values of 0 are ignnored during registration + 2D array having non-zero pixel values, where values of 0 are ignored during registration initial_M : (3x3) array Initial transformation matrix @@ -995,7 +995,7 @@ def shannon_entropy(self, X, k=1): def mutual_information(self, A, B): if self.HA_list[self.current_level] is None: - # Only need to caluclate once per level, becuase the fixed + # Only need to calculate once per level, because the fixed # image doesn't change self.HA_list[self.current_level] = self.shannon_entropy(A) @@ -1098,7 +1098,7 @@ def calc_cost(self, p): return self.cost_fxn(fixed_intensities, moving_intensities, self.pyramid_mask[self.current_level]) def cost_fxn(self, fixed_intensities, transformed_intensities, mask): - """ + """Cost function """ results, _, _ = np.histogram2d(fixed_intensities, transformed_intensities, bins=self.nbins) n = np.sum(results) diff --git a/examples/acrobat_2023/valis/feature_detectors.py b/examples/acrobat_2023/valis/feature_detectors.py index 45ab9c2f..6394bc4b 100644 --- a/examples/acrobat_2023/valis/feature_detectors.py +++ b/examples/acrobat_2023/valis/feature_detectors.py @@ -27,7 +27,7 @@ def filter_features(kp, desc, n_keep=MAX_FEATURES): - """Get keypoints with highest response + """Get keypoints with the highest response Parameters ---------- @@ -43,7 +43,7 @@ def filter_features(kp, desc, n_keep=MAX_FEATURES): Returns ------- - Keypoints and and corresponding descriptors that the the n_keep highest + Keypoints and corresponding descriptors that the n_keep highest responses. """ @@ -145,11 +145,11 @@ def detect_and_compute(self, image, mask=None): Returns ------- - kp : ndarry - (N, 2) array positions of keypoints in xy corrdinates for N + kp : np.ndarray + (N, 2) array positions of keypoints in xy coordinates for N keypoints - desc : ndarry + desc : np.ndarray (N, M) array containing M features for each of the N keypoints """ @@ -289,8 +289,8 @@ def detect(self, image): Uses keypoint info to create KeyPoint objects for OpenCV - Paramters - --------- + Parameters + ---------- image : ndarray image from keypoints will be detected diff --git a/examples/acrobat_2023/valis/micro_rigid_registrar.py b/examples/acrobat_2023/valis/micro_rigid_registrar.py index 6743f972..8abfa484 100644 --- a/examples/acrobat_2023/valis/micro_rigid_registrar.py +++ b/examples/acrobat_2023/valis/micro_rigid_registrar.py @@ -34,7 +34,7 @@ class MicroRigidRegistrar(object): Attributes ---------- val_obj : Valis - The "parent" object that registers all of the slides. + The "parent" object that registers all the slides. feature_detector_cls : FeatureDD, optional Uninstantiated FeatureDD object that detects and computes @@ -47,7 +47,7 @@ class MicroRigidRegistrar(object): Matcher object that will be used to match image features scale : float - Degree of downsampling to use for the reigistration, based on the + Degree of downsampling to use for the registration, based on the registered WSI shape (i.e. Slide.aligned_slide_shape_rc) tile_wh : int @@ -74,7 +74,7 @@ def __init__(self, val_obj, feature_detector_cls=DEFAULT_FD, Parameters ---------- val_obj : Valis - The "parent" object that registers all of the slides. + The "parent" object that registers all the slides. feature_detector_cls : FeatureDD, optional Uninstantiated FeatureDD object that detects and computes @@ -87,7 +87,7 @@ def __init__(self, val_obj, feature_detector_cls=DEFAULT_FD, Matcher object that will be used to match image features scale : float - Degree of downsampling to use for the reigistration, based on the + Degree of downsampling to use for the registration, based on the registered WSI shape (i.e. Slide.aligned_slide_shape_rc) tile_wh : int diff --git a/examples/acrobat_2023/valis/non_rigid_registrars.py b/examples/acrobat_2023/valis/non_rigid_registrars.py index 7740416b..7708d823 100644 --- a/examples/acrobat_2023/valis/non_rigid_registrars.py +++ b/examples/acrobat_2023/valis/non_rigid_registrars.py @@ -46,7 +46,7 @@ class NonRigidRegistrar(object): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple @@ -90,11 +90,11 @@ def __init__(self, params=None): Parameters ---------- params : dictionary - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Will get used in the calc() method. In the case where simple ITK will be used, params should be - a SimpleITK.ParameterMap. Note that numeric values needd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. """ @@ -128,9 +128,9 @@ def apply_mask(self, mask): return masked_moving, masked_fixed def calc(self, moving_img, fixed_img, mask, *args, **kwargs): - """Cacluate displacement fields + """Calculate displacement fields - Can record subclass specific atrributes here too + Can record subclass specific attributes here too Parameters ---------- @@ -142,7 +142,7 @@ def calc(self, moving_img, fixed_img, mask, *args, **kwargs): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. Returns @@ -188,7 +188,7 @@ def register(self, moving_img, fixed_img, mask=None, **kwargs): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. **kwargs : dict, optional @@ -337,7 +337,7 @@ class NonRigidRegistrarXY(NonRigidRegistrar): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple @@ -388,11 +388,11 @@ def __init__(self, params=None): Parameters ---------- params : dictionary - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Will get used in the calc() method. In the case where simple ITK will be used, params should be - a SimpleITK.ParameterMap. Note that numeric values needd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. moving_xy : ndarray, optional @@ -427,7 +427,7 @@ def register(self, moving_img, fixed_img, mask=None, moving_xy=None, mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. moving_xy : ndarray, optional @@ -497,7 +497,7 @@ class NonRigidRegistrarGroupwise(NonRigidRegistrar): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple of int @@ -789,7 +789,7 @@ def run_elastix(self, moving_img, fixed_img, moving_xy=None, fixed_xy=None, mask : ndarray, optional 2D array with shape (N,M) where non-zero pixel values are - foreground, and 0 is background, which is ignnored during + foreground, and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. @@ -929,7 +929,7 @@ def __init__(self, params=None, optical_flow_obj=None, Parameters ---------- params : dictionary - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Will get used in the calc() method. optical_flow_obj : object @@ -964,7 +964,7 @@ def __init__(self, params=None, optical_flow_obj=None, Folded regions will then be removed using inpainting. If "regularize", folded regions will be detected and - regularized using the method fescribed in + regularized using the method described in "Foldover-free maps in 50 lines of code" Garanzha et al. 2021. If "None" then no smoothing will be applied. @@ -1032,7 +1032,7 @@ class SimpleElastixGroupwiseWarper(NonRigidRegistrarGroupwise): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple of int @@ -1170,7 +1170,7 @@ class NonRigidTileRegistrar(object): mask : pyvips.Image 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple @@ -1197,11 +1197,11 @@ def __init__(self, params=None, tile_wh=512, tile_buffer=100): Parameters ---------- params : dictionary - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Will get used when initializing the `non_rigid_registrar_cls` In the case where simple ITK will be used, params should be - a SimpleITK.ParameterMap. Note that numeric values needd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. tile_wh : int @@ -1354,7 +1354,7 @@ def reg_tile(self, tile_idx, lock): self.pbar.update(1) def calc(self, *args, **kwargs): - """Cacluate displacement fields + """Calculate displacement fields Each tile is registered and then stitched together """ @@ -1390,18 +1390,18 @@ def register(self, moving_img, fixed_img, mask=None, non_rigid_registrar_cls=Opt mask : ndarray, pyvips.Image 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. non_rigid_registrar_cls : NonRigidRegistrar, optional Uninstantiated NonRigidRegistrar class that will be used to calculate the deformation fields between images. - processing_cls : preprocessing.ImageProcesser, optional - preprocessing.ImageProcesser used to process the images + processing_cls : preprocessing.ImageProcessor, optional + preprocessing.ImageProcessor used to process the images processing_kwargs : dict - Dictionary of keyward arguments to be passed to `processing_cls` + Dictionary of keyword arguments to be passed to `processing_cls` target_stats : ndarray Target stats used to normalize each tile after being processed. diff --git a/examples/acrobat_2023/valis/preprocessing.py b/examples/acrobat_2023/valis/preprocessing.py index e734d5b0..ba282c07 100644 --- a/examples/acrobat_2023/valis/preprocessing.py +++ b/examples/acrobat_2023/valis/preprocessing.py @@ -18,19 +18,19 @@ DEFAULT_COLOR_STD_C = 0.2 # cam16-ucs -class ImageProcesser(object): +class ImageProcessor(object): """Process images for registration - `ImageProcesser` sub-classes processes images to single channel + `ImageProcessor` sub-classes processes images to single channel images which are then used in image registration. - Each `ImageProcesser` is initialized with an image, the path to the + Each `ImageProcessor` is initialized with an image, the path to the image, the pyramid level, and the series number. These values will be set during the registration process. - `ImageProcesser` must also have a `process_image` method, which is - called during registration. As `ImageProcesser` has the image and - and its relevant information (filename, level, series) as attributes, + `ImageProcessor` must also have a `process_image` method, which is + called during registration. As `ImageProcessor` has the image and + its relevant information (filename, level, series) as attributes, it should be able to access and modify the image as needed. However, one can also pass extra args and kwargs to `process_image`. As such, `process_image` will also need to accept args and kwargs. @@ -91,7 +91,7 @@ def process_image(self, *args, **kwargs): """ -class ChannelGetter(ImageProcesser): +class ChannelGetter(ImageProcessor): """Select channel from image """ @@ -127,7 +127,7 @@ def process_image(self, channel="dapi", adaptive_eq=True, *args, **kwaargs): return chnl -class ColorfulStandardizer(ImageProcesser): +class ColorfulStandardizer(ImageProcessor): """Standardize the colorfulness of the image """ @@ -156,7 +156,7 @@ def process_image(self, c=DEFAULT_COLOR_STD_C, invert=True, adaptive_eq=False, * return processed_img -class Luminosity(ImageProcesser): +class Luminosity(ImageProcessor): """Get luminosity of an RGB image """ @@ -179,7 +179,7 @@ def process_image(self, *args, **kwaargs): return processed_img -class BgColorDistance(ImageProcesser): +class BgColorDistance(ImageProcessor): """Calculate distance between each pixel and the background color """ @@ -202,7 +202,7 @@ def process_image(self, brightness_q=0.99, *args, **kwargs): return processed_img -class StainFlattener(ImageProcesser): +class StainFlattener(ImageProcessor): def __init__(self, image, src_f, level, series, *args, **kwargs): super().__init__(image=image, src_f=src_f, level=level, series=series, *args, **kwargs) @@ -308,7 +308,7 @@ def process_image(self, n_stains=100, q=95, with_mask=True, adaptive_eq=True): return processed_img -class Gray(ImageProcesser): +class Gray(ImageProcessor): """Get luminosity of an RGB image """ @@ -330,8 +330,8 @@ def process_image(self, *args, **kwaargs): return processed_img -class HEDeconvolution(ImageProcesser): - """Normalize staining appearence of hematoxylin and eosin (H&E) stained image +class HEDeconvolution(ImageProcessor): + """Normalize staining appearance of hematoxylin and eosin (H&E) stained image and get the H or E deconvolution image. Reference @@ -389,7 +389,7 @@ def standardize_colorfulness(img, c=DEFAULT_COLOR_STD_C, h=0): """Give image constant colorfulness and hue Image is converted to cylindrical CAM-16UCS assigned a constant - hue and colorfulness, and then coverted back to RGB. + hue and colorfulness, and then converted back to RGB. Parameters ---------- @@ -493,7 +493,7 @@ def calc_background_color_dist(img, brightness_q=0.99, mask=None): def normalize_he(img: np.array, Io: int = 240, alpha: int = 1, beta: int = 0.15): - """ Normalize staining appearence of H&E stained images. + """ Normalize staining appearance of H&E stained images. Parameters ---------- @@ -719,7 +719,7 @@ def combine_masks(mask1, mask2, op="or"): def remove_small_obj_and_lines_by_dist(mask): """ Will remove smaller objects and thin lines that - do not interesct with larger objects + do not intersect with larger objects """ dist_transform = cv2.distanceTransform(mask, cv2.DIST_L2, 5) @@ -795,7 +795,7 @@ def create_tissue_mask_from_rgb(img, brightness_q=0.99, kernel_size=3, gray_thre cam_d, cam = calc_background_color_dist(img, brightness_q=brightness_q, mask=color_mask) - # Reduce intensity of thick horizontal and vertial lines, usually artifacts like edges, streaks, folds, etc... + # Reduce intensity of thick horizontal and vertical lines, usually artifacts like edges, streaks, folds, etc... vert_knl = np.ones((1, 5)) no_v_lines = morphology.opening(cam_d, vert_knl) @@ -803,7 +803,7 @@ def create_tissue_mask_from_rgb(img, brightness_q=0.99, kernel_size=3, gray_thre no_h_lines = morphology.opening(cam_d, horiz_knl) cam_d_no_lines = np.dstack([no_v_lines, no_h_lines]).min(axis=2) - # Foreground is where color is different than backaground color + # Foreground is where color is different than background color cam_d_t, _ = filters.threshold_multiotsu(cam_d_no_lines[grey_mask == 0]) tissue_mask = np.zeros(cam_d_no_lines.shape, dtype=np.uint8) tissue_mask[cam_d_no_lines >= cam_d_t] = 255 diff --git a/examples/acrobat_2023/valis/registration.py b/examples/acrobat_2023/valis/registration.py index 0da8c863..50868118 100644 --- a/examples/acrobat_2023/valis/registration.py +++ b/examples/acrobat_2023/valis/registration.py @@ -49,8 +49,8 @@ # Default image processing # DEFAULT_BRIGHTFIELD_CLASS = preprocessing.ColorfulStandardizer DEFAULT_BRIGHTFIELD_PROCESSING_ARGS = {'c': preprocessing.DEFAULT_COLOR_STD_C, "h": 0} -DEFAULT_FLOURESCENCE_CLASS = preprocessing.ChannelGetter -DEFAULT_FLOURESCENCE_PROCESSING_ARGS = {"channel": "dapi", "adaptive_eq": True} +DEFAULT_FLUORESCENCE_CLASS = preprocessing.ChannelGetter +DEFAULT_FLUORESCENCE_PROCESSING_ARGS = {"channel": "dapi", "adaptive_eq": True} DEFAULT_NORM_METHOD = "img_stats" # Default rigid registration parameters # @@ -75,9 +75,9 @@ FD_KEY = "feature_detector" MATCHER_KEY = "matcher" NAME_KEY = "name" -IMAGES_ORDERD_KEY = "imgs_ordered" +IMAGES_ORDERED_KEY = "imgs_ordered" REF_IMG_KEY = "reference_img_f" -QT_EMMITER_KEY = "qt_emitter" +QT_EMITTER_KEY = "qt_emitter" TFORM_SRC_SHAPE_KEY = "transformation_src_shape_rc" TFORM_DST_SHAPE_KEY = "transformation_dst_shape_rc" TFORM_MAT_KEY = "M" @@ -149,7 +149,7 @@ class Slide(object): `Slide` is a class that stores registration parameters and other metadata about a slide. Once registration has been - completed, `Slide` is also able warp the slide and/or points + completed, `Slide` is also able to warp the slide and/or points using the same registration parameters. Warped slides can be saved as ome.tiff images with valid ome-xml. @@ -164,7 +164,7 @@ class Slide(object): argument specified when creating a `Valis` object. val_obj : Valis - The "parent" object that registers all of the slide. + The "parent" object that registers all the slides. reader : SlideReader Object that can read slides and collect metadata. @@ -311,7 +311,7 @@ def __init__(self, src_f, image, val_obj, reader, name=None): argument specified when creating a `Valis` object. val_obj : Valis - The "parent" object that registers all of the slide. + The "parent" object that registers all the slides. reader : SlideReader Object that can read slides and collect metadata. @@ -402,7 +402,7 @@ def slide2image(self, level, series=None, xywh=None): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -430,7 +430,7 @@ def slide2vips(self, level, series=None, xywh=None): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -492,7 +492,7 @@ def get_overlap_crop_xywh(self, warped_img_shape_rc, scaled_warped_img_shape_rc= shape of registered image warped_scaled_img_shape_rc : tuple of int, optional - shape of scaled registered image (i.e. registered slied) + shape of scaled registered image (i.e. registered slide) Returns ------- @@ -525,7 +525,7 @@ def get_crop_xywh(self, crop, out_shape_rc=None): out_shape_rc : tuple of int, optional If crop is "reference", this should be the shape of scaled reference image, such - as the unwarped slide that corresponds to the unwarped processed reference image. + as the un-warped slide that corresponds to the un-warped processed reference image. If crop is "overlap", this should be the shape of the registered slides. @@ -663,7 +663,7 @@ def warp_img(self, img=None, non_rigid=True, crop=True, interp_method="bicubic") will be warped. non_rigid : bool - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. crop: bool, str @@ -672,7 +672,7 @@ def warp_img(self, img=None, non_rigid=True, crop=True, interp_method="bicubic") image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. interp_method : str Interpolation method used when warping slide. Default is "bicubic" @@ -756,7 +756,7 @@ def warp_img(self, img=None, non_rigid=True, crop=True, interp_method="bicubic") def warp_img_from_to(self, img, to_slide_obj, dst_slide_level=0, non_rigid=True, interp_method="bicubic", bg_color=None): - """Warp an image from this slide onto another unwarped slide + """Warp an image from this slide onto another un-warped slide Note that if `img` is a labeled image then it is recommended to set `interp_method` to "nearest" @@ -768,13 +768,13 @@ def warp_img_from_to(self, img, to_slide_obj, to_slide_obj : Slide Slide to which the points will be warped. I.e. `xy` will be warped from this Slide to their position in - the unwarped slide associated with `to_slide_obj`. + the un-warped slide associated with `to_slide_obj`. dst_slide_level: int, tuple, optional Pyramid level of the slide/image that `img` will be warped on to non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. """ @@ -826,7 +826,7 @@ def warp_slide(self, level, non_rigid=True, crop=True, Pyramid level to be warped non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True crop: bool, str @@ -835,7 +835,7 @@ def warp_slide(self, level, non_rigid=True, crop=True, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. src_f : str, optional Path of slide to be warped. If None (the default), Slide.src_f @@ -920,7 +920,7 @@ def warp_and_save_slide(self, dst_f, level=0, non_rigid=True, Pyramid level to be warped non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True crop: bool, str @@ -954,7 +954,7 @@ def warp_and_save_slide(self, dst_f, level=0, non_rigid=True, compression : str Compression method used to save ome.tiff . Default is lzw, but can also - be jpeg or jp2k. See pyips for more details. + be jpeg or jp2k. See pyvips for more details. """ @@ -1025,7 +1025,7 @@ def warp_xy(self, xy, M=None, slide_level=0, pt_level=0, the points should be warped. Default is 0. pt_level: int, tuple, optional - Pyramid level from which the points origingated. For example, if + Pyramid level from which the points originated. For example, if `xy` are from the centroids of cell segmentation performed on the full resolution image, this should be 0. Alternatively, the value can be a tuple of the image's shape (row, col) from which the points came. @@ -1034,7 +1034,7 @@ def warp_xy(self, xy, M=None, slide_level=0, pt_level=0, image's shape (row, col). Default is 0. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True. crop: bool, str @@ -1048,7 +1048,7 @@ def warp_xy(self, xy, M=None, slide_level=0, pt_level=0, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. """ if M is None: @@ -1102,10 +1102,10 @@ def warp_xy(self, xy, M=None, slide_level=0, pt_level=0, def warp_xy_from_to(self, xy, to_slide_obj, src_slide_level=0, src_pt_level=0, dst_slide_level=0, non_rigid=True): - """Warp points from this slide to another unwarped slide + """Warp points from this slide to another un-warped slide - Takes a set of points found in this unwarped slide, and warps them to - their position in the unwarped "to" slide. + Takes a set of points found in this un-warped slide, and warps them to + their position in the un-warped "to" slide. Parameters ---------- @@ -1115,12 +1115,12 @@ def warp_xy_from_to(self, xy, to_slide_obj, src_slide_level=0, src_pt_level=0, to_slide_obj : Slide Slide to which the points will be warped. I.e. `xy` will be warped from this Slide to their position in - the unwarped slide associated with `to_slide_obj`. + the un-warped slide associated with `to_slide_obj`. src_pt_level: int, tuple, optional Pyramid level of the slide/image in which `xy` originated. For example, if `xy` are from the centroids of cell segmentation - performed on the unwarped full resolution image, this should be 0. + performed on the un-warped full resolution image, this should be 0. Alternatively, the value can be a tuple of the image's shape (row, col) from which the points came. For example, if `xy` are bounding box coordinates from an analysis on a lower resolution image, @@ -1134,7 +1134,7 @@ def warp_xy_from_to(self, xy, to_slide_obj, src_slide_level=0, src_pt_level=0, to their location in an image with that same shape. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. """ @@ -1201,7 +1201,7 @@ def warp_geojson(self, geojson_f, M=None, slide_level=0, pt_level=0, the points should be warped. Default is 0. pt_level: int, tuple, optional - Pyramid level from which the points origingated. For example, if + Pyramid level from which the points originated. For example, if `xy` are from the centroids of cell segmentation performed on the full resolution image, this should be 0. Alternatively, the value can be a tuple of the image's shape (row, col) from which the points came. @@ -1210,7 +1210,7 @@ def warp_geojson(self, geojson_f, M=None, slide_level=0, pt_level=0, image's shape (row, col). Default is 0. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True. crop: bool, str @@ -1224,7 +1224,7 @@ def warp_geojson(self, geojson_f, M=None, slide_level=0, pt_level=0, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. """ if M is None: @@ -1291,10 +1291,10 @@ def warp_geojson(self, geojson_f, M=None, slide_level=0, pt_level=0, def warp_geojson_from_to(self, geojson_f, to_slide_obj, src_slide_level=0, src_pt_level=0, dst_slide_level=0, non_rigid=True): - """Warp geoms in geojson file from annotation slide to another unwarped slide + """Warp geoms in geojson file from annotation slide to another un-warped slide Takes a set of geometries found in this annotation slide, and warps them to - their position in the unwarped "to" slide. + their position in the un-warped "to" slide. Parameters ---------- @@ -1305,12 +1305,12 @@ def warp_geojson_from_to(self, geojson_f, to_slide_obj, src_slide_level=0, src_p to_slide_obj : Slide Slide to which the points will be warped. I.e. `xy` will be warped from this Slide to their position in - the unwarped slide associated with `to_slide_obj`. + the un-warped slide associated with `to_slide_obj`. src_pt_level: int, tuple, optional Pyramid level of the slide/image in which `xy` originated. For example, if `xy` are from the centroids of cell segmentation - performed on the unwarped full resolution image, this should be 0. + performed on the un-warped full resolution image, this should be 0. Alternatively, the value can be a tuple of the image's shape (row, col) from which the points came. For example, if `xy` are bounding box coordinates from an analysis on a lower resolution image, @@ -1324,7 +1324,7 @@ def warp_geojson_from_to(self, geojson_f, to_slide_obj, src_slide_level=0, src_p to their location in an image with that same shape. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Returns @@ -1479,10 +1479,10 @@ class Valis(object): Dictionary of Slide objects, each of which contains information about a slide, and methods to warp it. - brightfield_procsseing_fxn_str: str + brightfield_processing_fxn_str: str Name of function used to process brightfield images. - if_procsseing_fxn_str : str + if_processing_fxn_str : str Name of function used to process fluorescence images. max_image_dim_px : int @@ -1503,7 +1503,7 @@ class Valis(object): the `img_obj_list` has been sorted during rigid registration. align_to_reference : bool - Whether or not images should be aligne to a reference image + Whether or not images should be aligned to a reference image specified by `reference_img_f`. Will be set to True if `reference_img_f` is provided. @@ -1514,7 +1514,7 @@ class Valis(object): SerialRigidRegistrar object that performs the rigid registration. rigid_reg_kwargs : dict - Dictionary of keyward arguments passed to + Dictionary of keyword arguments passed to `serial_rigid.register_images`. feature_descriptor_str : str @@ -1537,7 +1537,7 @@ class Valis(object): non-rigid registration. non_rigid_reg_kwargs : dict - Dictionary of keyward arguments passed to + Dictionary of keyword arguments passed to `serial_non_rigid.register_images`. non_rigid_registrar_cls : NonRigidRegistrar @@ -1643,7 +1643,7 @@ class Valis(object): View ome.tiff, located at merged_slide_dst_f """ - @valtils.deprecated_args(max_non_rigid_registartion_dim_px="max_non_rigid_registration_dim_px", img_type="image_type") + @valtils.deprecated_args(max_non_rigid_registration_dim_px="max_non_rigid_registration_dim_px", img_type="image_type") def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, feature_detector_cls=DEFAULT_FD, transformer_cls=DEFAULT_TRANSFORM_CLASS, @@ -1703,8 +1703,8 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, transformation matrix that will warp each image to the target image. Default is SimilarityTransform - affine_optimizer_cls : AffineOptimzer class, optional - Uninstantiated AffineOptimzer that will minimize a + affine_optimizer_cls : AffineOptimizer class, optional + Uninstantiated AffineOptimizer that will minimize a cost function to find the optimal affine transformations. If a desired affine optimization is not available, one can be created by subclassing `affine_optimizer.AffineOptimizer`. @@ -1725,7 +1725,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, are already in the correct order. If True, then each filename should begin with the number that indicates its position in the z-stack. If False, then the images will be sorted by ordering a feature distance - matix. Default is False. + matrix. Default is False. reference_img_f : str, optional Filename of image that will be treated as the center of the stack. @@ -1740,7 +1740,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, non_rigid_registrar_cls : NonRigidRegistrar, optional Uninstantiated NonRigidRegistrar class that will be used to calculate the deformation fields between images. See - the `non_rigid_registrars` module for a desciption of available + the `non_rigid_registrars` module for a description of available methods. If a desired non-rigid registration method is not available, one can be implemented by subclassing.NonRigidRegistrar. If None, then only rigid registration will be performed @@ -1749,18 +1749,18 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, Dictionary containing key, value pairs to be used to initialize `non_rigid_registrar_cls`. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. See the NonRigidRegistrar classes in `non_rigid_registrars` for the available non-rigid registration methods and arguments. compose_non_rigid : bool, optional - Whether or not to compose non-rigid transformations. If `True`, + Whether to compose non-rigid transformations. If `True`, then an image is non-rigidly warped before aligning to the adjacent non-rigidly aligned image. This allows the transformations to accumulate, which may bring distant features together but could also result in un-wanted deformations, particularly around the edges. - If `False`, the image not warped before being aaligned to the adjacent + If `False`, the image not warped before being aligned to the adjacent non-rigidly aligned image. This can reduce unwanted deformations, but may not bring distant features together. @@ -1771,11 +1771,11 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, Valis.slide_dict. do_rigid: bool, dictionary, optional - Whether or not to perform rigid registration. If `False`, rigid + Whether to perform rigid registration. If `False`, rigid registration will be skipped. If `do_rigid` is a dictionary, it should contain inverse transformation - matrices to rigidly align images to the specificed by `reference_img_f`. + matrices to rigidly align images to the specified by `reference_img_f`. M will be estimated for images that are not in the dictionary. Each key is the filename of the image associated with the transformation matrix, and value is a dictionary containing the following values: @@ -1801,20 +1801,20 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, is defined, then `crop` will be set to "reference". create_masks : bool, optional - Whether or not to create and apply masks for registration. + Whether to create and apply masks for registration. Can help focus alignment on the tissue, but can sometimes mask too much if there is a lot of variation in the image. check_for_reflections : bool, optional - Determine if alignments are improved by relfecting/mirroring/flipping + Determine if alignments are improved by reflecting/mirroring/flipping images. Optional because it requires re-detecting features in each version - of the images and then re-matching features, and so can be time consuming and + of the images and then re-matching features, and so can be time-consuming and not always necessary. resolution_xyu: tuple, optional Physical size per pixel and the unit. If None (the default), these values will be determined for each slide using the slides' metadata. - If provided, this physical pixel sizes will be used for all of the slides. + If provided, this physical pixel sizes will be used for all the slides. This option is available in case one cannot easily access to the original slides, but does have the information on pixel's physical units. @@ -1837,7 +1837,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, max_non_rigid_registration_dim_px : int, optional Maximum width or height of images used for non-rigid registration. - Larger values may yeild more accurate results, at the expense of + Larger values may yield more accurate results, at the expense of speed and memory. There is also a practical limit, as the specified size may be too large to fit in memory. @@ -1860,7 +1860,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, this step is skipped. micro_rigid_registrar_params : dictionary - Dictionary of keyword arguments used intialize the `MicroRigidRegistrar` + Dictionary of keyword arguments used initialize the `MicroRigidRegistrar` qt_emitter : PySide2.QtCore.Signal, optional Used to emit signals that update the GUI's progress bars @@ -1905,8 +1905,8 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, self.slide_dict = {} # Fields related to image pre-processing # - self.brightfield_procsseing_fxn_str = None - self.if_procsseing_fxn_str = None + self.brightfield_processing_fxn_str = None + self.if_processing_fxn_str = None if max_image_dim_px < max_processed_image_dim_px: msg = f"max_image_dim_px is {max_image_dim_px} but needs to be less or equal to {max_processed_image_dim_px}. Setting max_image_dim_px to {max_processed_image_dim_px}" @@ -1960,7 +1960,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, compose_non_rigid=compose_non_rigid, qt_emitter=qt_emitter) - # Info realted to saving images to view results # + # Info related to saving images to view results # self.mask_dict = None self.create_masks = create_masks @@ -2005,9 +2005,9 @@ def _set_rigid_reg_kwargs(self, name, feature_detector, similarity_metric, MATCHER_KEY: matcher, AFFINE_OPTIMIZER_KEY: afo, REF_IMG_KEY: reference_img_f, - IMAGES_ORDERD_KEY: imgs_ordered, + IMAGES_ORDERED_KEY: imgs_ordered, CHECK_REFLECT_KEY: check_for_reflections, - QT_EMMITER_KEY: qt_emitter + QT_EMITTER_KEY: qt_emitter } # Save methods as strings since some objects cannot be pickled # @@ -2029,7 +2029,7 @@ def _set_non_rigid_reg_kwargs(self, name, non_rigid_reg_class, non_rigid_reg_par NON_RIGID_REG_CLASS_KEY: non_rigid_reg_class, NON_RIGID_REG_PARAMS_KEY: non_rigid_reg_params, REF_IMG_KEY: reference_img_f, - QT_EMMITER_KEY: qt_emitter, + QT_EMITTER_KEY: qt_emitter, NON_RIGID_COMPOSE_KEY: compose_non_rigid } @@ -2120,7 +2120,7 @@ def get_slide(self, src_f): * Save the warped slide as an ome.tiff (Slide.warp_and_save_slide) * Warp an image of the slide (Slide.warp_img) * Warp points (Slide.warp_xy) - * Warp points in one slide to their position in another unwarped slide (Slide.warp_xy_from_to) + * Warp points in one slide to their position in another un-warped slide (Slide.warp_xy_from_to) * Access slide ome-xml (Slide.original_xml) See Slide for more details. @@ -2220,7 +2220,7 @@ def get_img_names(self, img_list): for j, p in enumerate(dup_paths): new_name = f"{names_dict[p]}_{str(j).zfill(z)}" - msg = f"Renmaing {p} to {new_name} in Valis.slide_dict)" + msg = f"Renaming {p} to {new_name} in Valis.slide_dict)" valtils.print_warning(msg) names_dict[p] = new_name @@ -2246,7 +2246,7 @@ def convert_imgs(self, series=None, reader_cls=None): """Convert slides to images and create dictionary of Slides. series : int, optional - Slide series to be read. If None, the series with largest image will be read + Slide series to be read. If None, the series with the largest image will be read reader_cls : SlideReader, optional Uninstantiated SlideReader class that will convert @@ -2394,7 +2394,7 @@ def create_original_composite_img(self, rigid_registrar): return overlap_img def measure_original_mmi(self, img1, img2): - """Measure Mattes mutation inormation between 2 unregistered images. + """Measure Mattes mutation information between 2 unregistered images. """ dst_rc = np.max([img1.shape, img2.shape], axis=1) @@ -2410,8 +2410,8 @@ def measure_original_mmi(self, img1, img2): def create_img_processor_dict(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, brightfield_processing_kwargs=DEFAULT_BRIGHTFIELD_PROCESSING_ARGS, - if_processing_cls=DEFAULT_FLOURESCENCE_CLASS, - if_processing_kwargs=DEFAULT_FLOURESCENCE_PROCESSING_ARGS, + if_processing_cls=DEFAULT_FLUORESCENCE_CLASS, + if_processing_kwargs=DEFAULT_FLUORESCENCE_PROCESSING_ARGS, processor_dict=None): """Create dictionary to get processors for each image @@ -2420,19 +2420,19 @@ def create_img_processor_dict(self, brightfield_processing_cls=DEFAULT_BRIGHTFIE Parameters ---------- - brightfield_processing_cls : ImageProcesser - ImageProcesser to pre-process brightfield images to make them look as similar as possible. + brightfield_processing_cls : ImageProcessor + ImageProcessor to pre-process brightfield images to make them look as similar as possible. Should return a single channel uint8 image. brightfield_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `brightfield_processing_cls` + Dictionary of keyword arguments to be passed to `brightfield_processing_cls` - if_processing_cls : ImageProcesser - ImageProcesser to pre-process immunofluorescent images to make them look as similar as possible. + if_processing_cls : ImageProcessor + ImageProcessor to pre-process immunofluorescence images to make them look as similar as possible. Should return a single channel uint8 image. if_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `if_processing_cls` + Dictionary of keyword arguments to be passed to `if_processing_cls` processor_dict : dict Each key should be the filename of the image, and the value either a subclassed @@ -2729,7 +2729,7 @@ def get_all_overlap_mask(self, rigid_registrar): def get_null_overlap_mask(self, rigid_registrar): - """Create mask that covers all of the image. + """Create mask that covers all the images. Not really a mask @@ -2787,7 +2787,7 @@ def rigid_register_partial(self, tform_dict=None): transformation_src_shape_rc: shape (row, col) of image used to find the rigid transformation. If not provided, then it is assumed to be the shape of the level 0 slide - transformation_dst_shape_rc: shape of registered image. If not presesnt, but a reference was provided + transformation_dst_shape_rc: shape of registered image. If not present, but a reference was provided and `transformation_src_shape_rc` was not provided, this is assumed to be the shape of the reference slide If None, then all rigid M will be the identity matrix @@ -2822,7 +2822,7 @@ def rigid_register_partial(self, tform_dict=None): print("\n======== Matching images\n") - if rigid_registrar.aleady_sorted: + if rigid_registrar.already_sorted: rigid_registrar.match_sorted_imgs(matcher, keep_unfiltered=False) for i, img_obj in enumerate(rigid_registrar.img_obj_list): @@ -3075,8 +3075,8 @@ def rigid_register(self): def micro_rigid_register(self): - micro_rigid_registar = self.micro_rigid_registrar_cls(val_obj=self, **self.micro_rigid_registrar_params) - micro_rigid_registar.register() + micro_rigid_registrar = self.micro_rigid_registrar_cls(val_obj=self, **self.micro_rigid_registrar_params) + micro_rigid_registrar.register() rigid_img_list = [slide_obj.warp_img(slide_obj.processed_img, non_rigid=False) for slide_obj in self.slide_dict.values()] self.micro_rigid_overlap_img = self.draw_overlap_img(rigid_img_list) @@ -3349,7 +3349,7 @@ def prep_images_for_large_non_rigid_registration(self, max_img_dim, else: s = np.min(max_img_dim/np.array(ref_slide.processed_img_shape_rc)) else: - # Determine how big image would have to be to get mask with maxmimum dimension = max_img_dim + # Determine how big image would have to be to get mask with maximum dimension = max_img_dim if isinstance(mask, pyvips.Image): mask_shape_rc = np.array((mask.height, mask.width)) else: @@ -3702,13 +3702,13 @@ def non_rigid_register(self, rigid_registrar, processor_dict): if draw_img.ndim == 2: draw_img = np.dstack([draw_img] * 3) - thumbanil_deform_grid = viz.color_displacement_tri_grid(bk_dx=thumbnail_bk_dxdy[..., 0], + thumbnail_deform_grid = viz.color_displacement_tri_grid(bk_dx=thumbnail_bk_dxdy[..., 0], bk_dy=thumbnail_bk_dxdy[..., 1], img=draw_img, n_grid_pts=25) deform_img_f = os.path.join(self.deformation_field_dir, img_save_id + "_" + slide_obj.name + ".png") - warp_tools.save_img(deform_img_f, thumbanil_deform_grid, thumbnail_size=self.thumbnail_size) + warp_tools.save_img(deform_img_f, thumbnail_deform_grid, thumbnail_size=self.thumbnail_size) return non_rigid_registrar @@ -3724,10 +3724,10 @@ def measure_error(self): `summary_df` contains various information about the registration. The "from" column is the name of the image, while the "to" column - name of the image it was aligned to. "from" is analagous to "moving" - or "current", while "to" is analgous to "fixed" or "previous". + name of the image it was aligned to. "from" is analogous to "moving" + or "current", while "to" is analogous to "fixed" or "previous". - Columns begining with "original" refer to error measurements of the + Columns beginning with "original" refer to error measurements of the unregistered images. Those beginning with "rigid" or "non_rigid" refer to measurements related to rigid or non-rigid registration, respectively. @@ -3735,7 +3735,7 @@ def measure_error(self): the case of errors based on feature distances (i.e. those ending in "D"), the mean is weighted by the number of feature matches between "from" and "to". - Columns endining in "D" indicate the median distance between matched + Columns ending in "D" indicate the median distance between matched features in "from" and "to". Columns ending in "rTRE" indicate the target registration error between @@ -3751,7 +3751,7 @@ def measure_error(self): "aligned_shape" is the shape of the registered full resolution slide - "physical_units" are the names of the pixels physcial unit, e.g. u'\u00B5m' + "physical_units" are the names of the pixels physical unit, e.g. u'\u00B5m' "resolution" is the physical unit per pixel @@ -3921,8 +3921,8 @@ def measure_error(self): def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, brightfield_processing_kwargs=DEFAULT_BRIGHTFIELD_PROCESSING_ARGS, - if_processing_cls=DEFAULT_FLOURESCENCE_CLASS, - if_processing_kwargs=DEFAULT_FLOURESCENCE_PROCESSING_ARGS, + if_processing_cls=DEFAULT_FLUORESCENCE_CLASS, + if_processing_kwargs=DEFAULT_FLUORESCENCE_PROCESSING_ARGS, processor_dict=None, reader_cls=None): @@ -3932,13 +3932,13 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, then conduct rigid registration. Non-rigid registration will then be performed if the `non_rigid_registrar_cls` argument used to initialize the Valis object was not None. - In addition to the objects returned, the desination directory (i.e. `dst_dir`) + In addition to the objects returned, the destination directory (i.e. `dst_dir`) will contain thumbnails so that one can visualize the results: converted image thumbnails will be in "images/"; processed images in "processed/"; rigidly aligned images in "rigid_registration/"; non-rigidly aligned images in "non_rigid_registration/"; - non-rigid deformation field images (i.e. warped grids colored by the direction and magntidue) + non-rigid deformation field images (i.e. warped grids colored by the direction and magnitude) of the deformation) will be in ""deformation_fields/". The size of these thumbnails - is determined by the `thumbnail_size` argument used to initialze this object. + is determined by the `thumbnail_size` argument used to initialize this object. One can get a sense of how well the registration worked by looking in the "overlaps/", which shows how the images overlap before @@ -3947,26 +3947,26 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, blending those images. The "data/" directory will contain a pickled copy of this registrar, which can be - later be opened (unpickled) and used to warp slides and/or point data. + later be opened (un-pickled) and used to warp slides and/or point data. "data/" will also contain the `summary_df` saved as a csv file. Parameters ---------- - brightfield_processing_cls : preprocessing.ImageProcesser - preprocessing.ImageProcesser used to pre-process brightfield images to make + brightfield_processing_cls : preprocessing.ImageProcessor + preprocessing.ImageProcessor used to pre-process brightfield images to make them look as similar as possible. brightfield_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `brightfield_processing_cls` + Dictionary of keyword arguments to be passed to `brightfield_processing_cls` - if_processing_cls : preprocessing.ImageProcesser - preprocessing.ImageProcesser used to pre-process immunofluorescent images + if_processing_cls : preprocessing.ImageProcessor + preprocessing.ImageProcessor used to pre-process immunofluorescence images to make them look as similar as possible. if_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `if_processing_cls` + Dictionary of keyword arguments to be passed to `if_processing_cls` processor_dict : dict Each key should be the filename of the image, and the value either a subclassed @@ -3997,10 +3997,10 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, `summary_df` contains various information about the registration. The "from" column is the name of the image, while the "to" column - name of the image it was aligned to. "from" is analagous to "moving" - or "current", while "to" is analgous to "fixed" or "previous". + name of the image it was aligned to. "from" is analogous to "moving" + or "current", while "to" is analogous to "fixed" or "previous". - Columns begining with "original" refer to error measurements of the + Columns beginning with "original" refer to error measurements of the unregistered images. Those beginning with "rigid" or "non_rigid" refer to measurements related to rigid or non-rigid registration, respectively. @@ -4008,7 +4008,7 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, the case of errors based on feature distances (i.e. those ending in "D"), the mean is weighted by the number of feature matches between "from" and "to". - Columns endining in "D" indicate the median distance between matched + Columns ending in "D" indicate the median distance between matched features in "from" and "to". Columns ending in "TRE" indicate the target registration error between @@ -4024,7 +4024,7 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, "aligned_shape" is the shape of the registered full resolution slide - "physical_units" are the names of the pixels physcial unit, e.g. u'\u00B5m' + "physical_units" are the names of the pixels physical unit, e.g. u'\u00B5m' "resolution" is the physical unit per pixel @@ -4050,7 +4050,7 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, if_processing_kwargs=if_processing_kwargs, processor_dict=processor_dict) - self.brightfield_procsseing_fxn_str = brightfield_processing_cls.__name__ + self.brightfield_processing_fxn_str = brightfield_processing_cls.__name__ self.if_processing_fxn_str = if_processing_cls.__name__ self.process_imgs(processor_dict=slide_processors) @@ -4113,35 +4113,35 @@ def cleanup(self): self.non_rigid_registrar = None - @valtils.deprecated_args(max_non_rigid_registartion_dim_px="max_non_rigid_registration_dim_px") + @valtils.deprecated_args(max_non_rigid_registration_dim_px="max_non_rigid_registration_dim_px") def register_micro(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, brightfield_processing_kwargs=DEFAULT_BRIGHTFIELD_PROCESSING_ARGS, - if_processing_cls=DEFAULT_FLOURESCENCE_CLASS, - if_processing_kwargs=DEFAULT_FLOURESCENCE_PROCESSING_ARGS, + if_processing_cls=DEFAULT_FLUORESCENCE_CLASS, + if_processing_kwargs=DEFAULT_FLUORESCENCE_PROCESSING_ARGS, processor_dict=None, max_non_rigid_registration_dim_px=DEFAULT_MAX_NON_RIGID_REG_SIZE, non_rigid_registrar_cls=DEFAULT_NON_RIGID_CLASS, non_rigid_reg_params=DEFAULT_NON_RIGID_KWARGS, reference_img_f=None, align_to_reference=False, mask=None, tile_wh=DEFAULT_NR_TILE_WH): - """Improve alingment of microfeatures by performing second non-rigid registration on larger images + """Improve alignment of microfeatures by performing second non-rigid registration on larger images - Caclculates additional non-rigid deformations using a larger image + Calculates additional non-rigid deformations using a larger image Parameters ---------- - brightfield_processing_cls : preprocessing.ImageProcesser - preprocessing.ImageProcesser used to pre-process brightfield images to make + brightfield_processing_cls : preprocessing.ImageProcessor + preprocessing.ImageProcessor used to pre-process brightfield images to make them look as similar as possible. brightfield_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `brightfield_processing_cls` + Dictionary of keyword arguments to be passed to `brightfield_processing_cls` - if_processing_cls : preprocessing.ImageProcesser - preprocessing.ImageProcesser used to pre-process immunofluorescent images + if_processing_cls : preprocessing.ImageProcessor + preprocessing.ImageProcessor used to pre-process immunofluorescence images to make them look as similar as possible. if_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `if_processing_cls` + Dictionary of keyword arguments to be passed to `if_processing_cls` max_non_rigid_registration_dim_px : int, optional Maximum width or height of images used for non-rigid registration. @@ -4163,7 +4163,7 @@ def register_micro(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, non_rigid_registrar_cls : NonRigidRegistrar, optional Uninstantiated NonRigidRegistrar class that will be used to calculate the deformation fields between images. See - the `non_rigid_registrars` module for a desciption of available + the `non_rigid_registrars` module for a description of available methods. If a desired non-rigid registration method is not available, one can be implemented by subclassing.NonRigidRegistrar. @@ -4171,7 +4171,7 @@ def register_micro(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, Dictionary containing key, value pairs to be used to initialize `non_rigid_registrar_cls`. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. See the NonRigidRegistrar classes in `non_rigid_registrars` for the available non-rigid registration methods and arguments. @@ -4207,7 +4207,7 @@ def register_micro(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, if using_tiler: # Have determined that these images will be too big msg = (f"Registration would more than {TILER_THRESH_GB} GB if all images opened in memory. " - f"Will use NonRigidTileRegistrar to register cooresponding tiles to reduce memory consumption, " + f"Will use NonRigidTileRegistrar to register corresponding tiles to reduce memory consumption, " f"but this method is experimental") valtils.print_warning(msg) @@ -4415,7 +4415,7 @@ def warp_and_save_slides(self, dst_dir, level=0, non_rigid=True, resolution image will be warped and saved. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True crop: bool, str @@ -4424,7 +4424,7 @@ def warp_and_save_slides(self, dst_dir, level=0, non_rigid=True, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. colormap : list List of RGB colors (0-255) to use for channel colors @@ -4437,7 +4437,7 @@ def warp_and_save_slides(self, dst_dir, level=0, non_rigid=True, compression : str, optional Compression method used to save ome.tiff . Default is lzw, but can also - be jpeg or jp2k. See pyips for more details. + be jpeg or jp2k. See pyvips for more details. """ pathlib.Path(dst_dir).mkdir(exist_ok=True, parents=True) @@ -4482,7 +4482,7 @@ def warp_and_merge_slides(self, dst_f=None, level=0, non_rigid=True, resolution image will be warped and saved. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True crop: bool, str @@ -4491,13 +4491,13 @@ def warp_and_merge_slides(self, dst_f=None, level=0, non_rigid=True, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. channel_name_dict : dict of lists, optional. key = slide file name, value = list of channel names for that slide. If None, - the the channel names found in each slide will be used. + the channel names found in each slide will be used. - src_f_list : list of str, optionaal + src_f_list : list of str, optional List of paths to slide to be warped. If None (the default), Valis.original_img_list will be used. Otherwise, the paths to which `src_f_list` points to should be an alternative copy of the slides, such as ones that have undergone @@ -4507,7 +4507,7 @@ def warp_and_merge_slides(self, dst_f=None, level=0, non_rigid=True, List of RGB colors (0-255) to use for channel colors drop_duplicates : bool, optional - Whether or not to drop duplicate channels that might be found in multiple slides. + Whether to drop duplicate channels that might be found in multiple slides. For example, if DAPI is in multiple slides, then the only the DAPI channel in the first slide will be kept. @@ -4519,7 +4519,7 @@ def warp_and_merge_slides(self, dst_f=None, level=0, non_rigid=True, compression : str Compression method used to save ome.tiff . Default is lzw, but can also - be jpeg or jp2k. See pyips for more details. + be jpeg or jp2k. See pyvips for more details. Returns ------- diff --git a/examples/acrobat_2023/valis/serial_non_rigid.py b/examples/acrobat_2023/valis/serial_non_rigid.py index fb9c68b0..c5f09a5f 100644 --- a/examples/acrobat_2023/valis/serial_non_rigid.py +++ b/examples/acrobat_2023/valis/serial_non_rigid.py @@ -169,7 +169,7 @@ def get_imgs_from_dict(img_dict): "name_list" : list of image names. If not provided, will come from file names "mask_list" list of masks for each image - All of the above are optional, except `img_list`. + All the above are optional, except `img_list`. Returns ------- @@ -222,7 +222,7 @@ class NonRigidZImage(object): ---------- image : ndarray - Original, unwarped image with shape (P, Q) + Original, un-warped image with shape (P, Q) name : str Name of image. @@ -260,7 +260,7 @@ def __init__(self, reg_obj, image, name, stack_idx, moving_xy=None, fixed_xy=Non ---------- image : ndarray - Original, unwarped image with shape (P, Q) + Original, un-warped image with shape (P, Q) name : str Name of image. @@ -373,16 +373,16 @@ def calc_deformation(self, registered_fixed_image, non_rigid_reg_class, Used to warp the registered_img before finding deformation fields. params : dictionary, optional - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Passed to the non_rigid_reg_class' init() method. In the case where simple ITK will be used, params should be - a SimpleITK.ParameterMap. Note that numeric values needd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. mask : ndarray, optional 2D array with shape (P,Q) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. """ @@ -547,13 +547,13 @@ class SerialNonRigidRegistrar(object): non_rigid_obj_dict : dict Dictionary, where each key is the name of a NonRigidZImage, and - the value is the assocatiated NonRigidZImage + the value is the associated NonRigidZImage non_rigid_reg_params: dictionary Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. mask : ndarray @@ -578,7 +578,7 @@ def __init__(self, src, reference_img_f=None, moving_to_fixed_xy=None, A SerialRigidRegistrar object that was used to optimally align a series of images. - If a string, it should indicating where the images + If a string, it should indicate where the images to be aligned are located. If src is a string, the images should be named such that they are read in the correct order, i.e. each starting with a number. @@ -604,10 +604,10 @@ def __init__(self, src, reference_img_f=None, moving_to_fixed_xy=None, #. Rigid registered xy in moving/current/from image #. Rigid registered xy in fixed/next/to image - To deterime which pairs of images will be aligned, use + To determine which pairs of images will be aligned, use `get_alignment_indices`. Can use `get_imgs_from_dir` - to see the order inwhich the images will be read, which will correspond - to the indices retuned by `get_alignment_indices`. + to see the order in which the images will be read, which will correspond + to the indices returned by `get_alignment_indices`. If `src` is a SerialRigidRegistrar and `moving_to_fixed_xy` is True, then the matching features in the SerialRigidRegistrar will @@ -832,7 +832,7 @@ def register_serial(self, non_rigid_reg_class, non_rigid_reg_params=None, img_pa Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. """ @@ -882,7 +882,7 @@ def register_to_ref(self, non_rigid_reg_class, non_rigid_reg_params=None, img_pa Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. """ @@ -916,7 +916,7 @@ def register_groupwise(self, non_rigid_reg_class, non_rigid_reg_params=None): Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. """ @@ -937,7 +937,7 @@ def register(self, non_rigid_reg_class, non_rigid_reg_params, img_params=None): Images will be registered serially if `non_rigid_reg_class` is a subclass of NonRigidRegistrarGroupwise, then groupwise registration - will be conductedd. If `non_rigid_reg_class` is a subclass of + will be conducted. If `non_rigid_reg_class` is a subclass of NonRigidRegistrar then images will be aligned serially. Parameters @@ -950,7 +950,7 @@ def register(self, non_rigid_reg_class, non_rigid_reg_params, img_params=None): Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. img_params : dict, optional Dictionary of parameters to be used for each particular image. @@ -981,7 +981,7 @@ def summarize(self): Returns ------- summary_df: Dataframe - Pandas dataframe containin the registration error of the + Pandas dataframe containing the registration error of the alignment between each image and the previous one in the stack. """ @@ -1069,11 +1069,11 @@ def register_images(src, non_rigid_reg_class=non_rigid_registrars.OpticalFlowWar Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. dst_dir : str, optional - Top directory where aliged images should be save. SerialNonRigidRegistrar will + Top directory where aligned images should be save. SerialNonRigidRegistrar will be in this folder, and aligned images in the "registered_images" sub-directory. If None, the images will not be written to file @@ -1090,10 +1090,10 @@ def register_images(src, non_rigid_reg_class=non_rigid_registrars.OpticalFlowWar #. Rigid registered xy in moving/current/from image #. Rigid registered xy in fixed/next/to image - To deterime which pairs of images will be aligned, use + To determine which pairs of images will be aligned, use `warp_tools.get_alignment_indices`. Can use `get_imgs_from_dir` - to see the order inwhich the images will be read, which will correspond - to the indices retuned by `warp_tools.get_alignment_indices`. + to see the order in which the images will be read, which will correspond + to the indices returned by `warp_tools.get_alignment_indices`. If `src` is a SerialRigidRegistrar and `moving_to_fixed_xy` is True, then the matching features in the SerialRigidRegistrar will @@ -1113,7 +1113,7 @@ def register_images(src, non_rigid_reg_class=non_rigid_registrars.OpticalFlowWar Optional name for this SerialNonRigidRegistrar align_to_reference : bool, optional - Whether or not images should be aligne to a reference image + Whether or not images should be aligned to a reference image specified by `reference_img_f`. Will be set to True if `reference_img_f` is provided. @@ -1129,7 +1129,7 @@ def register_images(src, non_rigid_reg_class=non_rigid_registrars.OpticalFlowWar Returns ------- nr_reg : SerialNonRigidRegistrar - SerialNonRigidRegistrar that has registeredt the images in `src` + SerialNonRigidRegistrar that has registered the images in `src` """ tic = time() diff --git a/examples/acrobat_2023/valis/serial_rigid.py b/examples/acrobat_2023/valis/serial_rigid.py index 1dae2b00..62581bfb 100644 --- a/examples/acrobat_2023/valis/serial_rigid.py +++ b/examples/acrobat_2023/valis/serial_rigid.py @@ -34,7 +34,7 @@ def get_image_files(img_dir, imgs_ordered=False): img_dir : str Path to directory containing the images. - imgs_ordered: bool, optinal + imgs_ordered: bool, optional Whether or not the order of images already known. If True, the file names should start with ascending numbers, with the first image file having the smallest number, and the last image file having the largest @@ -86,8 +86,8 @@ def order_Dmat(D): Leaf sorting is accomplished using optimal leaf ordering (Bar-Joseph 2001) - Parmaters - --------- + Parameters + ---------- D: ndarray (N, N) Symmetric distance matrix for N samples @@ -138,7 +138,7 @@ class ZImage(object): Name of the image. Usually `img_f` but with the extension removed. desc : ndarray - (N, M) array of N desciptors for each keypoint, each of which has + (N, M) array of N descriptors for each keypoint, each of which has M features kp_pos_xy : ndarray @@ -153,7 +153,7 @@ class ZImage(object): unfiltered_match_dict : dict Dictionary of image matches. Key= img_obj this ZImage is being - compared to, value= MatchInfo containing inoformation about the + compared to, value= MatchInfo containing information about the comparison, such as the position of matches, features for each match, number of matches, etc... The MatchInfo objects in this dictionary contain info for all matches that were cross-checked. @@ -253,7 +253,7 @@ def __init__(self, image, img_f, img_id, name): def reduce(self, prev_img_obj, next_img_obj): """Reduce amount of info stored, which can take up a lot of space. - No longer need all descriptors. Only keep match info for neighgbors + No longer need all descriptors. Only keep match info for neighbors Parameters ---------- @@ -287,7 +287,7 @@ class SerialRigidRegistrar(object): Registration is conducted by first detecting features in all images. Features are then matched between images, which are then used to construct a distance matrix, D. D is then sorted such that the most similar images - are adjcent to one another. The rigid transformation matrics are then found to + are adjacent to one another. The rigid transformation metrics are then found to align each image with the previous image. Optionally, optimization can be performed to improve the alignments, although the "optimized" matrix will be discarded if it increases the distances between matched features. @@ -306,7 +306,7 @@ class SerialRigidRegistrar(object): contains methods for this, but the user may want/need to use other methods. - aleady_sorted: bool, optional + already_sorted: bool, optional Whether or not the order of images already known. If True, the file names should start with ascending numbers, with the first image file having the smallest number, and the last image file having the largest @@ -329,7 +329,7 @@ class SerialRigidRegistrar(object): distance_metric_type : str Name of the type of metric used to determine the dis/similarity between each pair of images. Despite the name, it could be "similarity" - if the Matcher object compares image feautres using a similarity + if the Matcher object compares image features using a similarity metric. In that case, similarities are converted to distances. img_obj_list : list @@ -345,12 +345,12 @@ class SerialRigidRegistrar(object): unsorted_distance_mat : ndarray Distance matrix with shape (N, N), where each element is the - disimilariy betweewn each pair of the N images. The order of + dissimilarity between each pair of the N images. The order of rows and columns reflects the order in which the images were read. This matrix is used to order the images the Z-stack. distance_mat : ndarray - `unsorted_distance_mat` reorderd such that the most similar images + `unsorted_distance_mat` reordered such that the most similar images are adjacent to one another unsorted_similarity_mat : ndarray @@ -374,7 +374,7 @@ class SerialRigidRegistrar(object): the `img_obj_list` has been sorted. align_to_reference : bool, optional - Whether or not images should be aligne to a reference image + Whether or not images should be aligned to a reference image specified by `reference_img_f`. Will be set to True if `reference_img_f` is provided. @@ -385,7 +385,7 @@ class SerialRigidRegistrar(object): image. summary_df : Dataframe - Pandas dataframe containin the registration error of the + Pandas dataframe containing the registration error of the alignment between each image and the previous one in the stack. """ @@ -419,13 +419,13 @@ def __init__(self, img_dir, imgs_ordered=False, reference_img_f=None, Descriptive name of registrar, such as the sample's name align_to_reference : bool, optional - Whether or not images should be aligne to a reference image + Whether or not images should be aligned to a reference image specified by `reference_img_f`. Will be set to True if `reference_img_f` is provided. """ self.img_dir = img_dir - self.aleady_sorted = imgs_ordered + self.already_sorted = imgs_ordered self.name = name self.img_file_list = get_image_files(img_dir, imgs_ordered=imgs_ordered) self.size = len(self.img_file_list) @@ -586,8 +586,8 @@ def match_imgs(self, matcher_obj, keep_unfiltered=False, qt_emitter=None): """ - n_comparisions = int((self.size*(self.size-1))/2) - pbar = tqdm(total=n_comparisions) + n_comparisons = int((self.size*(self.size-1))/2) + pbar = tqdm(total=n_comparisons) def match_img_obj(i): @@ -665,11 +665,12 @@ def get_neighbor_matches_idx(self, img_obj, prev_img_obj, next_img_obj): def get_common_desc(self, current_img_obj, neighbor_obj, nf_kp_idx): """Get descriptors that correspond to filtered neighbor points - Parameters - ---------- - nf_kp_idx : ndarray - Indicies of already matched keypoints that were found after - neighbonr filtering + + Parameters + ---------- + nf_kp_idx : ndarray + Indices of already matched keypoints that were found after + neighbor filtering """ neighbor_match_info12 = current_img_obj.match_dict[neighbor_obj] @@ -709,12 +710,12 @@ def neighbor_match_filtering(self, img_obj, prev_img_obj, next_img_obj, updated_prev_match_info12 : MatchInfo If improved is True, then `updated_prev_match_info12` includes only features, descriptors that were found in both neighbors. Otherwise, - all of the original features will be maintained + all the original features will be maintained updated_next_match_info12 : MatchInfo If improved is True, then `updated_next_match_info12` includes only features, descriptors that were found in both neighbors. Otherwise, - all of the original features will be maintained + all the original features will be maintained """ @@ -838,10 +839,10 @@ def build_metric_matrix(self, metric="n_matches"): Parameters ---------- metric: str - Name of metrric to use. If 'distance' that the distances and - similiarities calculated during feature matching will be used. + Name of metric to use. If 'distance' that the distances and + similarities calculated during feature matching will be used. If 'n_matches', then the number of matches will be used for - similariy, and 1/n_matches for distance. + similarity, and 1/n_matches for distance. """ @@ -870,7 +871,7 @@ def build_metric_matrix(self, metric="n_matches"): min_d = distance_mat.min() max_d = distance_mat.max() - # Make sure that image has highest similarity with itself + # Make sure that image has the highest similarity with itself similarity_mat[np.diag_indices_from(similarity_mat)] += max_s*0.01 # Scale metrics between 0 and 1 @@ -961,7 +962,7 @@ def align_to_prev_check_reflections(self, transformer, feature_detector, matcher else: filter_kwargs = None - # Estimate curent error without reflections. Don't need to re-detect and match features + # Estimate current error without reflections. Don't need to re-detect and match features to_prev_match_info = img_obj.match_dict[prev_img_obj] transformer.estimate(to_prev_match_info.matched_kp2_xy, to_prev_match_info.matched_kp1_xy) unreflected_warped_src_xy = warp_tools.warp_xy(to_prev_match_info.matched_kp1_xy, transformer.params) @@ -1038,7 +1039,7 @@ def align_to_prev_check_reflections(self, transformer, feature_detector, matcher ref_x, ref_y = best_reflect_M[[0, 1], [0, 1]] < 0 if ref_x or ref_y: - msg = f'detected relfections between {img_obj.name} and {prev_img_obj.name} along the' + msg = f'detected reflections between {img_obj.name} and {prev_img_obj.name} along the' if ref_x and ref_y: msg = f'{msg} x and y axes' elif ref_x: @@ -1106,7 +1107,7 @@ def optimize(self, affine_optimizer, qt_emitter=None): Parameters ----------- - affine_optimizer : AffineOptimzer + affine_optimizer : AffineOptimizer Object that will minimize a cost function to find the optimal affine transformations @@ -1345,7 +1346,7 @@ def summarize(self): Returns ------- summary_df: Dataframe - Pandas dataframe containin the registration error of the + Pandas dataframe containing the registration error of the alignment between each image and the previous one in the stack. """ @@ -1434,7 +1435,7 @@ def register_images(img_dir, dst_dir=None, name="registrar", to be registered. These images need to be single channel, uint8 images dst_dir : str, optional - Top directory where aliged images should be save. SerialRigidRegistrar will + Top directory where aligned images should be save. SerialRigidRegistrar will be in this folder, and aligned images in the "registered_images" sub-directory. If None, the images will not be written to file @@ -1451,25 +1452,25 @@ def register_images(img_dir, dst_dir=None, name="registrar", Transformer used to find transformation matrix that will warp each image to the target image. - affine_optimizer : AffineOptimzer object + affine_optimizer : AffineOptimizer object Object that will minimize a cost function to find the - optimal affine transoformations + optimal affine transformations imgs_ordered : bool Boolean defining whether or not the order of images in img_dir are already in the correct order. If True, then each filename should begin with the number that indicates its position in the z-stack. If False, then the images will be sorted by ordering a feature distance - matix. + matrix. reference_img_f : str, optional Filename of image that will be treated as the center of the stack. If None, the index of the middle image will be the reference. check_for_reflections : bool, optional - Determine if alignments are improved by relfecting/mirroring/flipping + Determine if alignments are improved by reflecting/mirroring/flipping images. Optional because it requires re-detecting features in each version - of the images and then re-matching features, and so can be time consuming and + of the images and then re-matching features, and so can be time-consuming and not always necessary. similarity_metric : str @@ -1490,10 +1491,10 @@ def register_images(img_dir, dst_dir=None, name="registrar", Returns ------- registrar : SerialRigidRegistrar - SerialRigidRegistrar object contains general information about the alginments, + SerialRigidRegistrar object contains general information about the alignments, but also a list of Z-images. Each ZImage contains the warp information for an image in the stack, including the transformation matrices - calculated at each step, keypoint poisions, image descriptors, and + calculated at each step, keypoint positions, image descriptors, and matches with other images. See attributes from Zimage for more information. @@ -1538,7 +1539,7 @@ def register_images(img_dir, dst_dir=None, name="registrar", img_obj.desc = img_obj.desc[features_in_mask_idx, :] print("\n======== Matching images\n") - if registrar.aleady_sorted: + if registrar.already_sorted: registrar.match_sorted_imgs(matcher, keep_unfiltered=False, qt_emitter=qt_emitter) diff --git a/examples/acrobat_2023/valis/slide_io.py b/examples/acrobat_2023/valis/slide_io.py index 0e5cb02f..be66e225 100644 --- a/examples/acrobat_2023/valis/slide_io.py +++ b/examples/acrobat_2023/valis/slide_io.py @@ -52,7 +52,7 @@ """str: Physical unit when the unit can't be found in the metadata""" MICRON_UNIT = u'\u00B5m' -"""str: Phyiscal unit for micron/micrometers""" +"""str: Physical unit for micron/micrometers""" ALL_OPENSLIDE_READABLE_FORMATS = [".svs", ".tif", ".vms", ".vmu", ".ndpi", ".scn", ".mrxs", ".tiff", ".svslide", ".bif"] """list: File extensions that OpenSlide can read""" @@ -74,20 +74,20 @@ Created after initializing JVM.""" BF_MICROMETER = None -"""Bioformats Unit mircometer object. +"""Bioformats Unit micrometer object. Created after initializing JVM.""" ome = None -"""Bioformats ome from bioforamts_jar. +"""Bioformats ome from bioformats_jar. Created after initializing JVM.""" loci = None -"""Bioformats loci from bioforamts_jar. +"""Bioformats loci from bioformats_jar. Created after initializing JVM.""" """ -NOTE: Commented out block is how to use boformats with javabrdige. +NOTE: Commented out block is how to use bioformats with javabrdige. However, on conda, javabridge isn't available for python 3.9. If using, remember to put bftools/bioformats_package.jar in the source directory. @@ -421,7 +421,7 @@ def check_flattened_pyramid_tiff(src_f): Returns ------- - is_flattended_pyramid : bool + is_flattened_pyramid : bool Whether or not the slide is a flattened pyramid can_use_bf : bool @@ -442,7 +442,7 @@ def check_flattened_pyramid_tiff(src_f): vips_img = pyvips.Image.new_from_file(src_f) vips_fields = vips_img.get_fields() - is_flattended_pyramid = False + is_flattened_pyramid = False if 'n-pages' in vips_fields: n_pages = vips_img.get("n-pages") @@ -487,9 +487,9 @@ def check_flattened_pyramid_tiff(src_f): unique_areas, _ = np.unique(all_areas, return_index=True) n_zero_diff = len(np.where(area_diff == 0)[0]) if most_common_channel_count == 1 and n_zero_diff >= len(unique_areas): - is_flattended_pyramid = True + is_flattened_pyramid = True - if is_flattended_pyramid: + if is_flattened_pyramid: nchannels_per_each_level = np.diff(level_starts) last_level_channel_count = np.sum(all_n_channels[level_starts[-1]:]) nchannels_per_each_level = np.hstack([nchannels_per_each_level, @@ -516,7 +516,7 @@ def check_flattened_pyramid_tiff(src_f): bf_channels = bf_reader.metadata.n_channels can_use_bf = bf_levels >= len(slide_dimensions) and bf_channels == n_channels - return is_flattended_pyramid, can_use_bf, slide_dimensions, levels_start_idx, n_channels + return is_flattened_pyramid, can_use_bf, slide_dimensions, levels_start_idx, n_channels # Read slides # @@ -631,7 +631,7 @@ def slide2vips(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -652,7 +652,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -835,7 +835,7 @@ def __init__(self, src_f, series=None, *args, **kwargs): Path to slide series : int - The series to be read. If `series` is None, the the `series` + The series to be read. If `series` is None, the `series` will be set to the series associated with the largest image. """ @@ -856,7 +856,7 @@ def __init__(self, src_f, series=None, *args, **kwargs): img_areas = [np.multiply(*meta.slide_dimensions[0]) for meta in self.meta_list] series = np.argmax(img_areas) msg = (f"No series provided. " - f"Selecting series with largest image, " + f"Selecting series with the largest image, " f"which is series {series}") valtils.print_warning(msg, warning_type=None, rgb=valtils.Fore.GREEN) @@ -922,12 +922,12 @@ def slide2vips(self, level, series=None, xywh=None, tile_wh=None, *args, **kwarg xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. tile_wh : int, optional - Size of tiles used to contstruct `vips_slide` + Size of tiles used to construct `vips_slide` Returns ------- @@ -983,7 +983,7 @@ def slide2image(self, level, series=None, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1182,7 +1182,7 @@ def _get_slide_dimensions(self, rdr): Notes ----- - Using javabridge and python-bioformmats, this can be accessed as follows + Using javabridge and python-bioformats, this can be accessed as follows ` bf_slide = bioformats.ImageReader(slide_f) bf_img_reader = javabridge.JWrapper(bf_slide.rdr.o) @@ -1354,7 +1354,7 @@ def _slide2vips_ome_one_series(self, level, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1393,7 +1393,7 @@ def slide2vips(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1440,7 +1440,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1486,7 +1486,7 @@ def _get_channel_names(self, vips_img): Returns ------- channel_names : list - List of channel naames. + List of channel names. """ @@ -1668,11 +1668,11 @@ def __init__(self, src_f, *args, **kwargs): def create_metadata(self): - is_flattended_pyramid, bf_reads_flat, slide_dimensions,\ + is_flattened_pyramid, bf_reads_flat, slide_dimensions,\ levels_start_idx, n_channels = \ check_flattened_pyramid_tiff(self.src_f) - assert is_flattended_pyramid and not bf_reads_flat, "Trying to use FlattenedPyramidReader but slide is not a flattened pyramid" + assert is_flattened_pyramid and not bf_reads_flat, "Trying to use FlattenedPyramidReader but slide is not a flattened pyramid" meta_name = f"{os.path.split(self.src_f)[1]}_Series(0)".strip("_") server = VIPS_RDR @@ -1713,7 +1713,7 @@ def slide2vips(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1768,7 +1768,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): except pyvips.error.Error as e: # Big hack for when get the error "tiff2vips: out of order read" even with random access out_shape_wh = self.metadata.slide_dimensions[level] - msg1 = f"pyvips.error.Error: {e} when converting pvips.Image to numpy array" + msg1 = f"pyvips.error.Error: {e} when converting pyvips.Image to numpy array" msg2 = f"Will try to resize level 0 to have shape {out_shape_wh} and convert" valtils.print_warning(msg1) valtils.print_warning(msg2, None) @@ -1816,9 +1816,9 @@ def _get_dtype(self): """Get Bio-Formats datatype from values in metadata. For example, BF metadata may have image datatype as - uint32, but in the image descriiption, min/max/resppnse, + uint32, but in the image description, min/max/response, are floats. This will determine if the slide should be cast - to a different dataatype to match values in metadata. + to a different datatype to match values in metadata. """ smallest_level = len(self.metadata.slide_dimensions) - 1 @@ -1899,7 +1899,7 @@ def __init__(self, src_f, series=None, *args, **kwargs): Path to slide series : int - The series to be read. If `series` is None, the the `series` + The series to be read. If `series` is None, the `series` will be set to the series associated with the largest image. """ @@ -1927,7 +1927,7 @@ def __init__(self, src_f, series=None, *args, **kwargs): img_areas = [np.multiply(*meta.slide_dimensions[0]) for meta in self.meta_list] series = np.argmax(img_areas) msg = (f"No series provided. " - f"Selecting series with largest image, " + f"Selecting series with the largest image, " f"which is series {series}") valtils.print_warning(msg, warning_type=None, rgb=valtils.Fore.GREEN) @@ -1956,7 +1956,7 @@ def slide2vips(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1985,7 +1985,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -2114,8 +2114,8 @@ def _get_slide_dimensions(self, scene=0, *args, **kwargs): czi_reader = CziFile(self.src_f) scene_bbox = czi_reader.get_all_scene_bounding_boxes()[scene] - scence_l0_wh = np.array([scene_bbox.w, scene_bbox.h]) - slide_dimensions = np.round(scence_l0_wh*zoom_levels[..., np.newaxis]).astype(int) + scene_l0_wh = np.array([scene_bbox.w, scene_bbox.h]) + slide_dimensions = np.round(scene_l0_wh*zoom_levels[..., np.newaxis]).astype(int) return slide_dimensions @@ -2261,7 +2261,7 @@ def slide2image(self, xywh=None, *args, **kwargs): return img def _get_slide_dimensions(self, pil_img, *args, **kwargs): - """ + """Get slide dimensions """ img_dims = np.array([[pil_img.width, pil_img.height]]) @@ -2302,7 +2302,7 @@ def get_slide_reader(src_f, series=None): Path to slide series : int, optional - The series to be read. If `series` is None, the the `series` + The series to be read. If `series` is None, the `series` will be set to the series associated with the largest image. In cases where there is only 1 image in the file, `series` will be 0. @@ -2310,7 +2310,7 @@ def get_slide_reader(src_f, series=None): Returns ------- reader: SlideReader - SlideReader class that can read the slide and and convert them to + SlideReader class that can read the slide and convert them to images or pyvips.Images at the specified level and series. They also contain a `MetaData` object that contains information about the slide, like dimensions at each level, physical units, etc... @@ -2402,7 +2402,7 @@ def get_slide_reader(src_f, series=None): elif is_ometiff: if series == 0 and n_series == 1 and is_rgb and is_rgb is not None: - # Seems pvips can only read ome.tiff if there is 1 series. + # Seems pyvips can only read ome.tiff if there is 1 series. # Converting a multichannel pyvips.Image is very slow, but is fast for RGB reader = VipsSlideReader else: @@ -2462,7 +2462,7 @@ def get_shape_xyzct(shape_wh, n_channels): Parameters ---------- shape_wh : tuple of int - Width and heigth of image + Width and height of image n_channels : int Number of channels in the image @@ -2486,7 +2486,7 @@ def create_channel(channel_id, name=None, color=None): channel_id : int Channel number - name : str, optinal + name : str, optional Channel name color : tuple of int @@ -2525,7 +2525,7 @@ def create_channel(channel_id, name=None, color=None): @valtils.deprecated_args(perceputally_uniform_channel_colors="colormap") def create_ome_xml(shape_xyzct, bf_dtype, is_rgb, pixel_physical_size_xyu=None, channel_names=None, colormap=None): - """Create new ome-xmml object + """Create new ome-xml object Parameters ------- @@ -2611,7 +2611,7 @@ def create_ome_xml(shape_xyzct, bf_dtype, is_rgb, pixel_physical_size_xyu=None, def update_xml_for_new_img(current_ome_xml_str, new_xyzct, bf_dtype, is_rgb, series, pixel_physical_size_xyu=None, channel_names=None, colormap=None): """Update dimensions ome-xml metadata - Used to create a new ome-xmlthat reflects changes in an image, such as its shape + Used to create a new ome-xml that reflects changes in an image, such as its shape If `current_ome_xml_str` is invalid or None, a new ome-xml will be created @@ -2728,7 +2728,7 @@ def warp_and_save_slide(src_f, dst_f, transformation_src_shape_rc, transformatio which can be done using `warp_tools.get_inverse_field` level : int, optional - Pyramid level to warp an save + Pyramid level to warp and save series : int, optional Series number of image @@ -2824,7 +2824,7 @@ def save_ome_tiff(img, dst_f, ome_xml=None, tile_wh=1024, compression="lzw"): compression : str Compression method used to save ome.tiff . Default is lzw, but can also - be jpeg or jp2k. See pyips for more details. + be jpeg or jp2k. See pyvips for more details. """ @@ -2969,7 +2969,7 @@ def convert_to_ome_tiff(src_f, dst_f, level, series=None, xywh=None, xywh : tuple of int, optional The region of the slide to be converted. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -2984,7 +2984,7 @@ def convert_to_ome_tiff(src_f, dst_f, level, series=None, xywh=None, compression : str Compression method used to save ome.tiff . Default is lzw, but can also - be jpeg or jp2k. See pyips for more details. + be jpeg or jp2k. See pyvips for more details. """ diff --git a/examples/acrobat_2023/valis/viz.py b/examples/acrobat_2023/valis/viz.py index 143d04a9..466b60ae 100644 --- a/examples/acrobat_2023/valis/viz.py +++ b/examples/acrobat_2023/valis/viz.py @@ -552,21 +552,21 @@ def color_multichannel(multichannel_img, marker_colors, rescale_channels=False, in areas where they are expressed in isolation, but can also make it appear more marker is expressed than there really is. - normalize_by : str, optionaal + normalize_by : str, optional "image" will produce an image where all values are scaled between 0 and the highest intensity in the composite image. This will produce an image where one can see the expression of each marker relative to the others, making it easier to compare marker expression levels. "channel" will first scale the intensity of each channel, and then - blend all of the channels together. This will allow one to see the + blend all the channels together. This will allow one to see the relative expression of each marker, but won't allow one to directly compare the expression of markers across channels. cspace : str Colorspace in which `marker_colors` will be blended. JzAzBz, Hunter Lab, and sRGB all work well. But, see - colour.COLOURSPACE_MODELS for other possible colorspaces + colour.COLOURSPACE_MODELS for other possible colorspace Returns ------- diff --git a/examples/acrobat_2023/valis/warp_tools.py b/examples/acrobat_2023/valis/warp_tools.py index d37382ab..025a8193 100644 --- a/examples/acrobat_2023/valis/warp_tools.py +++ b/examples/acrobat_2023/valis/warp_tools.py @@ -28,8 +28,8 @@ def is_pyvips_22(): - pvips_ver = pyvips.__version__.split(".") - pyvips_22 = eval(pvips_ver[0]) >= 2 and eval(pvips_ver[1]) >= 2 + pyvips_ver = pyvips.__version__.split(".") + pyvips_22 = eval(pyvips_ver[0]) >= 2 and eval(pyvips_ver[1]) >= 2 return pyvips_22 @@ -335,7 +335,7 @@ def save_img(dst_f, img, thumbnail_size=None): Filename for saved image img : ndarray, pyvips.Image - Image to be saved. Numpy arrays will be converted to pvips.Image + Image to be saved. Numpy arrays will be converted to pyvips.Image thumbnail_size : optional, int If not None, the image will be resized to fit within this size @@ -669,14 +669,14 @@ def mattes_mi(img1, img2, nbins=50, mask=None): Number of histogram bins mask : ndarray, None - Mask with shape (N, M) that indiates where the metric - should be calulated. If None, the metric will be calculated + Mask with shape (N, M) that indicates where the metric + should be calculated. If None, the metric will be calculated for all NxM pixels. Returns ------- mmi : float - Mattes mutation inormation + Mattes mutation information """ @@ -1076,7 +1076,7 @@ def warp_img(img, M=None, bk_dxdy=None, out_shape_rc=None, warp_index = (index[0] + warp_dxdy[0]).bandjoin(index[1] + warp_dxdy[1]) try: - #Option to set backround color in mapim added in libvips 8.13 + #Option to set background color in mapim added in libvips 8.13 warped = affine_warped.mapim(warp_index, premultiplied=True, background=bg_color, @@ -1206,7 +1206,7 @@ def warp_img_inv(img, M=None, fwd_dxdy=None, transformation_src_shape_rc=None, t warp_index = (index[0] + warp_dxdy[0]).bandjoin(index[1] + warp_dxdy[1]) try: - #Option to set backround color in mapim added in libvips 8.13 + #Option to set background color in mapim added in libvips 8.13 nr_warped = img.mapim(warp_index, premultiplied=True, background=bg_color, @@ -1288,7 +1288,7 @@ def warp_img_from_to(img, from_M=None, from_transformation_src_shape_rc=None, this shape should be the same for both images. from_src_shape_rc : optional, (int, int) - Shape of the unwarped image from which the points originated. For example, + Shape of the un-warped image from which the points originated. For example, this could be a larger/smaller version of the "from" image that was used for feature detection. @@ -1310,7 +1310,7 @@ def warp_img_from_to(img, from_M=None, from_transformation_src_shape_rc=None, For example, this could be the original image in which features were detected to_src_shape_rc : optional, (int, int) - Shape of the unwarped "to" image to which the points will be warped. For example, + Shape of the un-warped "to" image to which the points will be warped. For example, this could be a larger/smaller version of the "to" image that was used for feature detection. @@ -1328,7 +1328,7 @@ def warp_img_from_to(img, from_M=None, from_transformation_src_shape_rc=None, Returns ------- - in_target_space : ndarray, pvips.Image + in_target_space : ndarray, pyvips.Image `img` warped onto the "to" image """ @@ -1407,7 +1407,7 @@ def get_warp_map(M=None, dxdy=None, transformation_dst_shape_rc=None, Returns ------- - coord_map : ndarry + coord_map : np.ndarray A 2band numpy array that has location of each pixel in `src_shape_rc` the warped image (with shape `dst_shape_rc`) @@ -1499,10 +1499,10 @@ def get_reflection_M(reflect_x, reflect_y, shape_rc): ---------- reflect_x : bool - Whether or not to reflect the x-axis (columns) + Whether to reflect the x-axis (columns) reflecct y : bool - Whether or not to reflect the y-axis (rows) + Whether to reflect the y-axis (rows) shape_rc : tuple of int Shape of the image being reflected @@ -1698,7 +1698,7 @@ def get_mesh(shape, grid_spacing, bbox_rc_wh=None, inclusive=False): (row, column, width, height) of bounding box inclusive : bool - Whether or not to include image edges + Whether to include image edges """ @@ -2313,8 +2313,8 @@ def warp_xy_from_to(xy, from_M=None, from_transformation_src_shape_rc=None, to_dst_shape_rc=None, to_bk_dxdy=None, to_fwd_dxdy=None): """Warp points in one image to their position in another unregistered image - Takes a set of points found in the unwarped "from" image, and warps them to their - position in the unwarped "to" image. + Takes a set of points found in the un-warped "from" image, and warps them to their + position in the un-warped "to" image. Parameters ---------- @@ -2334,7 +2334,7 @@ def warp_xy_from_to(xy, from_M=None, from_transformation_src_shape_rc=None, this shape should be the same for both images. from_src_shape_rc : optional, (int, int) - Shape of the unwarped image from which the points originated. For example, + Shape of the un-warped image from which the points originated. For example, this could be a larger/smaller version of the "from" image that was used for feature detection. @@ -2356,7 +2356,7 @@ def warp_xy_from_to(xy, from_M=None, from_transformation_src_shape_rc=None, For example, this could be the original image in which features were detected to_src_shape_rc : optional, (int, int) - Shape of the unwarped "to" image to which the points will be warped. For example, + Shape of the un-warped "to" image to which the points will be warped. For example, this could be a larger/smaller version of the "to" image that was used for feature detection. @@ -2373,7 +2373,7 @@ def warp_xy_from_to(xy, from_M=None, from_transformation_src_shape_rc=None, Returns ------- xy_in_to : ndarray - position of `xy` in the unwarped "to" image + position of `xy` in the un-warped "to" image """ @@ -2723,7 +2723,7 @@ def get_xy_inside_mask(xy, mask): Returns ------- keep_idx : ndarray - Indices of `xy` that are inside of `mask` + Indices of `xy` that are inside `mask` """ mask_cnt, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) @@ -2798,7 +2798,7 @@ def measure_error(src_xy, dst_xy, shape, feature_similarity=None): Median relative Target Registration Error (rTRE) between images med_d : float - Median Euclidean distance between src_xy and dst_xy, optinally weighted by feature similarity + Median Euclidean distance between src_xy and dst_xy, optionally weighted by feature similarity """ d = np.sqrt((src_xy[:, 0]-dst_xy[:, 0])**2 + (src_xy[:, 1]-dst_xy[:, 1])**2) diff --git a/examples/acrobat_2023/valis_acrobat_2023.py b/examples/acrobat_2023/valis_acrobat_2023.py index 3cb235b6..f3685035 100644 --- a/examples/acrobat_2023/valis_acrobat_2023.py +++ b/examples/acrobat_2023/valis_acrobat_2023.py @@ -41,7 +41,7 @@ parser.add_argument('-PATH_OUTPUT_DIR', type=str, help='csv containing image pairs and landmarks') parser.add_argument('-row_idx', type=int, help='name/row of sample') parser.add_argument('-micro_reg_fraction', type=str, help='Size of images used for 2nd registation') - parser.add_argument('-use_masks', type=str, help='Whether or not to use masks for registration') + parser.add_argument('-use_masks', type=str, help='Whether to use masks for registration') args = vars(parser.parse_args()) diff --git a/examples/acrobat_grand_challenge.py b/examples/acrobat_grand_challenge.py index 5692d515..9d908e58 100644 --- a/examples/acrobat_grand_challenge.py +++ b/examples/acrobat_grand_challenge.py @@ -252,7 +252,7 @@ def create_reg_mask(reg, j_range=(0.05, 0.9), c_range=(0.05, 1), h_range=(150, 2 # Perform microregistration within the bounding box of the H&E+ tissue micro_reg_mask = create_reg_mask(registrar) - micro_reg, micro_error = registrar.register_micro(max_non_rigid_registartion_dim_px=micro_reg_size, + micro_reg, micro_error = registrar.register_micro(max_non_rigid_registration_dim_px=micro_reg_size, reference_img_f=he_img_f, align_to_reference=True, mask=micro_reg_mask, diff --git a/examples/register_and_merge_cycif.py b/examples/register_and_merge_cycif.py index db56f8ce..381a3558 100644 --- a/examples/register_and_merge_cycif.py +++ b/examples/register_and_merge_cycif.py @@ -11,7 +11,7 @@ dimensions, physical units, etc... * a pickled version of the registrar. This can be reloaded - (unpickled) and used later. For example, one could perform + (un-pickled) and used later. For example, one could perform the registration locally, but then use the pickled object to warp and save the slides on an HPC. Or, one could perform the registration and use the registrar later to warp diff --git a/examples/register_ihc.py b/examples/register_ihc.py index acd3653f..e3875861 100644 --- a/examples/register_ihc.py +++ b/examples/register_ihc.py @@ -11,7 +11,7 @@ dimensions, physical units, etc... * a pickled version of the registrar. This can be reloaded - (unpickled) and used later. For example, one could perform + (un-pickled) and used later. For example, one could perform the registration locally, but then use the pickled object to warp and save the slides on an HPC. Or, one could perform the registration and use the registrar later to warp @@ -42,7 +42,7 @@ After registraation is complete, one should view the results to determine if they aare acceptable. If they -are, then one can warp and save all of the slides. +are, then one can warp and save all the slides. """ diff --git a/examples/warp_annotation_image.py b/examples/warp_annotation_image.py index 15cc5000..52eb9ca6 100644 --- a/examples/warp_annotation_image.py +++ b/examples/warp_annotation_image.py @@ -14,7 +14,7 @@ -# Perform registration. Can optinally set the reference image to be the same as the one the annotations are based on (i.e. `reference_img_f`) +# Perform registration. Can optionally set the reference image to be the same as the one the annotations are based on (i.e. `reference_img_f`) registrar = registration.Valis(slide_src_dir, results_dst_dir, reference_img_f=reference_img_f) rigid_registrar, non_rigid_registrar, error_df = registrar.register() diff --git a/examples/warp_points.py b/examples/warp_points.py index 7ab84506..e750e15e 100644 --- a/examples/warp_points.py +++ b/examples/warp_points.py @@ -11,11 +11,11 @@ from which the ROI coordinates originated. 3. Warping of points assumes the coordinates are in pixel units. -However, here the original coordinaates are in microns, and so need to be +However, here the original coordinates are in microns, and so need to be converted pixel units. 4. The Slide object can now be used to warp the coordinates. -This yields the ROI coordinates in all of the registered slides. +This yields the ROI coordinates in all the registered slides. 5. Warp and slice the ROI from each slide using the Slide's pyvips.Image extract_area method. @@ -70,7 +70,7 @@ dst_dir = "./expected_results/roi" pathlib.Path(dst_dir).mkdir(exist_ok=True, parents=True) -# Warp each slide and slice the ROI from it using each pyips.Image's "extract_area" method. +# Warp each slide and slice the ROI from it using each pyvips.Image's "extract_area" method. fig, axes = plt.subplots(2, 3, figsize=(12, 8), sharex=True, sharey=True) ax = axes.ravel() for i, slide in enumerate(registrar.slide_dict.values()): diff --git a/tests/test_examples.py b/tests/test_examples.py index 227b054f..69b7dd9c 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -11,7 +11,7 @@ dimensions, physical units, etc... * a pickled version of the registrar. This can be reloaded - (unpickled) and used later. For example, one could perform + (un-pickled) and used later. For example, one could perform the registration locally, but then use the pickled object to warp and save the slides on an HPC. Or, one could perform the registration and use the registrar later to warp @@ -42,7 +42,7 @@ After registraation is complete, one should view the results to determine if they aare acceptable. If they -are, then one can warp and save all of the slides. +are, then one can warp and save all the slides. """ @@ -211,7 +211,7 @@ def test_register_cycif(max_error=3): * Make sure error is below threshold * Checks channel names of merged image are in the correct order (https://github.com/MathOnco/valis/issues/56#issuecomment-1821050877) * Check jpeg2000 compression - * Check that reference slide is unwarped + * Check that reference slide is un-warped """ diff --git a/valis/affine_optimizer.py b/valis/affine_optimizer.py index 6194bb6a..3f712fd1 100644 --- a/valis/affine_optimizer.py +++ b/valis/affine_optimizer.py @@ -1,10 +1,10 @@ """Optimize rigid alignment Contains functions related to optimization, as well as the AffineOptimizer -class that performs the optimzation. This class can be subclassed to implement +class that performs the optimization. This class can be subclassed to implement custom optimization methods. -There are several subclasses, but AffineOptimizerMattesMI is the +There are several subclasses, but AffineOptimizerMattesMI is the fastest and most accurate, and so is default affine optimizer in VALIS. It's not recommended that the other subclasses be used, but they are kept to provide examples on how to subclass AffineOptimizer. @@ -336,7 +336,7 @@ def build_P(A, B, r, mask): def entropy(x): """ - Caclulate Shannon's entropy for array x + Calculate Shannon's entropy for array x Parameters ---------- @@ -459,7 +459,7 @@ def MI(fixed, moving, nb, spacing): class AffineOptimizer(object): - """Class that optimizes ridid registration + """Class that optimizes rigid registration Attributes ---------- @@ -478,10 +478,10 @@ class AffineOptimizer(object): Type of transformation, "EuclideanTransform" or "SimilarityTransform" current_level : int - Current level of the Guassian pyramid that is being registered + Current level of the Gaussian pyramid that is being registered accepts_xy : bool - Bool declaring whether or not the optimizer will use corresponding points to optimize the registration + Boolean indicating whether the optimizer uses corresponding points to optimize registration. Methods ------- @@ -507,9 +507,9 @@ class AffineOptimizer(object): to have a new cost_fxn method. See AffineOptimizerDisplacement for an example implementing a new cost function Major overhauls are possible too. See AffineOptimizerMattesMI for an example on using SimpleITK's - optimization methods inside of an AffineOptimizer subclass + optimization methods inside an AffineOptimizer subclass - If the optimizer uses corressponding points, then the class attribute + If the optimizer uses corresponding points, then the class attribute accepts_xy needs to be set to True. The default is False. """ @@ -553,7 +553,7 @@ def setup(self, moving, fixed, mask, initial_M=None): Image moving is warped to align to mask : ndarray - 2D array having non-zero pixel values, where values of 0 are ignnored during registration + 2D array having non-zero pixel values, where values of 0 are ignored during registration initial_M : (3x3) array Initial transformation matrix @@ -614,7 +614,7 @@ def align(self, moving, fixed, mask, initial_M=None, moving_xy=None, fixed_xy=No Image moving is warped to align with mask : ndarray - 2D array having non-zero pixel values, where values of 0 are ignnored during registration + 2D array having non-zero pixel values, where values of 0 are ignored during registration initial_M : (3x3) array Initial transformation matrix @@ -799,7 +799,7 @@ def setup(self, moving, fixed, mask, initial_M=None, moving_xy=None, fixed_xy=No Image moving is warped to align to mask : ndarray - 2D array having non-zero pixel values, where values of 0 are ignnored during registration + 2D array having non-zero pixel values, where values of 0 are ignored during registration initial_M : (3x3) array Initial transformation matrix @@ -866,7 +866,7 @@ def align(self, moving, fixed, mask, initial_M=None, Image moving is warped to align with mask : ndarray - 2D array having non-zero pixel values, where values of 0 are ignnored during registration + 2D array having non-zero pixel values, where values of 0 are ignored during registration initial_M : (3x3) array Initial transformation matrix @@ -981,7 +981,7 @@ def shannon_entropy(self, X, k=1): def mutual_information(self, A, B): if self.HA_list[self.current_level] is None: - # Only need to caluclate once per level, becuase the fixed + # Only need to calculate once per level, because the fixed # image doesn't change self.HA_list[self.current_level] = self.shannon_entropy(A) @@ -1084,7 +1084,7 @@ def calc_cost(self, p): return self.cost_fxn(fixed_intensities, moving_intensities, self.pyramid_mask[self.current_level]) def cost_fxn(self, fixed_intensities, transformed_intensities, mask): - """ + """Cost function """ results, _, _ = np.histogram2d(fixed_intensities, transformed_intensities, bins=self.nbins) n = np.sum(results) diff --git a/valis/feature_detectors.py b/valis/feature_detectors.py index c7492694..f5299feb 100644 --- a/valis/feature_detectors.py +++ b/valis/feature_detectors.py @@ -33,7 +33,7 @@ def filter_features(kp, desc, n_keep=MAX_FEATURES): - """Get keypoints with highest response + """Get keypoints with the highest response Parameters ---------- @@ -49,7 +49,7 @@ def filter_features(kp, desc, n_keep=MAX_FEATURES): Returns ------- - Keypoints and and corresponding descriptors that the the n_keep highest + Keypoints and corresponding descriptors that the n_keep highest responses. """ @@ -154,11 +154,11 @@ def _detect_and_compute(self, image, mask=None): Returns ------- - kp : ndarry - (N, 2) array positions of keypoints in xy corrdinates for N + kp : np.ndarray + (N, 2) array positions of keypoints in xy coordinates for N keypoints - desc : ndarry + desc : np.ndarray (N, M) array containing M features for each of the N keypoints """ @@ -326,8 +326,8 @@ def detect(self, image): Uses keypoint info to create KeyPoint objects for OpenCV - Paramters - --------- + Parameters + ---------- image : ndarray image from keypoints will be detected @@ -593,11 +593,11 @@ def _detect_and_compute(self, image, *args, **kwargs): Returns ------- - kp : ndarry - (N, 2) array positions of keypoints in xy corrdinates for N + kp : np.ndarray + (N, 2) array positions of keypoints in xy coordinates for N keypoints - desc : ndarry + desc : np.ndarray (N, M) array containing M features for each of the N keypoints """ @@ -648,11 +648,11 @@ def _detect_and_compute(self, image, *args, **kwargs): Returns ------- - kp : ndarry - (N, 2) array positions of keypoints in xy corrdinates for N + kp : np.ndarray + (N, 2) array positions of keypoints in xy coordinates for N keypoints - desc : ndarry + desc : np.ndarray (N, M) array containing M features for each of the N keypoints """ diff --git a/valis/micro_rigid_registrar.py b/valis/micro_rigid_registrar.py index d254a945..b918c9cb 100644 --- a/valis/micro_rigid_registrar.py +++ b/valis/micro_rigid_registrar.py @@ -27,8 +27,8 @@ DEFAULT_BF_PROCESSOR = preprocessing.OD DEFAULT_BF_PROCESSOR_KWARGS = {} -DEFAULT_FLOURESCENCE_CLASS = preprocessing.ChannelGetter -DEFAULT_FLOURESCENCE_PROCESSING_ARGS = {"channel": "dapi", "adaptive_eq": True} +DEFAULT_FLUORESCENCE_CLASS = preprocessing.ChannelGetter +DEFAULT_FLUORESCENCE_PROCESSING_ARGS = {"channel": "dapi", "adaptive_eq": True} class MicroRigidRegistrar(object): """Refine rigid registration using higher resolution images @@ -44,7 +44,7 @@ class MicroRigidRegistrar(object): Attributes ---------- val_obj : Valis - The "parent" object that registers all of the slides. + The "parent" object that registers all the slides. feature_detector_cls : FeatureDD, optional Uninstantiated FeatureDD object that detects and computes @@ -57,7 +57,7 @@ class MicroRigidRegistrar(object): Matcher object that will be used to match image features scale : float - Degree of downsampling to use for the reigistration, based on the + Degree of downsampling to use for the registration, based on the registered WSI shape (i.e. Slide.aligned_slide_shape_rc) tile_wh : int @@ -83,7 +83,7 @@ def __init__(self, val_obj, feature_detector_cls=None, Parameters ---------- val_obj : Valis - The "parent" object that registers all of the slides. + The "parent" object that registers all the slides. feature_detector_cls : FeatureDD, optional Uninstantiated FeatureDD object that detects and computes @@ -102,7 +102,7 @@ def __init__(self, val_obj, feature_detector_cls=None, If `None`, a default processor will be assigned to each image based on its modality. scale : float - Degree of downsampling to use for the reigistration, based on the + Degree of downsampling to use for the registration, based on the registered WSI shape (i.e. Slide.aligned_slide_shape_rc) tile_wh : int @@ -164,24 +164,24 @@ def create_mask(self, moving_slide, fixed_slide): def register(self, brightfield_processing_cls=DEFAULT_BF_PROCESSOR, brightfield_processing_kwargs=DEFAULT_BF_PROCESSOR_KWARGS, - if_processing_cls=DEFAULT_FLOURESCENCE_CLASS, if_processing_kwargs=DEFAULT_FLOURESCENCE_PROCESSING_ARGS): + if_processing_cls=DEFAULT_FLUORESCENCE_CLASS, if_processing_kwargs=DEFAULT_FLUORESCENCE_PROCESSING_ARGS): """ Parameters ---------- - brightfield_processing_cls : ImageProcesser - ImageProcesser to pre-process brightfield images to make them look as similar as possible. + brightfield_processing_cls : ImageProcessor + ImageProcessor to pre-process brightfield images to make them look as similar as possible. Should return a single channel uint8 image. brightfield_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `brightfield_processing_cls` + Dictionary of keyword arguments to be passed to `brightfield_processing_cls` - if_processing_cls : ImageProcesser - ImageProcesser to pre-process immunofluorescent images to make them look as similar as possible. + if_processing_cls : ImageProcessor + ImageProcessor to pre-process immunofluorescence images to make them look as similar as possible. Should return a single channel uint8 image. if_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `if_processing_cls` + Dictionary of keyword arguments to be passed to `if_processing_cls` """ diff --git a/valis/non_rigid_registrars.py b/valis/non_rigid_registrars.py index 33e20d9c..6a0abaee 100644 --- a/valis/non_rigid_registrars.py +++ b/valis/non_rigid_registrars.py @@ -62,7 +62,7 @@ class NonRigidRegistrar(object): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple @@ -106,11 +106,11 @@ def __init__(self, params=None, rgb=False): Parameters ---------- params : dictionary - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Will get used in the calc() method. In the case where simple ITK will be used, params should be - a SimpleITK.ParameterMap. Note that numeric values needd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. """ @@ -145,9 +145,9 @@ def apply_mask(self, mask): return masked_moving, masked_fixed def calc(self, moving_img, fixed_img, mask, *args, **kwargs): - """Cacluate displacement fields + """Calculate displacement fields - Can record subclass specific atrributes here too + Can record subclass specific attributes here too Parameters ---------- @@ -159,7 +159,7 @@ def calc(self, moving_img, fixed_img, mask, *args, **kwargs): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. Returns @@ -205,7 +205,7 @@ def register(self, moving_img, fixed_img, mask=None, **kwargs): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. **kwargs : dict, optional @@ -352,7 +352,7 @@ class NonRigidRegistrarXY(NonRigidRegistrar): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple @@ -403,11 +403,11 @@ def __init__(self, params=None): Parameters ---------- params : dictionary - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Will get used in the calc() method. In the case where simple ITK will be used, params should be - a SimpleITK.ParameterMap. Note that numeric values needd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. moving_xy : ndarray, optional @@ -442,7 +442,7 @@ def register(self, moving_img, fixed_img, mask=None, moving_xy=None, mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. moving_xy : ndarray, optional @@ -512,7 +512,7 @@ class NonRigidRegistrarGroupwise(NonRigidRegistrar): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple of int @@ -804,7 +804,7 @@ def run_elastix(self, moving_img, fixed_img, moving_xy=None, fixed_xy=None, mask : ndarray, optional 2D array with shape (N,M) where non-zero pixel values are - foreground, and 0 is background, which is ignnored during + foreground, and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. @@ -944,7 +944,7 @@ def __init__(self, params=None, optical_flow_obj=cv2.optflow.createOptFlow_DeepF Parameters ---------- params : dictionary - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Will get used in the calc() method. optical_flow_obj : object @@ -979,7 +979,7 @@ def __init__(self, params=None, optical_flow_obj=cv2.optflow.createOptFlow_DeepF Folded regions will then be removed using inpainting. If "regularize", folded regions will be detected and - regularized using the method fescribed in + regularized using the method described in "Foldover-free maps in 50 lines of code" Garanzha et al. 2021. If "None" then no smoothing will be applied. @@ -1145,7 +1145,7 @@ class SimpleElastixGroupwiseWarper(NonRigidRegistrarGroupwise): mask : ndarray 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple of int @@ -1283,7 +1283,7 @@ class NonRigidTileRegistrar(object): mask : pyvips.Image 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. shape : tuple @@ -1307,11 +1307,11 @@ def __init__(self, params=None, tile_wh=512, tile_buffer=100): Parameters ---------- params : dictionary - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Will get used when initializing the `non_rigid_registrar_cls` In the case where simple ITK will be used, params should be - a SimpleITK.ParameterMap. Note that numeric values needd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. tile_wh : int @@ -1466,7 +1466,7 @@ def reg_tile(self, tile_idx, lock): self.fwd_dxdy_tiles[tile_idx] = vips_tile_fwd_dxdy def calc(self, *args, **kwargs): - """Cacluate displacement fields + """Calculate displacement fields Each tile is registered and then stitched together """ @@ -1505,18 +1505,18 @@ def register(self, moving_img, fixed_img, mask=None, non_rigid_registrar_cls=Opt mask : ndarray, pyvips.Image 2D array with shape (N,M) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. non_rigid_registrar_cls : NonRigidRegistrar, optional Uninstantiated NonRigidRegistrar class that will be used to calculate the deformation fields between images. - processing_cls : preprocessing.ImageProcesser, optional - preprocessing.ImageProcesser used to process the images + processing_cls : preprocessing.ImageProcessor, optional + preprocessing.ImageProcessor used to process the images processing_kwargs : dict - Dictionary of keyward arguments to be passed to `processing_cls` + Dictionary of keyword arguments to be passed to `processing_cls` target_stats : ndarray Target stats used to normalize each tile after being processed. diff --git a/valis/preprocessing.py b/valis/preprocessing.py index 00ad13c9..e1ee2e70 100644 --- a/valis/preprocessing.py +++ b/valis/preprocessing.py @@ -31,19 +31,19 @@ DEFAULT_COLOR_STD_C = 0.2 # cam16-ucs -class ImageProcesser(object): +class ImageProcessor(object): """Process images for registration - `ImageProcesser` sub-classes processes images to single channel + `ImageProcessor` sub-classes processes images to single channel images which are then used in image registration. - Each `ImageProcesser` is initialized with an image, the path to the + Each `ImageProcessor` is initialized with an image, the path to the image, the pyramid level, and the series number. These values will be set during the registration process. - `ImageProcesser` must also have a `process_image` method, which is - called during registration. As `ImageProcesser` has the image and - and its relevant information (filename, level, series) as attributes, + `ImageProcessor` must also have a `process_image` method, which is + called during registration. As `ImageProcessor` has the image and + its relevant information (filename, level, series) as attributes, it should be able to access and modify the image as needed. However, one can also pass extra args and kwargs to `process_image`. As such, `process_image` will also need to accept args and kwargs. @@ -117,7 +117,7 @@ def process_image(self, *args, **kwargs): """ -class ChannelGetter(ImageProcesser): +class ChannelGetter(ImageProcessor): """Select channel from image """ @@ -153,7 +153,7 @@ def process_image(self, channel="dapi", adaptive_eq=True, invert=False, *args, * return chnl -class ColorfulStandardizer(ImageProcesser): +class ColorfulStandardizer(ImageProcessor): """Standardize the colorfulness of the image """ @@ -182,7 +182,7 @@ def process_image(self, c=DEFAULT_COLOR_STD_C, invert=True, adaptive_eq=False, * return processed_img -class JCDist(ImageProcesser): +class JCDist(ImageProcessor): def __init__(self, image, src_f, level, series, *args, **kwargs): super().__init__(image=image, src_f=src_f, level=level, series=series, *args, **kwargs) @@ -207,7 +207,7 @@ def process_image(self, p=99, metric="euclidean", adaptive_eq=True, *args, **kwa return processed -class OD(ImageProcesser): +class OD(ImageProcessor): """Convert the image from RGB to optical density (OD) and calculate pixel norms. """ @@ -244,7 +244,7 @@ def process_image(self, adaptive_eq=False, p=95, *args, **kwargs): return processed -class ColorDeconvolver(ImageProcesser): +class ColorDeconvolver(ImageProcessor): def __init__(self, image, src_f, level, series, *args, **kwargs): super().__init__(image=image, src_f=src_f, level=level, series=series, *args, **kwargs) @@ -257,7 +257,7 @@ def create_mask(self): def process_image(self, cspace="JzAzBz", method="similarity", adaptive_eq=False, return_unmixed=False, *args, **kwargs): """ - Process image by enhance stained pixels and subtracting backroung pixels + Process image by enhance stained pixels and subtracting background pixels Parameters ---------- @@ -268,7 +268,7 @@ def process_image(self, cspace="JzAzBz", method="similarity", adaptive_eq=False, How to calculate similarity of each pixel to colors detected in image adaptive_eq : bool - Whether or not to apply adaptive histogram equalization + Whether to apply adaptive histogram equalization Returns ------- @@ -312,7 +312,7 @@ def process_image(self, cspace="JzAzBz", method="similarity", adaptive_eq=False, return processed -class Luminosity(ImageProcesser): +class Luminosity(ImageProcessor): """Get luminosity of an RGB image """ @@ -334,7 +334,7 @@ def process_image(self, *args, **kwaargs): return processed_img -class BgColorDistance(ImageProcesser): +class BgColorDistance(ImageProcessor): """Calculate distance between each pixel and the background color """ @@ -358,7 +358,7 @@ def process_image(self, brightness_q=0.99, *args, **kwargs): return processed_img -class StainFlattener(ImageProcesser): +class StainFlattener(ImageProcessor): def __init__(self, image, src_f, level, series, *args, **kwargs): super().__init__(image=image, src_f=src_f, level=level, series=series, *args, **kwargs) @@ -483,7 +483,7 @@ def process_image(self, n_colors=100, q=95, with_mask=True, adaptive_eq=True, ma return processed_img -class Gray(ImageProcesser): +class Gray(ImageProcessor): """Get luminosity of an RGB image """ @@ -505,8 +505,8 @@ def process_image(self, *args, **kwaargs): return processed_img -class HEDeconvolution(ImageProcesser): - """Normalize staining appearence of hematoxylin and eosin (H&E) stained image +class HEDeconvolution(ImageProcessor): + """Normalize staining appearance of hematoxylin and eosin (H&E) stained image and get the H or E deconvolution image. Reference @@ -628,7 +628,7 @@ def standardize_colorfulness(img, c=DEFAULT_COLOR_STD_C, h=0): """Give image constant colorfulness and hue Image is converted to cylindrical CAM-16UCS assigned a constant - hue and colorfulness, and then coverted back to RGB. + hue and colorfulness, and then converted back to RGB. Parameters ---------- @@ -732,7 +732,7 @@ def calc_background_color_dist(img, brightness_q=0.99, mask=None, cspace="CAM16U def normalize_he(img: np.array, Io: int = 240, alpha: int = 1, beta: int = 0.15): - """ Normalize staining appearence of H&E stained images. + """ Normalize staining appearance of H&E stained images. Parameters ---------- @@ -1340,7 +1340,7 @@ def polygon_tortuosity(img, window_size=3): def remove_small_obj_and_lines_by_dist(mask): """ Will remove smaller objects and thin lines that - do not interesct with larger objects + do not intersect with larger objects """ dist_transform = cv2.distanceTransform(mask, cv2.DIST_L2, 5) @@ -1416,7 +1416,7 @@ def create_tissue_mask_from_rgb(img, brightness_q=0.99, kernel_size=3, gray_thre cam_d, cam = calc_background_color_dist(img, brightness_q=brightness_q, mask=color_mask) - # Reduce intensity of thick horizontal and vertial lines, usually artifacts like edges, streaks, folds, etc... + # Reduce intensity of thick horizontal and vertical lines, usually artifacts like edges, streaks, folds, etc... vert_knl = np.ones((1, 5)) no_v_lines = morphology.opening(cam_d, vert_knl) @@ -1424,7 +1424,7 @@ def create_tissue_mask_from_rgb(img, brightness_q=0.99, kernel_size=3, gray_thre no_h_lines = morphology.opening(cam_d, horiz_knl) cam_d_no_lines = np.dstack([no_v_lines, no_h_lines]).min(axis=2) - # Foreground is where color is different than backaground color + # Foreground is where color is different than background color cam_d_t, _ = filters.threshold_multiotsu(cam_d_no_lines[grey_mask == 0]) tissue_mask = np.zeros(cam_d_no_lines.shape, dtype=np.uint8) tissue_mask[cam_d_no_lines >= cam_d_t] = 255 @@ -1437,7 +1437,7 @@ def create_tissue_mask_from_rgb(img, brightness_q=0.99, kernel_size=3, gray_thre def jc_dist(img, cspace="IHLS", p=99, metric="euclidean"): """ - Cacluate distance between backround and each pixel + Calculate distance between background and each pixel using a luminosity and colofulness/saturation in a polar colorspace Parameters @@ -1450,7 +1450,7 @@ def jc_dist(img, cspace="IHLS", p=99, metric="euclidean"): p: int Percentile used to determine background values, i.e. - background pixels have a luminosity greather 99% of other + background pixels have a luminosity greater 99% of other pixels. Needs to be between 0-100 metric: str @@ -1459,7 +1459,7 @@ def jc_dist(img, cspace="IHLS", p=99, metric="euclidean"): Returns ------- jc_dist : np.ndarray - Color distance between backround and each pixel + Color distance between background and each pixel """ @@ -1529,7 +1529,7 @@ def create_tissue_mask_with_jc_dist(img): def clean_mask(mask, img=None, rel_min_size=0.001): """ - Remove small objects, regions that are not very colorful (relativey) + Remove small objects, regions that are not very colorful (relatively) """ fg_labeled = measure.label(mask) @@ -1559,11 +1559,11 @@ def clean_mask(mask, img=None, rel_min_size=0.001): if c0 == 0: tb = np.where(r.image_filled[:, 0])[0] - # Touchng left border + # Touching left border r_filled_img[min(tb):max(tb), 0] = 255 if c1 == mask.shape[1]: - # Touchng right border + # Touching right border tb = np.where(r.image_filled[:, -1])[0] r_filled_img[min(tb):max(tb), -1] = 255 @@ -1666,7 +1666,7 @@ def remove_regular_shapes(mask, irreg_thresh=0.05): def entropy_mask(img, cspace="Hunter LAB", irreg_thresh=0.0, rel_min_size=0.2): - # Detect and mask out backround (brightest and least colorful) + # Detect and mask out background (brightest and least colorful) mean_rgb, color_mask, filtered_label_counts, color_clusterer = find_dominant_colors(img, cspace=cspace, return_xy_clusterer=True) to_cluster_jab = rgb2jab(img, cspace=cspace) xy = to_cluster_jab[..., 1:].reshape((-1, 2)) @@ -1712,7 +1712,7 @@ def separate_colors(img, cspace="JzAzBz", min_colorfulness=0.005, px_thresh=0.00 Colorspace to use to detect and separate colors using `separate_colors` min_colorfulness : str - Pixels with colorfulness/saturation less that this will be exluded. + Pixels with colorfulness/saturation less that this will be excluded. Calculated after binning colors. px_thresh: float @@ -1905,7 +1905,7 @@ def find_dominant_colors(img, cspace="JzAzBz", min_colorfulness=0, px_thresh=0.0 Colorspace to use to detect and separate colors using `separate_colors` min_colorfulness : str - Pixels with colorfulness/saturation less that this will be exluded. + Pixels with colorfulness/saturation less that this will be excluded. Calculated after binning colors. px_thresh: float @@ -2412,7 +2412,7 @@ def img_to_tensor(img, return_rgb=True): or (H, W) for single channel return_rgb: bool - Whether or not to convert greyscale image to RGB + Whether to convert greyscale image to RGB Returns -------- diff --git a/valis/registration.py b/valis/registration.py index fb98c30b..11c3d67a 100644 --- a/valis/registration.py +++ b/valis/registration.py @@ -62,8 +62,8 @@ # Default image processing # DEFAULT_BRIGHTFIELD_CLASS = preprocessing.OD DEFAULT_BRIGHTFIELD_PROCESSING_ARGS = {"adaptive_eq": False} #{'c': preprocessing.DEFAULT_COLOR_STD_C, "h": 0} -DEFAULT_FLOURESCENCE_CLASS = preprocessing.ChannelGetter -DEFAULT_FLOURESCENCE_PROCESSING_ARGS = {"channel": "dapi", "adaptive_eq": True} +DEFAULT_FLUORESCENCE_CLASS = preprocessing.ChannelGetter +DEFAULT_FLUORESCENCE_PROCESSING_ARGS = {"channel": "dapi", "adaptive_eq": True} DEFAULT_NORM_METHOD = "img_stats" # Default rigid registration parameters # @@ -91,9 +91,9 @@ MATCHER_KEY = "matcher" MATCHER_FOR_SORTING_KEY = "matcher_for_sorting" NAME_KEY = "name" -IMAGES_ORDERD_KEY = "imgs_ordered" +IMAGES_ORDERED_KEY = "imgs_ordered" REF_IMG_KEY = "reference_img_f" -QT_EMMITER_KEY = "qt_emitter" +QT_EMITTER_KEY = "qt_emitter" TFORM_SRC_SHAPE_KEY = "transformation_src_shape_rc" TFORM_DST_SHAPE_KEY = "transformation_dst_shape_rc" TFORM_MAT_KEY = "M" @@ -183,7 +183,7 @@ class Slide(object): `Slide` is a class that stores registration parameters and other metadata about a slide. Once registration has been - completed, `Slide` is also able warp the slide and/or points + completed, `Slide` is also able to warp the slide and/or points using the same registration parameters. Warped slides can be saved as ome.tiff images with valid ome-xml. @@ -198,7 +198,7 @@ class Slide(object): argument specified when creating a `Valis` object. val_obj : Valis - The "parent" object that registers all of the slide. + The "parent" object that registers all the slides. reader : SlideReader Object that can read slides and collect metadata. @@ -345,7 +345,7 @@ def __init__(self, src_f, image, val_obj, reader, name=None): argument specified when creating a `Valis` object. val_obj : Valis - The "parent" object that registers all of the slide. + The "parent" object that registers all the slides. reader : SlideReader Object that can read slides and collect metadata. @@ -456,7 +456,7 @@ def slide2image(self, level, series=None, xywh=None): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -484,7 +484,7 @@ def slide2vips(self, level, series=None, xywh=None): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -546,7 +546,7 @@ def get_overlap_crop_xywh(self, warped_img_shape_rc, scaled_warped_img_shape_rc= shape of registered image warped_scaled_img_shape_rc : tuple of int, optional - shape of scaled registered image (i.e. registered slied) + shape of scaled registered image (i.e. registered slide) Returns ------- @@ -579,7 +579,7 @@ def get_crop_xywh(self, crop, out_shape_rc=None): out_shape_rc : tuple of int, optional If crop is "reference", this should be the shape of scaled reference image, such - as the unwarped slide that corresponds to the unwarped processed reference image. + as the un-warped slide that corresponds to the un-warped processed reference image. If crop is "overlap", this should be the shape of the registered slides. @@ -630,7 +630,7 @@ def get_bg_color_px_pos(self, cspace="Hunter LAB"): mean_jab = preprocessing.rgb2jab(mean_rgb, cspace=cspace) mean_jch = colour.models.Jab_to_JCh(mean_jab) - # Find highest luminosity (L) and lowest colorfulness + # Find the highest luminosity (L) and lowest colorfulness bg_idx = np.lexsort([mean_jch[:, 1], -mean_jch[:, 0]])[0] # Last column sorted 1st. Returns ascending order self.bg_color = mean_rgb[bg_idx, :] @@ -735,7 +735,7 @@ def warp_img(self, img=None, non_rigid=True, crop=True, interp_method="bicubic") will be warped. non_rigid : bool - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. crop: bool, str @@ -744,7 +744,7 @@ def warp_img(self, img=None, non_rigid=True, crop=True, interp_method="bicubic") image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. interp_method : str Interpolation method used when warping slide. Default is "bicubic" @@ -832,7 +832,7 @@ def warp_img(self, img=None, non_rigid=True, crop=True, interp_method="bicubic") def warp_img_from_to(self, img, to_slide_obj, dst_slide_level=0, non_rigid=True, interp_method="bicubic", bg_color=None): - """Warp an image from this slide onto another unwarped slide + """Warp an image from this slide onto another un-warped slide Note that if `img` is a labeled image/mask then it is recommended to set `interp_method` to "nearest" @@ -844,13 +844,13 @@ def warp_img_from_to(self, img, to_slide_obj, to_slide_obj : Slide Slide to which the points will be warped. I.e. `xy` will be warped from this Slide to their position in - the unwarped slide associated with `to_slide_obj`. + the un-warped slide associated with `to_slide_obj`. dst_slide_level: int, tuple, optional Pyramid level of the slide/image that `img` will be warped on to non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. """ @@ -902,7 +902,7 @@ def warp_slide(self, level, non_rigid=True, crop=True, Pyramid level to be warped non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True crop: bool, str @@ -911,7 +911,7 @@ def warp_slide(self, level, non_rigid=True, crop=True, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. src_f : str, optional Path of slide to be warped. If None (the default), Slide.src_f @@ -1024,7 +1024,7 @@ def warp_and_save_slide(self, dst_f, level=0, non_rigid=True, Pyramid level to be warped non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True crop: bool, str @@ -1057,13 +1057,13 @@ def warp_and_save_slide(self, dst_f, level=0, non_rigid=True, Tile width and height used to save image compression : str - Compression method used to save ome.tiff. See pyips for more details. + Compression method used to save ome.tiff. See pyvips for more details. Q : int Q factor for lossy compression pyramid : bool - Whether or not to save an image pyramid. + Whether to save an image pyramid. """ if src_f is None: @@ -1123,7 +1123,7 @@ def warp_xy(self, xy, M=None, slide_level=0, pt_level=0, the points should be warped. Default is 0. pt_level: int, tuple, optional - Pyramid level from which the points origingated. For example, if + Pyramid level from which the points originated. For example, if `xy` are from the centroids of cell segmentation performed on the full resolution image, this should be 0. Alternatively, the value can be a tuple of the image's shape (row, col) from which the points came. @@ -1132,7 +1132,7 @@ def warp_xy(self, xy, M=None, slide_level=0, pt_level=0, image's shape (row, col). Default is 0. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True. crop: bool, str @@ -1146,7 +1146,7 @@ def warp_xy(self, xy, M=None, slide_level=0, pt_level=0, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. """ if M is None: @@ -1200,10 +1200,10 @@ def warp_xy(self, xy, M=None, slide_level=0, pt_level=0, def warp_xy_from_to(self, xy, to_slide_obj, src_slide_level=0, src_pt_level=0, dst_slide_level=0, non_rigid=True): - """Warp points from this slide to another unwarped slide + """Warp points from this slide to another un-warped slide - Takes a set of points found in this unwarped slide, and warps them to - their position in the unwarped "to" slide. + Takes a set of points found in this un-warped slide, and warps them to + their position in the un-warped "to" slide. Parameters ---------- @@ -1213,12 +1213,12 @@ def warp_xy_from_to(self, xy, to_slide_obj, src_slide_level=0, src_pt_level=0, to_slide_obj : Slide Slide to which the points will be warped. I.e. `xy` will be warped from this Slide to their position in - the unwarped slide associated with `to_slide_obj`. + the un-warped slide associated with `to_slide_obj`. src_pt_level: int, tuple, optional Pyramid level of the slide/image in which `xy` originated. For example, if `xy` are from the centroids of cell segmentation - performed on the unwarped full resolution image, this should be 0. + performed on the un-warped full resolution image, this should be 0. Alternatively, the value can be a tuple of the image's shape (row, col) from which the points came. For example, if `xy` are bounding box coordinates from an analysis on a lower resolution image, @@ -1232,7 +1232,7 @@ def warp_xy_from_to(self, xy, to_slide_obj, src_slide_level=0, src_pt_level=0, to their location in an image with that same shape. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. """ @@ -1299,7 +1299,7 @@ def warp_geojson(self, geojson_f, M=None, slide_level=0, pt_level=0, the points should be warped. Default is 0. pt_level: int, tuple, optional - Pyramid level from which the points origingated. For example, if + Pyramid level from which the points originated. For example, if `xy` are from the centroids of cell segmentation performed on the full resolution image, this should be 0. Alternatively, the value can be a tuple of the image's shape (row, col) from which the points came. @@ -1308,7 +1308,7 @@ def warp_geojson(self, geojson_f, M=None, slide_level=0, pt_level=0, image's shape (row, col). Default is 0. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True. crop: bool, str @@ -1322,7 +1322,7 @@ def warp_geojson(self, geojson_f, M=None, slide_level=0, pt_level=0, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. """ if M is None: @@ -1389,10 +1389,10 @@ def warp_geojson(self, geojson_f, M=None, slide_level=0, pt_level=0, def warp_geojson_from_to(self, geojson_f, to_slide_obj, src_slide_level=0, src_pt_level=0, dst_slide_level=0, non_rigid=True): - """Warp geoms in geojson file from annotation slide to another unwarped slide + """Warp geoms in geojson file from annotation slide to another un-warped slide Takes a set of geometries found in this annotation slide, and warps them to - their position in the unwarped "to" slide. + their position in the un-warped "to" slide. Parameters ---------- @@ -1403,12 +1403,12 @@ def warp_geojson_from_to(self, geojson_f, to_slide_obj, src_slide_level=0, src_p to_slide_obj : Slide Slide to which the points will be warped. I.e. `xy` will be warped from this Slide to their position in - the unwarped slide associated with `to_slide_obj`. + the un-warped slide associated with `to_slide_obj`. src_pt_level: int, tuple, optional Pyramid level of the slide/image in which `xy` originated. For example, if `xy` are from the centroids of cell segmentation - performed on the unwarped full resolution image, this should be 0. + performed on the un-warped full resolution image, this should be 0. Alternatively, the value can be a tuple of the image's shape (row, col) from which the points came. For example, if `xy` are bounding box coordinates from an analysis on a lower resolution image, @@ -1422,7 +1422,7 @@ def warp_geojson_from_to(self, geojson_f, to_slide_obj, src_slide_level=0, src_p to their location in an image with that same shape. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Returns @@ -1592,10 +1592,10 @@ class Valis(object): Dictionary of Slide objects, each of which contains information about a slide, and methods to warp it. - brightfield_procsseing_fxn_str: str + brightfield_processing_fxn_str: str Name of function used to process brightfield images. - if_procsseing_fxn_str : str + if_processing_fxn_str : str Name of function used to process fluorescence images. max_image_dim_px : int @@ -1616,7 +1616,7 @@ class Valis(object): the `img_obj_list` has been sorted during rigid registration. align_to_reference : bool - Whether or not images should be aligne to a reference image + Whether or not images should be aligned to a reference image specified by `reference_img_f`. Will be set to True if `reference_img_f` is provided. @@ -1627,7 +1627,7 @@ class Valis(object): SerialRigidRegistrar object that performs the rigid registration. rigid_reg_kwargs : dict - Dictionary of keyward arguments passed to + Dictionary of keyword arguments passed to `serial_rigid.register_images`. feature_descriptor_str : str @@ -1650,7 +1650,7 @@ class Valis(object): non-rigid registration. non_rigid_reg_kwargs : dict - Dictionary of keyward arguments passed to + Dictionary of keyword arguments passed to `serial_non_rigid.register_images`. non_rigid_registrar_cls : NonRigidRegistrar @@ -1759,7 +1759,7 @@ class Valis(object): View ome.tiff, located at merged_slide_dst_f """ - @valtils.deprecated_args(max_non_rigid_registartion_dim_px="max_non_rigid_registration_dim_px", img_type="image_type") + @valtils.deprecated_args(max_non_rigid_registration_dim_px="max_non_rigid_registration_dim_px", img_type="image_type") def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, feature_detector_cls=None, transformer_cls=DEFAULT_TRANSFORM_CLASS, @@ -1823,8 +1823,8 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, transformation matrix that will warp each image to the target image. Default is SimilarityTransform - affine_optimizer_cls : AffineOptimzer class, optional - Uninstantiated AffineOptimzer that will minimize a + affine_optimizer_cls : AffineOptimizer class, optional + Uninstantiated AffineOptimizer that will minimize a cost function to find the optimal affine transformations. If a desired affine optimization is not available, one can be created by subclassing `affine_optimizer.AffineOptimizer`. @@ -1848,7 +1848,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, are already in the correct order. If True, then each filename should begin with the number that indicates its position in the z-stack. If False, then the images will be sorted by ordering a feature distance - matix. Default is False. + matrix. Default is False. reference_img_f : str, optional Filename of image that will be treated as the center of the stack. @@ -1863,7 +1863,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, non_rigid_registrar_cls : NonRigidRegistrar, optional Uninstantiated NonRigidRegistrar class that will be used to calculate the deformation fields between images. See - the `non_rigid_registrars` module for a desciption of available + the `non_rigid_registrars` module for a description of available methods. If a desired non-rigid registration method is not available, one can be implemented by subclassing.NonRigidRegistrar. If None, then only rigid registration will be performed @@ -1878,12 +1878,12 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, methods and arguments. compose_non_rigid : bool, optional - Whether or not to compose non-rigid transformations. If `True`, + Whether to compose non-rigid transformations. If `True`, then an image is non-rigidly warped before aligning to the adjacent non-rigidly aligned image. This allows the transformations to accumulate, which may bring distant features together but could also result in un-wanted deformations, particularly around the edges. - If `False`, the image not warped before being aaligned to the adjacent + If `False`, the image not warped before being aligned to the adjacent non-rigidly aligned image. This can reduce unwanted deformations, but may not bring distant features together. @@ -1894,11 +1894,11 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, Valis.slide_dict. do_rigid: bool, dictionary, optional - Whether or not to perform rigid registration. If `False`, rigid + Whether to perform rigid registration. If `False`, rigid registration will be skipped. If `do_rigid` is a dictionary, it should contain inverse transformation - matrices to rigidly align images to the specificed by `reference_img_f`. + matrices to rigidly align images to the specified by `reference_img_f`. M will be estimated for images that are not in the dictionary. Each key is the filename of the image associated with the transformation matrix, and value is a dictionary containing the following values: @@ -1924,32 +1924,32 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, is defined, then `crop` will be set to "reference". create_masks : bool, optional - Whether or not to create and apply masks for registration. + Whether to create and apply masks for registration. Can help focus alignment on the tissue, but can sometimes mask too much if there is a lot of variation in the image. denoise_rigid : bool, optional - Whether or not to denoise processed images before rigid registion. + Whether to denoise processed images before rigid registration. Note that un-denoised images are used in the non-rigid registration crop_for_rigid_reg : bool, optional - Whether or not to crop the images used for rigid registration. If `True`, - then higher resolution images may be used for rigid registeration, as valis - will "zoom" in to the area around the mask created by `ImageProcesser.create_mask()`, + Whether to crop the images used for rigid registration. If `True`, + then higher resolution images may be used for rigid registration, as valis + will "zoom" in to the area around the mask created by `ImageProcessor.create_mask()`, and slice out that region and resize it to have a maximum dimension the same as `max_processed_image_dim_px`. If `False`, the full image will be used, although the tissue may be at a lower resolution. check_for_reflections : bool, optional - Determine if alignments are improved by relfecting/mirroring/flipping + Determine if alignments are improved by reflecting/mirroring/flipping images. Optional because it requires re-detecting features in each version - of the images and then re-matching features, and so can be time consuming and + of the images and then re-matching features, and so can be time-consuming and not always necessary. resolution_xyu: tuple, optional Physical size per pixel and the unit. If None (the default), these values will be determined for each slide using the slides' metadata. - If provided, this physical pixel sizes will be used for all of the slides. + If provided, this physical pixel sizes will be used for all the slides. This option is available in case one cannot easily access to the original slides, but does have the information on pixel's physical units. @@ -1972,7 +1972,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, max_non_rigid_registration_dim_px : int, optional Maximum width or height of images used for non-rigid registration. - Larger values may yeild more accurate results, at the expense of + Larger values may yield more accurate results, at the expense of speed and memory. There is also a practical limit, as the specified size may be too large to fit in memory. @@ -2001,7 +2001,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, this step is skipped. micro_rigid_registrar_params : dictionary - Dictionary of keyword arguments used intialize the `MicroRigidRegistrar` + Dictionary of keyword arguments used initialize the `MicroRigidRegistrar` qt_emitter : PySide2.QtCore.Signal, optional Used to emit signals that update the GUI's progress bars @@ -2080,8 +2080,8 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, self.slide_dict = {} # Fields related to image pre-processing # - self.brightfield_procsseing_fxn_str = None - self.if_procsseing_fxn_str = None + self.brightfield_processing_fxn_str = None + self.if_processing_fxn_str = None if max_image_dim_px < max_processed_image_dim_px: msg = f"max_image_dim_px is {max_image_dim_px} but needs to be less or equal to {max_processed_image_dim_px}. Setting max_image_dim_px to {max_processed_image_dim_px}" @@ -2156,7 +2156,7 @@ def __init__(self, src_dir, dst_dir, series=None, name=None, image_type=None, compose_non_rigid=compose_non_rigid, qt_emitter=qt_emitter) - # Info realted to saving images to view results # + # Info related to saving images to view results # self.mask_dict = None self.create_masks = create_masks @@ -2209,9 +2209,9 @@ def _set_rigid_reg_kwargs(self, name, feature_detector, similarity_metric, MATCHER_FOR_SORTING_KEY: matcher_for_sorting, AFFINE_OPTIMIZER_KEY: afo, REF_IMG_KEY: reference_img_f, - IMAGES_ORDERD_KEY: imgs_ordered, + IMAGES_ORDERED_KEY: imgs_ordered, CHECK_REFLECT_KEY: check_for_reflections, - QT_EMMITER_KEY: qt_emitter + QT_EMITTER_KEY: qt_emitter } # Save methods as strings since some objects cannot be pickled # @@ -2246,7 +2246,7 @@ def _set_non_rigid_reg_kwargs(self, name, non_rigid_reg_class, non_rigid_reg_par NON_RIGID_REG_CLASS_KEY: nr, NON_RIGID_REG_PARAMS_KEY: non_rigid_reg_params, REF_IMG_KEY: reference_img_f, - QT_EMMITER_KEY: qt_emitter, + QT_EMITTER_KEY: qt_emitter, NON_RIGID_COMPOSE_KEY: compose_non_rigid } @@ -2343,7 +2343,7 @@ def get_slide(self, src_f): * Save the warped slide as an ome.tiff (Slide.warp_and_save_slide) * Warp an image of the slide (Slide.warp_img) * Warp points (Slide.warp_xy) - * Warp points in one slide to their position in another unwarped slide (Slide.warp_xy_from_to) + * Warp points in one slide to their position in another un-warped slide (Slide.warp_xy_from_to) * Access slide ome-xml (Slide.original_xml) See Slide for more details. @@ -2443,7 +2443,7 @@ def get_img_names(self, img_list): for j, p in enumerate(dup_paths): new_name = f"{names_dict[p]}_{str(j).zfill(z)}" - msg = f"Renmaing {p} to {new_name} in Valis.slide_dict)" + msg = f"Renaming {p} to {new_name} in Valis.slide_dict)" valtils.print_warning(msg) names_dict[p] = new_name @@ -2518,7 +2518,7 @@ def convert_imgs(self, series=None, reader_dict=None, reader_cls=None): """Convert slides to images and create dictionary of Slides. series : int, optional - Slide series to be read. If None, the series with largest image will be read + Slide series to be read. If None, the series with the largest image will be read reader_cls : SlideReader, optional Uninstantiated SlideReader class that will convert @@ -2527,7 +2527,7 @@ def convert_imgs(self, series=None, reader_dict=None, reader_cls=None): reader_dict: dict, optional Dictionary specifying which readers to use for individual images. The keys, value pairs are image filename and instantiated `slide_io.SlideReader` - to use to read that file. Valis will try to find an appropritate reader + to use to read that file. Valis will try to find an appropriate reader for any omitted files, or will use `reader_cls` as the default. """ @@ -2662,7 +2662,7 @@ def create_original_composite_img(self, rigid_registrar): return overlap_img def measure_original_mmi(self, img1, img2): - """Measure Mattes mutation inormation between 2 unregistered images. + """Measure Mattes mutation information between 2 unregistered images. """ dst_rc = np.max([img1.shape, img2.shape], axis=1) @@ -2678,8 +2678,8 @@ def measure_original_mmi(self, img1, img2): def create_img_processor_dict(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, brightfield_processing_kwargs=DEFAULT_BRIGHTFIELD_PROCESSING_ARGS, - if_processing_cls=DEFAULT_FLOURESCENCE_CLASS, - if_processing_kwargs=DEFAULT_FLOURESCENCE_PROCESSING_ARGS, + if_processing_cls=DEFAULT_FLUORESCENCE_CLASS, + if_processing_kwargs=DEFAULT_FLUORESCENCE_PROCESSING_ARGS, processor_dict=None): """Create dictionary to get processors for each image @@ -2688,24 +2688,24 @@ def create_img_processor_dict(self, brightfield_processing_cls=DEFAULT_BRIGHTFIE Parameters ---------- - brightfield_processing_cls : ImageProcesser - ImageProcesser to pre-process brightfield images to make them look as similar as possible. + brightfield_processing_cls : ImageProcessor + ImageProcessor to pre-process brightfield images to make them look as similar as possible. Should return a single channel uint8 image. brightfield_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `brightfield_processing_cls` + Dictionary of keyword arguments to be passed to `brightfield_processing_cls` - if_processing_cls : ImageProcesser - ImageProcesser to pre-process immunofluorescent images to make them look as similar as possible. + if_processing_cls : ImageProcessor + ImageProcessor to pre-process immunofluorescence images to make them look as similar as possible. Should return a single channel uint8 image. if_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `if_processing_cls` + Dictionary of keyword arguments to be passed to `if_processing_cls` processor_dict : dict Each key should be the filename of the image, and the value either a subclassed preprocessing.ImageProcessor, or a list, where the 1st element is the processor, - and the second element a dictionary of keyword arguments passed to ImageProcesser.process_img. + and the second element a dictionary of keyword arguments passed to ImageProcessor.process_img. If `None`, then this function will assign a processor to each image. Returns @@ -2713,7 +2713,7 @@ def create_img_processor_dict(self, brightfield_processing_cls=DEFAULT_BRIGHTFIE named_processing_dict : Dict Each key is the name of the slide, and the value is a list, where the 1st element is the processor, and the second element a dictionary - of keyword arguments passed to ImageProcesser.process_img + of keyword arguments passed to ImageProcessor.process_img """ @@ -3047,7 +3047,7 @@ def get_all_overlap_mask(self): return mask, mask_bbox_xywh def get_null_overlap_mask(self): - """Create mask that covers all of the image. + """Create mask that covers all the images. Not really a mask @@ -3177,15 +3177,15 @@ def extract_rigid_transforms_from_serial_rigid(self, rigid_registrar): w = int(np.ceil(max_x - min_x)) h = int(np.ceil(max_y - min_y)) - registerd_out_shape_rc = np.array([h, w]) + registered_out_shape_rc = np.array([h, w]) for slide_obj in self.slide_dict.values(): M = slide_M_dict[slide_obj.name] @ pad_T slide_M_dict[slide_obj.name] = M - cropped_registerd_out_shape_rc = rigid_registrar.img_obj_list[0].registered_shape_rc + cropped_registered_out_shape_rc = rigid_registrar.img_obj_list[0].registered_shape_rc - return slide_M_dict, registerd_out_shape_rc, cropped_M_dict, cropped_registerd_out_shape_rc, matches_dict + return slide_M_dict, registered_out_shape_rc, cropped_M_dict, cropped_registered_out_shape_rc, matches_dict def get_cropped_img_for_rigid_warp(self, slide_obj): @@ -3213,7 +3213,7 @@ def rigid_register_partial(self, tform_dict=None): transformation_src_shape_rc: shape (row, col) of image used to find the rigid transformation. If not provided, then it is assumed to be the shape of the level 0 slide - transformation_dst_shape_rc: shape of registered image. If not presesnt, but a reference was provided + transformation_dst_shape_rc: shape of registered image. If not present, but a reference was provided and `transformation_src_shape_rc` was not provided, this is assumed to be the shape of the reference slide If None, then all rigid M will be the identity matrix @@ -3247,7 +3247,7 @@ def rigid_register_partial(self, tform_dict=None): # print("\n======== Matching images\n") - if rigid_registrar.aleady_sorted: + if rigid_registrar.already_sorted: rigid_registrar.match_sorted_imgs(matcher_for_sorting, keep_unfiltered=False, valis_obj=self) for i, img_obj in enumerate(rigid_registrar.img_obj_list): @@ -3426,7 +3426,7 @@ def rigid_register(self): ref_slide = self.slide_dict[valtils.get_name(rigid_registrar.reference_img_f)] self.reference_img_f = ref_slide.src_f - rigid_transform_dict, rigid_reg_shape, cropped_M_dict, cropped_registerd_out_shape_rc, rigid_matches_dict = \ + rigid_transform_dict, rigid_reg_shape, cropped_M_dict, cropped_registered_out_shape_rc, rigid_matches_dict = \ self.extract_rigid_transforms_from_serial_rigid(rigid_registrar) self.aligned_img_shape_rc = rigid_reg_shape @@ -3434,7 +3434,7 @@ def rigid_register(self): for slide_reg_obj in rigid_registrar.img_obj_list: slide_obj = self.slide_dict[slide_reg_obj.name] slide_obj.M_for_cropped = cropped_M_dict[slide_obj.name] - slide_obj.rigid_reg_cropped_shape_rc = cropped_registerd_out_shape_rc + slide_obj.rigid_reg_cropped_shape_rc = cropped_registered_out_shape_rc slide_obj.M = rigid_transform_dict[slide_obj.name] slide_obj.reg_img_shape_rc = rigid_reg_shape slide_obj.stack_idx = slide_reg_obj.stack_idx @@ -3507,10 +3507,10 @@ def rigid_register(self): return rigid_registrar def micro_rigid_register(self): - micro_rigid_registar = self.micro_rigid_registrar_cls(val_obj=self, **self.micro_rigid_registrar_params) - micro_rigid_registar.register() + micro_rigid_registrar = self.micro_rigid_registrar_cls(val_obj=self, **self.micro_rigid_registrar_params) + micro_rigid_registrar.register() - # Not all pairs will have keept high resolution M, so re-estimate M based on final matches + # Not all pairs will have kept high resolution M, so re-estimate M based on final matches slide_idx, slide_names = list(zip(*[[slide_obj.stack_idx, slide_obj.name] for slide_obj in self.slide_dict.values()])) slide_order = np.argsort(slide_idx) # sorts ascending slide_list = [self.slide_dict[slide_names[i]] for i in slide_order] @@ -3679,7 +3679,7 @@ def _create_mask_from_processed(self, slide_list=None): rigid_mask = slide_obj.warp_img(slide_obj.rigid_reg_mask, non_rigid=False, crop=False, interp_method="nearest") combo_mask[rigid_mask > 0] += 1 - # Caclulate running average + # Calculate running average padded_processed = slide_obj.pad_cropped_processed_img() padded_processed[slide_obj.rigid_reg_mask == 0] = 0 padded_processed[slide_obj.rigid_reg_mask > 0] = exposure.rescale_intensity(padded_processed[slide_obj.rigid_reg_mask > 0], out_range=(0, 255)) @@ -3868,7 +3868,7 @@ def prep_images_for_large_non_rigid_registration(self, max_img_dim, else: s = np.min(max_img_dim/np.array(ref_slide.processed_img_shape_rc)) else: - # Determine how big image would have to be to get mask with maxmimum dimension = max_img_dim + # Determine how big image would have to be to get mask with maximum dimension = max_img_dim if isinstance(mask, pyvips.Image): mask_shape_rc = np.array((mask.height, mask.width)) else: @@ -4376,12 +4376,12 @@ def non_rigid_register(self, rigid_registrar, processor_dict): if draw_img.ndim == 2: draw_img = np.dstack([draw_img] * 3) - thumbanil_deform_grid = viz.draw_displacement_vector_field(dxdy=[-thumbnail_bk_dxdy[..., 0], -thumbnail_bk_dxdy[..., 1]], + thumbnail_deform_grid = viz.draw_displacement_vector_field(dxdy=[-thumbnail_bk_dxdy[..., 0], -thumbnail_bk_dxdy[..., 1]], img=draw_img, spacing=10) deform_img_f = os.path.join(self.deformation_field_dir, img_save_id + "_" + slide_obj.name + ".png") - warp_tools.save_img(deform_img_f, thumbanil_deform_grid, thumbnail_size=self.thumbnail_size) + warp_tools.save_img(deform_img_f, thumbnail_deform_grid, thumbnail_size=self.thumbnail_size) return non_rigid_registrar @@ -4397,10 +4397,10 @@ def measure_error(self): `summary_df` contains various information about the registration. The "from" column is the name of the image, while the "to" column - name of the image it was aligned to. "from" is analagous to "moving" - or "current", while "to" is analgous to "fixed" or "previous". + name of the image it was aligned to. "from" is analogous to "moving" + or "current", while "to" is analogous to "fixed" or "previous". - Columns begining with "original" refer to error measurements of the + Columns beginning with "original" refer to error measurements of the unregistered images. Those beginning with "rigid" or "non_rigid" refer to measurements related to rigid or non-rigid registration, respectively. @@ -4408,7 +4408,7 @@ def measure_error(self): the case of errors based on feature distances (i.e. those ending in "D"), the mean is weighted by the number of feature matches between "from" and "to". - Columns endining in "D" indicate the median distance between matched + Columns ending in "D" indicate the median distance between matched features in "from" and "to". Columns ending in "rTRE" indicate the target registration error between @@ -4424,7 +4424,7 @@ def measure_error(self): "aligned_shape" is the shape of the registered full resolution slide - "physical_units" are the names of the pixels physcial unit, e.g. u'\u00B5m' + "physical_units" are the names of the pixels physical unit, e.g. u'\u00B5m' "resolution" is the physical unit per pixel @@ -4592,8 +4592,8 @@ def measure_error(self): def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, brightfield_processing_kwargs=DEFAULT_BRIGHTFIELD_PROCESSING_ARGS, - if_processing_cls=DEFAULT_FLOURESCENCE_CLASS, - if_processing_kwargs=DEFAULT_FLOURESCENCE_PROCESSING_ARGS, + if_processing_cls=DEFAULT_FLUORESCENCE_CLASS, + if_processing_kwargs=DEFAULT_FLUORESCENCE_PROCESSING_ARGS, processor_dict=None, reader_cls=None, reader_dict=None): @@ -4604,13 +4604,13 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, then conduct rigid registration. Non-rigid registration will then be performed if the `non_rigid_registrar_cls` argument used to initialize the Valis object was not None. - In addition to the objects returned, the desination directory (i.e. `dst_dir`) + In addition to the objects returned, the destination directory (i.e. `dst_dir`) will contain thumbnails so that one can visualize the results: converted image thumbnails will be in "images/"; processed images in "processed/"; rigidly aligned images in "rigid_registration/"; non-rigidly aligned images in "non_rigid_registration/"; - non-rigid deformation field images (i.e. warped grids colored by the direction and magntidue) + non-rigid deformation field images (i.e. warped grids colored by the direction and magnitude) of the deformation) will be in ""deformation_fields/". The size of these thumbnails - is determined by the `thumbnail_size` argument used to initialze this object. + is determined by the `thumbnail_size` argument used to initialize this object. One can get a sense of how well the registration worked by looking in the "overlaps/", which shows how the images overlap before @@ -4619,26 +4619,26 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, blending those images. The "data/" directory will contain a pickled copy of this registrar, which can be - later be opened (unpickled) and used to warp slides and/or point data. + later be opened (un-pickled) and used to warp slides and/or point data. "data/" will also contain the `summary_df` saved as a csv file. Parameters ---------- - brightfield_processing_cls : preprocessing.ImageProcesser - preprocessing.ImageProcesser used to pre-process brightfield images to make + brightfield_processing_cls : preprocessing.ImageProcessor + preprocessing.ImageProcessor used to pre-process brightfield images to make them look as similar as possible. brightfield_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `brightfield_processing_cls` + Dictionary of keyword arguments to be passed to `brightfield_processing_cls` - if_processing_cls : preprocessing.ImageProcesser - preprocessing.ImageProcesser used to pre-process immunofluorescent images + if_processing_cls : preprocessing.ImageProcessor + preprocessing.ImageProcessor used to pre-process immunofluorescence images to make them look as similar as possible. if_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `if_processing_cls` + Dictionary of keyword arguments to be passed to `if_processing_cls` processor_dict : dict, optional Each key should be the filename of the image, and the value either a subclassed @@ -4658,7 +4658,7 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, reader_dict: dict, optional Dictionary specifying which readers to use for individual images. The keys should be the image's filename, and the values the instantiated slide_io.SlideReader - to use to read that file. Valis will try to find an appropritate reader + to use to read that file. Valis will try to find an appropriate reader for any omitted files, or will use `reader_cls` as the default. Returns @@ -4675,10 +4675,10 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, `summary_df` contains various information about the registration. The "from" column is the name of the image, while the "to" column - name of the image it was aligned to. "from" is analagous to "moving" - or "current", while "to" is analgous to "fixed" or "previous". + name of the image it was aligned to. "from" is analogous to "moving" + or "current", while "to" is analogous to "fixed" or "previous". - Columns begining with "original" refer to error measurements of the + Columns beginning with "original" refer to error measurements of the unregistered images. Those beginning with "rigid" or "non_rigid" refer to measurements related to rigid or non-rigid registration, respectively. @@ -4686,7 +4686,7 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, the case of errors based on feature distances (i.e. those ending in "D"), the mean is weighted by the number of feature matches between "from" and "to". - Columns endining in "D" indicate the median distance between matched + Columns ending in "D" indicate the median distance between matched features in "from" and "to". Columns ending in "TRE" indicate the target registration error between @@ -4702,7 +4702,7 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, "aligned_shape" is the shape of the registered full resolution slide - "physical_units" are the names of the pixels physcial unit, e.g. u'\u00B5m' + "physical_units" are the names of the pixels physical unit, e.g. u'\u00B5m' "resolution" is the physical unit per pixel @@ -4728,7 +4728,7 @@ def register(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, if_processing_kwargs=if_processing_kwargs, processor_dict=processor_dict) - self.brightfield_procsseing_fxn_str = brightfield_processing_cls.__name__ + self.brightfield_processing_fxn_str = brightfield_processing_cls.__name__ self.if_processing_fxn_str = if_processing_cls.__name__ self.process_imgs(processor_dict=slide_processors) @@ -4794,35 +4794,35 @@ def cleanup(self): self.micro_rigid_registrar_cls = None self.non_rigid_registrar = None - @valtils.deprecated_args(max_non_rigid_registartion_dim_px="max_non_rigid_registration_dim_px") + @valtils.deprecated_args(max_non_rigid_registration_dim_px="max_non_rigid_registration_dim_px") def register_micro(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, brightfield_processing_kwargs=DEFAULT_BRIGHTFIELD_PROCESSING_ARGS, - if_processing_cls=DEFAULT_FLOURESCENCE_CLASS, - if_processing_kwargs=DEFAULT_FLOURESCENCE_PROCESSING_ARGS, + if_processing_cls=DEFAULT_FLUORESCENCE_CLASS, + if_processing_kwargs=DEFAULT_FLUORESCENCE_PROCESSING_ARGS, processor_dict=None, max_non_rigid_registration_dim_px=DEFAULT_MAX_MICRO_REG_SIZE, non_rigid_registrar_cls=DEFAULT_NON_RIGID_CLASS, non_rigid_reg_params=DEFAULT_NON_RIGID_KWARGS, reference_img_f=None, align_to_reference=False, mask=None, tile_wh=DEFAULT_NR_TILE_WH): - """Improve alingment of microfeatures by performing second non-rigid registration on larger images + """Improve alignment of microfeatures by performing second non-rigid registration on larger images - Caclculates additional non-rigid deformations using a larger image + Calculates additional non-rigid deformations using a larger image Parameters ---------- - brightfield_processing_cls : preprocessing.ImageProcesser - preprocessing.ImageProcesser used to pre-process brightfield images to make + brightfield_processing_cls : preprocessing.ImageProcessor + preprocessing.ImageProcessor used to pre-process brightfield images to make them look as similar as possible. brightfield_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `brightfield_processing_cls` + Dictionary of keyword arguments to be passed to `brightfield_processing_cls` - if_processing_cls : preprocessing.ImageProcesser - preprocessing.ImageProcesser used to pre-process immunofluorescent images + if_processing_cls : preprocessing.ImageProcessor + preprocessing.ImageProcessor used to pre-process immunofluorescence images to make them look as similar as possible. if_processing_kwargs : dict - Dictionary of keyward arguments to be passed to `if_processing_cls` + Dictionary of keyword arguments to be passed to `if_processing_cls` max_non_rigid_registration_dim_px : int, optional Maximum width or height of images used for non-rigid registration. @@ -4844,7 +4844,7 @@ def register_micro(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, non_rigid_registrar_cls : NonRigidRegistrar, optional Uninstantiated NonRigidRegistrar class that will be used to calculate the deformation fields between images. See - the `non_rigid_registrars` module for a desciption of available + the `non_rigid_registrars` module for a description of available methods. If a desired non-rigid registration method is not available, one can be implemented by subclassing.NonRigidRegistrar. @@ -4852,7 +4852,7 @@ def register_micro(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, Dictionary containing key, value pairs to be used to initialize `non_rigid_registrar_cls`. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. See the NonRigidRegistrar classes in `non_rigid_registrars` for the available non-rigid registration methods and arguments. @@ -4910,7 +4910,7 @@ def register_micro(self, brightfield_processing_cls=DEFAULT_BRIGHTFIELD_CLASS, if using_tiler: # Have determined that these images will be too big msg = (f"Registration would more than {TILER_THRESH_GB} GB if all images opened in memory. " - f"Will use NonRigidTileRegistrar to register cooresponding tiles to reduce memory consumption, " + f"Will use NonRigidTileRegistrar to register corresponding tiles to reduce memory consumption, " f"but this method is experimental") valtils.print_warning(msg) @@ -5109,7 +5109,6 @@ def warp_and_save_slides(self, dst_dir, level=0, non_rigid=True, colormap=slide_io.CMAP_AUTO, interp_method="bicubic", tile_wh=None, compression=DEFAULT_COMPRESSION, Q=100, pyramid=True): - f"""Warp and save all slides Each slide will be saved as an ome.tiff. The extension of each file will @@ -5125,7 +5124,7 @@ def warp_and_save_slides(self, dst_dir, level=0, non_rigid=True, resolution image will be warped and saved. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True crop: bool, str @@ -5134,7 +5133,7 @@ def warp_and_save_slides(self, dst_dir, level=0, non_rigid=True, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. colormap : list List of RGB colors (0-255) to use for channel colors. @@ -5148,7 +5147,7 @@ def warp_and_save_slides(self, dst_dir, level=0, non_rigid=True, Tile width and height used to save image compression : str, optional - Compression method used to save ome.tiff. See pyips for more details. + Compression method used to save ome.tiff. See pyvips for more details. Q : int Q factor for lossy compression @@ -5222,7 +5221,7 @@ def warp_and_merge_slides(self, dst_f=None, level=0, non_rigid=True, resolution image will be warped and saved. non_rigid : bool, optional - Whether or not to conduct non-rigid warping. If False, + Whether to conduct non-rigid warping. If False, then only a rigid transformation will be applied. Default is True crop: bool, str @@ -5231,13 +5230,13 @@ def warp_and_merge_slides(self, dst_f=None, level=0, non_rigid=True, image will not be cropped. If "overlap", the warped slide will be cropped to include only areas where all images overlapped. "reference" crops to the area that overlaps with the reference image, - defined by `reference_img_f` when initialzing the `Valis object`. + defined by `reference_img_f` when initializing the `Valis object`. channel_name_dict : dict of lists, optional. key = slide file name, value = list of channel names for that slide. If None, - the the channel names found in each slide will be used. + the channel names found in each slide will be used. - src_f_list : list of str, optionaal + src_f_list : list of str, optional List of paths to slide to be warped. If None (the default), Valis.original_img_list will be used. Otherwise, the paths to which `src_f_list` points to should be an alternative copy of the slides, such as ones that have undergone @@ -5247,7 +5246,7 @@ def warp_and_merge_slides(self, dst_f=None, level=0, non_rigid=True, List of RGB colors (0-255) to use for channel colors drop_duplicates : bool, optional - Whether or not to drop duplicate channels that might be found in multiple slides. + Whether to drop duplicate channels that might be found in multiple slides. For example, if DAPI is in multiple slides, then the only the DAPI channel in the first slide will be kept. @@ -5259,13 +5258,13 @@ def warp_and_merge_slides(self, dst_f=None, level=0, non_rigid=True, compression : str Compression method used to save ome.tiff . Default is lzw, but can also - be jpeg or jp2k. See pyips for more details. + be jpeg or jp2k. See pyvips for more details. Q : int Q factor for lossy compression pyramid : bool - Whether or not to save an image pyramid. + Whether to save an image pyramid. Returns ------- diff --git a/valis/serial_non_rigid.py b/valis/serial_non_rigid.py index de345f69..89cbf881 100644 --- a/valis/serial_non_rigid.py +++ b/valis/serial_non_rigid.py @@ -171,7 +171,7 @@ def get_imgs_from_dict(img_dict): "name_list" : list of image names. If not provided, will come from file names "mask_list" list of masks for each image - All of the above are optional, except `img_list`. + All the above are optional, except `img_list`. Returns ------- @@ -224,7 +224,7 @@ class NonRigidZImage(object): ---------- image : ndarray - Original, unwarped image with shape (P, Q) + Original, un-warped image with shape (P, Q) name : str Name of image. @@ -262,7 +262,7 @@ def __init__(self, reg_obj, image, name, stack_idx, moving_xy=None, fixed_xy=Non ---------- image : ndarray - Original, unwarped image with shape (P, Q) + Original, un-warped image with shape (P, Q) name : str Name of image. @@ -375,16 +375,16 @@ def calc_deformation(self, registered_fixed_image, non_rigid_reg_obj, Used to warp the registered_img before finding deformation fields. params : dictionary, optional - Keyword: value dictionary of parameters to be used in reigstration. + Keyword: value dictionary of parameters to be used in registration. Passed to the non_rigid_reg_class' init() method. In the case where simple ITK will be used, params should be - a SimpleITK.ParameterMap. Note that numeric values needd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. mask : ndarray, optional 2D array with shape (P,Q) where non-zero pixel values are foreground, - and 0 is background, which is ignnored during registration. If None, + and 0 is background, which is ignored during registration. If None, then all non-zero pixels in images will be used to create the mask. """ @@ -546,13 +546,13 @@ class SerialNonRigidRegistrar(object): non_rigid_obj_dict : dict Dictionary, where each key is the name of a NonRigidZImage, and - the value is the assocatiated NonRigidZImage + the value is the associated NonRigidZImage non_rigid_reg_params: dictionary Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. mask : ndarray @@ -577,7 +577,7 @@ def __init__(self, src, reference_img_f=None, moving_to_fixed_xy=None, A SerialRigidRegistrar object that was used to optimally align a series of images. - If a string, it should indicating where the images + If a string, it should indicate where the images to be aligned are located. If src is a string, the images should be named such that they are read in the correct order, i.e. each starting with a number. @@ -603,10 +603,10 @@ def __init__(self, src, reference_img_f=None, moving_to_fixed_xy=None, #. Rigid registered xy in moving/current/from image #. Rigid registered xy in fixed/next/to image - To deterime which pairs of images will be aligned, use + To determine which pairs of images will be aligned, use `get_alignment_indices`. Can use `get_imgs_from_dir` - to see the order inwhich the images will be read, which will correspond - to the indices retuned by `get_alignment_indices`. + to see the order in which the images will be read, which will correspond + to the indices returned by `get_alignment_indices`. If `src` is a SerialRigidRegistrar and `moving_to_fixed_xy` is True, then the matching features in the SerialRigidRegistrar will @@ -852,7 +852,7 @@ def register_serial(self, non_rigid_reg_obj, non_rigid_reg_params=None, img_para Dictionary containing parameters {name: value} to be used to initialize `non_rigid_reg_class`. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. """ @@ -903,7 +903,7 @@ def register_to_ref(self, non_rigid_reg_obj, non_rigid_reg_params=None, img_para Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. """ @@ -938,7 +938,7 @@ def register_groupwise(self, non_rigid_reg_class, non_rigid_reg_params=None): Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. """ @@ -960,7 +960,7 @@ def register(self, non_rigid_reg_class, non_rigid_reg_params, img_params=None): Images will be registered serially if `non_rigid_reg_class` is a subclass of NonRigidRegistrarGroupwise, then groupwise registration - will be conductedd. If `non_rigid_reg_class` is a subclass of + will be conducted. If `non_rigid_reg_class` is a subclass of NonRigidRegistrar then images will be aligned serially. Parameters @@ -973,7 +973,7 @@ def register(self, non_rigid_reg_class, non_rigid_reg_params, img_params=None): Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. img_params : dict, optional Dictionary of parameters to be used for each particular image. @@ -1013,7 +1013,7 @@ def summarize(self): Returns ------- summary_df: Dataframe - Pandas dataframe containin the registration error of the + Pandas dataframe containing the registration error of the alignment between each image and the previous one in the stack. """ @@ -1101,11 +1101,11 @@ def register_images(src, non_rigid_reg_class=non_rigid_registrars.OpticalFlowWar Dictionary containing parameters {name: value} to be used to initialize the NonRigidRegistrar. In the case where simple ITK is used by the, params should be - a SimpleITK.ParameterMap. Note that numeric values nedd to be + a SimpleITK.ParameterMap. Note that numeric values need to be converted to strings. dst_dir : str, optional - Top directory where aliged images should be save. SerialNonRigidRegistrar will + Top directory where aligned images should be save. SerialNonRigidRegistrar will be in this folder, and aligned images in the "registered_images" sub-directory. If None, the images will not be written to file @@ -1122,10 +1122,10 @@ def register_images(src, non_rigid_reg_class=non_rigid_registrars.OpticalFlowWar #. Rigid registered xy in moving/current/from image #. Rigid registered xy in fixed/next/to image - To deterime which pairs of images will be aligned, use + To determine which pairs of images will be aligned, use `warp_tools.get_alignment_indices`. Can use `get_imgs_from_dir` - to see the order inwhich the images will be read, which will correspond - to the indices retuned by `warp_tools.get_alignment_indices`. + to see the order in which the images will be read, which will correspond + to the indices returned by `warp_tools.get_alignment_indices`. If `src` is a SerialRigidRegistrar and `moving_to_fixed_xy` is True, then the matching features in the SerialRigidRegistrar will @@ -1145,7 +1145,7 @@ def register_images(src, non_rigid_reg_class=non_rigid_registrars.OpticalFlowWar Optional name for this SerialNonRigidRegistrar align_to_reference : bool, optional - Whether or not images should be aligne to a reference image + Whether or not images should be aligned to a reference image specified by `reference_img_f`. Will be set to True if `reference_img_f` is provided. @@ -1161,7 +1161,7 @@ def register_images(src, non_rigid_reg_class=non_rigid_registrars.OpticalFlowWar Returns ------- nr_reg : SerialNonRigidRegistrar - SerialNonRigidRegistrar that has registeredt the images in `src` + SerialNonRigidRegistrar that has registered the images in `src` """ tic = time() diff --git a/valis/serial_rigid.py b/valis/serial_rigid.py index 3ecd4f2d..37ff989b 100644 --- a/valis/serial_rigid.py +++ b/valis/serial_rigid.py @@ -54,7 +54,7 @@ def get_image_files(img_dir, imgs_ordered=False): img_dir : str Path to directory containing the images. - imgs_ordered: bool, optinal + imgs_ordered: bool, optional Whether or not the order of images already known. If True, the file names should start with ascending numbers, with the first image file having the smallest number, and the last image file having the largest @@ -106,8 +106,8 @@ def order_Dmat(D): Leaf sorting is accomplished using optimal leaf ordering (Bar-Joseph 2001) - Parmaters - --------- + Parameters + ---------- D: ndarray (N, N) Symmetric distance matrix for N samples @@ -158,7 +158,7 @@ class ZImage(object): Name of the image. Usually `img_f` but with the extension removed. desc : ndarray - (N, M) array of N desciptors for each keypoint, each of which has + (N, M) array of N descriptors for each keypoint, each of which has M features kp_pos_xy : ndarray @@ -173,7 +173,7 @@ class ZImage(object): unfiltered_match_dict : dict Dictionary of image matches. Key= img_obj this ZImage is being - compared to, value= MatchInfo containing inoformation about the + compared to, value= MatchInfo containing information about the comparison, such as the position of matches, features for each match, number of matches, etc... The MatchInfo objects in this dictionary contain info for all matches that were cross-checked. @@ -273,7 +273,7 @@ def __init__(self, image, img_f, img_id, name): def reduce(self, prev_img_obj, next_img_obj): """Reduce amount of info stored, which can take up a lot of space. - No longer need all descriptors. Only keep match info for neighgbors + No longer need all descriptors. Only keep match info for neighbors Parameters ---------- @@ -307,7 +307,7 @@ class SerialRigidRegistrar(object): Registration is conducted by first detecting features in all images. Features are then matched between images, which are then used to construct a distance matrix, D. D is then sorted such that the most similar images - are adjcent to one another. The rigid transformation matrics are then found to + are adjacent to one another. The rigid transformation metrics are then found to align each image with the previous image. Optionally, optimization can be performed to improve the alignments, although the "optimized" matrix will be discarded if it increases the distances between matched features. @@ -326,7 +326,7 @@ class SerialRigidRegistrar(object): contains methods for this, but the user may want/need to use other methods. - aleady_sorted: bool, optional + already_sorted: bool, optional Whether or not the order of images already known. If True, the file names should start with ascending numbers, with the first image file having the smallest number, and the last image file having the largest @@ -349,7 +349,7 @@ class SerialRigidRegistrar(object): distance_metric_type : str Name of the type of metric used to determine the dis/similarity between each pair of images. Despite the name, it could be "similarity" - if the Matcher object compares image feautres using a similarity + if the Matcher object compares image features using a similarity metric. In that case, similarities are converted to distances. img_obj_list : list @@ -365,12 +365,12 @@ class SerialRigidRegistrar(object): unsorted_distance_mat : ndarray Distance matrix with shape (N, N), where each element is the - disimilariy betweewn each pair of the N images. The order of + dissimilarity between each pair of the N images. The order of rows and columns reflects the order in which the images were read. This matrix is used to order the images the Z-stack. distance_mat : ndarray - `unsorted_distance_mat` reorderd such that the most similar images + `unsorted_distance_mat` reordered such that the most similar images are adjacent to one another unsorted_similarity_mat : ndarray @@ -394,7 +394,7 @@ class SerialRigidRegistrar(object): the `img_obj_list` has been sorted. align_to_reference : bool, optional - Whether or not images should be aligne to a reference image + Whether or not images should be aligned to a reference image specified by `reference_img_f`. Will be set to True if `reference_img_f` is provided. @@ -405,7 +405,7 @@ class SerialRigidRegistrar(object): image. summary_df : Dataframe - Pandas dataframe containin the registration error of the + Pandas dataframe containing the registration error of the alignment between each image and the previous one in the stack. """ @@ -439,13 +439,13 @@ def __init__(self, img_dir, imgs_ordered=False, reference_img_f=None, Descriptive name of registrar, such as the sample's name align_to_reference : bool, optional - Whether or not images should be aligne to a reference image + Whether or not images should be aligned to a reference image specified by `reference_img_f`. Will be set to True if `reference_img_f` is provided. """ self.img_dir = img_dir - self.aleady_sorted = imgs_ordered + self.already_sorted = imgs_ordered self.name = name self.img_file_list = get_image_files(img_dir, imgs_ordered=imgs_ordered) self.size = len(self.img_file_list) @@ -473,7 +473,7 @@ def __init__(self, img_dir, imgs_ordered=False, reference_img_f=None, msg = (f"The reference was specified as {og_ref_name} ", f"but `align_to_reference` is `False`, and so images will be aligned serially *towards* the reference image. ", f"If you would like all images to be *directly* aligned to {og_ref_name}, " - f"then set `align_to_reference` to `True`. Note that in both cases, {og_ref_name} will remain unwarped.") + f"then set `align_to_reference` to `True`. Note that in both cases, {og_ref_name} will remain un-warped.") valtils.print_warning(msg) def generate_img_obj_list(self, feature_detector, valis_obj=None, qt_emitter=None): @@ -627,8 +627,8 @@ def get_common_desc(self, current_img_obj, neighbor_obj, nf_kp_idx): Parameters ---------- nf_kp_idx : ndarray - Indicies of already matched keypoints that were found after - neighbonr filtering + Indices of already matched keypoints that were found after + neighbor filtering """ neighbor_match_info12 = current_img_obj.match_dict[neighbor_obj] @@ -691,12 +691,12 @@ def neighbor_match_filtering(self, img_obj, prev_img_obj, next_img_obj, tform, w updated_prev_match_info12 : MatchInfo If improved is True, then `updated_prev_match_info12` includes only features, descriptors that were found in both neighbors. Otherwise, - all of the original features will be maintained + all the original features will be maintained updated_next_match_info12 : MatchInfo If improved is True, then `updated_next_match_info12` includes only features, descriptors that were found in both neighbors. Otherwise, - all of the original features will be maintained + all the original features will be maintained """ @@ -1046,10 +1046,10 @@ def build_metric_matrix(self, metric="n_matches"): Parameters ---------- metric: str - Name of metrric to use. If 'distance' that the distances and - similiarities calculated during feature matching will be used. + Name of metric to use. If 'distance' that the distances and + similarities calculated during feature matching will be used. If 'n_matches', then the number of matches will be used for - similariy, and 1/n_matches for distance. + similarity, and 1/n_matches for distance. """ @@ -1078,7 +1078,7 @@ def build_metric_matrix(self, metric="n_matches"): min_d = distance_mat.min() max_d = distance_mat.max() - # Make sure that image has highest similarity with itself + # Make sure that image has the highest similarity with itself similarity_mat[np.diag_indices_from(similarity_mat)] += max_s*0.01 # Scale metrics between 0 and 1 @@ -1245,7 +1245,7 @@ def align_to_prev_check_reflections(self, transformer, matcher_obj, valis_obj=No ref_x, ref_y = best_reflect_M[[0, 1], [0, 1]] < 0 if ref_x or ref_y: - msg = f'detected relfections between {img_obj.name} and {prev_img_obj.name} along the' + msg = f'detected reflections between {img_obj.name} and {prev_img_obj.name} along the' if ref_x and ref_y: msg = f'{msg} x and y axes' elif ref_x: @@ -1323,7 +1323,7 @@ def optimize(self, affine_optimizer, qt_emitter=None): Parameters ----------- - affine_optimizer : AffineOptimzer + affine_optimizer : AffineOptimizer Object that will minimize a cost function to find the optimal affine transformations @@ -1588,7 +1588,7 @@ def summarize(self): Returns ------- summary_df: Dataframe - Pandas dataframe containin the registration error of the + Pandas dataframe containing the registration error of the alignment between each image and the previous one in the stack. """ @@ -1677,7 +1677,7 @@ def register_images(img_dir, dst_dir=None, name="registrar", to be registered. These images need to be single channel, uint8 images dst_dir : str, optional - Top directory where aliged images should be save. SerialRigidRegistrar will + Top directory where aligned images should be save. SerialRigidRegistrar will be in this folder, and aligned images in the "registered_images" sub-directory. If None, the images will not be written to file @@ -1694,25 +1694,25 @@ def register_images(img_dir, dst_dir=None, name="registrar", Transformer used to find transformation matrix that will warp each image to the target image. - affine_optimizer : AffineOptimzer object + affine_optimizer : AffineOptimizer object Object that will minimize a cost function to find the - optimal affine transoformations + optimal affine transformations imgs_ordered : bool Boolean defining whether or not the order of images in img_dir are already in the correct order. If True, then each filename should begin with the number that indicates its position in the z-stack. If False, then the images will be sorted by ordering a feature distance - matix. + matrix. reference_img_f : str, optional Filename of image that will be treated as the center of the stack. If None, the index of the middle image will be the reference. check_for_reflections : bool, optional - Determine if alignments are improved by relfecting/mirroring/flipping + Determine if alignments are improved by reflecting/mirroring/flipping images. Optional because it requires re-detecting features in each version - of the images and then re-matching features, and so can be time consuming and + of the images and then re-matching features, and so can be time-consuming and not always necessary. similarity_metric : str @@ -1733,10 +1733,10 @@ def register_images(img_dir, dst_dir=None, name="registrar", Returns ------- registrar : SerialRigidRegistrar - SerialRigidRegistrar object contains general information about the alginments, + SerialRigidRegistrar object contains general information about the alignments, but also a list of Z-images. Each ZImage contains the warp information for an image in the stack, including the transformation matrices - calculated at each step, keypoint poisions, image descriptors, and + calculated at each step, keypoint positions, image descriptors, and matches with other images. See attributes from Zimage for more information. @@ -1792,7 +1792,7 @@ def register_images(img_dir, dst_dir=None, name="registrar", img_obj.desc = img_obj.desc[features_in_mask_idx, :] # print("\n======== Matching images\n") - if registrar.aleady_sorted: + if registrar.already_sorted: registrar.match_sorted_imgs(matcher_for_sorting, keep_unfiltered=False, valis_obj=valis_obj, qt_emitter=qt_emitter) diff --git a/valis/slide_io.py b/valis/slide_io.py index a2df2abd..7bafe5d1 100644 --- a/valis/slide_io.py +++ b/valis/slide_io.py @@ -68,7 +68,7 @@ """str: Physical unit when the unit can't be found in the metadata""" MICRON_UNIT = u'\u00B5m' -"""str: Phyiscal unit for micron/micrometers""" +"""str: Physical unit for micron/micrometers""" ALL_OPENSLIDE_READABLE_FORMATS = [".svs", ".tif", ".vms", ".vmu", ".ndpi", ".scn", ".mrxs", ".tiff", ".svslide", ".bif"] """list: File extensions that OpenSlide can read""" @@ -122,21 +122,21 @@ def read_bf_formats(): Created after initializing JVM.""" BF_MICROMETER = None -"""Bioformats Unit mircometer object. +"""Bioformats Unit micrometer object. Created after initializing JVM.""" ome = None -"""Bioformats ome from bioforamts_jar. +"""Bioformats ome from bioformats_jar. Created after initializing JVM.""" loci = None -"""Bioformats loci from bioforamts_jar. +"""Bioformats loci from bioformats_jar. Created after initializing JVM.""" OME_TYPES_PARSER = "lxml" """ -NOTE: Commented out block is how to use boformats with javabrdige. +NOTE: Commented out block is how to use bioformats with javabrdige. However, on conda, javabridge isn't available for python 3.9. If using, remember to put bftools/bioformats_package.jar in the source directory. @@ -432,7 +432,7 @@ def bf2vips_dtype(bf_dtype): return vips_format -def check_czi_jpegxr(src_f): +def check_czi_jpgxr(src_f): f_extension = slide_tools.get_slide_extension(src_f) if f_extension != ".czi": return False @@ -482,8 +482,8 @@ def check_to_use_openslide(src_f): def get_ome_obj(x): """Get ome_types.model.ome.OME object - Paramters - --------- + Parameters + ---------- x: str Either OME-XML or path to ome.tiff @@ -597,7 +597,7 @@ def check_flattened_pyramid_tiff(src_f, check_with_bf=False): Returns ------- - is_flattended_pyramid : bool + is_flattened_pyramid : bool Whether or not the slide is a flattened pyramid can_use_bf : bool @@ -618,7 +618,7 @@ def check_flattened_pyramid_tiff(src_f, check_with_bf=False): vips_img = pyvips.Image.new_from_file(src_f) vips_fields = vips_img.get_fields() - is_flattended_pyramid = False + is_flattened_pyramid = False can_use_bf = False if 'n-pages' in vips_fields: @@ -661,9 +661,9 @@ def check_flattened_pyramid_tiff(src_f, check_with_bf=False): unique_areas, _ = np.unique(all_areas, return_index=True) n_zero_diff = len(np.where(area_diff == 0)[0]) if most_common_channel_count == 1 and n_zero_diff >= len(unique_areas): - is_flattended_pyramid = True + is_flattened_pyramid = True - if is_flattended_pyramid: + if is_flattened_pyramid: nchannels_per_each_level = np.diff(level_starts) last_level_channel_count = np.sum(all_n_channels[level_starts[-1]:]) nchannels_per_each_level = np.hstack([nchannels_per_each_level, @@ -682,7 +682,7 @@ def check_flattened_pyramid_tiff(src_f, check_with_bf=False): n_channels = most_common_channel_count else: - return is_flattended_pyramid, can_use_bf, None, None, None + return is_flattened_pyramid, can_use_bf, None, None, None # Now check if Bioformats reads it similarly # if check_with_bf: with valtils.HiddenPrints(): @@ -691,7 +691,7 @@ def check_flattened_pyramid_tiff(src_f, check_with_bf=False): bf_channels = bf_reader.metadata.n_channels can_use_bf = bf_levels >= len(slide_dimensions) and bf_channels == n_channels - return is_flattended_pyramid, can_use_bf, slide_dimensions, levels_start_idx, n_channels + return is_flattened_pyramid, can_use_bf, slide_dimensions, levels_start_idx, n_channels def check_xml_img_match(xml, vips_img, metadata, series=0): @@ -822,7 +822,7 @@ def metadata_from_xml(xml, name, server, series=0, metadata=None): def openslide_desc_2_omexml(vips_img): - """Get basic metatad using openslide and convert to ome-xml + """Get basic metadata using openslide and convert to ome-xml """ assert "openslide.vendor" in vips_img.get_fields(), "image does not appear to be openslide metadata" @@ -982,7 +982,7 @@ def slide2vips(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1003,7 +1003,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1187,7 +1187,7 @@ def __init__(self, src_f, series=None, *args, **kwargs): Path to slide series : int - The series to be read. If `series` is None, the the `series` + The series to be read. If `series` is None, the `series` will be set to the series associated with the largest image. """ @@ -1210,7 +1210,7 @@ def __init__(self, src_f, series=None, *args, **kwargs): series = np.argmax(img_areas) if len(img_areas) > 1: msg = (f"No series provided. " - f"Selecting series with largest image, " + f"Selecting series with the largest image, " f"which is series {series}") valtils.print_warning(msg, warning_type=None, rgb=valtils.Fore.GREEN) @@ -1275,12 +1275,12 @@ def slide2vips(self, level, series=None, xywh=None, tile_wh=None, z=0, t=0, *arg xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. tile_wh : int, optional - Size of tiles used to contstruct `vips_slide` + Size of tiles used to construct `vips_slide` Returns ------- @@ -1340,7 +1340,7 @@ def slide2image(self, level, series=None, xywh=None, z=0, t=0, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1537,7 +1537,7 @@ def _get_slide_dimensions(self, rdr): Notes ----- - Using javabridge and python-bioformmats, this can be accessed as follows + Using javabridge and python-bioformats, this can be accessed as follows ` bf_slide = bioformats.ImageReader(slide_f) bf_img_reader = javabridge.JWrapper(bf_slide.rdr.o) @@ -1747,7 +1747,7 @@ def _slide2vips_ome_one_series(self, level, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1785,7 +1785,7 @@ def slide2vips(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1836,7 +1836,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -1905,7 +1905,7 @@ def _get_channel_names(self, vips_img, *args, **kwargs): Returns ------- channel_names : list - List of channel naames. + List of channel names. """ @@ -2123,11 +2123,11 @@ def __init__(self, src_f, *args, **kwargs): def create_metadata(self): - is_flattended_pyramid, bf_reads_flat, slide_dimensions,\ + is_flattened_pyramid, bf_reads_flat, slide_dimensions,\ levels_start_idx, n_channels = \ check_flattened_pyramid_tiff(self.src_f) - assert is_flattended_pyramid and not bf_reads_flat, "Trying to use FlattenedPyramidReader but slide is not a flattened pyramid" + assert is_flattened_pyramid and not bf_reads_flat, "Trying to use FlattenedPyramidReader but slide is not a flattened pyramid" meta_name = f"{os.path.split(self.src_f)[1]}_Series(0)".strip("_") server = VIPS_RDR @@ -2175,7 +2175,7 @@ def slide2vips(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -2237,7 +2237,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): except pyvips.error.Error as e: # Big hack for when get the error "tiff2vips: out of order read" even with random access out_shape_wh = self.metadata.slide_dimensions[level] - msg1 = f"pyvips.error.Error: {e} when converting pvips.Image to numpy array" + msg1 = f"pyvips.error.Error: {e} when converting pyvips.Image to numpy array" msg2 = f"Will try to resize level 0 to have shape {out_shape_wh} and convert" valtils.print_warning(msg1) valtils.print_warning(msg2, None) @@ -2264,7 +2264,7 @@ def _get_channel_names(self, vips_img, *args, **kwargs): Returns ------- channel_names : list - List of channel naames. + List of channel names. """ @@ -2325,9 +2325,9 @@ def _get_dtype(self): """Get Bio-Formats datatype from values in metadata. For example, BF metadata may have image datatype as - uint32, but in the image descriiption, min/max/resppnse, + uint32, but in the image description, min/max/response, are floats. This will determine if the slide should be cast - to a different dataatype to match values in metadata. + to a different datatype to match values in metadata. """ smallest_level = len(self.metadata.slide_dimensions) - 1 @@ -2414,7 +2414,7 @@ def __init__(self, src_f, series=None, *args, **kwargs): Path to slide series : int - The series to be read. If `series` is None, the the `series` + The series to be read. If `series` is None, the `series` will be set to the series associated with the largest image. """ @@ -2445,7 +2445,7 @@ def __init__(self, src_f, series=None, *args, **kwargs): series = np.argmax(img_areas) if len(img_areas) > 1: msg = (f"No series provided. " - f"Selecting series with largest image, " + f"Selecting series with the largest image, " f"which is series {series}") valtils.print_warning(msg, warning_type=None, rgb=valtils.Fore.GREEN) @@ -2465,7 +2465,7 @@ def _get_series(self): doc="Slide scene") def _read_whole_img(self, level=0, xywh=None, *args, **kwargs): - """ + """Read whole image Return ------ @@ -2553,7 +2553,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): xywh : tuple of int, optional The region to be sliced from the slide. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -2573,7 +2573,7 @@ def slide2image(self, level, xywh=None, *args, **kwargs): return np_img def create_metadata(self): - """ Create and fill in a MetaData object + """Create and fill in a MetaData object Returns ------- @@ -2731,8 +2731,8 @@ def _get_slide_dimensions(self, scene=0, *args, **kwargs): czi_reader = CziFile(self.src_f) scene_bbox = czi_reader.get_all_scene_bounding_boxes()[scene] - scence_l0_wh = np.array([scene_bbox.w, scene_bbox.h]) - slide_dimensions = np.round(scence_l0_wh*zoom_levels[..., np.newaxis]).astype(int) + scene_l0_wh = np.array([scene_bbox.w, scene_bbox.h]) + slide_dimensions = np.round(scene_l0_wh*zoom_levels[..., np.newaxis]).astype(int) return slide_dimensions @@ -2844,7 +2844,7 @@ def slide2image(self, xywh=None, *args, **kwargs): return img def _get_slide_dimensions(self, pil_img, *args, **kwargs): - """ + """Get slide dimensions """ img_dims = np.array([[pil_img.width, pil_img.height]]) @@ -2883,7 +2883,7 @@ def get_slide_reader(src_f, series=None): Path to slide series : int, optional - The series to be read. If `series` is None, the the `series` + The series to be read. If `series` is None, the `series` will be set to the series associated with the largest image. In cases where there is only 1 image in the file, `series` will be 0. @@ -2891,7 +2891,7 @@ def get_slide_reader(src_f, series=None): Returns ------- reader: SlideReader - SlideReader class that can read the slide and and convert them to + SlideReader class that can read the slide and convert them to images or pyvips.Images at the specified level and series. They also contain a `MetaData` object that contains information about the slide, like dimensions at each level, physical units, etc... @@ -2932,7 +2932,7 @@ def get_slide_reader(src_f, series=None): return VipsSlideReader if is_czi: - is_jpegxr = check_czi_jpegxr(src_f) + is_jpegxr = check_czi_jpgxr(src_f) is_m1_mac = valtils.check_m1_mac() if is_m1_mac and is_jpegxr: msg = "Will likely be errors using Bioformats to read a JPEGXR compressed CZI on this Apple M1 machine. Will use CziJpgxrReader instead." @@ -3020,7 +3020,7 @@ def get_shape_xyzct(shape_wh, n_channels, nt=1, nz=1): Parameters ---------- shape_wh : tuple of int - Width and heigth of image + Width and height of image n_channels : int Number of channels in the image @@ -3044,7 +3044,7 @@ def create_channel(channel_id, name=None, color=None, samples_per_pixel=1): channel_id : int Channel number - name : str, optinal + name : str, optional Channel name color : tuple of int @@ -3198,7 +3198,7 @@ def check_channel_names(channel_names, is_rgb, nc, src_f=None): def create_ome_xml(shape_xyzct, bf_dtype, is_rgb, pixel_physical_size_xyu=None, channel_names=None, colormap=CMAP_AUTO): - """Create new ome-xmml object + """Create new ome-xml object Parameters ------- @@ -3312,7 +3312,7 @@ def get_tile_wh(reader, level, out_shape_wh, default_wh=512): tile_wh = 16 if np.any(np.array(out_shape_wh[0:2]) < tile_wh): - # Tile is too big for the image. Get niggest tile size that fit in image + # Tile is too big for the image. Get the biggest tile size that fits in the image. if tile_wh < default_wh: min_wh = 16 else: @@ -3333,13 +3333,13 @@ def get_tile_wh(reader, level, out_shape_wh, default_wh=512): def update_xml_for_new_img(img, reader, level=0, channel_names=None, colormap=CMAP_AUTO, pixel_physical_size_xyu=None): """Update dimensions ome-xml metadata - Used to create a new ome-xmlthat reflects changes in an image, such as its shape + Used to create a new ome-xml that reflects changes in an image, such as its shape If `current_ome_xml_str` is invalid or None, a new ome-xml will be created Parameters ------- - img : ndarry or pyvips.Image + img : np.ndarray or pyvips.Image Image for which xml will be generated. Used to determine shape and datatype. reader : SlideReader @@ -3461,7 +3461,7 @@ def warp_and_save_slide(src_f, dst_f, transformation_src_shape_rc, transformatio which can be done using `warp_tools.get_inverse_field` level : int, optional - Pyramid level to warp an save + Pyramid level to warp and save series : int, optional Series number of image @@ -3492,7 +3492,7 @@ def warp_and_save_slide(src_f, dst_f, transformation_src_shape_rc, transformatio Q factor for lossy compression pyramid : bool - Whether or not to save an image pyramid. + Whether to save an image pyramid. reader: SlideReader, optional Instantiated SlideReader to use to read image. If `None`, @@ -3551,13 +3551,13 @@ def save_ome_tiff(img, dst_f, ome_xml=None, tile_wh=512, compression=DEFAULT_COM is both the width and height. compression : str - Compression method used to save ome.tiff . See pyips for more details. + Compression method used to save ome.tiff . See pyvips for more details. Q : int Q factor for lossy compression pyramid : bool - Whether or not to save an image pyramid. + Whether to save an image pyramid. """ compression = compression.lower() @@ -3724,7 +3724,7 @@ def convert_to_ome_tiff(src_f, dst_f, level, series=None, xywh=None, xywh : tuple of int, optional The region of the slide to be converted. If None, - then the entire slide will be converted. Otherwise + then the entire slide will be converted. Otherwise, xywh is the (top left x, top left y, width, height) of the region to be sliced. @@ -3738,13 +3738,13 @@ def convert_to_ome_tiff(src_f, dst_f, level, series=None, xywh=None, so `tile_wh` is both the width and height. compression : str - Compression method used to save ome.tiff. See pyips for more details. + Compression method used to save ome.tiff. See pyvips for more details. Q : int Q factor for lossy compression pyramid : bool - Whether or not to save an image pyramid. + Whether to save an image pyramid. """ diff --git a/valis/superglue_models/superpoint.py b/valis/superglue_models/superpoint.py index 7d22443d..7cf1c95c 100644 --- a/valis/superglue_models/superpoint.py +++ b/valis/superglue_models/superpoint.py @@ -184,7 +184,7 @@ def forward(self, data): remove_borders(k, s, self.config['remove_borders'], h*8, w*8) for k, s in zip(keypoints, scores)])) - # Keep the k keypoints with highest score + # Keep the k keypoints with the highest score if self.config['max_keypoints'] >= 0: keypoints, scores = list(zip(*[ top_k_keypoints(k, s, self.config['max_keypoints']) diff --git a/valis/viz.py b/valis/viz.py index 1c193ed3..01028803 100644 --- a/valis/viz.py +++ b/valis/viz.py @@ -710,21 +710,21 @@ def color_multichannel(multichannel_img, marker_colors, rescale_channels=False, in areas where they are expressed in isolation, but can also make it appear more marker is expressed than there really is. - normalize_by : str, optionaal + normalize_by : str, optional "image" will produce an image where all values are scaled between 0 and the highest intensity in the composite image. This will produce an image where one can see the expression of each marker relative to the others, making it easier to compare marker expression levels. "channel" will first scale the intensity of each channel, and then - blend all of the channels together. This will allow one to see the + blend all the channels together. This will allow one to see the relative expression of each marker, but won't allow one to directly compare the expression of markers across channels. cspace : str Colorspace in which `marker_colors` will be blended. JzAzBz, Hunter Lab, and sRGB all work well. But, see - colour.COLOURSPACE_MODELS for other possible colorspaces + colour.COLOURSPACE_MODELS for other possible colorspace Returns ------- diff --git a/valis/warp_tools.py b/valis/warp_tools.py index a5038707..0eb7f434 100644 --- a/valis/warp_tools.py +++ b/valis/warp_tools.py @@ -29,8 +29,8 @@ def is_pyvips_22(): - pvips_ver = pyvips.__version__.split(".") - pyvips_22 = eval(pvips_ver[0]) >= 2 and eval(pvips_ver[1]) >= 2 + pyvips_ver = pyvips.__version__.split(".") + pyvips_22 = eval(pyvips_ver[0]) >= 2 and eval(pyvips_ver[1]) >= 2 return pyvips_22 def get_ref_img_idx(img_f_list, ref_img_name=None): @@ -326,7 +326,7 @@ def save_img(dst_f, img, thumbnail_size=None): Filename for saved image img : ndarray, pyvips.Image - Image to be saved. Numpy arrays will be converted to pvips.Image + Image to be saved. Numpy arrays will be converted to pyvips.Image thumbnail_size : optional, int If not None, the image will be resized to fit within this size @@ -660,14 +660,14 @@ def mattes_mi(img1, img2, nbins=50, mask=None): Number of histogram bins mask : ndarray, None - Mask with shape (N, M) that indiates where the metric - should be calulated. If None, the metric will be calculated + Mask with shape (N, M) that indicates where the metric + should be calculated. If None, the metric will be calculated for all NxM pixels. Returns ------- mmi : float - Mattes mutation inormation + Mattes mutation information """ @@ -1206,7 +1206,7 @@ def warp_img(img, M=None, bk_dxdy=None, out_shape_rc=None, warp_index = (index[0] + warp_dxdy[0]).bandjoin(index[1] + warp_dxdy[1]) try: - #Option to set backround color in mapim added in libvips 8.13 + #Option to set background color in mapim added in libvips 8.13 warped = affine_warped.mapim(warp_index, premultiplied=True, background=bg_color, @@ -1336,7 +1336,7 @@ def warp_img_inv(img, M=None, fwd_dxdy=None, transformation_src_shape_rc=None, t warp_index = (index[0] + warp_dxdy[0]).bandjoin(index[1] + warp_dxdy[1]) try: - # Option to set backround color in mapim added in libvips 8.13 + # Option to set background color in mapim added in libvips 8.13 nr_warped = img.mapim(warp_index, premultiplied=True, background=bg_color, @@ -1418,7 +1418,7 @@ def warp_img_from_to(img, from_M=None, from_transformation_src_shape_rc=None, this shape should be the same for both images. from_src_shape_rc : optional, (int, int) - Shape of the unwarped image from which the points originated. For example, + Shape of the un-warped image from which the points originated. For example, this could be a larger/smaller version of the "from" image that was used for feature detection. @@ -1440,7 +1440,7 @@ def warp_img_from_to(img, from_M=None, from_transformation_src_shape_rc=None, For example, this could be the original image in which features were detected to_src_shape_rc : optional, (int, int) - Shape of the unwarped "to" image to which the points will be warped. For example, + Shape of the un-warped "to" image to which the points will be warped. For example, this could be a larger/smaller version of the "to" image that was used for feature detection. @@ -1458,7 +1458,7 @@ def warp_img_from_to(img, from_M=None, from_transformation_src_shape_rc=None, Returns ------- - in_target_space : ndarray, pvips.Image + in_target_space : ndarray, pyvips.Image `img` warped onto the "to" image """ @@ -1537,7 +1537,7 @@ def get_warp_map(M=None, dxdy=None, transformation_dst_shape_rc=None, Returns ------- - coord_map : ndarry + coord_map : np.ndarray A 2band numpy array that has location of each pixel in `src_shape_rc` the warped image (with shape `dst_shape_rc`) @@ -1629,10 +1629,10 @@ def get_reflection_M(reflect_x, reflect_y, shape_rc): ---------- reflect_x : bool - Whether or not to reflect the x-axis (columns) + Whether to reflect the x-axis (columns) reflecct y : bool - Whether or not to reflect the y-axis (rows) + Whether to reflect the y-axis (rows) shape_rc : tuple of int Shape of the image being reflected @@ -1828,7 +1828,7 @@ def get_mesh(shape, grid_spacing, bbox_rc_wh=None, inclusive=False): (row, column, width, height) of bounding box inclusive : bool - Whether or not to include image edges + Whether to include image edges """ @@ -2457,8 +2457,8 @@ def warp_xy_from_to(xy, from_M=None, from_transformation_src_shape_rc=None, to_dst_shape_rc=None, to_bk_dxdy=None, to_fwd_dxdy=None): """Warp points in one image to their position in another unregistered image - Takes a set of points found in the unwarped "from" image, and warps them to their - position in the unwarped "to" image. + Takes a set of points found in the un-warped "from" image, and warps them to their + position in the un-warped "to" image. Parameters ---------- @@ -2478,7 +2478,7 @@ def warp_xy_from_to(xy, from_M=None, from_transformation_src_shape_rc=None, this shape should be the same for both images. from_src_shape_rc : optional, (int, int) - Shape of the unwarped image from which the points originated. For example, + Shape of the un-warped image from which the points originated. For example, this could be a larger/smaller version of the "from" image that was used for feature detection. @@ -2500,7 +2500,7 @@ def warp_xy_from_to(xy, from_M=None, from_transformation_src_shape_rc=None, For example, this could be the original image in which features were detected to_src_shape_rc : optional, (int, int) - Shape of the unwarped "to" image to which the points will be warped. For example, + Shape of the un-warped "to" image to which the points will be warped. For example, this could be a larger/smaller version of the "to" image that was used for feature detection. @@ -2517,7 +2517,7 @@ def warp_xy_from_to(xy, from_M=None, from_transformation_src_shape_rc=None, Returns ------- xy_in_to : ndarray - position of `xy` in the unwarped "to" image + position of `xy` in the un-warped "to" image """ @@ -2876,7 +2876,7 @@ def get_xy_inside_mask(xy, mask): Returns ------- keep_idx : ndarray - Indices of `xy` that are inside of `mask` + Indices of `xy` that are inside `mask` """ mask_cnt, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) @@ -2936,7 +2936,7 @@ def measure_error(src_xy, dst_xy, shape, feature_similarity=None): Median relative Target Registration Error (rTRE) between images med_d : float - Median Euclidean distance between src_xy and dst_xy, optinally weighted by feature similarity + Median Euclidean distance between src_xy and dst_xy, optionally weighted by feature similarity """ d = np.sqrt((src_xy[:, 0]-dst_xy[:, 0])**2 + (src_xy[:, 1]-dst_xy[:, 1])**2)