Skip to contents

Vesalius: Quick Start

Do you like to live in the fast lane? Do you sigh every time you see a long vignette? Do you wish there was a TLDR on everything?

I understand.

Welcome to the Vesalius quick start!

In this vignette, you will find a very short guide on how to work with Vesalius. Vesalius provides an internal data set taken from real Spatial transcrtiptomic data.

We show in context Vesalius workflows in the articles section.

For all intents and purposes, this is a dummy data set and should only be used to get a feel for the Vesalius package. We strongly advise you to use real and complete data sets to fully understand the Vesalius package and its benefits.

Introduction

Vesalius is a tool to perform high-resolution in silico anatomization and molecular characterization from Spatial omices data without requiring companion images. The nature of the vesalius algorithm makes it condusive to being using on various spatial omics modalities without requiuring substantial changes.

Vesalius achieves this by converting reducded dimensionality latent space into gray scale images (one of each dimension). These images are processed using various image analysis techniques such as smoothing and segmentation.

Loading & building a vesalius assay

Loading data

First, let’s load the package and the data. Data originates from slide-seqV2 data (availble at Single Cell Portal).

We took a small subset of the mouse hippocampus centered around the Dentate Gyrus.

Here, we show an example using transcriptomic data but the same principles will apply for other modalities. For examples using other modalities, please refer to the other articles.

What do we have?

Once loaded we have two new variables: counts and cooridnates.

The counts are the gene counts for all genes. As per convention, columns r epresent the spatial indices (barcodes, spots, beads,…) and rows are the genes that were captured.

str(counts)
## Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
##   ..@ i       : int [1:653622] 4 8 10 15 18 19 30 38 41 51 ...
##   ..@ p       : int [1:1053] 0 2982 6344 9623 12651 15540 18593 21462 24241 26859 ...
##   ..@ Dim     : int [1:2] 15932 1052
##   ..@ Dimnames:List of 2
##   .. ..$ : chr [1:15932] "0610005C13Rik" "0610007P14Rik" "0610009B22Rik" "0610009E02Rik" ...
##   .. ..$ : chr [1:1052] "CTCCAGCCTTGCAT" "AACCCCAAGGTAAT" "GCCCAACACACTTT" "GTCCAGAGTCTTAT" ...
##   ..@ x       : num [1:653622] 1 4 1 2 2 2 2 1 1 1 ...
##   ..@ factors : list()

The coordinates represent the x and y coordinates for each spatial index.

str(coordinates)
## 'data.frame':    1052 obs. of  3 variables:
##  $ barcodes: chr  "CTCCAGCCTTGCAT" "AACCCCAAGGTAAT" "GCCCAACACACTTT" "GTCCAGAGTCTTAT" ...
##  $ xcoord  : num  3536 3472 3634 3589 3535 ...
##  $ ycoord  : num  3485 3410 3636 3257 3352 ...

In other modalities, count matrices are still required for vesalius to run.

For example, Spatial-ATAC-seq or Spatial-cut&tag can be converted into count matrices (more specifically tile matrices) using the ArchR package

Building a Vesalius assay

We can build a vesalius assay by simply parsing both counts and cooridnates to the (vesalius assay contructor)[link to manual page].

vesalius <- build_vesalius_assay(
  coordinates = coordinates, # spatial coordinates
  counts  = counts, # count matrix
  assay = "spatial_omics", # name you wish to give your assay
  verbose = FALSE # Do you want progress messages?
)

What do we have?

A vesalius object is a container that requires at the very least spatial indices. Here, we parsed both counts and spatial indices

vesalius
## #--------------------------------------------------------------------------------# 
## spatial_omics as vesalius assay containing:
## 
## 1 modifications applied to base object. 
## 
## 1052 spatial indices. 
## 
## 15932 observations in the raw count matrix. 
## #--------------------------------------------------------------------------------#

Count matrices can be added sperately using the add_counts function.

Embedding latent space into gray scale images

Embed Latent Space

We can use this object top embed our latent space into grey scale images.

vesalius <- generate_embeddings(vesalius,
  dim_reduction = "PCA",
  normalization = "log_norm",
  nfeatures = 100, # Setting number of features low for low run time
  verbose = FALSE)

