Author: Marcel Ramos
Date: 2026-04-28

# XeniumIO: Import 10X Genomics Xenium Analyzer Data

Marcel Ramos

#### April 28, 2026

#### Package

XeniumIO 1.4.0

# Contents

# Introduction

The `XeniumIO` package provides functions to import 10X Genomics Xenium Analyzer data into R. The package is designed to work with the output of the Xenium Analyzer, which is a software tool that processes Visium spatial gene expression data. The package provides functions to import the output of the Xenium Analyzer into R, and to create a `TENxXenium` object that can be used with other Bioconductor packages.

# Supported Formats

## TENxIO

The 10X suite of packages support multiple file formats. The following table lists the supported file formats and the corresponding classes that are imported into R.

Extension | Class | Imported as
--- | --- | ---
.h5 | TENxH5 | SingleCellExperiment w/ TENxMatrix
.mtx / .mtx.gz | TENxMTX | SummarizedExperiment w/ dgCMatrix
.tar.gz | TENxFileList | SingleCellExperiment w/ dgCMatrix
peak_annotation.tsv | TENxPeaks | GRanges
fragments.tsv.gz | TENxFragments | RaggedExperiment
.tsv / .tsv.gz | TENxTSV | tibble

## VisiumIO

Extension | Class | Imported as
--- | --- | ---
spatial.tar.gz | TENxSpatialList | DataFrame list *
.parquet | TENxSpatialParquet | tibble *

## XeniumIO

Extension | Class | Imported as
--- | --- | ---
.zarr.zip | TENxZarr | (TBD)

# Installation

    if (!require("BiocManager", quietly = TRUE))
        install.packages("BiocManager")))

    BiocManager::install("XeniumIO")

# Loading package

    library(XeniumIO)

# XeniumIO

The `TENxXenium` class has a `metadata` slot for the `experiment.xenium` file. The `resources` slot is a `TENxFileList` or `TENxH5` object containing the cell feature matrix. The `coordNames` slot is a vector specifying the names of the columns in the spatial data containing the spatial coordinates. The `sampleId` slot is a scalar specifying the sample identifier.

    TENxXenium(
        resources = "path/to/matrix/folder/or/file",
        xeniumOut = "path/to/xeniumOut/folder",
        sample_id = "sample01",
        format = c("mtx", "h5"),
        boundaries_format = c("parquet", "csv.gz"),
        spatialCoordsNames = c("x_centroid", "y_centroid"),
        ...
    )

The `format` argument specifies the format of the `resources` object, either “mtx” or “h5”. The `boundaries_format` allows the user to choose whether to read in the data using the `parquet` or `csv.gz` format.

# Example Folder Structure

Note that the `xeniumOut` unzipped folder must contain the following files:

        *outs
        ├── cell_feature_matrix.h5
        ├── cell_feature_matrix.tar.gz
        |   ├── barcodes.tsv*
        |   ├── features.tsv*
        |   └── matrix.mtx*
        ├── cell_feature_matrix.zarr.zip
        ├── experiment.xenium
        ├── cells.csv.gz
        ├── cells.parquet
        ├── cells.zarr.zip
        [...]

Note that currently the `zarr` format is not supported as the infrastructure is currently under development.

## Xenium class

The `resources` slot should either be the `TENxFileList` from the `mtx` format or a `TENxH5` instance from an `h5` file. The boundaries can either be a `TENxSpatialParquet` instance or a `TENxSpatialCSV`. These classes are automatically instantiated by the constructor function.

    showClass("TENxXenium")

    ## Class "TENxXenium" [package "XeniumIO"]
    ##
    ## Slots:
    ##
    ## Name:                             resources
    ## Class:               TENxFileList_OR_TENxH5
    ##
    ## Name:                            boundaries
    ## Class: TENxSpatialParquet_OR_TENxSpatialCSV
    ##
    ## Name:                            coordNames
    ## Class:                            character
    ##
    ## Name:                              sampleId
    ## Class:                            character
    ##
    ## Name:                               colData
    ## Class:                   TENxSpatialParquet
    ##
    ## Name:                              metadata
    ## Class:                           XeniumFile

## `import` method

