Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c23ff68
fix outdated argument for seurat object and fix typo
josschavezf Oct 5, 2025
b73ac46
Merge pull request #326 from josschavezf/dev
josschavezf Oct 5, 2025
181bc69
upgrade R version
josschavezf Oct 8, 2025
5e1da1e
replace = -> assingment symbol
josschavezf Oct 8, 2025
200183b
fix indentation
josschavezf Oct 8, 2025
00ef247
run devtools::document
josschavezf Oct 8, 2025
dba4dac
Merge pull request #327 from josschavezf/dev
josschavezf Oct 8, 2025
e131ff1
Add functionality to read OME Map Annotations (K/Vs) (tif_metadata)
iqraAmin Oct 18, 2025
77ccdd4
Merge pull request #328 from iqraAmin/dev
jiajic Oct 20, 2025
66eca1c
fix: typo
wwang-chcn Oct 28, 2025
9d8dce4
Merge pull request #330 from wwang-chcn/dev
jiajic Oct 28, 2025
62c2418
slot checking changes
jiajic Oct 30, 2025
9790ce4
chore: docs
jiajic Oct 30, 2025
f6e8fdc
fix: tests now align with changes
jiajic Oct 30, 2025
1ef5eaf
Merge pull request #331 from jiajic/slot_checks_update
jiajic Oct 30, 2025
451e35a
new: misc slot for unstructured data
jiajic Nov 6, 2025
af288d9
Merge pull request #332 from jiajic/misc_patch
jiajic Nov 6, 2025
e86adc6
require misc to be a list
jiajic Nov 6, 2025
bbc3983
Merge pull request #333 from jiajic/misc_patch
jiajic Nov 6, 2025
f77f34f
fix numeric_version() and numeric incompat
jiajic Nov 6, 2025
8bf876f
run devtools::document
josschavezf Nov 7, 2025
824c1e4
Merge pull request #334 from josschavezf/dev
josschavezf Nov 7, 2025
9dcbb81
fix: automatically use count column if present
jiajic Dec 12, 2025
937fa30
enh: autodetect "count" col in feature points
jiajic Dec 12, 2025
b3b2294
chore: docs
jiajic Dec 12, 2025
c7af931
conflict fix
jiajic Dec 12, 2025
54b25ad
Merge pull request #335 from drieslab/dev
jiajic Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: GiottoClass
Title: Giotto Suite Object Definitions and Framework
Version: 0.4.10
Version: 0.4.12
Authors@R: c(
person("Ruben", "Dries", email = "rubendries@gmail.com",
role = c("aut", "cre"), comment = c(ORCID = "0000-0001-7650-7754")),
Expand All @@ -26,7 +26,7 @@ Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.3
Depends:
R (>= 4.4.1)
R (>= 4.5.0)
Imports:
checkmate,
data.table (>= 1.12.2),
Expand Down
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# GiottoClass 0.4.12 (2025/12/12)

## enhancements
- automatic checking for `"count"` column in feature info

## new
- `misc` slot for storing unstructured data

## enhancements
- escape hatch for gobject initialize checking. Set option `"giotto.init_check_severity"` to `"stop"` (default), or `"warning"` depending on needs.

# GiottoClass 0.4.10 (2025/09/30)

## bug fixes
Expand Down
34 changes: 31 additions & 3 deletions R/aggregate.R
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ polygon_to_raster <- function(polygon, field = NULL) {
#' in `feat_subset_column` in order to subset feature points when performing
#' overlap calculation.
#' @param count_info_column character. (optional) column with count information.
#' Useful in cases when more than one detection is reported per point.
#' Useful in cases when more than one detection is reported per point. If a
#' column called "count" is present in the feature points data, it will be
#' automatically selected.
#' @param verbose be verbose
#' @param \dots additional params to pass to methods.
#' @details `feat_subset_column`, `feat_subset_ids`, and `count_info_column` are
Expand Down Expand Up @@ -328,6 +330,17 @@ setMethod(
return_gpolygon = TRUE,
verbose = TRUE,
...) {
if ("count" %in% names(y) && is.null(count_info_column)) {
vmsg(.v = verbose,
"[overlap] Found column \"count\" in feature info.
- Using as `count_info_column`
[!] Set count_info_column = FALSE to disable.")
count_info_column <- "count"
}
if (isFALSE(count_info_column)) {
count_info_column <- NULL
}
Comment on lines +333 to +342
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Count-column autodetect should key off y[] (SpatVector) to avoid names() method ambiguity.

Right now detection uses names(y) while the actual downstream overlap runs on y[]. If names(giottoPoints) ever diverges from names(giottoPoints[]), autodetect can misfire.

-        if ("count" %in% names(y) && is.null(count_info_column)) {
+        if ("count" %in% names(y[]) && is.null(count_info_column)) {
             vmsg(.v = verbose,
                 "[overlap] Found column \"count\" in feature info.
                 - Using as `count_info_column`
                 [!] Set count_info_column = FALSE to disable.")
             count_info_column <- "count"
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if ("count" %in% names(y) && is.null(count_info_column)) {
vmsg(.v = verbose,
"[overlap] Found column \"count\" in feature info.
- Using as `count_info_column`
[!] Set count_info_column = FALSE to disable.")
count_info_column <- "count"
}
if (isFALSE(count_info_column)) {
count_info_column <- NULL
}
if ("count" %in% names(y[]) && is.null(count_info_column)) {
vmsg(.v = verbose,
"[overlap] Found column \"count\" in feature info.
- Using as `count_info_column`
[!] Set count_info_column = FALSE to disable.")
count_info_column <- "count"
}
if (isFALSE(count_info_column)) {
count_info_column <- NULL
}
🤖 Prompt for AI Agents
In R/aggregate.R around lines 333 to 342, the autodetect for a "count" info
column uses names(y) which can differ from the actual feature attributes
accessed as y[], so change the check to inspect names(y[]) (or the equivalent
accessor that returns the SpatVector attribute names) instead of names(y);
update the vmsg conditional and assignment to use that result, and keep the
existing logic that sets count_info_column <- "count" and converts FALSE to
NULL.


res <- calculateOverlap(
x = x[],
y = y[],
Expand Down Expand Up @@ -1220,7 +1233,9 @@ calculateOverlapParallel <- function(gobject,
#' @param x object containing overlaps info. Can be giotto object or SpatVector
#' points or data.table of overlaps generated from `calculateOverlap`
#' @param name name for the overlap count matrix
#' @param count_info_column column with count information
#' @param count_info_column column with count information. If a
#' column called "count" is present in the feature points data, it will be
#' automatically selected.
#' @param \dots additional params to pass to methods
#' @concept overlap
#' @returns giotto object or count matrix
Expand Down Expand Up @@ -1260,7 +1275,7 @@ setMethod(
...) {
type <- match.arg(type, choices = c("point", "intensity"))
checkmate::assert_character(name, len = 1L)
if (!is.null(count_info_column)) {
if (!is.null(count_info_column) && !isFALSE(count_info_column)) {
checkmate::assert_character(count_info_column, len = 1L)
}
checkmate::assert_logical(return_gobject)
Expand Down Expand Up @@ -1439,6 +1454,19 @@ setMethod(


# 2. Perform aggregation to counts DT

# autodetect counts col
if ("count" %in% names(dtoverlap) && is.null(count_info_column)) {
vmsg(.v = verbose,
"[overlap] Found column \"count\" in feature info.
- Using as `count_info_column`
[!] Set count_info_column = FALSE to disable.")
count_info_column <- "count"
}
if (isFALSE(count_info_column)) {
count_info_column <- NULL
}

if (!is.null(count_info_column)) { # if there is a counts col

if (!count_info_column %in% colnames(dtoverlap)) {
Expand Down
27 changes: 19 additions & 8 deletions R/classes.R
Original file line number Diff line number Diff line change
Expand Up @@ -453,13 +453,14 @@ updateGiottoObject <- function(gobject) {
if (!is.null(attr(gobject, "OS_platform"))) {
attr(gobject, "OS_platform") <- NULL
}
if (is.null(attr(gobject, "versions"))) { # apply default version 0
if (is.null(attr(gobject, "versions"))) { # apply default version 0.0.0
attr(gobject, "versions") <- .versions_info()
gobject@versions$gclass <- 0 # untracked
gobject@versions$gclass <- "0.0.0" # untracked
}

# warn if gobject newer than package
if (as.character(.gversion(gobject)) > as.character(packageVersion("GiottoClass"))) {
if (.gversion(gobject) >
numeric_version(packageVersion("GiottoClass"))) {
warning(
call. = FALSE,
sprintf(
Expand All @@ -473,14 +474,19 @@ updateGiottoObject <- function(gobject) {
# [version-based updates] -------------------------------------------------#

# GiottoClass 0.3.0 removes @largeImages slot
if (.gversion(gobject) < "0.3.0") {
if (.gversion(gobject) < numeric_version("0.3.0")) {
gobject <- .update_image_slot(gobject)
}

# GiottoClass 0.1.2 image updates moved here
# TODO remove in future update
gobject@images <- lapply(gobject@images, .update_giotto_image)

# GiottoClass 0.4.12 adds @misc slot
if (.gversion(gobject) < numeric_version("0.4.12")) {
attr(gobject, "misc") <- list()
}

# -------------------------------------------------------------------------#

# finally, set updated version number
Expand Down Expand Up @@ -567,6 +573,7 @@ updateGiottoObject <- function(gobject) {
#' @slot join_info information about joined Giotto objects
#' @slot multiomics multiomics integration results
#' @slot h5_file path to h5 file
#' @slot misc miscellaneous or unstructured data
#' @details
#'
#' \[**initialize**\]
Expand Down Expand Up @@ -618,7 +625,8 @@ giotto <- setClass(
versions = "list",
join_info = "ANY",
multiomics = "ANY",
h5_file = "ANY"
h5_file = "ANY",
misc = "list"
# mirai = 'list'
),
prototype = list(
Expand All @@ -643,7 +651,8 @@ giotto <- setClass(
versions = .versions_info(),
join_info = NULL,
multiomics = NULL,
h5_file = NULL
h5_file = NULL,
misc = list()
# mirai = list()
)

Expand Down Expand Up @@ -694,7 +703,8 @@ setClass(
versions = "ANY",
join_info = "ANY",
multiomics = "ANY",
h5_file = "ANY"
h5_file = "ANY",
misc = "list"
),
prototype = list(
packed_spatial_info = NULL,
Expand All @@ -718,7 +728,8 @@ setClass(
versions = NULL,
join_info = NULL,
multiomics = NULL,
h5_file = NULL
h5_file = NULL,
misc = list()
)
)

Expand Down
6 changes: 3 additions & 3 deletions R/combine_metadata.R
Original file line number Diff line number Diff line change
Expand Up @@ -695,10 +695,10 @@ calculateLabelProportions <- function(gobject, labels,
), call. = FALSE)
}

spat_unit = set_default_spat_unit(
spat_unit <- set_default_spat_unit(
gobject = gobject, spat_unit = spat_unit
)
feat_type = set_default_feat_type(
feat_type <- set_default_feat_type(
gobject = gobject, spat_unit = spat_unit, feat_type = feat_type
)

Expand Down Expand Up @@ -881,7 +881,7 @@ calculateLabelProportions <- function(gobject, labels,
sn <- sn[, c("source", "target")] # drop weights info if any
} else if (!"weight" %in% colnames(sn) || isFALSE(weights)) {
warning(wrap_txt("No 'weight' information present in spatial network.
Using adjacency instead."), call. = FALSE)
Using adjacency instead."), call. = FALSE)
sn[, "weight" := 1] # fallback if no weight info exists
}
# ensure unique
Expand Down
2 changes: 1 addition & 1 deletion R/create.R
Original file line number Diff line number Diff line change
Expand Up @@ -3136,7 +3136,7 @@ createGiottoImage <- function(gobject = NULL,
if (transf == "flip_x_axis") {
mg_object <- magick::image_flop(mg_object)
} else if (transf == "flip_y_axis") {
mg_object <- magick::image_flop(mg_object)
mg_object <- magick::image_flip(mg_object)
} else {
wrap_msg(transf, " is not a supported transformation, see
details")
Expand Down
4 changes: 2 additions & 2 deletions R/data_evaluation.R
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ evaluate_input <- function(type, x, ...) {
.gstop(
"expression input needs to be a path to matrix-like data or an",
"object of class 'Matrix', 'data.table', 'data.frame', 'matrix'",
"'DelayedMatrix' or 'dbSparseMatrix'."
"'DelayedMatrix' or 'dbSparseMatrix'."
)
Comment on lines 152 to 156
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Align the error message with supported classes (dbSparseMatrix vs dbMatrix).
Right now the message says 'dbSparseMatrix', but the code path and args are built around "dbMatrix". If dbSparseMatrix isn’t a real accepted input here, this is misleading.

-            "'DelayedMatrix' or 'dbSparseMatrix'."
+            "'DelayedMatrix' or 'dbMatrix'."
🤖 Prompt for AI Agents
In R/data_evaluation.R around lines 152 to 156, the error message lists
'dbSparseMatrix' which is inconsistent with the actual accepted class name used
elsewhere ('dbMatrix'); update the error text to reference the correct supported
class (change 'dbSparseMatrix' to 'dbMatrix') or, if the code truly accepts
dbSparseMatrix, update the code/args to include that class — ensure the message
exactly matches the real supported class names used by the function.

}

Expand Down Expand Up @@ -321,7 +321,7 @@ evaluate_input <- function(type, x, ...) {
rnames <- rownames(x)
if (!is.null(rnames)) {
vmsg(.v = verbose, "[spatlocs] matrix input has rownames.
Using these as IDs.")
Using these as IDs.")
dt[, id := rnames]
}
.evaluate_spatial_locations(dt, verbose = verbose, ...)
Expand Down
30 changes: 23 additions & 7 deletions R/images.R
Original file line number Diff line number Diff line change
Expand Up @@ -2850,7 +2850,7 @@ to_simple_tif <- function(input_file,
unlink(outpath, force = TRUE) # if overwrite, delete original
} else {
stop("File already exists: ", outpath,
"\nSet overwrite = TRUE to replace.\n",
"\nSet overwrite = TRUE to replace.\n",
call. = FALSE
)
}
Expand Down Expand Up @@ -2884,11 +2884,11 @@ ometif_to_tif <- to_simple_tif
#' "integer"). `output = "structure"` can help
#' with figuring out which is most appropriate.
#' @param output character. One of "data.frame" to return a data.frame of the
#' attributes information of the xml node, "xmL" for an \{xml2\} representation
#' attributes information of the xml node, "xml" for an \{xml2\} representation
#' of the node, "list" for an R native list (note that many items in the
#' list may have overlapping names that make indexing difficult), or
#' list may have overlapping names that make indexing difficult),
#' "structure" to invisibly return NULL, but print the structure of the XML
#' document or node.
#' document/node, or "kv" (extract key/value pairs from OME MapAnnotations).
#' @returns list/data.frame/XML depending on `output`
#' @examples
#' if (FALSE) {
Expand All @@ -2911,7 +2911,7 @@ tif_metadata <- function(path,
node = NULL,
page = NULL,
type = c("attribute", "text", "double", "integer"),
output = c("data.frame", "xml", "list", "structure")) {
output = c("data.frame", "xml", "list", "structure", "kv")) {
checkmate::assert_file_exists(path)
package_check(
pkg_name = c("tifffile", "imagecodecs", "xml2"),
Expand All @@ -2923,7 +2923,7 @@ tif_metadata <- function(path,
img <- TIF$TiffFile(path)
on.exit(try(img$close(), silent = TRUE), add = TRUE)
output <- match.arg(output,
choices = c("data.frame", "xml", "list", "structure")
choices = c("data.frame", "xml", "list", "structure", "kv")
)
type <- match.arg(type,
choices = c("attribute", "text", "double", "integer")
Expand Down Expand Up @@ -2992,12 +2992,14 @@ ometif_metadata <- tif_metadata
# qptiff: per-page description
p1 <- as.integer(page)[1]
x <- tryCatch(img$pages[[p1 - 1L]]$description, error = function(e) NULL)
if (is.null(x) || !nzchar(x)) {
x <- tryCatch(img$series[[1]]$pages[[p1 - 1L]]$description, error = function(e) NULL)
}
} else if (img$is_fluoview) x <- img$fluoview_metadata
else if (img$is_nih) x <- img$nih_metadata
else if (img$is_astrotiff) x <- img$astrotiff_metadata
else if (img$is_imagej) x <- img$imagej_metadata
else if (img$is_lsm) x <- img$lsm_metadata
else if (img$is_qpi) x <- img$series[[1]]$pages[[page - 1L]]$description
else if (img$is_micromanager) x <- img$micromanager_metadata
else stop("unrecognized tif format\n", call. = FALSE)

Expand All @@ -3009,6 +3011,20 @@ ometif_metadata <- tif_metadata
ns <- xml2::xml_ns(x)
has_namespace <- length(ns) > 0L

## NEW: output = "kv" (read OME MapAnnotation K/Vs) ---
if (identical(output, "kv")) {
m_nodes <- xml2::xml_find_all(
x,
".//*[local-name()='StructuredAnnotations']//*[local-name()='MapAnnotation']/*[local-name()='Value']//*[local-name()='M']"
)
if (!length(m_nodes)) return(NULL)
keys <- xml2::xml_attr(m_nodes, "K")
values <- xml2::xml_text(m_nodes)
out <- as.list(values)
names(out) <- keys
return(out)
}

if (!is.null(node)) {
node_parts <- node
node_path <- paste(node_parts, collapse = "/")
Expand Down
Loading
Loading