What do we have?

We see that we have added a set of embedding with one used one default embedding called the “active” embedding. See section below on understanding active embeddings.

## #--------------------------------------------------------------------------------# 
## spatial_omics as vesalius assay containing:
## 
## 3 modifications applied to base object. 
## 
## 1052 spatial indices used to form pixel tiles. 
## 
## 15932 observations in the log_norm count matrix. 
## 
## PCA as embeddings. 
## with PCA as active embedding. 
## #--------------------------------------------------------------------------------#

Testing multiple embeddings

We can test out multiple embeddings and every trial will be stored into the vesalius_assay object.

vesalius <- generate_embeddings(vesalius,
  dim_reduction = "UMAP",
  nfeatures = 100, # Setting number of features low for low run time
  verbose = FALSE)

vesalius <- generate_embeddings(vesalius,
  dim_reduction = "PCA",
  nfeatures = 200, # Setting number of features low for low run time
  verbose = FALSE)

vesalius <- generate_embeddings(vesalius,
  dim_reduction = "PCA",
  verbose = FALSE)

Every time you run a new dimensionality reduction approach it will be appended to the previous ones. Vesalius does the same thing for different normalisation approaches. This lets you decided which combination you would want to use in later stages.

Note that since you might be want to use the same embedding more than once, you will end up with more than one embedding called “PCA” for example. In this case, each embedding or normalisation will have a unique name.

For every subsequent embedding called PCA, the trial name will be PCA.1, PCA.2 etc The same applies to any embedding or normalisation method you select.

What do we have ?

vesalius
## #--------------------------------------------------------------------------------# 
## spatial_omics as vesalius assay containing:
## 
## 6 modifications applied to base object. 
## 
## 1052 spatial indices used to form pixel tiles. 
## 
## 15932 observations in the log_norm.3 count matrix. 
## 
## 4 total embedding trials
## with PCA.2 as active embedding. 
## #--------------------------------------------------------------------------------#

You can also add your own embeddings and they will be appended into vesalius in a similar manner. You can also check the manual page for add_embeddings

Visualising Grey scale images

To visualise embeddings, we can simply plot the vesalius object and specify which dimension we wish to view. See (imagePlot)[link to page] for more information. Since we are leaving the embedding argument as the default “last” value, we can only look at the 3 UMAP dimensions. We can look at them simulaneously by creating RGB images with one dimension per color channel.

p1 <- image_plot(vesalius, dimensions = 1) + labs(title = "Grey PCA dim 1")
p2 <- image_plot(vesalius, dimensions = seq(1, 3)) + labs(title = "RGB PCA")

If we wanted to look at “UMAP” instead, we can simply specify the embedding. Since we used 30 dimensions for UMAP, we can use any dimensions to build RGB images.

p3 <- image_plot(vesalius, dimensions = 1, embedding = "UMAP") +
  labs(title = "Grey UMAP dim 1")
p4 <- image_plot(vesalius, dimensions = c(1, 2, 3), embedding = "UMAP") +
  labs(title = "RGB UMAP dim 1, 2, and 3")
(p1 + p2) / (p3 + p4)

Understanding Active Embeddings

The active embedding slot in a vesalius_assay object contains the embedding values that will be used during image processing and image segmentation.

In the examples above, we tested multiple embeddings.

## [1] "PCA.2"

We see that “UMAP.1” is used as the active embedding. Any time the embeddings are being used in subsequent functions they will be taken from here as this is the “last” embedding used.

In fact, in any subsequent function that contains the keyword “last” for one of its arguments, vesalius will use the last target created. This can mean the last embedding used, the last count matrix or the last segmentation / territory isolation / territory morphology used.

If you are unstaified with the results, you can always call the embedding or trial you want to use explictely and the active slot will be replace with a fresh version of your embeddings of choice. No need to re-run everything from scratch!

While this flexibility can be a boon, it can also be a curse! Anytime you explictely request an embedding or a trial it will use that fresh instance. This means that every time the active slot will be updated and any processing you may have done to it will be overwritten.

