--- title: "Getting Started with phenoscapR" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting Started with phenoscapR} %\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 = 7, fig.height = 5, dpi = 96 ) ``` ## Overview **phenoscapR** takes you from a raw multiplexed-imaging cell-segmentation table all the way to publication-ready spatial statistics and figures. The workflow mirrors the way single-cell analysts already think: 1. **Read** segmentation output into a `SpatialCellData` object 2. **Quality-control** cells by area and intensity 3. **Normalise** marker intensities 4. **Phenotype** cells from marker thresholds 5. **Analyse** the spatial arrangement of those phenotypes 6. **Visualise** every step Every function comes in two flavours: a high-level **S4 interface** that takes and returns a `SpatialCellData` object (used throughout this vignette), and a low-level **`data.table` interface** (`read_spatial()`, `qc_filter()`, …) for scripting. They share one compute engine, so results are identical. ## The bundled example dataset The package ships `phenoscapR_example`, a fully synthetic two-sample tonsil assay with planted spatial niches (a B-cell follicle, an overlapping T-cell zone, an epithelial region, and scattered macrophages). It lets every example here run without downloading anything. ```{r data} library(phenoscapR) data(phenoscapR_example) phenoscapR_example ``` It carries 640 cells across two samples and eight markers, plus a `phenotype_true` column recording the ground-truth population of each cell: ```{r data-shape} table(phenoscapR_example$sample_id, phenoscapR_example$phenotype_true) ``` > **Reading your own data.** In practice you would start from > `ReadSpatial("segmentation.csv")` (or a directory of CSVs). phenoscapR > auto-detects QuPath full/minimal exports and flat segmentation tables. See > `vignette("phenoscapR-02-object-model")` for the object model and import > details. ## 1. Quality control `QCFilter()` removes implausibly small or large cells and, optionally, cells outside an intensity band. We work on a copy so the original stays intact. ```{r qc} obj <- QCFilter(phenoscapR_example, min_area = 20, max_area = 1000) obj ``` Use `QCPlot()` to inspect what was kept against any two metadata columns: ```{r qcplot, fig.height = 4, fig.alt = "Synthetic cell area versus local cell density, coloured by known simulated phenotype after QC."} obj <- CellDensity(obj, radius = 40) QCPlot(obj, x = "cell_area", y = "density", colour_by = "phenotype_true") ``` ## 2. Normalisation `NormaliseData()` rescales each marker. `"zscore"` centres and scales to unit variance; `"minmax"` maps to `[0, 1]`; `"quantile"` is rank-based. ```{r normalise} obj <- NormaliseData(obj, method = "zscore") round(GetData(obj)[1:4, ], 2) ``` ## 3. Phenotyping Assign phenotypes by thresholding normalised markers. Because the data are z-scored, a threshold of `1` means "at least one standard deviation above the marker's mean". `PhenotypeCells()` builds composite labels such as `CD3+/CD4+`. ```{r phenotype} obj <- PhenotypeCells(obj, thresholds = list( CD20 = 1, CD3 = 1, CD8 = 1, CD4 = 1, CD68 = 1, PanCK = 1, FoxP3 = 1 )) head(PhenotypeSummary(obj)) ``` For the rest of this vignette we use the curated ground-truth populations so the figures stay easy to read: ```{r use-truth} obj@meta_data$phenotype <- obj@meta_data$phenotype_true ``` `CompositionPlot()` shows phenotype proportions per sample: ```{r composition, fig.height = 4, fig.alt = "Stacked phenotype proportions for the two synthetic example sections."} CompositionPlot(obj, group_by = "sample_id") ``` ## 4. The phenotype map `CellMap()` is the workhorse plot — every cell drawn at its tissue position, coloured by phenotype. Spatial structure (the follicle, the T-cell zone) is immediately visible. ```{r cellmap, fig.alt = "Synthetic tonsil A cell positions coloured by known simulated phenotype."} tonsil_a <- obj[obj$sample_id == "tonsil_A", ] CellMap(tonsil_a) ``` Colour instead by a continuous marker with `FeaturePlot()`: ```{r featureplot, fig.alt = "Synthetic tonsil A cell positions coloured by normalised CD20, CD3 and PanCK intensities."} FeaturePlot(tonsil_a, features = c("CD20", "CD3", "PanCK")) ``` ## 5. Spatial analysis ### Local density and nearest neighbours ```{r nn-density, fig.alt = "Synthetic tonsil A cell positions coloured by local cell density within radius 40."} obj <- FindNeighbours(obj, k = 5) summary(Meta(obj)$nn_distance) DensityPlot(tonsil_a <- CellDensity(tonsil_a, radius = 40)) ``` ### Phenotype interactions `InteractionMatrix()` counts, per sample, how often each phenotype pair sits within `radius` of one another versus what random mixing would predict. The score is `log2(observed / expected)` — positive means attraction, negative means avoidance. Neighbours are **never** counted across samples. ```{r interactions, fig.alt = "Pairwise phenotype interaction scores within the synthetic sections at radius 40."} im <- InteractionMatrix(obj, radius = 40) head(im[order(-im$interaction_score), ]) InteractionPlot(im) ``` ### Marker signatures per phenotype ```{r heatmap, fig.height = 5, fig.alt = "Mean normalised marker intensities by simulated phenotype in the synthetic example data."} MarkerHeatmap(obj) ``` ## Where to next phenoscapR has much more spatial machinery — Ripley's K, Moran's I, neighbourhood-enrichment permutation tests, the pair correlation function, Delaunay contact graphs — and a full gallery of plots and dimensionality reductions. | Vignette | Focus | |---|---| | [The SpatialCellData Object](phenoscapR-02-object-model.html) | class internals, import, accessors, subsetting | | [Advanced Spatial Analysis](phenoscapR-03-spatial-analysis.html) | Ripley's K, Moran's I, enrichment, choosing a statistic | | [Visualisation Gallery](phenoscapR-04-visualisation.html) | every plotting function, side by side |