From 1202202196fa467f7bb3ffe33563ee317ee4b30d Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 9 Nov 2023 13:04:44 -0500 Subject: [PATCH 1/5] code cleanup - Version bump - export of some functions that are required by other modules - add ability to calculate centroids for giottoPolygons but return the attached objects instead of the centroids. --- DESCRIPTION | 2 +- NAMESPACE | 1 + R/classes.R | 30 +++++++++++----------- R/generate_poly.R | 8 +++++- R/giotto_structures.R | 38 ---------------------------- R/globals.R | 2 +- R/images.R | 2 +- R/methods-centroids.R | 32 +++++++++++++++++------ R/methods-spin.R | 23 +++++++++++++++++ R/spatial_structures.R | 22 ++++++++-------- R/subset.R | 12 ++------- man/add_img_array_alpha.Rd | 1 - man/cellMetaObj-class.Rd | 1 + man/centroids-generic.Rd | 5 +++- man/dimObj-class.Rd | 1 + man/exprObj-class.Rd | 1 + man/featMetaObj-class.Rd | 1 + man/nnNetObj-class.Rd | 1 + man/spatLocsObj-class.Rd | 1 + man/subsetGiottoLocs.Rd | 31 ++--------------------- man/subsetGiottoLocsMulti.Rd | 49 ++++++++++++++++++++++++++++++++++++ 21 files changed, 148 insertions(+), 116 deletions(-) create mode 100644 man/subsetGiottoLocsMulti.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 8064ac74..eff379e8 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: GiottoClass Title: Giotto Suite object definitions and framework -Version: 0.0.0.9007 +Version: 0.0.0.9008 Authors@R: c( person("Ruben", "Dries", email = "rubendries@gmail.com", role = c("aut", "cre")), diff --git a/NAMESPACE b/NAMESPACE index ab8c4381..66eed63d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -16,6 +16,7 @@ export(addGiottoPolygons) export(addNetworkLayout) export(addSpatialCentroidLocations) export(addSpatialCentroidLocationsLayer) +export(add_img_array_alpha) export(aggregateStacks) export(aggregateStacksExpression) export(aggregateStacksLocations) diff --git a/R/classes.R b/R/classes.R index f9cfc47c..6f6cbda9 100644 --- a/R/classes.R +++ b/R/classes.R @@ -475,7 +475,8 @@ updateGiottoObject <- function(gobject) { #' that are provided in the expression slot. #' #' -#' @export +#' @export giotto +#' @exportClass giotto giotto <- setClass( "giotto", slots = c( @@ -658,8 +659,8 @@ check_expr_obj <- function(object) { #' @slot feat_type feature type of expression (e.g. 'rna', 'protein') #' @slot provenance origin data of expression information (if applicable) #' @slot misc misc -#' @export -setClass("exprObj", +#' @exportClass exprObj +exprObj = setClass("exprObj", contains = c("nameData", "exprData", "spatFeatData", "miscData", 'giottoSubobject'), validity = check_expr_obj ) @@ -713,8 +714,8 @@ check_cell_meta_obj <- function(object) { #' @slot spat_unit spatial unit of aggregated expression (e.g. 'cell') #' @slot feat_type feature type of aggregated expression (e.g. 'rna', 'protein') #' @slot provenance origin data of aggregated expression information (if applicable) -#' @export -setClass("cellMetaObj", +#' @exportClass cellMetaObj +cellMetaObj = setClass("cellMetaObj", contains = c("metaData", "spatFeatData", "giottoSubobject"), validity = check_cell_meta_obj ) @@ -758,8 +759,8 @@ check_feat_meta_obj <- function(object) { #' @slot spat_unit spatial unit of aggregated expression (e.g. 'cell') #' @slot feat_type feature type of aggregated expression (e.g. 'rna', 'protein') #' @slot provenance origin data of aggregated expression information (if applicable) -#' @export -setClass("featMetaObj", +#' @exportClass featMetaObj +featMetaObj = setClass("featMetaObj", contains = c("metaData", "spatFeatData", 'giottoSubobject'), validity = check_feat_meta_obj ) @@ -825,8 +826,8 @@ check_dim_obj <- function(object) { #' @slot reduction_method method used to generate dimension reduction #' @slot coordinates embedding coordinates #' @slot misc method-specific additional outputs -#' @export -setClass("dimObj", +#' @exportClass dimObj +dimObj = setClass("dimObj", contains = c("nameData", "spatFeatData", 'giottoSubobject'), slots = c( reduction = "character", @@ -888,8 +889,8 @@ S3toS4dimObj <- function(object) { #' @slot spat_unit spatial unit of data #' @slot provenance origin of aggregated information (if applicable) #' @slot misc misc -#' @export -setClass("nnNetObj", +#' @exportClass nnNetObj +nnNetObj = setClass("nnNetObj", contains = c("nameData", "nnData", "spatFeatData", "miscData", 'giottoSubobject') ) @@ -955,8 +956,8 @@ check_spat_locs_obj <- function(object) { #' @slot coordinates data.table of spatial coordinates/locations #' @slot spat_unit spatial unit tag #' @slot provenance origin of aggregated information (if applicable) -#' @export -setClass("spatLocsObj", +#' @exportClass spatLocsObj +spatLocsObj = setClass("spatLocsObj", contains = c("nameData", "coordDataDT", "spatData", "miscData", 'giottoSubobject'), validity = check_spat_locs_obj ) @@ -1467,7 +1468,8 @@ giottoImage <- setClass( #' @slot is_int values are integers #' @slot file_path file path to the image if given #' @slot OS_platform Operating System to run Giotto analysis on -#' @export +#' @export giottoLargeImage +#' @exportClass giottoLargeImage giottoLargeImage <- setClass( Class = "giottoLargeImage", slots = c( diff --git a/R/generate_poly.R b/R/generate_poly.R index 106a970e..f05473a0 100644 --- a/R/generate_poly.R +++ b/R/generate_poly.R @@ -41,7 +41,7 @@ polyStamp <- function(stamp_dt, centroid_dt = data.table::as.data.table(terra::centroids(stamp_poly), geom = "XY", include_values = F) - + stamp_centroid = c(x = centroid_dt$x, y = centroid_dt$y) @@ -279,3 +279,9 @@ makePseudoVisium <- function(extent = NULL, skip_eval_dfr = TRUE, copy_dt = FALSE) } + + + + + + diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 3e877d51..eebe88d1 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -255,44 +255,6 @@ fix_multipart_geoms = function(spatVector) { -# Parallelized giottoPolygon creation workflows # - -# Internal function to create a giottoPolygon object, smooth it, then wrap it so -# that results are portable/possible to use with parallelization. -# dotparams are passed to smoothGiottoPolygons -#' @title Polygon creation and smoothing for parallel -#' @name gpoly_from_dfr_smoothed_wrapped -#' @keywords internal -gpoly_from_dfr_smoothed_wrapped = function(segmdfr, - name = 'cell', - calc_centroids = FALSE, - smooth_polygons = FALSE, - vertices = 20L, - k = 3L, - set_neg_to_zero = TRUE, - skip_eval_dfr = FALSE, - copy_dt = TRUE, - verbose = TRUE) { - - gpoly = createGiottoPolygonsFromDfr(segmdfr = segmdfr, - name = name, - calc_centroids = FALSE, - skip_eval_dfr = skip_eval_dfr, - copy_dt = copy_dt, - verbose = verbose) - if(isTRUE(smooth_polygons)) gpoly = smoothGiottoPolygons(gpolygon = gpoly, - vertices = vertices, - k = k, - set_neg_to_zero = set_neg_to_zero) - if(isTRUE(calc_centroids)) gpoly = calculate_centroids_polygons(gpolygon = gpoly, - append_gpolygon = TRUE) - - slot(gpoly, 'spatVector') = terra::wrap(slot(gpoly, 'spatVector')) - if(isTRUE(calc_centroids)) { - slot(gpoly, 'spatVectorCentroids') = terra::wrap(slot(gpoly, 'spatVectorCentroids')) - } - return(gpoly) -} diff --git a/R/globals.R b/R/globals.R index e5b6148f..8aa1a23a 100644 --- a/R/globals.R +++ b/R/globals.R @@ -15,7 +15,7 @@ utils::globalVariables( "extract_layered_data","set_adg_nn","find_NN_keys", "extract_NN_connectivities","extract_NN_distances", "extract_NN_info", "align_network_data", "extract_SN_connectivities", - "extract_SN_distances", "get_distance", "set_adg_sn" + "extract_SN_distances", "set_adg_sn" ) ) diff --git a/R/images.R b/R/images.R index 5e1b2bd4..573518bb 100644 --- a/R/images.R +++ b/R/images.R @@ -2344,7 +2344,7 @@ distGiottoImage = function(gobject = NULL, #' @param alpha global alpha value to use. Numeric. Scales from 0 to 1, with 0 #' being fully transparent and 1 being fully visible #' @return image array with 4th channel for transparency -#' @keywords internal +#' @export add_img_array_alpha = function(x, alpha) { img_dims = dim(x) diff --git a/R/methods-centroids.R b/R/methods-centroids.R index ba935825..6c7c1d37 100644 --- a/R/methods-centroids.R +++ b/R/methods-centroids.R @@ -15,12 +15,28 @@ NULL # ---------------------------------------------------------------- # #' @rdname centroids-generic +#' @param append_gpolygon whether to append the centroids results to the +#' `giottoPolygon` instead of returning bare `SpatVector`. Defaults to FALSE #' @export -setMethod('centroids', signature(x = 'giottoPolygon'), - function(x) { - if(!is.null(x@spatVectorCentroids)) { - return(x@spatVectorCentroids) - } else { - return(terra::centroids(x@spatVector)) - } - }) +setMethod( + 'centroids', signature(x = 'giottoPolygon'), + function(x, append_gpolygon = FALSE) + { + if (!is.null(x@spatVectorCentroids)) { # centroids exist in gpoly + if (isTRUE(append_gpolygon)) { + return(x) + } else { + return(x@spatVectorCentroids) + } + + } else { # centroids do not exist in gpoly + ctrds = terra::centroids(x@spatVector) + if (isTRUE(append_gpolygon)) { + x@spatVectorCentroids <- ctrds + return(x) + } else { + return(ctrds) + } + } + } +) diff --git a/R/methods-spin.R b/R/methods-spin.R index a22636af..234279aa 100644 --- a/R/methods-spin.R +++ b/R/methods-spin.R @@ -70,6 +70,29 @@ setMethod('spin', signature(x = 'spatLocsObj'), # internals #### +#' @param DT data.table with xy values +#' @param xy character vector of the columns that contain respectively x and y +#' info +#' @noRd +rotate2D = function(DT, xy = c('x', 'y'), rotate_rad = NULL, rotate_deg = NULL) { + if (is.null(rotate_rad) && is.null(rotate_deg) || + !is.null(rotate_rad) && !is.null(rotate_deg)) { + stop(wrap_txt( + "GiottoClass: rotate2D: + rotation must be supplied through one of 'rotate_rad' or 'rotate_deg'") + ) + } + + if (!is.null(rotate_deg)) rotate_rad = radians(deg = rotate_deg) + + xvals = DT[, xy[[1L]], with = FALSE] + yvals = DT[, xy[[2L]], with = FALSE] + DT[, (xy[[1L]]) := xvals*cos(rotate_rad) + yvals*sin(rotate_rad)] + DT[, (xy[[2L]]) := -xvals*sin(rotate_rad) + yvals*cos(rotate_rad)] + return(DT) +} + +# TODO cleanup rotate_spatial_locations code using rotate2D #' @title Rotate spatial locations #' @name rotate_spatial_locations diff --git a/R/spatial_structures.R b/R/spatial_structures.R index 301c78a3..98264fea 100644 --- a/R/spatial_structures.R +++ b/R/spatial_structures.R @@ -145,19 +145,19 @@ calculate_distance_and_weight <- function(networkDT = NULL, #' @title get_distance #' @name get_distance -#' @description estimate average distance between neighboring cells with network table as input +#' @description estimate average distance between neighboring cells with network +#' table as input #' @param networkDT networkDT #' @param method method -#' @keywords internal +#' @export get_distance <- function(networkDT, - method=c("mean","median") + method = c("mean","median") ){ - - if (method=="median"){ - distance = stats::median(networkDT$distance) - }else if(method=="mean"){ - distance = mean(networkDT$distance) - } + distance = switch( + method, + "median" = stats::median(networkDT$distance), + "mean" = mean(networkDT$distance) + ) return(distance) } @@ -1987,7 +1987,7 @@ createSpatialGrid <- function(gobject, #' @param spatloc spatial_locs slot from giotto object #' @param spatgrid selected spatial_grid slot from giotto object #' @return annotated spatial location data.table -#' @keywords internal +#' @export annotate_spatlocs_with_spatgrid_2D = function(spatloc, spatgrid) { @@ -2031,7 +2031,7 @@ annotate_spatlocs_with_spatgrid_2D = function(spatloc, #' @param spatloc spatial_locs slot from giotto object #' @param spatgrid selected spatial_grid slot from giotto object #' @return annotated spatial location data.table -#' @keywords internal +#' @export annotate_spatlocs_with_spatgrid_3D = function(spatloc, spatgrid) { diff --git a/R/subset.R b/R/subset.R index 03e39d09..3b9bc0be 100644 --- a/R/subset.R +++ b/R/subset.R @@ -1435,15 +1435,6 @@ subsetGiotto <- function(gobject, #' If no spatial locations are available, the polygon information will be subset. #' Spatial IDs surviving the crop are then applied to the rest of the Giotto object #' using [subsetGiotto]. -#' -#' Since spatial subsetting results are unique for each spatial unit, it must -#' be performed separately for each spat_unit that is desired to be spatially -#' subset. -#' Thus, we split the workflow into two functions: -#' \itemize{ -#' \item [subsetGiottoLocs] for subsetting a single spat_unit -#' \item [subsetGiottoLocsMulti] for iterating through every spat_unit requested -#' } #' @inheritParams data_access_params #' @param spat_loc_name name of spatial locations to use within spat_unit #' @param spat_unit spatial unit to subset @@ -1524,7 +1515,8 @@ subsetGiottoLocs = function(gobject, -#' @rdname subsetGiottoLocs +#' @name subsetGiottoLocsMulti +#' @title deprecated #' @inheritParams subsetGiottoLocs #' @param poly_info named list of character vectors. names correspond to spat_unit #' and character vectors are the polygons associated with those spat units diff --git a/man/add_img_array_alpha.Rd b/man/add_img_array_alpha.Rd index beb68c25..c5391960 100644 --- a/man/add_img_array_alpha.Rd +++ b/man/add_img_array_alpha.Rd @@ -21,4 +21,3 @@ Add alpha channel to image array \details{ Add 4th alpha channel to 3 channel RGB image arrays } -\keyword{internal} diff --git a/man/cellMetaObj-class.Rd b/man/cellMetaObj-class.Rd index d8e8f45b..a64c2b96 100644 --- a/man/cellMetaObj-class.Rd +++ b/man/cellMetaObj-class.Rd @@ -3,6 +3,7 @@ \docType{class} \name{cellMetaObj-class} \alias{cellMetaObj-class} +\alias{cellMetaObj} \title{S4 cellMetaObj} \description{ Framework to store cell metadata diff --git a/man/centroids-generic.Rd b/man/centroids-generic.Rd index 229a1035..d0dcdeed 100644 --- a/man/centroids-generic.Rd +++ b/man/centroids-generic.Rd @@ -6,10 +6,13 @@ \alias{centroids,giottoPolygon-method} \title{centroids-generic} \usage{ -\S4method{centroids}{giottoPolygon}(x) +\S4method{centroids}{giottoPolygon}(x, append_gpolygon = FALSE) } \arguments{ \item{x}{object} + +\item{append_gpolygon}{whether to append the centroids results to the +\code{giottoPolygon} instead of returning bare \code{SpatVector}. Defaults to FALSE} } \description{ Access centroids information from polygon objects diff --git a/man/dimObj-class.Rd b/man/dimObj-class.Rd index a776e4e1..3d9f3146 100644 --- a/man/dimObj-class.Rd +++ b/man/dimObj-class.Rd @@ -3,6 +3,7 @@ \docType{class} \name{dimObj-class} \alias{dimObj-class} +\alias{dimObj} \title{S4 dimObj Class} \description{ Framework to store dimension reduction information diff --git a/man/exprObj-class.Rd b/man/exprObj-class.Rd index 97234658..564a872a 100644 --- a/man/exprObj-class.Rd +++ b/man/exprObj-class.Rd @@ -3,6 +3,7 @@ \docType{class} \name{exprObj-class} \alias{exprObj-class} +\alias{exprObj} \title{S4 exprObj} \description{ Framework to store aggregated expression information diff --git a/man/featMetaObj-class.Rd b/man/featMetaObj-class.Rd index e9805eb8..06a93b21 100644 --- a/man/featMetaObj-class.Rd +++ b/man/featMetaObj-class.Rd @@ -3,6 +3,7 @@ \docType{class} \name{featMetaObj-class} \alias{featMetaObj-class} +\alias{featMetaObj} \title{S4 featMetaObj} \description{ Framework to store feature metadata diff --git a/man/nnNetObj-class.Rd b/man/nnNetObj-class.Rd index 12e0e54f..28798307 100644 --- a/man/nnNetObj-class.Rd +++ b/man/nnNetObj-class.Rd @@ -3,6 +3,7 @@ \docType{class} \name{nnNetObj-class} \alias{nnNetObj-class} +\alias{nnNetObj} \title{S4 nnNetObj} \description{ Framework to store nearest neighbor network information diff --git a/man/spatLocsObj-class.Rd b/man/spatLocsObj-class.Rd index 4f7687c4..076d024f 100644 --- a/man/spatLocsObj-class.Rd +++ b/man/spatLocsObj-class.Rd @@ -3,6 +3,7 @@ \docType{class} \name{spatLocsObj-class} \alias{spatLocsObj-class} +\alias{spatLocsObj} \title{S4 spatLocsObj Class} \description{ Framework to store spatial location information diff --git a/man/subsetGiottoLocs.Rd b/man/subsetGiottoLocs.Rd index 52a95a21..6a4d6bd5 100644 --- a/man/subsetGiottoLocs.Rd +++ b/man/subsetGiottoLocs.Rd @@ -2,7 +2,6 @@ % Please edit documentation in R/subset.R \name{subsetGiottoLocs} \alias{subsetGiottoLocs} -\alias{subsetGiottoLocsMulti} \title{Subset by spatial locations} \usage{ subsetGiottoLocs( @@ -21,23 +20,6 @@ subsetGiottoLocs( return_gobject = TRUE, verbose = FALSE ) - -subsetGiottoLocsMulti( - gobject, - spat_unit = ":all:", - feat_type = NULL, - feat_type_ssub = ":all:", - spat_loc_name = NULL, - x_max = NULL, - x_min = NULL, - y_max = NULL, - y_min = NULL, - z_max = NULL, - z_min = NULL, - poly_info = NULL, - return_gobject = TRUE, - verbose = TRUE -) } \arguments{ \item{gobject}{giotto object} @@ -55,8 +37,8 @@ subset} \item{x_max, x_min, y_max, y_min, z_max, z_min}{minimum and maximum x, y, and z coordinates to subset to} -\item{poly_info}{named list of character vectors. names correspond to spat_unit -and character vectors are the polygons associated with those spat units} +\item{poly_info}{character. polygon information to subset (considered +separately from the spat_units to subset)} \item{return_gobject}{return Giotto object} @@ -73,15 +55,6 @@ spatial locations for the \code{spat_unit} will be picked. If no spatial locations are available, the polygon information will be subset. Spatial IDs surviving the crop are then applied to the rest of the Giotto object using \link{subsetGiotto}. - -Since spatial subsetting results are unique for each spatial unit, it must -be performed separately for each spat_unit that is desired to be spatially -subset. -Thus, we split the workflow into two functions: -\itemize{ -\item \link{subsetGiottoLocs} for subsetting a single spat_unit -\item \link{subsetGiottoLocsMulti} for iterating through every spat_unit requested -} } \details{ If \code{return_gobject = FALSE}, then a filtered combined metadata diff --git a/man/subsetGiottoLocsMulti.Rd b/man/subsetGiottoLocsMulti.Rd new file mode 100644 index 00000000..7f6ca26c --- /dev/null +++ b/man/subsetGiottoLocsMulti.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/subset.R +\name{subsetGiottoLocsMulti} +\alias{subsetGiottoLocsMulti} +\title{deprecated} +\usage{ +subsetGiottoLocsMulti( + gobject, + spat_unit = ":all:", + feat_type = NULL, + feat_type_ssub = ":all:", + spat_loc_name = NULL, + x_max = NULL, + x_min = NULL, + y_max = NULL, + y_min = NULL, + z_max = NULL, + z_min = NULL, + poly_info = NULL, + return_gobject = TRUE, + verbose = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit to subset} + +\item{feat_type}{(optional) feat type to use if \code{return_gobject = TRUE} and +a combined data.table output is desired.} + +\item{feat_type_ssub}{which feat types across which to apply the spatial +subset} + +\item{spat_loc_name}{name of spatial locations to use within spat_unit} + +\item{x_max, x_min, y_max, y_min, z_max, z_min}{minimum and maximum x, y, and z coordinates +to subset to} + +\item{poly_info}{named list of character vectors. names correspond to spat_unit +and character vectors are the polygons associated with those spat units} + +\item{return_gobject}{return Giotto object} + +\item{verbose}{be verbose} +} +\description{ +deprecated +} From 23402b4bc849c516e0ed5765c66bef8d0190efc5 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 9 Nov 2023 15:11:45 -0500 Subject: [PATCH 2/5] refactor aggregation and document - run document - refactor calculateOverlapRaster to have the workflow portion be its own separate function so that input can be a poly and points SpatVector instead of a giotto object --- NAMESPACE | 4 + R/aggregate.R | 139 +++++++++++++--------- man/annotate_spatlocs_with_spatgrid_2D.Rd | 1 - man/annotate_spatlocs_with_spatgrid_3D.Rd | 1 - man/calculateOverlapRaster.Rd | 7 +- man/calculate_overlap_raster.Rd | 21 ++++ man/get_distance.Rd | 4 +- man/gpoly_from_dfr_smoothed_wrapped.Rd | 23 ---- 8 files changed, 115 insertions(+), 85 deletions(-) create mode 100644 man/calculate_overlap_raster.Rd delete mode 100644 man/gpoly_from_dfr_smoothed_wrapped.Rd diff --git a/NAMESPACE b/NAMESPACE index 66eed63d..5e857997 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -27,6 +27,8 @@ export(anndataToGiotto) export(annotateGiotto) export(annotateSpatialGrid) export(annotateSpatialNetwork) +export(annotate_spatlocs_with_spatgrid_2D) +export(annotate_spatlocs_with_spatgrid_3D) export(calculateMetaTable) export(calculateMetaTableCells) export(calculateOverlapParallel) @@ -34,6 +36,7 @@ export(calculateOverlapPolygonImages) export(calculateOverlapRaster) export(calculateOverlapSerial) export(calculateSpatCellMetadataProportions) +export(calculate_overlap_raster) export(changeGiottoInstructions) export(changeImageBg) export(checkGiottoEnvironment) @@ -117,6 +120,7 @@ export(get_adj_rescale_img) export(get_args) export(get_cell_metadata) export(get_dimReduction) +export(get_distance) export(get_expression_values) export(get_feature_info) export(get_feature_metadata) diff --git a/R/aggregate.R b/R/aggregate.R index 73a52790..7d6ad144 100644 --- a/R/aggregate.R +++ b/R/aggregate.R @@ -52,12 +52,13 @@ polygon_to_raster = function(polygon, field = NULL) { #' @title calculateOverlapRaster #' @name calculateOverlapRaster -#' @description calculate overlap between cellular structures (polygons) and features (points) +#' @description calculate overlap between cellular structures (polygons) and +#' features (points) #' @param gobject giotto object #' @param name_overlap name for the overlap results (default to feat_info parameter) -#' @param spatial_info polygon information +#' @param spatial_info character. name polygon information #' @param poly_ID_names (optional) list of poly_IDs to use -#' @param feat_info feature information +#' @param feat_info character. name of feature information #' @param feat_subset_column feature info column to subset features with #' @param feat_subset_ids ids within feature info column to use for subsetting #' @param count_info_column column with count information (optional) @@ -67,25 +68,18 @@ polygon_to_raster = function(polygon, field = NULL) { #' @details Serial overlapping function. #' @concept overlap #' @export -calculateOverlapRaster = function(gobject, - name_overlap = NULL, - spatial_info = NULL, - poly_ID_names = NULL, - feat_info = NULL, - feat_subset_column = NULL, - feat_subset_ids = NULL, - count_info_column = NULL, - return_gobject = TRUE, - verbose = TRUE) { - - # define for := - poly_ID = NULL - poly_i = NULL - ID = NULL - x = NULL - y = NULL - feat_ID = NULL - feat_ID_uniq = NULL +calculateOverlapRaster = function( + gobject, + name_overlap = NULL, + spatial_info = NULL, + poly_ID_names = NULL, + feat_info = NULL, + feat_subset_column = NULL, + feat_subset_ids = NULL, + count_info_column = NULL, + return_gobject = TRUE, + verbose = TRUE +) { # set defaults if not provided if(is.null(feat_info)) { @@ -101,30 +95,75 @@ calculateOverlapRaster = function(gobject, } - # spatial vector - if(verbose) cat('1. convert polygon to raster \n') - spatvec = gobject@spatial_info[[spatial_info]]@spatVector + # get information from gobject + # * spatial vector + spatvec = getPolygonInfo( + gobject = gobject, + polygon_name = spatial_info, + return_giottoPolygon = FALSE + ) + + # * point vector + pointvec = getFeatureInfo( + gobject = gobject, + feat_type = feat_info, + return_giottoPoints = FALSE, + set_defaults = FALSE + ) - # subset spatvec + + # subset points and polys if needed + # * subset spatvec if(!is.null(poly_ID_names)) { spatvec = spatvec[spatvec$poly_ID %in% poly_ID_names] } - # spatial vector to raster - spatrast_res = polygon_to_raster(spatvec, field = 'poly_ID') - spatrast = spatrast_res[['raster']] - ID_vector = spatrast_res[['ID_vector']] - - # point vector - pointvec = gobject@feat_info[[feat_info]]@spatVector - - # subset points if needed + # * subset points if needed # e.g. to select transcripts within a z-plane if(!is.null(feat_subset_column) & !is.null(feat_subset_ids)) { bool_vector = pointvec[[feat_subset_column]][[1]] %in% feat_subset_ids pointvec = pointvec[bool_vector] } + # run overlap workflow + overlap_points = calculate_overlap_raster( + spatvec = spatvec, + pointvec = pointvec, + verbose = verbose + ) + + # return values + if(isTRUE(return_gobject)) { + + if(is.null(name_overlap)) name_overlap = feat_info + gobject@spatial_info[[spatial_info]]@overlaps[[name_overlap]] = overlap_points + return(gobject) + + } else { + return(overlap_points) + } +} + + + +#' @name calculate_overlap_raster +#' @title Find feature points overlapped by rasterized polygon +#' @param spatvec `SpatVector` polygon from a `giottoPolygon` object +#' @param pointvec `SpatVector` points from a `giottoPoints` object +#' @param verbose be verbose +#' @return `SpatVector` of overlapped points info +#' @export +calculate_overlap_raster = function(spatvec, pointvec, verbose = TRUE) { + + # DT vars + poly_ID = poly_i = ID = x = y = feat_ID = feat_ID_uniq = NULL + + # spatial vector to raster + if(verbose) cat('1. convert polygon to raster \n') + spatrast_res = polygon_to_raster(spatvec, field = 'poly_ID') + spatrast = spatrast_res[['raster']] + ID_vector = spatrast_res[['ID_vector']] + ## overlap between raster and point if(verbose) cat('2. overlap raster and points \n') overlap_test = terra::extract(x = spatrast, y = pointvec) @@ -136,7 +175,7 @@ calculateOverlapRaster = function(gobject, # add point information if(verbose) cat('4. add points information \n') - pointvec_dt = spatVector_to_dt(pointvec) + pointvec_dt = data.table::as.data.table(pointvec, geom = "XY") pointvec_dt_x = pointvec_dt$x ; names(pointvec_dt_x) = pointvec_dt$geom pointvec_dt_y = pointvec_dt$y ; names(pointvec_dt_y) = pointvec_dt$geom @@ -154,25 +193,15 @@ calculateOverlapRaster = function(gobject, } if(verbose) cat('5. create overlap polygon information \n') - overlap_test_dt_spatvector = terra::vect(x = as.matrix(overlap_test_dt[, c('x', 'y'), with = F]), - type = "points", - atts = overlap_test_dt[, c('poly_ID', 'feat_ID', 'feat_ID_uniq', count_info_column), with = F]) - names(overlap_test_dt_spatvector) = c('poly_ID', 'feat_ID', 'feat_ID_uniq', count_info_column) - - - - if(return_gobject == TRUE) { - if(is.null(name_overlap)) { - name_overlap = feat_info - } - - gobject@spatial_info[[spatial_info]]@overlaps[[name_overlap]] = overlap_test_dt_spatvector - return(gobject) - - } else { - return(overlap_test_dt_spatvector) - } - + overlap_test_dt_spatvector = terra::vect( + x = as.matrix(overlap_test_dt[, c('x', 'y'), with = F]), + type = "points", + atts = overlap_test_dt[, c('poly_ID', 'feat_ID', 'feat_ID_uniq', count_info_column), with = F] + ) + names(overlap_test_dt_spatvector) = c( + 'poly_ID', 'feat_ID', 'feat_ID_uniq', count_info_column + ) + return(overlap_test_dt_spatvector) } diff --git a/man/annotate_spatlocs_with_spatgrid_2D.Rd b/man/annotate_spatlocs_with_spatgrid_2D.Rd index f18933c4..520428a9 100644 --- a/man/annotate_spatlocs_with_spatgrid_2D.Rd +++ b/man/annotate_spatlocs_with_spatgrid_2D.Rd @@ -17,4 +17,3 @@ annotated spatial location data.table \description{ annotate spatial locations with 2D spatial grid information } -\keyword{internal} diff --git a/man/annotate_spatlocs_with_spatgrid_3D.Rd b/man/annotate_spatlocs_with_spatgrid_3D.Rd index 4b1d269d..8ade34dc 100644 --- a/man/annotate_spatlocs_with_spatgrid_3D.Rd +++ b/man/annotate_spatlocs_with_spatgrid_3D.Rd @@ -17,4 +17,3 @@ annotated spatial location data.table \description{ annotate spatial locations with 3D spatial grid information } -\keyword{internal} diff --git a/man/calculateOverlapRaster.Rd b/man/calculateOverlapRaster.Rd index ec711516..45c7aed5 100644 --- a/man/calculateOverlapRaster.Rd +++ b/man/calculateOverlapRaster.Rd @@ -22,11 +22,11 @@ calculateOverlapRaster( \item{name_overlap}{name for the overlap results (default to feat_info parameter)} -\item{spatial_info}{polygon information} +\item{spatial_info}{character. name polygon information} \item{poly_ID_names}{(optional) list of poly_IDs to use} -\item{feat_info}{feature information} +\item{feat_info}{character. name of feature information} \item{feat_subset_column}{feature info column to subset features with} @@ -42,7 +42,8 @@ calculateOverlapRaster( giotto object or spatVector with overlapping information } \description{ -calculate overlap between cellular structures (polygons) and features (points) +calculate overlap between cellular structures (polygons) and +features (points) } \details{ Serial overlapping function. diff --git a/man/calculate_overlap_raster.Rd b/man/calculate_overlap_raster.Rd new file mode 100644 index 00000000..278fe3a5 --- /dev/null +++ b/man/calculate_overlap_raster.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/aggregate.R +\name{calculate_overlap_raster} +\alias{calculate_overlap_raster} +\title{Find feature points overlapped by rasterized polygon} +\usage{ +calculate_overlap_raster(spatvec, pointvec, verbose = TRUE) +} +\arguments{ +\item{spatvec}{\code{SpatVector} polygon from a \code{giottoPolygon} object} + +\item{pointvec}{\code{SpatVector} points from a \code{giottoPoints} object} + +\item{verbose}{be verbose} +} +\value{ +\code{SpatVector} of overlapped points info +} +\description{ +Find feature points overlapped by rasterized polygon +} diff --git a/man/get_distance.Rd b/man/get_distance.Rd index bb432137..67005f6a 100644 --- a/man/get_distance.Rd +++ b/man/get_distance.Rd @@ -12,6 +12,6 @@ get_distance(networkDT, method = c("mean", "median")) \item{method}{method} } \description{ -estimate average distance between neighboring cells with network table as input +estimate average distance between neighboring cells with network +table as input } -\keyword{internal} diff --git a/man/gpoly_from_dfr_smoothed_wrapped.Rd b/man/gpoly_from_dfr_smoothed_wrapped.Rd deleted file mode 100644 index 83d65ce8..00000000 --- a/man/gpoly_from_dfr_smoothed_wrapped.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto_structures.R -\name{gpoly_from_dfr_smoothed_wrapped} -\alias{gpoly_from_dfr_smoothed_wrapped} -\title{Polygon creation and smoothing for parallel} -\usage{ -gpoly_from_dfr_smoothed_wrapped( - segmdfr, - name = "cell", - calc_centroids = FALSE, - smooth_polygons = FALSE, - vertices = 20L, - k = 3L, - set_neg_to_zero = TRUE, - skip_eval_dfr = FALSE, - copy_dt = TRUE, - verbose = TRUE -) -} -\description{ -Polygon creation and smoothing for parallel -} -\keyword{internal} From be7b024bb7dc02d4950d9de14c0b7f6f7ebe02c8 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 10 Nov 2023 03:33:41 -0500 Subject: [PATCH 3/5] `as.stars()` converter --- NAMESPACE | 1 + NEWS.md | 3 +- R/create.R | 8 ----- R/generics.R | 1 + R/giotto_structures.R | 6 ++-- R/methods-coerce.R | 78 ++++++++++++++++++++++++++++++++++++++++--- man/as.data.table.Rd | 3 +- man/as.sf.Rd | 10 ++++-- man/as.stars.Rd | 30 +++++++++++++++++ 9 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 man/as.stars.Rd diff --git a/NAMESPACE b/NAMESPACE index 5e857997..877546e8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -315,6 +315,7 @@ exportMethods("spatUnit<-") exportMethods(activeFeatType) exportMethods(activeSpatUnit) exportMethods(as.sf) +exportMethods(as.stars) exportMethods(centroids) exportMethods(colnames) exportMethods(copy) diff --git a/NEWS.md b/NEWS.md index 03f5abbd..fcd14bd2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,8 +8,9 @@ - Added `crop()` method for `giottoLargeImage`, `giottoPoints` - Added `terraVectData` as virtual parent class for `giottoPolygon` and `giottoPoints` classes - Added `$` and `$<-` methods for `terraVectData` -- Added `[` subsetting for `giottoPoints` and `giottoPolygon` +- Added `[` subsetting for `giottoPoints` and `giottoPolygon` with numerical, logical, and character (by ID) - Added `setGiotto()` generic +- Added `as.sf()` and `as.stars()` converters for `giottoPoints` and `giottoPolygon` ## Changes - Improved performance of gefToGiotto() diff --git a/R/create.R b/R/create.R index f4d106cd..714915b6 100644 --- a/R/create.R +++ b/R/create.R @@ -659,12 +659,6 @@ createGiottoObjectSubcellular = function(gpolygons = NULL, centroidsDT_loc = centroidsDT[, .(poly_ID, x, y)] colnames(centroidsDT_loc) = c('cell_ID', 'sdimx', 'sdimy') - # gobject = set_spatial_locations(gobject = gobject, - # spat_unit = polygon_info, - # spat_loc_name = 'raw', - # spatlocs = centroidsDT_loc, - # verbose = FALSE) - locsObj = create_spat_locs_obj(name = 'raw', coordinates = centroidsDT_loc, spat_unit = polygon_info, @@ -778,9 +772,7 @@ createGiottoObjectSubcellular = function(gpolygons = NULL, gobject@feat_metadata[[feat_type]] = data.table::as.data.table(gobject@feat_metadata[[feat_type]]) gobject@feat_metadata[[feat_type]][, feat_ID := gobject@feat_ID[[feat_type]]] } - } - } diff --git a/R/generics.R b/R/generics.R index 9ffd665e..5f876fd8 100644 --- a/R/generics.R +++ b/R/generics.R @@ -69,4 +69,5 @@ setGeneric('setGiotto', function(gobject, x, ...) standardGeneric('setGiotto')) # coerce #### setGeneric('as.sf', function(x, ...) standardGeneric('as.sf')) +setGeneric('as.stars', function(x, ...) standardGeneric('as.stars')) diff --git a/R/giotto_structures.R b/R/giotto_structures.R index eebe88d1..1cf40f15 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -582,8 +582,10 @@ smoothGiottoPolygons = function(gpolygon, #' @param x data.frame object #' @param verbose be verbose #' @keywords internal -create_spatvector_object_from_dfr = function(x, - verbose = TRUE) { +create_spatvector_object_from_dfr = function( + x, + verbose = TRUE +) { x = data.table::as.data.table(x) diff --git a/R/methods-coerce.R b/R/methods-coerce.R index 4851031b..0c68b466 100644 --- a/R/methods-coerce.R +++ b/R/methods-coerce.R @@ -17,11 +17,21 @@ NULL #' @title Coerce to sf #' @name as.sf #' @param x The object to coerce +#' @param drop When TRUE, returned object will be the sf object instead of +#' wrapped in a `giottoPoints` or `giottoPolygon` object +#' @family As coercion functions +NULL + +#' @title Coerce to stars +#' @name as.stars +#' @param x The object to coerce +#' @param drop When TRUE, returned object will be the sf object instead of +#' wrapped in a `giottoPoints` or `giottoPolygon` object #' @family As coercion functions NULL # ---------------------------------------------------------------- # -# SpatVector -> DT #### +# to DT #### #' @rdname as.data.table #' @method as.data.table SpatVector #' @export @@ -55,7 +65,7 @@ as.data.table.giottoPoints <- function(x, ...) { } -# DT -> SpatVector #### +# to SpatVector #### # TODO # as.points / as.polygon generics from terra are an option, but terra deals with # this kind of conversion using vect() usually @@ -72,7 +82,7 @@ as.data.table.giottoPoints <- function(x, ...) { -# SpatVector -> sf #### +# to sf #### #' @rdname as.sf #' @export setMethod('as.sf', signature('SpatVector'), @@ -81,12 +91,70 @@ setMethod('as.sf', signature('SpatVector'), #' @rdname as.sf #' @export setMethod('as.sf', signature('giottoPolygon'), - function(x) spatvector_to_sf(x[])) + function(x, drop = TRUE) { + + if (isTRUE(drop)) { + return(spatvector_to_sf(x[])) + } else { + x <- do_gpoly(x = x, what = spatvector_to_sf, args = list()) + return(x) + } + }) #' @rdname as.sf #' @export setMethod('as.sf', signature('giottoPoints'), - function(x) spatvector_to_sf(x[])) + function(x, drop = TRUE) { + s <- spatvector_to_sf(x[]) + + if (isTRUE(drop)) { + return(s) + } else { + x[] <- s + return(x) + } + }) + +# to stars #### + +# st_as_stars does not handle SpatVector. Only SpatRaster +# however, conversions from sf work fine +#' @rdname as.stars +#' @export +setMethod('as.stars', signature('SpatVector'), + function(x) { + as.sf(x) %>% + stars::st_as_stars() + }) + +#' @rdname as.stars +#' @export +setMethod('as.stars', signature('giottoPolygon'), + function(x, drop = TRUE) { + if (isTRUE(drop)) { + return(as.stars(x[])) + } else { + x <- as.sf(x, drop = FALSE) + x <- do_gpoly(x = x, what = stars::st_as_stars, args = list()) + return(x) + } + }) + +#' @rdname as.stars +#' @export +setMethod('as.stars', signature('giottoPoints'), + function(x, drop = TRUE) { + s <- as.stars(x[]) + + if (isTRUE(drop)) { + return(s) + } else { + x[] <- s + return(x) + } + }) + + # internals #### diff --git a/man/as.data.table.Rd b/man/as.data.table.Rd index 0dc5ed96..469b8fa7 100644 --- a/man/as.data.table.Rd +++ b/man/as.data.table.Rd @@ -37,6 +37,7 @@ Coerce to data.table if possible } \seealso{ Other As coercion functions: -\code{\link{as.sf}()} +\code{\link{as.sf}()}, +\code{\link{as.stars}()} } \concept{As coercion functions} diff --git a/man/as.sf.Rd b/man/as.sf.Rd index 4ed1ac0b..d6aa0557 100644 --- a/man/as.sf.Rd +++ b/man/as.sf.Rd @@ -9,18 +9,22 @@ \usage{ \S4method{as.sf}{SpatVector}(x) -\S4method{as.sf}{giottoPolygon}(x) +\S4method{as.sf}{giottoPolygon}(x, drop = TRUE) -\S4method{as.sf}{giottoPoints}(x) +\S4method{as.sf}{giottoPoints}(x, drop = TRUE) } \arguments{ \item{x}{The object to coerce} + +\item{drop}{When TRUE, returned object will be the sf object instead of +wrapped in a \code{giottoPoints} or \code{giottoPolygon} object} } \description{ Coerce to sf } \seealso{ Other As coercion functions: -\code{\link{as.data.table}()} +\code{\link{as.data.table}()}, +\code{\link{as.stars}()} } \concept{As coercion functions} diff --git a/man/as.stars.Rd b/man/as.stars.Rd new file mode 100644 index 00000000..6f85b5b8 --- /dev/null +++ b/man/as.stars.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-coerce.R +\name{as.stars} +\alias{as.stars} +\alias{as.stars,SpatVector-method} +\alias{as.stars,giottoPolygon-method} +\alias{as.stars,giottoPoints-method} +\title{Coerce to stars} +\usage{ +\S4method{as.stars}{SpatVector}(x) + +\S4method{as.stars}{giottoPolygon}(x, drop = TRUE) + +\S4method{as.stars}{giottoPoints}(x, drop = TRUE) +} +\arguments{ +\item{x}{The object to coerce} + +\item{drop}{When TRUE, returned object will be the sf object instead of +wrapped in a \code{giottoPoints} or \code{giottoPolygon} object} +} +\description{ +Coerce to stars +} +\seealso{ +Other As coercion functions: +\code{\link{as.data.table}()}, +\code{\link{as.sf}()} +} +\concept{As coercion functions} From 5cfad68ae41d9d2af3e6192afaba42f7cc014e75 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 10 Nov 2023 11:52:09 -0500 Subject: [PATCH 4/5] fix: issue with aggregation workflow - missing param for counts info added --- R/aggregate.R | 16 +++++++++++++--- man/calculateOverlapRaster.Rd | 5 ++++- man/calculate_overlap_raster.Rd | 18 +++++++++++++++--- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/R/aggregate.R b/R/aggregate.R index 7d6ad144..6394dd8e 100644 --- a/R/aggregate.R +++ b/R/aggregate.R @@ -53,7 +53,7 @@ polygon_to_raster = function(polygon, field = NULL) { #' @title calculateOverlapRaster #' @name calculateOverlapRaster #' @description calculate overlap between cellular structures (polygons) and -#' features (points) +#' features (points). #' @param gobject giotto object #' @param name_overlap name for the overlap results (default to feat_info parameter) #' @param spatial_info character. name polygon information @@ -67,6 +67,7 @@ polygon_to_raster = function(polygon, field = NULL) { #' @return giotto object or spatVector with overlapping information #' @details Serial overlapping function. #' @concept overlap +#' @seealso [calculate_overlap_raster()] #' @export calculateOverlapRaster = function( gobject, @@ -129,6 +130,7 @@ calculateOverlapRaster = function( overlap_points = calculate_overlap_raster( spatvec = spatvec, pointvec = pointvec, + count_info_column = count_info_column, verbose = verbose ) @@ -147,13 +149,21 @@ calculateOverlapRaster = function( #' @name calculate_overlap_raster -#' @title Find feature points overlapped by rasterized polygon +#' @title Find feature points overlapped by rasterized polygon. +#' @description Core workflow function that accepts simple `SpatVector` inputs, +#' performs rasterization of the polys and then checks for overlaps. #' @param spatvec `SpatVector` polygon from a `giottoPolygon` object #' @param pointvec `SpatVector` points from a `giottoPoints` object +#' @param count_info_column column with count information (optional) #' @param verbose be verbose #' @return `SpatVector` of overlapped points info +#' @concept overlap +#' @seealso [calculateOverlapRaster()] #' @export -calculate_overlap_raster = function(spatvec, pointvec, verbose = TRUE) { +calculate_overlap_raster = function(spatvec, + pointvec, + count_info_column = NULL, + verbose = TRUE) { # DT vars poly_ID = poly_i = ID = x = y = feat_ID = feat_ID_uniq = NULL diff --git a/man/calculateOverlapRaster.Rd b/man/calculateOverlapRaster.Rd index 45c7aed5..4256dfde 100644 --- a/man/calculateOverlapRaster.Rd +++ b/man/calculateOverlapRaster.Rd @@ -43,9 +43,12 @@ giotto object or spatVector with overlapping information } \description{ calculate overlap between cellular structures (polygons) and -features (points) +features (points). } \details{ Serial overlapping function. } +\seealso{ +\code{\link[=calculate_overlap_raster]{calculate_overlap_raster()}} +} \concept{overlap} diff --git a/man/calculate_overlap_raster.Rd b/man/calculate_overlap_raster.Rd index 278fe3a5..f62fdc89 100644 --- a/man/calculate_overlap_raster.Rd +++ b/man/calculate_overlap_raster.Rd @@ -2,20 +2,32 @@ % Please edit documentation in R/aggregate.R \name{calculate_overlap_raster} \alias{calculate_overlap_raster} -\title{Find feature points overlapped by rasterized polygon} +\title{Find feature points overlapped by rasterized polygon.} \usage{ -calculate_overlap_raster(spatvec, pointvec, verbose = TRUE) +calculate_overlap_raster( + spatvec, + pointvec, + count_info_column = NULL, + verbose = TRUE +) } \arguments{ \item{spatvec}{\code{SpatVector} polygon from a \code{giottoPolygon} object} \item{pointvec}{\code{SpatVector} points from a \code{giottoPoints} object} +\item{count_info_column}{column with count information (optional)} + \item{verbose}{be verbose} } \value{ \code{SpatVector} of overlapped points info } \description{ -Find feature points overlapped by rasterized polygon +Core workflow function that accepts simple \code{SpatVector} inputs, +performs rasterization of the polys and then checks for overlaps. +} +\seealso{ +\code{\link[=calculateOverlapRaster]{calculateOverlapRaster()}} } +\concept{overlap} From 74af0aedfba053c880172e78ab2a1d1f1b5a2661 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 10 Nov 2023 15:27:12 -0500 Subject: [PATCH 5/5] Update methods-show.R --- R/methods-show.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/methods-show.R b/R/methods-show.R index 0ee8c69e..72e05833 100644 --- a/R/methods-show.R +++ b/R/methods-show.R @@ -98,7 +98,7 @@ setMethod( cat('attached images ------------------\n') if('image' %in% avail_im$img_type) { if(sum(avail_im$img_type == 'image') > 3) { - cat( 'giottoLargeImage :', sum(avail_im$img_type == 'image'), 'items...\n') + cat( 'giottoImage :', sum(avail_im$img_type == 'image'), 'items...\n') } else { cat('giottoImage :', wrap_txt(avail_im[img_type == 'image', name]), '\n') }