Image processing and Image segmentation

Image Processing

Once we have these images, we can apply image processing techniques to each gray scale image.

vesalius <- regularise_image(vesalius, lambda = 1)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:17  Converting Vesalius to Image
## 2025-08-01/17/25 22:08:18  Regularising Image 
## 2025-08-01/17/25 22:08:21  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
vesalius <- smooth_image(vesalius, sigma = 5, iter = 10)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:22  Converting Vesalius to Image
## 2025-08-01/17/25 22:08:22  Smoothing Image Arrays 
## 2025-08-01/17/25 22:08:22  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
vesalius <- equalize_image(vesalius, sleft = 5, sright = 5)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:23  Converting Vesalius to Image
## 2025-08-01/17/25 22:08:24  Equalizing Histogram 
## 2025-08-01/17/25 22:08:24  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#

You can apply any image processing method you wish and in any order you desire. Please note that the default number of dimensions for these function is defined by seq(1,3) giving the first three dimensions. If working with PCA, please set this argument according to how many dimensions you wish to process.

This also alows for the selction of abitrary of PCs. For example, based on the grey scale images, you might decided that this would be a better choice of PCs

# Selecting a subset of PCs
dims <- c(1, 3, 4, 5, 7:11)

# running smoothing o
vesalius <- regularise_image(vesalius,
  dimensions = dims,
  embedding = "PCA",
  verbose = FALSE)
vesalius <- equalize_image(vesalius,
  dimensions = dims,
  verbose = FALSE)
vesalius <- smooth_image(vesalius,
  dimensions = dims,
  iter = 10,
  sigma = 1,
  verbose = FALSE)

In this example, we explicetely requested the PCA embedding. This means that we will take a fresh instance of the PCA embedding and use this as our active embedding. Once specified, all subsequent functions will use this new active embedding unless specified otherwise.

However, note that dimensions are being parsed at every step. Only the images coressponding to these dimensions will be processed. Vesalius still retains the other ones just in case.

Image segmentation

Vesalius will attempts to segment the images into color segments. Vesalius use a kmeans clustering approach to segment grey scale images. Note that the segmentation here is applied to the whole stack and not individually.

The goal is top obtain colour segments that we can subdivived into territories.

vesalius <- segment_image(vesalius,
  method = "kmeans",
  col_resolution = 2,
  verbose = FALSE)

What do we have?

We can see that the vesalius_assay object now contains some more information related to the segmentation.

vesalius
## #--------------------------------------------------------------------------------# 
## spatial_omics as vesalius assay containing:
## 
## 10 modifications applied to base object. 
## 
## 1052 spatial indices used to form pixel tiles. 
## 
## 15932 observations in the log_norm.3 count matrix. 
## 
## 4 total embedding trials
## with PCA.2 as active embedding. 
## 
## 1 Segmentation trials. 
## 0 Territory trials. 
## 0 Morphing trials. 
## 0 Layering trials. 
## #--------------------------------------------------------------------------------#

We can also have a look at the results of the image segmentation.

p5 <- image_plot(vesalius) + labs(title = "Segments only")
print(p5)

Kmeans is the default setting for image segmentation but Vesalius also provides louvain and leiden based approaches.

Isolating territories

Isolating territories from colour segments

The final step is to isolate color segments into seperate territories. Similar color segments may be of the same colour but are seperated in 2D space. We want to be able to isolate each patch. For this, we can use the isolate_territories function.

vesalius <- isolate_territories(vesalius, capture_radius = 0.05)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:26  Pooling Segment  1 
## 2025-08-01/17/25 22:08:26  Pooling Segment  2 
## #--------------------------------------------------------------------------------#

What do we have?

Now we can have a look at the isolated territories. We can keep track of how many instances of image segmentation and image manipulation we have gone through.

vesalius
## #--------------------------------------------------------------------------------# 
## spatial_omics as vesalius assay containing:
## 
## 11 modifications applied to base object. 
## 
## 1052 spatial indices used to form pixel tiles. 
## 
## 15932 observations in the log_norm.3 count matrix. 
## 
## 4 total embedding trials
## with PCA.2 as active embedding. 
## 
## 1 Segmentation trials. 
## 1 Territory trials. 
## 0 Morphing trials. 
## 0 Layering trials. 
## #--------------------------------------------------------------------------------#

