---
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
---
[](https://github.com/CTTIR/phenoscapR/actions/workflows/R-CMD-check.yaml)
[](https://cttir.github.io/phenoscapR/)
[](https://app.codecov.io/gh/CTTIR/phenoscapR?branch=main)
[](https://opensource.org/licenses/MIT)
[](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