diff --git a/NAMESPACE b/NAMESPACE index 55de5eabd..6fa2ade63 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -58,6 +58,7 @@ export(binSpect) export(binSpectMulti) export(binSpectSingle) export(binSpectSingleMatrix) +export(calculateAffineMatrixFromLandmarks) export(calculateHVF) export(calculateMetaTable) export(calculateMetaTableCells) @@ -181,6 +182,7 @@ export(doLouvainSubCluster) export(doRandomWalkCluster) export(doSNNCluster) export(doScrubletDetect) +export(estimateAutomatedImageRegistrationWithSIFT) export(estimateImageBg) export(exportGiottoViewer) export(exprCellCellcom) @@ -271,6 +273,7 @@ export(insertCrossSectionFeatPlot3D) export(insertCrossSectionSpatPlot3D) export(installGiottoEnvironment) export(instructions) +export(interactiveLandmarkSelection) export(jackstrawPlot) export(joinGiottoObjects) export(loadGiotto) @@ -291,6 +294,7 @@ export(overlapToMatrix) export(overlapToMatrixMultiPoly) export(overlaps) export(pDataDT) +export(performCellposeSegmentation) export(pieCellTypesFromEnrichment) export(plotCCcomDotplot) export(plotCCcomHeatmap) @@ -328,6 +332,7 @@ export(plotUMAP) export(plotUMAP_2D) export(plotUMAP_3D) export(polyStamp) +export(preprocessImageToMatrix) export(print.combIcfObject) export(print.icfObject) export(processGiotto) diff --git a/R/cell_segmentation.R b/R/cell_segmentation.R index 05ff56040..a411e320a 100644 --- a/R/cell_segmentation.R +++ b/R/cell_segmentation.R @@ -84,3 +84,137 @@ doCellSegmentation <- function( print(segmentation_result) } + + + + + +#' +#' @title perform cellpose segmentation +#' @description +#' +#' perform the Giotto Wrapper of cellpose segmentation. This is for a model inference to generate segmentation mask file from input image. +#' main parameters needed +#' @name performCellposeSegmentation +#' @param image_dir character, required. Provide a path to a gray scale or a three channel image. +#' @param python_path python environment with cellpose installed. default = "giotto_cellpose". +#' @param mask_output required. Provide a path to the output mask file. +#' @param channel_1 channel number for cytoplasm, default to 0(gray scale) +#' @param channel_2 channel number for Nuclei, default to 0(gray scale) +#' @param model_name Name of the model to run inference. Default to 'cyto3', if you want to run cutomized trained model, place your model file in ~/.cellpose/models and specify your model name. +#' @param batch_size Cellpose Parameter, Number of 224x224 patches to run simultaneously on the GPU. Can make smaller or bigger depending on GPU memory usage. Defaults to 8. +#' @param resample Cellpose Parameter +#' @param channel_axis Cellpose Parameter +#' @param z_axis Cellpose Parameter +#' @param normalize Cellpose Parameter +#' @param invert Cellpose Parameter +#' @param rescale Cellpose Parameter +#' @param diameter Cellpose Parameter +#' @param flow_threshold Cellpose Parameter +#' @param cellprob_threshold Cellpose Parameter +#' @param do_3D Cellpose Parameter +#' @param anisotropy Cellpose Parameter +#' @param stitch_threshold Cellpose Parameter +#' @param min_size Cellpose Parameter +#' @param niter Cellpose Parameter +#' @param augment Cellpose Parameter +#' @param tile Cellpose Parameter +#' @param tile_overlap Cellpose Parameter +#' @param bsize Cellpose Parameter +#' @param interp Cellpose Parameter +#' @param compute_masks Cellpose Parameter +#' @param progress Cellpose Parameter +#' @returns No return variable, as this will write directly to output path provided. +#' @examples +#' # example code +#' performCellposeSegmentation(image_dir = input_image, mask_output = output, channel_1 = 2, channel_2 = 1, model_name = 'cyto3',batch_size=4) +#' @export +performCellposeSegmentation <- function(python_env = 'giotto_cellpose', + image_dir, + mask_output, + channel_1 = 0, + channel_2 = 0, + model_name = 'cyto3', + batch_size=8, + resample=TRUE, + channel_axis=NULL, + z_axis=NULL, + normalize=TRUE, + invert=FALSE, + rescale=NULL, + diameter=NULL, + flow_threshold=0.4, + cellprob_threshold=0.0, + do_3D=FALSE, + anisotropy=NULL, + stitch_threshold=0.0, + min_size=15, + niter=NULL, + augment=FALSE, + tile=TRUE, + tile_overlap=0.1, + bsize=224, + interp=TRUE, + compute_masks=TRUE, + progress=NULL, + verbose = TRUE,...){ + + + #Check Input arguments + model_name <- match.arg(model_name, unique(c('cyto3', 'cyto2', 'cyto','nuclei', model_name))) + ## Load required python libraries + GiottoClass::set_giotto_python_path(python_env) + GiottoUtils::package_check('cellpose',repository = 'pip') + + cellpose <- reticulate::import("cellpose") + np <- reticulate::import("numpy") + cv2 <- reticulate::import("cv2") + torch <- reticulate::import("torch") + message('successfully loaded giotto environment with cellpose.') + + if (!(torch$cuda$is_available())){ + warning('GPU is not available for this session, inference may be slow.\n ') + } + + GiottoUtils::vmsg(.v = verbose, .is_debug = F,'Loading Image from ',image_dir) + + img <- cellpose$io$imread(image_dir) + GiottoUtils::vmsg(.v = verbose, .is_debug = F,'Loading Model...') + + model_to_seg <- cellpose$models$Cellpose(model_type=model_name,gpu = torch$cuda$is_available()) + channel_to_seg <- as.integer(c(channel_1,channel_2)) + + GiottoUtils::vmsg(.v = verbose, .is_debug = F,'Segmenting Image...') + segmentation <- model_to_seg$eval + + result <- segmentation(img, + diameter=diameter, + channels=channel_to_seg, + batch_size = batch_size, + resample=resample, + channel_axis=channel_axis, + z_axis=z_axis, + normalize=normalize, + invert=invert, + rescale=rescale, + flow_threshold=flow_threshold, + cellprob_threshold=cellprob_threshold, + do_3D=do_3D, + anisotropy=anisotropy, + stitch_threshold=stitch_threshold, + min_size=min_size, + niter=niter, + augment=augment, + tile=tile, + tile_overlap=tile_overlap, + bsize=bsize, + interp=interp, + compute_masks=compute_masks, + progress=progress) + masks <- result[[1]] + GiottoUtils::vmsg(.v = verbose, .is_debug = F,'Segmentation finished... Saving mask file...') + GiottoUtils::package_check('terra') + rast = terra::rast(masks) + terra::writeRaster(rast, mask_output,overwrite=TRUE) +} + diff --git a/R/image_registration.R b/R/image_registration.R index cdd120cdc..a98e9a280 100644 --- a/R/image_registration.R +++ b/R/image_registration.R @@ -1018,3 +1018,513 @@ registerImagesFIJI <- function( return(0 == system(cmd)) } + + +#' @title title Record landmarks by interactive selection +#' @name interactiveLandmarkSelection +#' @description Record landmarks by interactive selection +#' @param source_image the image to be plotted on the left, and landmarks will output in the first of the list. Input can be a ggplot object, a GiottoImage, or a character represent a path to a image +#' @param target_image the image to be plotted on the right, and landmarks will output in the second of the list. Input can be a ggplot object, a GiottoImage, or a character represent a path to a image +#' +#' @returns a list of landmarks +#' +#' @export +interactiveLandmarkSelection <- function(source, target) { + GiottoUtils::package_check("shiny") + GiottoUtils::package_check("ggplot2") + GiottoUtils::package_check("miniUI") + + .create_image_to_plot <- function(x){ + if (inherits(x, "gg")){ + return(x) + } + else if (is.character(x)){ + gimg = Giotto::createGiottoLargeImage(x) + gg <- ggplot2::ggplot() + gg_raster = GiottoVisuals::gg_annotation_raster(gg,gimg) + return(gg_raster) + } + else{ + gg <- ggplot2::ggplot() + gg_raster = GiottoVisuals::gg_annotation_raster(gg,x) + return(gg_raster) + } + } + source_image <- .create_image_to_plot(source) + target_image <- .create_image_to_plot(target) + + # Function to extract the range of x and y values from a ggplot object + .extract_plot_ranges <- function(plot) { + data <- ggplot2::ggplot_build(plot)$data[[1]] + x_range <- range(data$x, na.rm = TRUE) + y_range <- range(data$y, na.rm = TRUE) + list(x_range = x_range, y_range = y_range) + } + + # Extract ranges for the input plots + source_ranges <- .extract_plot_ranges(source_image) + target_ranges <- .extract_plot_ranges(target_image) + + ui <- miniUI::miniPage( + miniUI::gadgetTitleBar("Select Extents and Points"), + miniUI::miniContentPanel( + shiny::fluidRow( + shiny::column(6, shiny::plotOutput("plot1", click = "plot1_click")), + shiny::column(6, shiny::plotOutput("plot2", click = "plot2_click")) + ), + shiny::fluidRow( + shiny::column(6, + shiny::sliderInput("xrange1", "X Range for Plot 1", min = source_ranges$x_range[1], max = source_ranges$x_range[2], value = source_ranges$x_range), + shiny::sliderInput("yrange1", "Y Range for Plot 1", min = source_ranges$y_range[1], max = source_ranges$y_range[2], value = source_ranges$y_range) + ), + shiny::column(6, + shiny::sliderInput("xrange2", "X Range for Plot 2", min = target_ranges$x_range[1], max = target_ranges$x_range[2], value = target_ranges$x_range), + shiny::sliderInput("yrange2", "Y Range for Plot 2", min = target_ranges$y_range[1], max = target_ranges$y_range[2], value = target_ranges$y_range) + ) + ), + shiny::fluidRow( + shiny::column(6, shiny::verbatimTextOutput("click_info1")), + shiny::column(6, shiny::verbatimTextOutput("click_info2")) + ), + shiny::fluidRow( + shiny::column(6, shiny::actionButton("undo1", "Undo Click on Source Image")), + shiny::column(6, shiny::actionButton("undo2", "Undo Click on Target Image")) + ) + ) + ) + + server <- function(input, output, session) { + click_history1 <- shiny::reactiveVal(data.frame(x = numeric(), y = numeric())) + click_history2 <- shiny::reactiveVal(data.frame(x = numeric(), y = numeric())) + + output$plot1 <- shiny::renderPlot({ + source_image + + ggplot2::coord_cartesian(xlim = input$xrange1, ylim = input$yrange1) + + ggplot2::geom_point(data = click_history1(), ggplot2::aes(x = x, y = y), color = "red", size = 4.5) + }) + + output$plot2 <- shiny::renderPlot({ + target_image + + ggplot2::coord_cartesian(xlim = input$xrange2, ylim = input$yrange2) + + ggplot2::geom_point(data = click_history2(), ggplot2::aes(x = x, y = y), color = "blue",size = 4.5) + }) + + shiny::observeEvent(input$plot1_click, { + click <- input$plot1_click + new_coords <- rbind(click_history1(), data.frame(x = click$x, y = click$y)) + click_history1(new_coords) + }) + + shiny::observeEvent(input$plot2_click, { + click <- input$plot2_click + new_coords <- rbind(click_history2(), data.frame(x = click$x, y = click$y)) + click_history2(new_coords) + }) + + shiny::observeEvent(input$undo1, { + if (nrow(click_history1()) > 0) { + new_coords <- click_history1()[-nrow(click_history1()), , drop = FALSE] + click_history1(new_coords) + } + }) + + shiny::observeEvent(input$undo2, { + if (nrow(click_history2()) > 0) { + new_coords <- click_history2()[-nrow(click_history2()), , drop = FALSE] + click_history2(new_coords) + } + }) + + output$click_info1 <- shiny::renderPrint({ + click_history1() + }) + + output$click_info2 <- shiny::renderPrint({ + click_history2() + }) + + shiny::observeEvent(input$done, { + returnValue <- list(click_history1(),click_history2()) + shiny::stopApp(returnValue) + }) + } + + shiny::runGadget(ui, server) +} + + + + + + +#' @title Calculate a affine transformation matrix from two set of landmarks +#' @name calculateAffineMatrixFromLandmarks +#' @description calculate a affine transformation matrix from two set of landmarks +#' @param source_df source landmarks, two columns, first column represent x coordinate and second column represent y coordinate. +#' @param target_df target landmarks, two columns, first column represent x coordinate and second column represent y coordinate. +#' +#' @returns a 3 by 3 matrix with the third row close to (0,0,1) +#' +#' @export +calculateAffineMatrixFromLandmarks <- function(source_df,target_df){ + source_landmarks_matrix = as.matrix(source_df) + source_landmarks_matrix = cbind(source_landmarks_matrix,rep(1,nrow(source_landmarks_matrix))) + ## Create landmark matrix for the target image + target_landmarks_matrix <- as.matrix(target_df) + target_landmarks_matrix = cbind(target_landmarks_matrix,rep(1,nrow(target_landmarks_matrix))) + ## Compute the affine matrix + source_dp = t(source_landmarks_matrix) %*% source_landmarks_matrix + source_target_dp = t(source_landmarks_matrix) %*% target_landmarks_matrix + source_dp_inv <- solve(source_dp) + Affine_matrix = t(source_dp_inv %*% source_target_dp) + return(Affine_matrix) +} + + + + +#' @name .sift_detect +#' @title Run SIFT feature detector and descriptor extractor +#' @description +#' Perform feature detector and descriptor extractor on a matrix object or preprocessed image object +#' @param x input matrix or preprocessed image to extract feature and descriptor from +#' @param ... additional params to pass to `skimage.feature.SIFT()` +#' @returns list of keypoints and descriptors +#' +.sift_detect <- function(x, ..., pkg_ptr) { + + if (missing(pkg_ptr)) { + GiottoUtils::package_check("skimage", repository = "pip:scikit-image") + SKI <- reticulate::import("skimage", convert = TRUE, delay_load = TRUE) + } else { + SKI <- pkg_ptr + } + + # sift object + SIFT <- SKI$feature$SIFT() + + SIFT$detect_and_extract(x) + + out <- list( + keypoints = SIFT$keypoints, + descriptors = SIFT$descriptors + ) + + return(out) +} + +#' @name .match_descriptor +#' @title Match image descriptors +#' @description +#' Brute force matching of descriptors using \pkg{scikit-image}. Find matching +#' image descriptors between moving images and a target image. +#' @param descriptor_list list of descriptor matrices +#' @param target_idx which item in the list is the target image. Default is 1 +#' @param cross_check whether to check that only the best match is returned +#' @param max_ratio Maximum ratio of distances between first and second closest +#' descriptor in the second set of descriptors. This threshold is useful to +#' filter ambiguous matches between the two descriptor sets. The choice of this +#' value depends on the statistics of the chosen descriptor, e.g., for SIFT +#' descriptors a value of 0.8 is usually chosen, see D.G. Lowe, "Distinctive +#' Image Features from Scale-Invariant Keypoints", International Journal of +#' Computer Vision, 2004. +#' @param ... additional params to pass to `skimage.feature.match_descriptors()` +#' @returns list +#' +.match_descriptor <- function( + descriptor_list, + target_idx = 1L, + cross_check = TRUE, + max_ratio = 0.8, + ..., + pkg_ptr +) { + + checkmate::assert_list(descriptor_list, min.len = 2L) + target_idx <- as.integer(target_idx) + + if (missing(pkg_ptr)) { + package_check("skimage", repository = "pip:scikit-image") + SKI <- reticulate::import("skimage", convert = TRUE, delay_load = TRUE) + } else { + SKI <- pkg_ptr + } + + target <- descriptor_list[[target_idx]] + + out <- lapply( + seq_along(descriptor_list), + function(moving_idx) { + if (moving_idx == target_idx) { + return(matrix( + rep(seq_len(nrow(target)), 2L), + ncol = 2L, + byrow = FALSE + )) + # directly return all as matches + } + + moving <- descriptor_list[[moving_idx]] + + m <- .match_descriptor_single( + x = target, + y = moving, + ..., + pkg_ptr = pkg_ptr + ) + m + 1 # since it is 0 indexed + } + ) + + return(out) +} + + +# wrapper for sklearn-image match_descriptors +# returns a 2 col matrix of x to y index matches +.match_descriptor_single <- function(x, y,max_ratio, ..., pkg_ptr) { + + checkmate::assert_class(x, "matrix") + checkmate::assert_class(y, "matrix") + + if (missing(pkg_ptr)) { + GiottoUtils::package_check("skimage", repository = "pip:scikit-image") + SKI <- reticulate::import("skimage", convert = TRUE, delay_load = TRUE) + } else { + SKI <- pkg_ptr + } + + match_descriptors <- SKI$feature$match_descriptors + m <- match_descriptors( + descriptors1 = x, + descriptors2 = y, + max_ratio = max_ratio, + ... # max_ratio of 0.6 - 0.8 recommended for sift, cross_check = TRUE + ) + + return(m) +} + + +#' @name preprocessImageToMatrix +#' @title Preprocess from image directory to the required matrix format for Image registration pipeline built on scikit-image +#' @description +#' Preprocess a image path to the required matrix format for Image registration pipeline built on scikit-image +#' @param x input file path, required +#' @param invert whether or not to invert intensity to make calculation of descriptors more accurate, default FALSE +#' @param equalize_histogram whether or not to calculate equalized histogram of the image,default TRUE +#' @param flip_vertical whether or not to flip vertical, default FALSE +#' @param flip_horizontal whether or not to flip horizontal, default FALSE +#' @param rotate_90 whether or not to rotates the image 90 degrees counter-clockwise, default FALSE +#' @param use_single_channel If input is a multichannel image, whether or not to extract single channel, default FALSE +#' @param single_channel_number Channel number in the multichannel image, required if use_single_channel = TRUE +#' @returns a matrix array to input to .sift_detect +#' +#' @export +preprocessImageToMatrix <- function(x, + invert = F, + equalize_histogram = T, + flip_vertical = F, + flip_horizontal = F, + rotate_90 = F, + use_single_channel = F, + single_channel_number = NULL, + pkg_ptr) { + + if (missing(pkg_ptr)) { + GiottoUtils::package_check("skimage", repository = "pip:scikit-image") + SKI <- reticulate::import("skimage", convert = TRUE, delay_load = TRUE) + } else { + SKI <- pkg_ptr + } + GiottoUtils::package_check("numpy", repository = "pip:scikit-image") + np <- reticulate::import("numpy", convert = TRUE, delay_load = TRUE) + + image = SKI$io$imread(x) + + if (length(dim(image)) >2 & use_single_channel == FALSE){ + image = SKI$color$rgb2gray(image) + } + if (use_single_channel == TRUE) { + if (is.null(single_channel_number)) {stop("Set use single channel == TRUE, please provide a channel number to continue")} + image <- image[,,single_channel_number] + } + + + if (flip_vertical == T){ + image = np$flipud(image) + } + if (flip_horizontal == T){ + image = np$fliplr(image) + } + if (rotate_90 == T){ + image = np$rot90(image) + } + if (invert == T){ + image = SKI$util$invert(image) + } + if (equalize_histogram == T){ + image = SKI$exposure$equalize_hist(image) + } + return(image) +} + + +#' @name .estimate_transform_from_matched_descriptor +#' @title Estimate affine transformation from matched descriptor +#' @description +#' Estimate affine transformation from matched descriptor +#' @param keypoints1 keypoints extracted from source image via .sift_detect +#' @param keypoints1 keypoints extracted from target image via .sift_detect +#' @param match a 2 col matrix of x to y index matched descriptors via .match_descriptor_single +#' @returns a list of model and inliners +.estimate_transform_from_matched_descriptor <- function(keypoints1, + keypoints2, + match, + estimate_fun, + ..., + pkg_ptr){ + if (missing(pkg_ptr)) { + GiottoUtils::package_check("skimage", repository = "pip:scikit-image") + SKI <- reticulate::import("skimage", convert = TRUE, delay_load = TRUE) + } else { + SKI <- pkg_ptr + } + + # Extract matched keypoints + src_pts <- keypoints1[match[, 1] + 1, , drop = FALSE] + dst_pts <- keypoints2[match[, 2] + 1, , drop = FALSE] + + estimate_fun <- match.arg(estimate_fun, unique(c('euclidean', 'similarity', 'affine', 'piecewise-affine', 'projective', 'polynomial', estimate_fun))) + + # Estimate homography matrix + ransac_result <- SKI$transform$estimate_transform( + ttype = estimate_fun, + src = src_pts, + dst = dst_pts, + ) + + return(ransac_result) +} + + +#' @name .warp_transformed_image +#' @title Warp transformed images from estimated transformation +#' @description +#' Warp transformed images from estimated transformation +#' @param x source image from .sift_preprocess +#' @param y target image from .sift_preprocess +#' @param model estimated transformation object from .estimate_transform_from_matched_descriptor +#' @returns None, it will write to a output path +.warp_transformed_image <- function(x, + y, + model, + outpath = NULL, + pkg_ptr){ + if (missing(pkg_ptr)) { + GiottoUtils::package_check("skimage", repository = "pip:scikit-image") + SKI <- reticulate::import("skimage", convert = TRUE, delay_load = TRUE) + } else { + SKI <- pkg_ptr + } + + # Ensure the source image array is writable by making a copy + x_copy <- reticulate::r_to_py(x)$copy() + + # Warp the source image to align with the destination image + warped_image <- SKI$transform$warp(x_copy, model, output_shape = dim(y)) + SKI$io$imsave(outpath,warped_image) +} + + + +#' @name .plot_matched_descriptors +#' @title plot matched descriptors +#' @description +#' A wrapper function for the plot_matches for the SIFT feature extractor and descriptor pipeline +#' @param x source image from .sift_preprocess +#' @param y target image from .sift_preprocess +#' @param keypoints1 keypoints extracted from source image via .sift_detect +#' @param keypoints1 keypoints extracted from target image via .sift_detect +#' @param match a 2 col matrix of x to y index matched descriptors via .match_descriptor_single +#' @returns None +.plot_matched_descriptors <- function(x, y, keypoints1, keypoints2, match, pkg_ptr){ + if (missing(pkg_ptr)) { + GiottoUtils::package_check("skimage", repository = "pip:scikit-image") + SKI <- reticulate::import("skimage", convert = TRUE, delay_load = TRUE) + } else { + SKI <- pkg_ptr + } + + matplotlib <-reticulate::import("matplotlib", convert = TRUE, delay_load = TRUE) + np <- reticulate::import("numpy",convert = T, delay_load = T) + plt <- matplotlib$pyplot + + match_py <- reticulate::r_to_py(match) + match_py <- np$array(match_py, dtype = np$int32) + + # Create a subplot + fig_ax <- plt$subplots(nrows = 1L, ncols = 1L, figsize = c(11, 8)) + fig <- fig_ax[[1]] + ax <- fig_ax[[2]] + + # Plot the matches + SKI$feature$plot_matches(ax, x, y, keypoints1, keypoints2, match_py, only_matches = TRUE) + + ax$axis('off') + plt$show() + plt$close() +} + +#' +#' @title Estimate Automated ImageRegistration With SIFT +#' @name estimateAutomatedImageRegistrationWithSIFT +#' @description +#' Automatically estimate a transform with SIFT feature detection, descriptor match and returns a transformation object to use +#' @param x required. Source matrix input, could be generated from preprocessImageToMatrix +#' @param y required. Source matrix input, could be generated from preprocessImageToMatrix +#' @param max_ratio max_ratio parameter for matching descriptors, default 0.6 +#' @param save_warp default NULL, if not NULL, please provide an output image path to save the warpped image. +#' @param estimate_fun default Affine. The transformation model to use estimation +#' @param plot_match whether or not to plot the matching descriptors.Default False +#' @returns a list of the estimated transformation object +#' example estimation <- estimateAutomatedImageRegistrationWithSIFT(x = image_mtx1,y = image_mtx2) +#' @export +estimateAutomatedImageRegistrationWithSIFT <- function(x, + y, + plot_match = F, + max_ratio = 0.6, + estimate_fun = 'affine', + save_warp = NULL, + verbose = T){ + + GiottoUtils::vmsg(.v = verbose, .is_debug = T,'Detecting features via SIFT... ') + x_sift <- .sift_detect(x) + y_sift <- .sift_detect(y) + + GiottoUtils::vmsg(.v = verbose, .is_debug = T,'Matching Descriptors via SIFT... ') + matched <- .match_descriptor_single(x_sift$descriptor, y_sift$descriptor,max_ratio = max_ratio) + + if (plot_match == TRUE){ + .plot_matched_descriptors(x, y, x_sift$keypoints, y_sift$keypoints, matched) + } + + + GiottoUtils::vmsg(.v = verbose, .is_debug = T,'Estimating transformation matrix from matched descriptor... ') + estimation <- .estimate_transform_from_matched_descriptor(x_sift$keypoints, + y_sift$keypoints, + matched, + estimate_fun = estimate_fun) + + if (!is.null(save_warp)){ + .warp_transformed_image(x = x, + y = y, + model = estimation$inverse, outpath = save_warp) + } + + return(estimation) +} + + + + diff --git a/inst/python/configuration/genv_cellpose.yml b/inst/python/configuration/genv_cellpose.yml new file mode 100644 index 000000000..572d53d48 --- /dev/null +++ b/inst/python/configuration/genv_cellpose.yml @@ -0,0 +1,19 @@ +name: giotto_cellpose +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - python=3.8 + - pip + - pandas + - networkx + - python-igraph + - leidenalg + - scikit-learn + - tifffile + - pip: + - cellpose + - python-louvain + - smfishHmrf + - git+https://github.com/wwang-chcn/bento-tools.git@giotto_install diff --git a/man/calculateAffineMatrixFromLandmarks.Rd b/man/calculateAffineMatrixFromLandmarks.Rd new file mode 100644 index 000000000..eb1fcaf21 --- /dev/null +++ b/man/calculateAffineMatrixFromLandmarks.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{calculateAffineMatrixFromLandmarks} +\alias{calculateAffineMatrixFromLandmarks} +\title{Calculate a affine transformation matrix from two set of landmarks} +\usage{ +calculateAffineMatrixFromLandmarks(source_df, target_df) +} +\arguments{ +\item{source_df}{source landmarks, two columns, first column represent x coordinate and second column represent y coordinate.} + +\item{target_df}{target landmarks, two columns, first column represent x coordinate and second column represent y coordinate.} +} +\value{ +a 3 by 3 matrix with the third row close to (0,0,1) +} +\description{ +calculate a affine transformation matrix from two set of landmarks +} diff --git a/man/dot-estimate_transform_from_matched_descriptor.Rd b/man/dot-estimate_transform_from_matched_descriptor.Rd new file mode 100644 index 000000000..45c31a330 --- /dev/null +++ b/man/dot-estimate_transform_from_matched_descriptor.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{.estimate_transform_from_matched_descriptor} +\alias{.estimate_transform_from_matched_descriptor} +\title{Estimate affine transformation from matched descriptor} +\usage{ +.estimate_transform_from_matched_descriptor( + keypoints1, + keypoints2, + match, + estimate_fun, + ..., + pkg_ptr +) +} +\arguments{ +\item{keypoints1}{keypoints extracted from target image via .sift_detect} + +\item{match}{a 2 col matrix of x to y index matched descriptors via .match_descriptor_single} +} +\value{ +a list of model and inliners +} +\description{ +Estimate affine transformation from matched descriptor +} diff --git a/man/dot-match_descriptor.Rd b/man/dot-match_descriptor.Rd new file mode 100644 index 000000000..cb902e2f9 --- /dev/null +++ b/man/dot-match_descriptor.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{.match_descriptor} +\alias{.match_descriptor} +\title{Match image descriptors} +\usage{ +.match_descriptor( + descriptor_list, + target_idx = 1L, + cross_check = TRUE, + max_ratio = 0.8, + ..., + pkg_ptr +) +} +\arguments{ +\item{descriptor_list}{list of descriptor matrices} + +\item{target_idx}{which item in the list is the target image. Default is 1} + +\item{cross_check}{whether to check that only the best match is returned} + +\item{max_ratio}{Maximum ratio of distances between first and second closest +descriptor in the second set of descriptors. This threshold is useful to +filter ambiguous matches between the two descriptor sets. The choice of this +value depends on the statistics of the chosen descriptor, e.g., for SIFT +descriptors a value of 0.8 is usually chosen, see D.G. Lowe, "Distinctive +Image Features from Scale-Invariant Keypoints", International Journal of +Computer Vision, 2004.} + +\item{...}{additional params to pass to `skimage.feature.match_descriptors()`} +} +\value{ +list +} +\description{ +Brute force matching of descriptors using \pkg{scikit-image}. Find matching +image descriptors between moving images and a target image. +} diff --git a/man/dot-plot_matched_descriptors.Rd b/man/dot-plot_matched_descriptors.Rd new file mode 100644 index 000000000..4b64af54a --- /dev/null +++ b/man/dot-plot_matched_descriptors.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{.plot_matched_descriptors} +\alias{.plot_matched_descriptors} +\title{plot matched descriptors} +\usage{ +.plot_matched_descriptors(x, y, keypoints1, keypoints2, match, pkg_ptr) +} +\arguments{ +\item{x}{source image from .sift_preprocess} + +\item{y}{target image from .sift_preprocess} + +\item{keypoints1}{keypoints extracted from target image via .sift_detect} + +\item{match}{a 2 col matrix of x to y index matched descriptors via .match_descriptor_single} +} +\value{ +None +} +\description{ +A wrapper function for the plot_matches for the SIFT feature extractor and descriptor pipeline +} diff --git a/man/dot-sift_detect.Rd b/man/dot-sift_detect.Rd new file mode 100644 index 000000000..a28954503 --- /dev/null +++ b/man/dot-sift_detect.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{.sift_detect} +\alias{.sift_detect} +\title{Run SIFT feature detector and descriptor extractor} +\usage{ +.sift_detect(x, ..., pkg_ptr) +} +\arguments{ +\item{x}{input matrix or preprocessed image to extract feature and descriptor from} + +\item{...}{additional params to pass to `skimage.feature.SIFT()`} +} +\value{ +list of keypoints and descriptors +} +\description{ +Perform feature detector and descriptor extractor on a matrix object or preprocessed image object +} diff --git a/man/dot-warp_transformed_image.Rd b/man/dot-warp_transformed_image.Rd new file mode 100644 index 000000000..662dad1c4 --- /dev/null +++ b/man/dot-warp_transformed_image.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{.warp_transformed_image} +\alias{.warp_transformed_image} +\title{Warp transformed images from estimated transformation} +\usage{ +.warp_transformed_image(x, y, model, outpath = NULL, pkg_ptr) +} +\arguments{ +\item{x}{source image from .sift_preprocess} + +\item{y}{target image from .sift_preprocess} + +\item{model}{estimated transformation object from .estimate_transform_from_matched_descriptor} +} +\value{ +None, it will write to a output path +} +\description{ +Warp transformed images from estimated transformation +} diff --git a/man/estimateAutomatedImageRegistrationWithSIFT.Rd b/man/estimateAutomatedImageRegistrationWithSIFT.Rd new file mode 100644 index 000000000..a8601a0f2 --- /dev/null +++ b/man/estimateAutomatedImageRegistrationWithSIFT.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{estimateAutomatedImageRegistrationWithSIFT} +\alias{estimateAutomatedImageRegistrationWithSIFT} +\title{Estimate Automated ImageRegistration With SIFT} +\usage{ +estimateAutomatedImageRegistrationWithSIFT( + x, + y, + plot_match = F, + max_ratio = 0.6, + estimate_fun = "affine", + save_warp = NULL, + verbose = T +) +} +\arguments{ +\item{x}{required. Source matrix input, could be generated from preprocessImageToMatrix} + +\item{y}{required. Source matrix input, could be generated from preprocessImageToMatrix} + +\item{plot_match}{whether or not to plot the matching descriptors.Default False} + +\item{max_ratio}{max_ratio parameter for matching descriptors, default 0.6} + +\item{estimate_fun}{default Affine. The transformation model to use estimation} + +\item{save_warp}{default NULL, if not NULL, please provide an output image path to save the warpped image.} +} +\value{ +a list of the estimated transformation object +example estimation <- estimateAutomatedImageRegistrationWithSIFT(x = image_mtx1,y = image_mtx2) +} +\description{ +Automatically estimate a transform with SIFT feature detection, descriptor match and returns a transformation object to use +} diff --git a/man/interactiveLandmarkSelection.Rd b/man/interactiveLandmarkSelection.Rd new file mode 100644 index 000000000..c0b1ecef4 --- /dev/null +++ b/man/interactiveLandmarkSelection.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{interactiveLandmarkSelection} +\alias{interactiveLandmarkSelection} +\title{title Record landmarks by interactive selection} +\usage{ +interactiveLandmarkSelection(source, target) +} +\arguments{ +\item{source_image}{the image to be plotted on the left, and landmarks will output in the first of the list. Input can be a ggplot object, a GiottoImage, or a character represent a path to a image} + +\item{target_image}{the image to be plotted on the right, and landmarks will output in the second of the list. Input can be a ggplot object, a GiottoImage, or a character represent a path to a image} +} +\value{ +a list of landmarks +} +\description{ +Record landmarks by interactive selection +} diff --git a/man/performCellposeSegmentation.Rd b/man/performCellposeSegmentation.Rd new file mode 100644 index 000000000..92e8e3b11 --- /dev/null +++ b/man/performCellposeSegmentation.Rd @@ -0,0 +1,107 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cell_segmentation.R +\name{performCellposeSegmentation} +\alias{performCellposeSegmentation} +\title{perform cellpose segmentation} +\usage{ +performCellposeSegmentation( + python_env = "giotto_cellpose", + image_dir, + mask_output, + channel_1 = 0, + channel_2 = 0, + model_name = "cyto3", + batch_size = 8, + resample = TRUE, + channel_axis = NULL, + z_axis = NULL, + normalize = TRUE, + invert = FALSE, + rescale = NULL, + diameter = NULL, + flow_threshold = 0.4, + cellprob_threshold = 0, + do_3D = FALSE, + anisotropy = NULL, + stitch_threshold = 0, + min_size = 15, + niter = NULL, + augment = FALSE, + tile = TRUE, + tile_overlap = 0.1, + bsize = 224, + interp = TRUE, + compute_masks = TRUE, + progress = NULL, + verbose = TRUE, + ... +) +} +\arguments{ +\item{image_dir}{character, required. Provide a path to a gray scale or a three channel image.} + +\item{mask_output}{required. Provide a path to the output mask file.} + +\item{channel_1}{channel number for cytoplasm, default to 0(gray scale)} + +\item{channel_2}{channel number for Nuclei, default to 0(gray scale)} + +\item{model_name}{Name of the model to run inference. Default to 'cyto3', if you want to run cutomized trained model, place your model file in ~/.cellpose/models and specify your model name.} + +\item{batch_size}{Cellpose Parameter, Number of 224x224 patches to run simultaneously on the GPU. Can make smaller or bigger depending on GPU memory usage. Defaults to 8.} + +\item{resample}{Cellpose Parameter} + +\item{channel_axis}{Cellpose Parameter} + +\item{z_axis}{Cellpose Parameter} + +\item{normalize}{Cellpose Parameter} + +\item{invert}{Cellpose Parameter} + +\item{rescale}{Cellpose Parameter} + +\item{diameter}{Cellpose Parameter} + +\item{flow_threshold}{Cellpose Parameter} + +\item{cellprob_threshold}{Cellpose Parameter} + +\item{do_3D}{Cellpose Parameter} + +\item{anisotropy}{Cellpose Parameter} + +\item{stitch_threshold}{Cellpose Parameter} + +\item{min_size}{Cellpose Parameter} + +\item{niter}{Cellpose Parameter} + +\item{augment}{Cellpose Parameter} + +\item{tile}{Cellpose Parameter} + +\item{tile_overlap}{Cellpose Parameter} + +\item{bsize}{Cellpose Parameter} + +\item{interp}{Cellpose Parameter} + +\item{compute_masks}{Cellpose Parameter} + +\item{progress}{Cellpose Parameter} + +\item{python_path}{python environment with cellpose installed. default = "giotto_cellpose".} +} +\value{ +No return variable, as this will write directly to output path provided. +} +\description{ +perform the Giotto Wrapper of cellpose segmentation. This is for a model inference to generate segmentation mask file from input image. +main parameters needed +} +\examples{ +# example code +performCellposeSegmentation(image_dir = input_image, mask_output = output, channel_1 = 2, channel_2 = 1, model_name = 'cyto3',batch_size=4) +} diff --git a/man/preprocessImageToMatrix.Rd b/man/preprocessImageToMatrix.Rd new file mode 100644 index 000000000..842cbefcb --- /dev/null +++ b/man/preprocessImageToMatrix.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/image_registration.R +\name{preprocessImageToMatrix} +\alias{preprocessImageToMatrix} +\title{Preprocess from image directory to the required matrix format for Image registration pipeline built on scikit-image} +\usage{ +preprocessImageToMatrix( + x, + invert = F, + equalize_histogram = T, + flip_vertical = F, + flip_horizontal = F, + rotate_90 = F, + use_single_channel = F, + single_channel_number = NULL, + pkg_ptr +) +} +\arguments{ +\item{x}{input file path, required} + +\item{invert}{whether or not to invert intensity to make calculation of descriptors more accurate, default FALSE} + +\item{equalize_histogram}{whether or not to calculate equalized histogram of the image,default TRUE} + +\item{flip_vertical}{whether or not to flip vertical, default FALSE} + +\item{flip_horizontal}{whether or not to flip horizontal, default FALSE} + +\item{rotate_90}{whether or not to rotates the image 90 degrees counter-clockwise, default FALSE} + +\item{use_single_channel}{If input is a multichannel image, whether or not to extract single channel, default FALSE} + +\item{single_channel_number}{Channel number in the multichannel image, required if use_single_channel = TRUE} +} +\value{ +a matrix array to input to .sift_detect +} +\description{ +Preprocess a image path to the required matrix format for Image registration pipeline built on scikit-image +} diff --git a/man/reexports.Rd b/man/reexports.Rd index c4a2e34b5..f5533929f 100644 --- a/man/reexports.Rd +++ b/man/reexports.Rd @@ -298,7 +298,7 @@ These objects are imported from other packages. Follow the links below to see their documentation. \describe{ - \item{GiottoClass}{\code{\link[GiottoClass:activeFeatType-generic]{activeFeatType}}, \code{\link[GiottoClass:activeFeatType-generic]{activeFeatType<-}}, \code{\link[GiottoClass:activeSpatUnit-generic]{activeSpatUnit}}, \code{\link[GiottoClass:activeSpatUnit-generic]{activeSpatUnit<-}}, \code{\link[GiottoClass]{addCellMetadata}}, \code{\link[GiottoClass]{addFeatMetadata}}, \code{\link[GiottoClass]{addGiottoImage}}, \code{\link[GiottoClass]{addGiottoImageMG}}, \code{\link[GiottoClass]{addGiottoLargeImage}}, \code{\link[GiottoClass]{addGiottoPoints}}, \code{\link[GiottoClass:addGiottoPoints]{addGiottoPoints3D}}, \code{\link[GiottoClass]{addGiottoPolygons}}, \code{\link[GiottoClass]{addNetworkLayout}}, \code{\link[GiottoClass]{addSpatialCentroidLocations}}, \code{\link[GiottoClass]{addSpatialCentroidLocationsLayer}}, \code{\link[GiottoClass]{aggregateStacks}}, \code{\link[GiottoClass]{aggregateStacksExpression}}, \code{\link[GiottoClass]{aggregateStacksLocations}}, \code{\link[GiottoClass]{aggregateStacksPolygonOverlaps}}, \code{\link[GiottoClass]{aggregateStacksPolygons}}, \code{\link[GiottoClass]{anndataToGiotto}}, \code{\link[GiottoClass]{annotateGiotto}}, \code{\link[GiottoClass]{annotateSpatialGrid}}, \code{\link[GiottoClass]{annotateSpatialNetwork}}, \code{\link[GiottoClass]{as.points}}, \code{\link[GiottoClass]{as.polygons}}, \code{\link[GiottoClass:r_spatial_conversions]{as.sf}}, \code{\link[GiottoClass:r_spatial_conversions]{as.sp}}, \code{\link[GiottoClass:r_spatial_conversions]{as.stars}}, \code{\link[GiottoClass:r_spatial_conversions]{as.terra}}, \code{\link[GiottoClass]{calculateMetaTable}}, \code{\link[GiottoClass]{calculateMetaTableCells}}, \code{\link[GiottoClass]{calculateOverlap}}, \code{\link[GiottoClass]{calculateOverlapParallel}}, \code{\link[GiottoClass]{calculateOverlapPolygonImages}}, \code{\link[GiottoClass]{calculateOverlapRaster}}, \code{\link[GiottoClass]{calculateOverlapSerial}}, \code{\link[GiottoClass]{calculateSpatCellMetadataProportions}}, \code{\link[GiottoClass:centroids-generic]{centroids}}, \code{\link[GiottoClass]{changeGiottoInstructions}}, \code{\link[GiottoClass]{changeImageBg}}, \code{\link[GiottoClass]{checkGiottoEnvironment}}, \code{\link[GiottoClass]{circleVertices}}, \code{\link[GiottoClass]{combineCellData}}, \code{\link[GiottoClass]{combineFeatureData}}, \code{\link[GiottoClass]{combineFeatureOverlapData}}, \code{\link[GiottoClass]{combineMetadata}}, \code{\link[GiottoClass]{combineSpatialCellFeatureInfo}}, \code{\link[GiottoClass]{combineSpatialCellMetadataInfo}}, \code{\link[GiottoClass]{combineToMultiPolygon}}, \code{\link[GiottoClass]{convertGiottoLargeImageToMG}}, \code{\link[GiottoClass]{copy}}, \code{\link[GiottoClass]{createBentoAdata}}, \code{\link[GiottoClass]{createCellMetaObj}}, \code{\link[GiottoClass]{createDimObj}}, \code{\link[GiottoClass]{createExprObj}}, \code{\link[GiottoClass]{createFeatMetaObj}}, \code{\link[GiottoClass]{createGiottoImage}}, \code{\link[GiottoClass]{createGiottoInstructions}}, \code{\link[GiottoClass]{createGiottoLargeImage}}, \code{\link[GiottoClass]{createGiottoLargeImageList}}, \code{\link[GiottoClass]{createGiottoObject}}, \code{\link[GiottoClass]{createGiottoObjectSubcellular}}, \code{\link[GiottoClass]{createGiottoPoints}}, \code{\link[GiottoClass]{createGiottoPolygon}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromDfr}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromGeoJSON}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromMask}}, \code{\link[GiottoClass]{createMetafeats}}, \code{\link[GiottoClass]{createNearestNetObj}}, \code{\link[GiottoClass]{createNearestNetwork}}, \code{\link[GiottoClass]{createSpatEnrObj}}, \code{\link[GiottoClass]{createSpatLocsObj}}, \code{\link[GiottoClass]{createSpatNetObj}}, \code{\link[GiottoClass]{createSpatialDefaultGrid}}, \code{\link[GiottoClass]{createSpatialDelaunayNetwork}}, \code{\link[GiottoClass]{createSpatialFeaturesKNNnetwork}}, \code{\link[GiottoClass]{createSpatialGrid}}, \code{\link[GiottoClass]{createSpatialKNNnetwork}}, \code{\link[GiottoClass]{createSpatialNetwork}}, \code{\link[GiottoClass]{createSpatialWeightMatrix}}, \code{\link[GiottoClass]{crop}}, \code{\link[GiottoClass]{cropGiottoLargeImage}}, \code{\link[GiottoClass]{density}}, \code{\link[GiottoClass]{distGiottoImage}}, \code{\link[GiottoClass]{estimateImageBg}}, \code{\link[GiottoClass]{ext}}, \code{\link[GiottoClass:ext]{ext<-}}, \code{\link[GiottoClass]{fDataDT}}, \code{\link[GiottoClass:spatIDs-generic]{featIDs}}, \code{\link[GiottoClass:featType-generic]{featType}}, \code{\link[GiottoClass:featType-generic]{featType<-}}, \code{\link[GiottoClass:featureNetwork-class]{featureNetwork}}, \code{\link[GiottoClass]{flip}}, \code{\link[GiottoClass]{gefToGiotto}}, \code{\link[GiottoClass]{getCellMetadata}}, \code{\link[GiottoClass]{getDimReduction}}, \code{\link[GiottoClass]{getExpression}}, \code{\link[GiottoClass]{getFeatureInfo}}, \code{\link[GiottoClass]{getFeatureMetadata}}, \code{\link[GiottoClass]{getGiottoImage}}, \code{\link[GiottoClass]{getMultiomics}}, \code{\link[GiottoClass]{getNearestNetwork}}, \code{\link[GiottoClass]{getPolygonInfo}}, \code{\link[GiottoClass]{getSpatialEnrichment}}, \code{\link[GiottoClass]{getSpatialEnrichment}}, \code{\link[GiottoClass]{getSpatialGrid}}, \code{\link[GiottoClass]{getSpatialGrid}}, \code{\link[GiottoClass]{getSpatialLocations}}, \code{\link[GiottoClass]{getSpatialLocations}}, \code{\link[GiottoClass]{getSpatialNetwork}}, \code{\link[GiottoClass]{getSpatialNetwork}}, \code{\link[GiottoClass:giotto-class]{giotto}}, \code{\link[GiottoClass:giottoImage-class]{giottoImage}}, \code{\link[GiottoClass:giottoLargeImage-class]{giottoLargeImage}}, \code{\link[GiottoClass]{giottoMasterToSuite}}, \code{\link[GiottoClass:giottoPoints-class]{giottoPoints}}, \code{\link[GiottoClass:giottoPolygon-class]{giottoPolygon}}, \code{\link[GiottoClass]{giottoToAnnData}}, \code{\link[GiottoClass]{giottoToSeurat}}, \code{\link[GiottoClass]{giottoToSeuratV4}}, \code{\link[GiottoClass]{giottoToSeuratV5}}, \code{\link[GiottoClass]{giottoToSpatialExperiment}}, \code{\link[GiottoClass]{hexVertices}}, \code{\link[GiottoClass]{hist}}, \code{\link[GiottoClass]{installGiottoEnvironment}}, \code{\link[GiottoClass:instructions-generic]{instructions}}, \code{\link[GiottoClass:instructions-generic]{instructions<-}}, \code{\link[GiottoClass]{joinGiottoObjects}}, \code{\link[GiottoClass]{loadGiotto}}, \code{\link[GiottoClass]{makePseudoVisium}}, \code{\link[GiottoClass]{objHistory}}, \code{\link[GiottoClass:objName-generic]{objName}}, \code{\link[GiottoClass:objName-generic]{objName<-}}, \code{\link[GiottoClass:generate_grid]{orthoGrid}}, \code{\link[GiottoClass]{overlapImagesToMatrix}}, \code{\link[GiottoClass]{overlapToMatrix}}, \code{\link[GiottoClass]{overlapToMatrixMultiPoly}}, \code{\link[GiottoClass:overlaps-generic]{overlaps}}, \code{\link[GiottoClass]{pDataDT}}, \code{\link[GiottoClass]{plotGiottoImage}}, \code{\link[GiottoClass]{polyStamp}}, \code{\link[GiottoClass:prov-generic]{prov}}, \code{\link[GiottoClass:prov-generic]{prov<-}}, \code{\link[GiottoClass]{readCellMetadata}}, \code{\link[GiottoClass]{readDimReducData}}, \code{\link[GiottoClass]{readExprData}}, \code{\link[GiottoClass]{readExprMatrix}}, \code{\link[GiottoClass]{readFeatData}}, \code{\link[GiottoClass]{readFeatMetadata}}, \code{\link[GiottoClass]{readGiottoInstructions}}, \code{\link[GiottoClass]{readNearestNetData}}, \code{\link[GiottoClass]{readPolygonData}}, \code{\link[GiottoClass]{readSpatEnrichData}}, \code{\link[GiottoClass]{readSpatLocsData}}, \code{\link[GiottoClass]{readSpatNetData}}, \code{\link[GiottoClass]{reconnectGiottoImage}}, \code{\link[GiottoClass]{rectVertices}}, \code{\link[GiottoClass]{removeCellAnnotation}}, \code{\link[GiottoClass]{removeFeatAnnotation}}, \code{\link[GiottoClass]{removeGiottoEnvironment}}, \code{\link[GiottoClass]{replaceGiottoInstructions}}, \code{\link[GiottoClass]{rescale}}, \code{\link[GiottoClass]{rescalePolygons}}, \code{\link[GiottoClass]{saveGiotto}}, \code{\link[GiottoClass]{setCellMetadata}}, \code{\link[GiottoClass]{setDimReduction}}, \code{\link[GiottoClass]{setExpression}}, \code{\link[GiottoClass]{setFeatureInfo}}, \code{\link[GiottoClass]{setFeatureMetadata}}, \code{\link[GiottoClass]{setGiotto}}, \code{\link[GiottoClass]{setGiottoImage}}, \code{\link[GiottoClass]{setMultiomics}}, \code{\link[GiottoClass]{setNearestNetwork}}, \code{\link[GiottoClass]{setPolygonInfo}}, \code{\link[GiottoClass]{setSpatialEnrichment}}, \code{\link[GiottoClass]{setSpatialGrid}}, \code{\link[GiottoClass]{setSpatialLocations}}, \code{\link[GiottoClass]{setSpatialNetwork}}, \code{\link[GiottoClass]{seuratToGiotto}}, \code{\link[GiottoClass]{seuratToGiottoV4}}, \code{\link[GiottoClass]{seuratToGiottoV5}}, \code{\link[GiottoClass]{showGiottoCellMetadata}}, \code{\link[GiottoClass]{showGiottoDimRed}}, \code{\link[GiottoClass]{showGiottoExpression}}, \code{\link[GiottoClass]{showGiottoFeatInfo}}, \code{\link[GiottoClass]{showGiottoFeatMetadata}}, \code{\link[GiottoClass]{showGiottoImageNames}}, \code{\link[GiottoClass]{showGiottoInstructions}}, \code{\link[GiottoClass]{showGiottoNearestNetworks}}, \code{\link[GiottoClass]{showGiottoSpatEnrichments}}, \code{\link[GiottoClass]{showGiottoSpatGrids}}, \code{\link[GiottoClass]{showGiottoSpatLocs}}, \code{\link[GiottoClass]{showGiottoSpatNetworks}}, \code{\link[GiottoClass]{showGiottoSpatialInfo}}, \code{\link[GiottoClass]{showProcessingSteps}}, \code{\link[GiottoClass]{smoothGiottoPolygons}}, \code{\link[GiottoClass:spatIDs-generic]{spatIDs}}, \code{\link[GiottoClass]{spatQueryGiottoPolygons}}, \code{\link[GiottoClass]{spatShift}}, \code{\link[GiottoClass:spatUnit-generic]{spatUnit}}, \code{\link[GiottoClass:spatUnit-generic]{spatUnit<-}}, \code{\link[GiottoClass]{spatialExperimentToGiotto}}, \code{\link[GiottoClass]{spin}}, \code{\link[GiottoClass]{stitchFieldCoordinates}}, \code{\link[GiottoClass]{stitchFieldCoordinates}}, \code{\link[GiottoClass]{stitchGiottoLargeImage}}, \code{\link[GiottoClass]{subsetGiotto}}, \code{\link[GiottoClass]{subsetGiottoLocs}}, \code{\link[GiottoClass]{subsetGiottoLocsMulti}}, \code{\link[GiottoClass]{subsetGiottoLocsSubcellular}}, \code{\link[GiottoClass]{tessellate}}, \code{\link[GiottoClass:generate_grid]{triGrid}}, \code{\link[GiottoClass]{updateGiottoImage}}, \code{\link[GiottoClass]{updateGiottoImageMG}}, \code{\link[GiottoClass]{updateGiottoLargeImage}}, \code{\link[GiottoClass]{updateGiottoObject}}, \code{\link[GiottoClass]{updateGiottoPointsObject}}, \code{\link[GiottoClass]{updateGiottoPolygonObject}}, \code{\link[GiottoClass:wrap]{vect}}, \code{\link[GiottoClass]{wrap}}, \code{\link[GiottoClass]{writeGiottoLargeImage}}} + \item{GiottoClass}{\code{\link[GiottoClass:activeFeatType-generic]{activeFeatType}}, \code{\link[GiottoClass:activeFeatType-generic]{activeFeatType<-}}, \code{\link[GiottoClass:activeSpatUnit-generic]{activeSpatUnit}}, \code{\link[GiottoClass:activeSpatUnit-generic]{activeSpatUnit<-}}, \code{\link[GiottoClass]{addCellMetadata}}, \code{\link[GiottoClass]{addFeatMetadata}}, \code{\link[GiottoClass]{addGiottoImage}}, \code{\link[GiottoClass]{addGiottoImageMG}}, \code{\link[GiottoClass]{addGiottoLargeImage}}, \code{\link[GiottoClass]{addGiottoPoints}}, \code{\link[GiottoClass:addGiottoPoints]{addGiottoPoints3D}}, \code{\link[GiottoClass]{addGiottoPolygons}}, \code{\link[GiottoClass]{addNetworkLayout}}, \code{\link[GiottoClass]{addSpatialCentroidLocations}}, \code{\link[GiottoClass]{addSpatialCentroidLocationsLayer}}, \code{\link[GiottoClass]{aggregateStacks}}, \code{\link[GiottoClass]{aggregateStacksExpression}}, \code{\link[GiottoClass]{aggregateStacksLocations}}, \code{\link[GiottoClass]{aggregateStacksPolygonOverlaps}}, \code{\link[GiottoClass]{aggregateStacksPolygons}}, \code{\link[GiottoClass]{anndataToGiotto}}, \code{\link[GiottoClass]{annotateGiotto}}, \code{\link[GiottoClass]{annotateSpatialGrid}}, \code{\link[GiottoClass]{annotateSpatialNetwork}}, \code{\link[GiottoClass]{as.points}}, \code{\link[GiottoClass]{as.polygons}}, \code{\link[GiottoClass:r_spatial_conversions]{as.sf}}, \code{\link[GiottoClass:r_spatial_conversions]{as.sp}}, \code{\link[GiottoClass:r_spatial_conversions]{as.stars}}, \code{\link[GiottoClass:r_spatial_conversions]{as.terra}}, \code{\link[GiottoClass]{calculateMetaTable}}, \code{\link[GiottoClass]{calculateMetaTableCells}}, \code{\link[GiottoClass]{calculateOverlap}}, \code{\link[GiottoClass]{calculateOverlapParallel}}, \code{\link[GiottoClass]{calculateOverlapPolygonImages}}, \code{\link[GiottoClass]{calculateOverlapRaster}}, \code{\link[GiottoClass]{calculateOverlapSerial}}, \code{\link[GiottoClass]{calculateSpatCellMetadataProportions}}, \code{\link[GiottoClass:centroids-generic]{centroids}}, \code{\link[GiottoClass]{changeGiottoInstructions}}, \code{\link[GiottoClass]{changeImageBg}}, \code{\link[GiottoClass]{checkGiottoEnvironment}}, \code{\link[GiottoClass]{circleVertices}}, \code{\link[GiottoClass]{combineCellData}}, \code{\link[GiottoClass]{combineFeatureData}}, \code{\link[GiottoClass]{combineFeatureOverlapData}}, \code{\link[GiottoClass]{combineMetadata}}, \code{\link[GiottoClass]{combineSpatialCellFeatureInfo}}, \code{\link[GiottoClass]{combineSpatialCellMetadataInfo}}, \code{\link[GiottoClass]{combineToMultiPolygon}}, \code{\link[GiottoClass]{convertGiottoLargeImageToMG}}, \code{\link[GiottoClass]{copy}}, \code{\link[GiottoClass]{createBentoAdata}}, \code{\link[GiottoClass]{createCellMetaObj}}, \code{\link[GiottoClass]{createDimObj}}, \code{\link[GiottoClass]{createExprObj}}, \code{\link[GiottoClass]{createFeatMetaObj}}, \code{\link[GiottoClass]{createGiottoImage}}, \code{\link[GiottoClass]{createGiottoInstructions}}, \code{\link[GiottoClass]{createGiottoLargeImage}}, \code{\link[GiottoClass]{createGiottoLargeImageList}}, \code{\link[GiottoClass]{createGiottoObject}}, \code{\link[GiottoClass]{createGiottoObjectSubcellular}}, \code{\link[GiottoClass]{createGiottoPoints}}, \code{\link[GiottoClass]{createGiottoPolygon}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromDfr}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromGeoJSON}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromMask}}, \code{\link[GiottoClass]{createMetafeats}}, \code{\link[GiottoClass]{createNearestNetObj}}, \code{\link[GiottoClass]{createNearestNetwork}}, \code{\link[GiottoClass]{createSpatEnrObj}}, \code{\link[GiottoClass]{createSpatialDefaultGrid}}, \code{\link[GiottoClass]{createSpatialDelaunayNetwork}}, \code{\link[GiottoClass]{createSpatialFeaturesKNNnetwork}}, \code{\link[GiottoClass]{createSpatialGrid}}, \code{\link[GiottoClass]{createSpatialKNNnetwork}}, \code{\link[GiottoClass]{createSpatialNetwork}}, \code{\link[GiottoClass]{createSpatialWeightMatrix}}, \code{\link[GiottoClass]{createSpatLocsObj}}, \code{\link[GiottoClass]{createSpatNetObj}}, \code{\link[GiottoClass]{crop}}, \code{\link[GiottoClass]{cropGiottoLargeImage}}, \code{\link[GiottoClass]{density}}, \code{\link[GiottoClass]{distGiottoImage}}, \code{\link[GiottoClass]{estimateImageBg}}, \code{\link[GiottoClass]{ext}}, \code{\link[GiottoClass:ext]{ext<-}}, \code{\link[GiottoClass]{fDataDT}}, \code{\link[GiottoClass:spatIDs-generic]{featIDs}}, \code{\link[GiottoClass:featType-generic]{featType}}, \code{\link[GiottoClass:featType-generic]{featType<-}}, \code{\link[GiottoClass:featureNetwork-class]{featureNetwork}}, \code{\link[GiottoClass]{flip}}, \code{\link[GiottoClass]{gefToGiotto}}, \code{\link[GiottoClass]{getCellMetadata}}, \code{\link[GiottoClass]{getDimReduction}}, \code{\link[GiottoClass]{getExpression}}, \code{\link[GiottoClass]{getFeatureInfo}}, \code{\link[GiottoClass]{getFeatureMetadata}}, \code{\link[GiottoClass]{getGiottoImage}}, \code{\link[GiottoClass]{getMultiomics}}, \code{\link[GiottoClass]{getNearestNetwork}}, \code{\link[GiottoClass]{getPolygonInfo}}, \code{\link[GiottoClass]{getSpatialEnrichment}}, \code{\link[GiottoClass]{getSpatialEnrichment}}, \code{\link[GiottoClass]{getSpatialGrid}}, \code{\link[GiottoClass]{getSpatialGrid}}, \code{\link[GiottoClass]{getSpatialLocations}}, \code{\link[GiottoClass]{getSpatialLocations}}, \code{\link[GiottoClass]{getSpatialNetwork}}, \code{\link[GiottoClass]{getSpatialNetwork}}, \code{\link[GiottoClass:giotto-class]{giotto}}, \code{\link[GiottoClass:giottoImage-class]{giottoImage}}, \code{\link[GiottoClass:giottoLargeImage-class]{giottoLargeImage}}, \code{\link[GiottoClass]{giottoMasterToSuite}}, \code{\link[GiottoClass:giottoPoints-class]{giottoPoints}}, \code{\link[GiottoClass:giottoPolygon-class]{giottoPolygon}}, \code{\link[GiottoClass]{giottoToAnnData}}, \code{\link[GiottoClass]{giottoToSeurat}}, \code{\link[GiottoClass]{giottoToSeuratV4}}, \code{\link[GiottoClass]{giottoToSeuratV5}}, \code{\link[GiottoClass]{giottoToSpatialExperiment}}, \code{\link[GiottoClass]{hexVertices}}, \code{\link[GiottoClass]{hist}}, \code{\link[GiottoClass]{installGiottoEnvironment}}, \code{\link[GiottoClass:instructions-generic]{instructions}}, \code{\link[GiottoClass:instructions-generic]{instructions<-}}, \code{\link[GiottoClass]{joinGiottoObjects}}, \code{\link[GiottoClass]{loadGiotto}}, \code{\link[GiottoClass]{makePseudoVisium}}, \code{\link[GiottoClass]{objHistory}}, \code{\link[GiottoClass:objName-generic]{objName}}, \code{\link[GiottoClass:objName-generic]{objName<-}}, \code{\link[GiottoClass:generate_grid]{orthoGrid}}, \code{\link[GiottoClass]{overlapImagesToMatrix}}, \code{\link[GiottoClass:overlaps-generic]{overlaps}}, \code{\link[GiottoClass]{overlapToMatrix}}, \code{\link[GiottoClass]{overlapToMatrixMultiPoly}}, \code{\link[GiottoClass]{pDataDT}}, \code{\link[GiottoClass]{plotGiottoImage}}, \code{\link[GiottoClass]{polyStamp}}, \code{\link[GiottoClass:prov-generic]{prov}}, \code{\link[GiottoClass:prov-generic]{prov<-}}, \code{\link[GiottoClass]{readCellMetadata}}, \code{\link[GiottoClass]{readDimReducData}}, \code{\link[GiottoClass]{readExprData}}, \code{\link[GiottoClass]{readExprMatrix}}, \code{\link[GiottoClass]{readFeatData}}, \code{\link[GiottoClass]{readFeatMetadata}}, \code{\link[GiottoClass]{readGiottoInstructions}}, \code{\link[GiottoClass]{readNearestNetData}}, \code{\link[GiottoClass]{readPolygonData}}, \code{\link[GiottoClass]{readSpatEnrichData}}, \code{\link[GiottoClass]{readSpatLocsData}}, \code{\link[GiottoClass]{readSpatNetData}}, \code{\link[GiottoClass]{reconnectGiottoImage}}, \code{\link[GiottoClass]{rectVertices}}, \code{\link[GiottoClass]{removeCellAnnotation}}, \code{\link[GiottoClass]{removeFeatAnnotation}}, \code{\link[GiottoClass]{removeGiottoEnvironment}}, \code{\link[GiottoClass]{replaceGiottoInstructions}}, \code{\link[GiottoClass]{rescale}}, \code{\link[GiottoClass]{rescalePolygons}}, \code{\link[GiottoClass]{saveGiotto}}, \code{\link[GiottoClass]{setCellMetadata}}, \code{\link[GiottoClass]{setDimReduction}}, \code{\link[GiottoClass]{setExpression}}, \code{\link[GiottoClass]{setFeatureInfo}}, \code{\link[GiottoClass]{setFeatureMetadata}}, \code{\link[GiottoClass]{setGiotto}}, \code{\link[GiottoClass]{setGiottoImage}}, \code{\link[GiottoClass]{setMultiomics}}, \code{\link[GiottoClass]{setNearestNetwork}}, \code{\link[GiottoClass]{setPolygonInfo}}, \code{\link[GiottoClass]{setSpatialEnrichment}}, \code{\link[GiottoClass]{setSpatialGrid}}, \code{\link[GiottoClass]{setSpatialLocations}}, \code{\link[GiottoClass]{setSpatialNetwork}}, \code{\link[GiottoClass]{seuratToGiotto}}, \code{\link[GiottoClass]{seuratToGiottoV4}}, \code{\link[GiottoClass]{seuratToGiottoV5}}, \code{\link[GiottoClass]{showGiottoCellMetadata}}, \code{\link[GiottoClass]{showGiottoDimRed}}, \code{\link[GiottoClass]{showGiottoExpression}}, \code{\link[GiottoClass]{showGiottoFeatInfo}}, \code{\link[GiottoClass]{showGiottoFeatMetadata}}, \code{\link[GiottoClass]{showGiottoImageNames}}, \code{\link[GiottoClass]{showGiottoInstructions}}, \code{\link[GiottoClass]{showGiottoNearestNetworks}}, \code{\link[GiottoClass]{showGiottoSpatEnrichments}}, \code{\link[GiottoClass]{showGiottoSpatGrids}}, \code{\link[GiottoClass]{showGiottoSpatialInfo}}, \code{\link[GiottoClass]{showGiottoSpatLocs}}, \code{\link[GiottoClass]{showGiottoSpatNetworks}}, \code{\link[GiottoClass]{showProcessingSteps}}, \code{\link[GiottoClass]{smoothGiottoPolygons}}, \code{\link[GiottoClass]{spatialExperimentToGiotto}}, \code{\link[GiottoClass:spatIDs-generic]{spatIDs}}, \code{\link[GiottoClass]{spatQueryGiottoPolygons}}, \code{\link[GiottoClass]{spatShift}}, \code{\link[GiottoClass:spatUnit-generic]{spatUnit}}, \code{\link[GiottoClass:spatUnit-generic]{spatUnit<-}}, \code{\link[GiottoClass]{spin}}, \code{\link[GiottoClass]{stitchFieldCoordinates}}, \code{\link[GiottoClass]{stitchFieldCoordinates}}, \code{\link[GiottoClass]{stitchGiottoLargeImage}}, \code{\link[GiottoClass]{subsetGiotto}}, \code{\link[GiottoClass]{subsetGiottoLocs}}, \code{\link[GiottoClass]{subsetGiottoLocsMulti}}, \code{\link[GiottoClass]{subsetGiottoLocsSubcellular}}, \code{\link[GiottoClass]{tessellate}}, \code{\link[GiottoClass:generate_grid]{triGrid}}, \code{\link[GiottoClass]{updateGiottoImage}}, \code{\link[GiottoClass]{updateGiottoImageMG}}, \code{\link[GiottoClass]{updateGiottoLargeImage}}, \code{\link[GiottoClass]{updateGiottoObject}}, \code{\link[GiottoClass]{updateGiottoPointsObject}}, \code{\link[GiottoClass]{updateGiottoPolygonObject}}, \code{\link[GiottoClass:wrap]{vect}}, \code{\link[GiottoClass]{wrap}}, \code{\link[GiottoClass]{writeGiottoLargeImage}}} \item{GiottoUtils}{\code{\link[GiottoUtils:pipe]{\%>\%}}, \code{\link[GiottoUtils]{getDistinctColors}}, \code{\link[GiottoUtils]{getRainbowColors}}}