Visualizing Territories

We can plot our territories using vesalius plotting functions. Note that this is a ggplot object as such it is customisable using ggplot2 functionalities.

p6 <- territory_plot(vesalius, cex_pt = 3.5)
p6

Comparing territories

Once we have our territories, we can compare the expression of genes between territories.

vesalius <- identify_markers(vesalius, seed = 1, query = 2)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:27 ===> Computing DEGs in spatial_omics <===
## 2025-08-01/17/25 22:08:28 ===> 1 VS 2 <=== 
## #--------------------------------------------------------------------------------#
deg <- get_markers(vesalius)

And finally we can visualise the expression of our genes of interest. You can parse more than one gene. Here we show the overall expression profile of Malat1 but also its mean expression in each territory.

p7 <- view_gene_expression(vesalius, genes = "Malat1")
p8 <- view_gene_expression(vesalius, genes = "Malat1", as_layer = TRUE)
p7 + p8

Mapping Cells across samples

Another key features of Vesalius is to be able to map cells across samples. Here, we will show a quick break down of how to achieve this. A more in depth view of cell mapping is available in the Vesalius analysis repository

Mapping cells

First, we build 2 vesalius objects that we have process independantly. The jitter territory is the same as the original version but we flipped the coordinates, added noise to coordinates and counts, and remove a few randomly sampled locations.

# load vesalius data 
data(vesalius)

# Create Vesalius object for processing
vesalius <- build_vesalius_assay(coordinates, counts)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:29  Checking Coordinates in spatial_omics 
## 2025-08-01/17/25 22:08:29  Checking Counts in spatial_omics 
## 2025-08-01/17/25 22:08:29  Calculating Assay scale from coordinates
## #--------------------------------------------------------------------------------#
cells <- sample(LETTERS[1:6], size = nrow(vesalius@tiles),replace =T)
names(cells) <- vesalius@tiles$barcodes
vesalius <- add_cells(vesalius, cells = cells, add_name = "Cells")
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:29  Adding cell labels to Cells territory column in spatial_omics 
## #--------------------------------------------------------------------------------#
jitter_ves <- build_vesalius_assay(jitter_coord, jitter_counts)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:29  Checking Coordinates in spatial_omics 
## 2025-08-01/17/25 22:08:30  Checking Counts in spatial_omics 
## 2025-08-01/17/25 22:08:31  Calculating Assay scale from coordinates
## #--------------------------------------------------------------------------------#
cells <- sample(LETTERS[1:6], size = nrow(jitter_ves@tiles),replace =T)
names(cells) <- jitter_ves@tiles$barcodes
jitter_ves <- add_cells(jitter_ves, cells = cells, add_name = "Cells")
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:31  Adding cell labels to Cells territory column in spatial_omics 
## #--------------------------------------------------------------------------------#
vesalius <- generate_embeddings(vesalius,
    filter_threshold = 1,
    filter_grid = 1)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:31 ===> Generating Tiles in spatial_omics <===
## 2025-08-01/17/25 22:08:31  Generating Voronoi Tesselation 
## 2025-08-01/17/25 22:08:31  Filtering Tiles
## 2025-08-01/17/25 22:08:31  Rasterising Tiles 
## 2025-08-01/17/25 22:08:33  Adjusting count matrix
## 2025-08-01/17/25 22:08:33 ===> Pre-processing counts in spatial_omics <===
## 2025-08-01/17/25 22:08:34 ===> Compute Latent Space in spatial_omics <===
## 2025-08-01/17/25 22:08:34  Running Principal Component Analysis 
## 2025-08-01/17/25 22:08:36  Converting PCA Embedding Values to gray scale 
## #--------------------------------------------------------------------------------#
vesalius <- smooth_image(vesalius, embedding = "PCA", sigma = 5, iter = 10)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:36  Converting Vesalius to Image
## 2025-08-01/17/25 22:08:37  Smoothing Image Arrays 
## 2025-08-01/17/25 22:08:37  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
vesalius <- equalize_image(vesalius, sleft = 5, sright = 5)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:37  Converting Vesalius to Image
## 2025-08-01/17/25 22:08:38  Equalizing Histogram 
## 2025-08-01/17/25 22:08:38  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
vesalius <- segment_image(vesalius, col_resolution = 2)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:38  Segmenting Image using kmeans 
## #--------------------------------------------------------------------------------#
vesalius <- isolate_territories(vesalius)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:38  Pooling Segment  1 
## 2025-08-01/17/25 22:08:38  Pooling Segment  2 
## #--------------------------------------------------------------------------------#
jitter_ves <- generate_embeddings(jitter_ves,
    filter_threshold = 1,
    filter_grid = 1)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:38 ===> Generating Tiles in spatial_omics <===