The `import` method for a `TENxXenium` instance returns a `SpatialExperiment` class object. Dispatch is only done on the `con` argument. See `?BiocIO::import` for details on the generic. The `import` function call is meant to be a simple call without much input. For more details in the package, see `?TENxXenium`.

    getMethod("import", c(con = "TENxXenium"))

    ## Method Definition:
    ##
    ## function (con, format, text, ...)
    ## {
    ##     sce <- import(con@resources, ...)
    ##     metadata <- import(con@metadata)
    ##     coldata <- import(con@colData)
    ##     SpatialExperiment::SpatialExperiment(assays = list(counts = assay(sce)),
    ##         rowData = rowData(sce), mainExpName = mainExpName(sce),
    ##         altExps = altExps(sce), sample_id = con@sampleId, colData = as(coldata,
    ##             "DataFrame"), spatialCoordsNames = con@coordNames,
    ##         metadata = list(experiment.xenium = metadata, polygons = import(con@boundaries)))
    ## }
    ## <bytecode: 0x8154d79a0>
    ## <environment: namespace:XeniumIO>
    ##
    ## Signatures:
    ##         con          format text
    ## target  "TENxXenium" "ANY"  "ANY"
    ## defined "TENxXenium" "ANY"  "ANY"

# Importing an Example Xenium Dataset

The following code snippet demonstrates how to import a Xenium Analyzer output into R. The `TENxXenium` object is created by specifying the path to the `xeniumOut` folder. The `TENxXenium` object is then imported into R using the `import` method for the `TENxXenium` class.

First, we cache the ~12 MB file to avoid downloading it multiple times (via BiocFileCache).

    zipfile <- paste0(
        "https://mghp.osn.xsede.org/bir190004-bucket01/BiocXenDemo/",
        "Xenium_Prime_MultiCellSeg_Mouse_Ileum_tiny_outs.zip"
    )
    destfile <- XeniumIO:::.cache_url_file(zipfile)

We then create an output folder for the contents of the zipped file. We use the same name as the zip file but without the extension (with `tools::file_path_sans_ext`).

    outfold <- file.path(
        tempdir(), tools::file_path_sans_ext(basename(zipfile))
    )
    if (!dir.exists(outfold))
        dir.create(outfold, recursive = TRUE)

We now unzip the file and use the `outfold` as the `exdir` argument to `unzip`. The `outfold` variable and folder will be used as the `xeniumOut` argument in the `TENxXenium` constructor. Note that we use the `ref = "Gene Expression"` argument in the `import` method to pass down to the internal `splitAltExps` function call. This will set the `mainExpName` in the `SpatialExperiment` object.

    unzip(
        zipfile = destfile, exdir = outfold, overwrite = FALSE
    )
    TENxXenium(xeniumOut = outfold) |>
        import(ref = "Gene Expression")

    ## class: SpatialExperiment
    ## dim: 5006 36
    ## metadata(2): experiment.xenium polygons
    ## assays(1): counts
    ## rownames(5006): ENSMUSG00000052595 ENSMUSG00000030111 ...
    ##   ENSMUSG00000055670 ENSMUSG00000027596
    ## rowData names(3): ID Symbol Type
    ## colnames(36): aaamobki-1 aaclkaod-1 ... olbjkpjc-1 omjmdimk-1
    ## colData names(13): cell_id transcript_counts ... segmentation_method
    ##   sample_id
    ## reducedDimNames(0):
    ## mainExpName: Gene Expression
    ## altExpNames(5): Deprecated Codeword Genomic Control Negative Control
    ##   Codeword Negative Control Probe Unassigned Codeword
    ## spatialCoords names(2) : x_centroid y_centroid
    ## imgData names(0):

