--- title: "The SpatialCellData Object" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{The SpatialCellData Object} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} resource_files: - figures/logo.svg - figures/logo-dark.svg --- [![R-CMD-check](https://github.com/CTTIR/phenoscapR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/CTTIR/phenoscapR/actions/workflows/R-CMD-check.yaml) [![pkgdown](https://github.com/CTTIR/phenoscapR/actions/workflows/pkgdown.yaml/badge.svg)](https://cttir.github.io/phenoscapR/) [![Codecov test coverage](https://codecov.io/gh/CTTIR/phenoscapR/branch/main/graph/badge.svg)](https://app.codecov.io/gh/CTTIR/phenoscapR?branch=main) [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 6, fig.height = 4 ) ``` ## Overview The **`SpatialCellData`** S4 class is the central data container in phenoscapR. It keeps everything about an experiment in one object: | Slot | Type | Contents | |------|------|----------| | `counts` | numeric matrix | Raw marker intensities (cells × markers) | | `data` | numeric matrix | Normalised intensities (filled by `NormaliseData()`) | | `coords` | data.frame | Spatial coordinates (`x`, `y`) | | `meta_data` | data.frame | Per-cell metadata (`cell_id`, `sample_id`, phenotype, …) | | `project` | character | Project / experiment name | | `spatial` | list | Stored spatial results (neighbour distances, Delaunay edges, …) | | `reductions` | list | Embeddings from `RunPCA()`, `RunUMAP()`, … | A validity method guarantees the matrices, coordinates, and metadata always describe the same set of cells in the same order. ## Construction ### From raw matrices Use `CreateSpatialObject()` when you already have a counts matrix and a coordinate table: ```{r create} library(phenoscapR) set.seed(1) n <- 200 counts <- matrix( abs(rnorm(n * 4, mean = 500, sd = 200)), nrow = n, dimnames = list(NULL, c("CD3", "CD8", "CD20", "PanCK")) ) coords <- data.frame(x = runif(n, 0, 1000), y = runif(n, 0, 1000)) obj <- CreateSpatialObject(counts, coords, project = "demo") obj ``` ### From CSV files `ReadSpatial()` reads one or more segmentation CSVs and returns a `SpatialCellData` directly. It auto-detects the delimiter, byte-order marks, and three common layouts (QuPath full export, QuPath minimal, and flat segmentation tables), and parses a `sample_id` per file. ```{r read, eval = FALSE} # A single file obj <- ReadSpatial("path/to/segmentation.csv", sample_id = "sample1") # A whole directory (sample_id defaults to each file's name) obj <- ReadSpatial("path/to/csv_dir/") ``` ## A worked object The rest of this vignette uses the bundled two-sample example so every line runs: ```{r example} data(phenoscapR_example) spe <- phenoscapR_example spe ``` ## Inspecting the object ```{r inspect} dim(spe) # cells × markers NCells(spe) NMarkers(spe) Markers(spe) head(Meta(spe)) head(Coords(spe)) ``` ## Accessing expression data ```{r data} # Raw counts GetData(spe, slot = "counts")[1:3, ] # Normalised values live in the "data" slot spe <- NormaliseData(spe, method = "zscore") round(GetData(spe, slot = "data")[1:3, ], 2) ``` ## Working with metadata Metadata columns are reachable with `$` and `[[`: ```{r meta} head(spe$sample_id) head(spe[["phenotype_true"]]) ``` `Idents()` returns the active identity — phenotype labels when present, otherwise sample identities. Here we promote the ground-truth populations to the active phenotype: ```{r idents} spe@meta_data$phenotype <- spe@meta_data$phenotype_true table(Idents(spe)) ``` ## Subsetting `SpatialCellData` follows matrix-style `[cells, markers]` subsetting. Both indices are optional. ```{r subset} # By cells: keep one sample a <- spe[spe$sample_id == "tonsil_A", ] dim(a) # By cells: keep just the B-cell follicle follicle <- spe[spe$phenotype == "B cell", ] NCells(follicle) # By markers: keep two channels spe[, c("CD3", "CD20")] ``` Subsetting carries every slot — counts, normalised data, coordinates, metadata, and any reductions — along together, so downstream analysis on a subset is always self-consistent. ## Next steps - **[Getting Started](phenoscapR.html)** — the end-to-end workflow - **[Advanced Spatial Analysis](phenoscapR-03-spatial-analysis.html)** — Ripley's K, Moran's I, neighbourhood enrichment, and choosing a statistic - **[Visualisation Gallery](phenoscapR-04-visualisation.html)** — every plot