## 2025-08-01/17/25 22:08:38  Generating Voronoi Tesselation 
## 2025-08-01/17/25 22:08:38  Filtering Tiles
## 2025-08-01/17/25 22:08:38  Rasterising Tiles 
## 2025-08-01/17/25 22:08:40  Adjusting count matrix
## 2025-08-01/17/25 22:08:40 ===> Pre-processing counts in spatial_omics <===
## 2025-08-01/17/25 22:08:44 ===> Compute Latent Space in spatial_omics <===
## 2025-08-01/17/25 22:08:44  Running Principal Component Analysis 
## 2025-08-01/17/25 22:08:45  Converting PCA Embedding Values to gray scale 
## #--------------------------------------------------------------------------------#
jitter_ves <- smooth_image(jitter_ves, embedding = "PCA", sigma = 5, iter = 10)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:45  Converting Vesalius to Image
## 2025-08-01/17/25 22:08:46  Smoothing Image Arrays 
## 2025-08-01/17/25 22:08:46  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
jitter_ves <- equalize_image(jitter_ves, sleft = 5, sright = 5)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:46  Converting Vesalius to Image
## 2025-08-01/17/25 22:08:47  Equalizing Histogram 
## 2025-08-01/17/25 22:08:47  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
jitter_ves <- segment_image(jitter_ves, col_resolution = 2)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:47  Segmenting Image using kmeans 
## #--------------------------------------------------------------------------------#
jitter_ves <- isolate_territories(jitter_ves)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:47  Pooling Segment  1 
## 2025-08-01/17/25 22:08:47  Pooling Segment  2 
## #--------------------------------------------------------------------------------#

Next, we can proceed with the mapping of cells on to the other. We will run the mapping using cell (feature), niche, territory similarity and cell composition.

matched <- map_assays(vesalius,
    jitter_ves,
    threshold = 0,
    use_cost = c("feature","niche","territory","composition"),
    batch_size = 500,
    epoch = 5,
    jitter = 1)
## #--------------------------------------------------------------------------------# 
## 2025-08-01/17/25 22:08:47  Extracting assay signal
## 2025-08-01/17/25 22:08:47  Computing Feature cost in spatial_omics 
## 2025-08-01/17/25 22:08:47  Getting Neighborhoods in spatial_omics 
## 2025-08-01/17/25 22:08:48  Computing Neighborhood cost in spatial_omics 
## 2025-08-01/17/25 22:08:48  Computing Territory cost in spatial_omics 
## 2025-08-01/17/25 22:08:49  Computing Niche Composition Index in spatial_omics 
## 2025-08-01/17/25 22:08:54  Filtering Cost Matrices 
## 2025-08-01/17/25 22:08:55  Mapping query to seed - Epoch =  1 
## 2025-08-01/17/25 22:08:55  Mapping query to seed - Epoch =  2 
## 2025-08-01/17/25 22:08:55  Mapping query to seed - Epoch =  3 
## 2025-08-01/17/25 22:08:55  Mapping query to seed - Epoch =  4 
## 2025-08-01/17/25 22:08:55  Mapping query to seed - Epoch =  5 
## 2025-08-01/17/25 22:08:55  Filtering Mapped Indices 
## #--------------------------------------------------------------------------------#

The mapping produces a new vesalius object with mapped coordinates for the query data set. In this case our query was jitter_ves.