Note that you may also use the `swapAltExp` function to set a `mainExpName` in the `SpatialExperiment` but this is not recommended. The operation returns a `SingleCellExperiment` which has to be coerced back into a `SpatialExperiment`. The coercion also loses some metadata information particularly the `spatialCoords`.

    TENxXenium(xeniumOut = outfold) |>
        import() |>
        swapAltExp(name = "Gene Expression") |>
        as("SpatialExperiment")

    ## class: SpatialExperiment
    ## dim: 5006 36
    ## metadata(1): TENxFileList
    ## assays(1): counts
    ## rownames(5006): ENSMUSG00000052595 ENSMUSG00000030111 ...
    ##   ENSMUSG00000055670 ENSMUSG00000027596
    ## rowData names(3): ID Symbol Type
    ## colnames(36): aaamobki-1 aaclkaod-1 ... olbjkpjc-1 omjmdimk-1
    ## colData names(13): cell_id transcript_counts ... segmentation_method
    ##   sample_id
    ## reducedDimNames(0):
    ## mainExpName: Gene Expression
    ## altExpNames(5): Genomic Control Negative Control Codeword Negative
    ##   Control Probe Unassigned Codeword Deprecated Codeword
    ## spatialCoords names(0) :
    ## imgData names(0):

The dataset was obtained from the 10X Genomics website under the X0A v3.0 section and is a subset of the Xenium Prime 5K Mouse Pan Tissue & Pathways Panel. The link to the data can be seen as the `url` input above and shown below for completeness.

https://cf.10xgenomics.com/samples/xenium/3.0.0/Xenium_Prime_MultiCellSeg_Mouse_Ileum_tiny/Xenium_Prime_MultiCellSeg_Mouse_Ileum_tiny_outs.zip

# Session Info

Click to expand `sessionInfo()`

    R version 4.6.0 Patched (2026-04-24 r89963)
    Platform: aarch64-apple-darwin23
    Running under: macOS Tahoe 26.3.1

    Matrix products: default
    BLAS:   /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRblas.0.dylib
    LAPACK: /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1

    locale:
    [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

    time zone: America/New_York
    tzcode source: internal

    attached base packages:
    [1] stats4    stats     graphics  grDevices utils     datasets  methods
    [8] base

    other attached packages:
     [1] XeniumIO_1.4.0              TENxIO_1.14.0
     [3] SingleCellExperiment_1.34.0 SummarizedExperiment_1.42.0
     [5] Biobase_2.72.0              GenomicRanges_1.64.0
     [7] Seqinfo_1.2.0               IRanges_2.46.0
     [9] S4Vectors_0.50.0            BiocGenerics_0.58.0
    [11] generics_0.1.4              MatrixGenerics_1.24.0
    [13] matrixStats_1.5.0           BiocStyle_2.40.0

    loaded via a namespace (and not attached):
     [1] httr2_1.2.2              rjson_0.2.23             xfun_0.57
     [4] bslib_0.10.0             lattice_0.22-9           tzdb_0.5.0
     [7] vctrs_0.7.3              tools_4.6.0              curl_7.1.0
    [10] tibble_3.3.1             RSQLite_2.4.6            blob_1.3.0
    [13] pkgconfig_2.0.3          BiocBaseUtils_1.14.0     Matrix_1.7-5
    [16] dbplyr_2.5.2             assertthat_0.2.1         lifecycle_1.0.5
    [19] compiler_4.6.0           codetools_0.2-20         htmltools_0.5.9
    [22] sass_0.4.10              yaml_2.3.12              pillar_1.11.1
    [25] jquerylib_0.1.4          DelayedArray_0.38.0      cachem_1.1.0
    [28] magick_2.9.1             abind_1.4-8              tidyselect_1.2.1
    [31] digest_0.6.39            purrr_1.2.2              dplyr_1.2.1
    [34] bookdown_0.46            arrow_23.0.1.2           fastmap_1.2.0
    [37] grid_4.6.0               cli_3.6.6                SparseArray_1.12.0
    [40] magrittr_2.0.5           S4Arrays_1.12.0          withr_3.0.2
    [43] readr_2.2.0              filelock_1.0.3           rappdirs_0.3.4
    [46] bit64_4.8.0              rmarkdown_2.31           XVector_0.52.0
    [49] bit_4.6.0                otel_0.2.0               hms_1.1.4
    [52] SpatialExperiment_1.22.0 memoise_2.0.1            evaluate_1.0.5
    [55] knitr_1.51               BiocIO_1.22.0            BiocFileCache_3.2.0
    [58] rlang_1.2.0              Rcpp_1.1.1-1.1           glue_1.8.1
    [61] DBI_1.3.0                BiocManager_1.30.27      VisiumIO_1.8.0
    [64] jsonlite_2.0.0           R6_2.6.1