From here, we can treat this new object as a frech data sets with new coordinates. As such:

matched <- generate_embeddings(matched,
    dim_reduction = "PCA",
  nfeatures = 200, 
  verbose = FALSE)
matched <- smooth_image(matched, sigma = 5, iter = 10)
## #--------------------------------------------------------------------------------# 
## 2025-09-01/17/25 22:09:03  Converting Vesalius to Image
## 2025-09-01/17/25 22:09:03  Smoothing Image Arrays 
## 2025-09-01/17/25 22:09:04  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
matched <- equalize_image(matched, sleft = 5, sright = 5)
## #--------------------------------------------------------------------------------# 
## 2025-09-01/17/25 22:09:04  Converting Vesalius to Image
## 2025-09-01/17/25 22:09:04  Equalizing Histogram 
## 2025-09-01/17/25 22:09:04  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
matched <- segment_image(matched,col_resolution = 2)
## #--------------------------------------------------------------------------------# 
## 2025-09-01/17/25 22:09:05  Segmenting Image using kmeans 
## #--------------------------------------------------------------------------------#

We can then look at the resulting embeddings

m <- image_plot(vesalius)
m1 <- image_plot(jitter_ves)
m2 <- image_plot(matched)

m + m1 + m2

We can also look at the new territories.

t <- territory_plot(vesalius)
t1 <- territory_plot(jitter_ves)
t2 <- territory_plot(matched)
t + t1 + t2

Integrating data sets

Once we have our data sets and the new set of coordinates, we can integrate the data sets to obtain an integrate mapping object upon which we can perform differential gene expression analysis.

inter <- integrate_assays(matched,
    vesalius)
## #--------------------------------------------------------------------------------# 
## 2025-09-01/17/25 22:09:11  Intergrating Counts
## Warning in merge_coordinates(mapped, reference,
## rownames(integrated$integrated)): No duplicated coordinates allowed - Adding
## noise!
## 2025-09-01/17/25 22:09:19 ===> Generating Tiles in spatial_omics <===
## 2025-09-01/17/25 22:09:19  Generating Voronoi Tesselation 
## 2025-09-01/17/25 22:09:19  Filtering Tiles
## 2025-09-01/17/25 22:09:19  Rasterising Tiles 
## 2025-09-01/17/25 22:09:23  Adjusting count matrix
## 2025-09-01/17/25 22:09:23  Setting integrated as active embedding 
## 2025-09-01/17/25 22:09:23  Setting inferred as active count matrix 
## #--------------------------------------------------------------------------------#

Since this data set now contains an integrated latent space, we can also call territories on this object. There is no need to create new embeddings. They are provided during integration.

inter <- smooth_image(inter, sigma = 5, iter = 10)
## #--------------------------------------------------------------------------------# 
## 2025-09-01/17/25 22:09:23  Converting Vesalius to Image
## 2025-09-01/17/25 22:09:23  Smoothing Image Arrays 
## 2025-09-01/17/25 22:09:23  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
inter <- equalize_image(inter, sleft = 5, sright = 5)
## #--------------------------------------------------------------------------------# 
## 2025-09-01/17/25 22:09:24  Converting Vesalius to Image
## 2025-09-01/17/25 22:09:24  Equalizing Histogram 
## 2025-09-01/17/25 22:09:24  Converting Images to Vesalius
## #--------------------------------------------------------------------------------#
inter <- segment_image(inter, col_resolution = 2)
## #--------------------------------------------------------------------------------# 
## 2025-09-01/17/25 22:09:24  Segmenting Image using kmeans 
## #--------------------------------------------------------------------------------#

We can view the resulting embeddings and territories.

i <- image_plot(inter)
i1 <- territory_plot(inter)

i + i1

DEG analysis between samples

Finally, we can look at DEG analysis between samples in specific territories.

inter <- identify_markers(inter, sample = TRUE)
## #--------------------------------------------------------------------------------# 
## 2025-09-01/17/25 22:09:26  No territory Specified - Comparing all territories
## 2025-09-01/17/25 22:09:26 ===> Computing DEGs in spatial_omics <===
## 2025-09-01/17/25 22:09:26 ===> 1_reference VS remaining_matched <=== 
## 2025-09-01/17/25 22:09:27 ===> 2_reference VS remaining_matched <=== 
## #--------------------------------------------------------------------------------#
degs <- get_markers(inter)
head(degs)
##         genes       p_value   p_value_adj  seed_pct query_pct fold_change
## Lrrtm4 Lrrtm4 9.987024e-130 2.616600e-127 0.4984802 0.9796954  -0.9817074
## Kcnip4 Kcnip4 4.748354e-122 1.187089e-119 0.6990881 0.9974619  -0.8965227
## Lsamp   Lsamp  2.161155e-51  4.106194e-50 1.0000000 1.0000000  -0.4403134
## Kcnd2   Kcnd2 5.273962e-118 1.255203e-115 0.3449848 0.9390863  -0.7492261
## Dlg2     Dlg2 2.059128e-102 3.829978e-100 0.5820669 0.9923858  -0.6078071
## Grin2a Grin2a 1.523576e-123 3.854647e-121 0.4483283 0.9720812  -0.8326261
##        effect_size        seed             query
## Lrrtm4    1.410820 1_reference remaining_matched
## Kcnip4    1.410820 1_reference remaining_matched
## Lsamp     1.014281 1_reference remaining_matched
## Kcnd2     1.410820 1_reference remaining_matched
## Dlg2      1.410820 1_reference remaining_matched
## Grin2a    1.410820 1_reference remaining_matched

Session Info

## R version 4.4.2 (2024-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.1 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
##  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
##  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
## [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
## 
## time zone: UTC
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] ggplot2_3.5.1   patchwork_1.3.0 vesalius_2.0.0 
## 
## loaded via a namespace (and not attached):
##   [1] RcppAnnoy_0.0.22            splines_4.4.2              
##   [3] later_1.4.1                 bitops_1.0-9               
##   [5] R.oo_1.27.0                 tibble_3.2.1               
##   [7] polyclip_1.10-7             fastDummies_1.7.4          
##   [9] lifecycle_1.0.4             Rdpack_2.6.2               
##  [11] rstatix_0.7.2               edgeR_4.4.1                
##  [13] globals_0.16.3              lattice_0.22-6             
##  [15] MASS_7.3-61                 readbitmap_0.1.5           
##  [17] backports_1.5.0             magrittr_2.0.3             
##  [19] limma_3.62.2                plotly_4.10.4              
##  [21] sass_0.4.9                  rmarkdown_2.29             
##  [23] jquerylib_0.1.4             yaml_2.3.10                
##  [25] httpuv_1.6.15               Seurat_5.2.0               
##  [27] sctransform_0.4.1           spam_2.11-0                
##  [29] sp_2.1-4                    spatstat.sparse_3.1-0      
##  [31] reticulate_1.40.0           cowplot_1.1.3              
##  [33] pbapply_1.7-2               RColorBrewer_1.1-3         
##  [35] abind_1.4-8                 zlibbioc_1.52.0            
##  [37] R.cache_0.16.0              Rtsne_0.17                 
##  [39] GenomicRanges_1.58.0        R.utils_2.12.3             
##  [41] purrr_1.0.2                 RCurl_1.98-1.16            
##  [43] imagerExtra_1.3.2           BiocGenerics_0.52.0        
##  [45] GenomeInfoDbData_1.2.13     IRanges_2.40.1             
##  [47] S4Vectors_0.44.0            ggrepel_0.9.6              
##  [49] irlba_2.3.5.1               kohonen_3.0.12             
##  [51] listenv_0.9.1               spatstat.utils_3.1-2       
##  [53] goftest_1.2-3               RSpectra_0.16-2            
##  [55] spatstat.random_3.3-2       fitdistrplus_1.2-2         
##  [57] parallelly_1.41.0           pkgdown_2.1.1              
##  [59] codetools_0.2-20            DelayedArray_0.32.0        
##  [61] RcppRoll_0.3.1              tidyselect_1.2.1           
##  [63] UCSC.utils_1.2.0            farver_2.1.2               
##  [65] imager_1.0.2                matrixStats_1.5.0          
##  [67] stats4_4.4.2                spatstat.explore_3.3-4     
##  [69] jsonlite_1.8.9              bmp_0.3                    
##  [71] progressr_0.15.1            Formula_1.2-5              
##  [73] ggridges_0.5.6              survival_3.7-0             
##  [75] systemfonts_1.2.0           TreeTools_1.13.0           
##  [77] tools_4.4.2                 ggnewscale_0.5.0           
##  [79] ragg_1.3.3                  ica_1.0-3                  
##  [81] Rcpp_1.0.14                 glue_1.8.0                 
##  [83] gridExtra_2.3               SparseArray_1.6.0          
##  [85] xfun_0.50                   DESeq2_1.46.0              
##  [87] MatrixGenerics_1.18.1       GenomeInfoDb_1.42.1        
##  [89] dplyr_1.1.4                 withr_3.0.2                
##  [91] fastmap_1.2.0               shinyjs_2.1.0              
##  [93] digest_0.6.37               R6_2.5.1                   
##  [95] mime_0.12                   textshaping_0.4.1          
##  [97] colorspace_2.1-1            scattermore_1.2            
##  [99] tensor_1.5                  jpeg_0.1-10                
## [101] spatstat.data_3.1-4         R.methodsS3_1.8.2          
## [103] tidyr_1.3.1                 generics_0.1.3             
## [105] data.table_1.16.4           httr_1.4.7                 
## [107] htmlwidgets_1.6.4           S4Arrays_1.6.0             
## [109] uwot_0.2.2                  pkgconfig_2.0.3            
## [111] gtable_0.3.6                lmtest_0.9-40              
## [113] XVector_0.46.0              htmltools_0.5.8.1          
## [115] carData_3.0-5               pwr_1.3-0                  
## [117] dotCall64_1.2               fftwtools_0.9-11           
## [119] SeuratObject_5.0.2          scales_1.3.0               
## [121] Biobase_2.66.0              png_0.1-8                  
## [123] spatstat.univar_3.1-1       tvR_0.3.2                  
## [125] knitr_1.49                  Signac_1.14.0              
## [127] reshape2_1.4.4              nlme_3.1-166               
## [129] cachem_1.1.0                zoo_1.8-12                 
## [131] stringr_1.5.1               KernSmooth_2.23-24         
## [133] parallel_4.4.2              miniUI_0.1.1.1             
## [135] desc_1.4.3                  infix_0.1.0                
## [137] pillar_1.10.1               grid_4.4.2                 
## [139] vctrs_0.6.5                 TreeDist_2.9.2             
## [141] RANN_2.6.2                  PlotTools_0.3.1            
## [143] promises_1.3.2              ggpubr_0.6.0               
## [145] car_3.1-3                   xtable_1.8-4               
## [147] cluster_2.1.6               evaluate_1.0.3             
## [149] cli_3.6.3                   locfit_1.5-9.10            
## [151] compiler_4.4.2              Rsamtools_2.22.0           
## [153] rlang_1.1.4                 crayon_1.5.3               
## [155] future.apply_1.11.3         ggsignif_0.6.4             
## [157] labeling_0.4.3              plyr_1.8.9                 
## [159] fs_1.6.5                    stringi_1.8.4              
## [161] viridisLite_0.4.2           deldir_2.0-4               
## [163] BiocParallel_1.40.0         munsell_0.5.1              
## [165] Biostrings_2.74.1           tiff_0.1-12                
## [167] lazyeval_0.2.2              spatstat.geom_3.3-4        
## [169] Matrix_1.7-1                RcppHNSW_0.6.0             
## [171] bit64_4.6.0-1               future_1.34.0              
## [173] statmod_1.5.0               shiny_1.10.0               
## [175] SummarizedExperiment_1.36.0 rbibutils_2.3              
## [177] ROCR_1.0-11                 memoise_2.0.1              
## [179] igraph_2.1.3                broom_1.0.7                
## [181] bslib_0.8.0                 fastmatch_1.1-6            
## [183] bit_4.5.0.1                 ape_5.8-1