# Bioconductor packages
if (!requireNamespace("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
BiocManager::install(c("rhdf5", "SingleCellExperiment"))
# schard: reads .h5ad in pure R, no Python needed
if (!requireNamespace("remotes", quietly = TRUE)) {
install.packages("remotes")
}
remotes::install_github("cellgeni/schard")Opening SEA-AD single-cell files in R
Quick-start with a single donor
This tutorial walks through loading one SEA-AD donor’s single-nucleus RNA-seq file into R and looking at what is inside. Using one donor instead of the whole cohort keeps the download and memory requirements small, so you can get a working object in a few minutes before you split off into your own track. Everything after the download stays in R.
SEA-AD ships its data as .h5ad, a format from the Python world. We read it straight into R with schard, which is pure R (no Python environment is required) and returns a SingleCellExperiment, the standard Bioconductor object used by both downstream pipelines.
Before you start
You need R 4.2 or newer and a web browser. One donor file is small enough for any laptop.
Step 1 — Install the R packages
Run this once. The first two packages come from Bioconductor; schard comes from GitHub.
If schard reports an installation error, install rhdf5 on its own first (it is the component that reads the HDF5 file), then try installing schard again.
Step 2 — Download one donor’s file in a web browser
The single-cell data is available from the public SEA-AD download site. No account or command-line tool is required. The per-donor RNA-seq files are in PFC/RNAseq/donors_objects/. PFC is the prefrontal cortex, Brodmann area 9, also called DLPFC. There is one file per donor in that folder, plus a large all-cohort file elsewhere in RNAseq/ that you should skip for now.
- Open the SEA-AD public data browser.
- Open the
PFCfolder, thenRNAseq, thendonors_objects. - Find the filename containing
H20.33.001(its full name isH20.33.001_SEAAD_DFC_RNAseq_final-nuclei.<date>.h5ad). - Download that
.h5adfile. - In the repository root, create a
data/sea-ad/folder if it does not exist, then move the downloaded file into it and rename itdonor_H20.33.001.h5ad. The full path from the repository root should bedata/sea-ad/donor_H20.33.001.h5ad.
This is the shared data folder for the whole tutorial series. Later tutorials reuse the same file from here, so you only download it once. It is already git-ignored, so it will never be committed.
Any donor works; H20.33.001 is just a concrete choice. If you use a different donor, change the filename in the R code below. The other brain region, MTG (middle temporal gyrus), has the same layout under MTG/RNAseq/donors_objects/.
Step 3 — Load it into R
Set R’s working directory to this tutorial’s folder. In RStudio, select Session > Set Working Directory > To Source File Location. The path below then reaches the shared data/sea-ad/ folder from here (../../ steps up out of tutorials/01-read-h5ad/ to the repository root). Run the following code.
library(schard)
library(SingleCellExperiment)
sce <- schard::h5ad2sce("../../data/sea-ad/donor_H20.33.001.h5ad")
sceThis prints a summary of the object. A SingleCellExperiment holds three things you will reach for constantly:
- the expression matrix:
counts(sce)orassay(sce); - the per-cell metadata:
colData(sce); and - the per-gene metadata:
rowData(sce).
Step 4 — Look at what you loaded
Get your bearings before doing anything else. This is also the raw material for the variable dictionary you were asked to start.
dim(sce) # genes (rows) x cells (columns)
assayNames(sce) # which matrices are stored
head(rownames(sce)) # gene identifiers
colnames(colData(sce)) # every per-cell metadata columnNow find the columns that matter for the Alzheimer’s work: the cell-type label, the donor’s sex, and the pathology measure.
cd <- colData(sce)
# Cell-type labels in the SEA-AD taxonomy
table(cd$Subclass) # broad types (e.g. Astrocyte, Oligodendrocyte)
table(cd$Supertype) # fine-grained types
# Sex and the categorical AD pathology score
table(cd$Sex)
table(cd$`Overall AD neuropathological Change`)
# Pathology staging variables: find them, then inspect their levels. In these
# per-donor files these are all *ordinal stages* (not a continuous number).
grep(
"Braak|Thal|CERAD|CAA|neuropath",
colnames(cd),
value = TRUE,
ignore.case = TRUE
)
table(cd$Braak) # e.g. Braak IV
table(cd$Thal) # e.g. Thal 2
table(cd$`CERAD score`) # e.g. SparseTwo things to notice:
- Column names with spaces need backticks, as with
Overall AD neuropathological Change. Copy the capitalization exactly ascolnames(colData(sce))prints it; here the “n” in “neuropathological” is lowercase. - Because this is a single donor,
Sexand the pathology stages are the same for every cell. The differences you care about appear only when you compare donors, which is the next step in both tracks.
These per-donor files carry only the ordinal pathology stages above. SEA-AD also defines a Continuous Pseudo-progression Score (CPS), a continuous 0–1 axis of disease severity, but it is not stored in these files. It lives in the combined atlas object and in the supplementary data of the original paper (Gabitto et al., Nat Neurosci 2024). Download the per-donor CPS table here, a simple sheet with two columns, Donor ID and CPS: sea-ad_global_and_local_cps.xlsx. Join it to your cells by Donor ID:
library(readxl)
cps <- read_excel("../../data/sea-ad/sea-ad_global_and_local_cps.xlsx")
# match(): pull each cell's donor CPS out of the lookup table
cd$CPS <- cps$CPS[match(cd$`Donor ID`, cps$`Donor ID`)]As you explore, keep a running variable dictionary: your own notes on the colData columns, what each one means, whether it is categorical or continuous, and whether it describes a single cell or the whole donor. This is your artifact, not a graded worksheet, and you will lean on it constantly: the grouping variables, confounders, and contrasts you choose in later tutorials all come from here. Start it now with the columns above (Subclass, Supertype, Sex, Overall AD neuropathological Change, and the other ordinal staging scores Braak, Thal, CERAD score), and add to it whenever you meet a new column. Nobody hands you the “right” set of variables; deciding which ones matter for your question is the first piece of the analysis that is yours.
Step 5 — Subset to one cell type
To see how subsetting works, keep just one cell type. Match the label exactly to what table(cd$Subclass) printed.
astro <- sce[, sce$Subclass == "Astrocyte"]
dim(astro)Microglia, the brain’s resident immune cells and a focus of Alzheimer’s research, are worth finding too. In this taxonomy they are not their own Subclass; they sit inside the broader Immune subclass, with Supertype labels beginning Micro-PVM. You can select them either way:
immune <- sce[, sce$Subclass == "Immune"] # whole immune compartment
micro <- sce[, grepl("^Micro-PVM", sce$Supertype)] # microglia specifically
dim(immune)
dim(micro)If something breaks
Confirm that the file is at data/sea-ad/donor_H20.33.001.h5ad under the repository root and that R’s working directory is this tutorial’s folder. Check with:
getwd()
file.exists("../../data/sea-ad/donor_H20.33.001.h5ad")'p' must be a nondecreasing vector
This can happen with very large .h5ad files, such as the full 1.2-million-cell cohort file, which is about 35 GB. Using one donor avoids the problem; this is a known limitation of reading very large files this way.
Do not load the all-cohort file on a laptop. A one-donor file is appropriate for this tutorial.
table() result is empty or a column is oddly named
Run colnames(colData(sce)) again and copy the column name exactly, including spaces and capitalization.
Where this goes next
You now have a SingleCellExperiment for one donor and know where sex, pathology, and cell type live in it.
Before you move on, spend a few minutes exploring on your own. This is where the analysis choices you’ll make later begin:
- Browse the full metadata with
colnames(colData(sce))and a fewtable()orsummary()calls. Which variables would you use to compare cells within this donor? Which only make sense when comparing donors? - Which columns look like they could be confounders, things that might track with pathology but aren’t pathology itself (sex, age, post-mortem interval, RNA quality)? Note them in your variable dictionary; you’ll decide what to do about them when you run a real comparison.
There isn’t one right answer here; the point is to start reasoning about this as your dataset rather than a fixed recipe.
Next comes tutorial 02: Preprocessing, the shared foundation for everything that follows. There you’ll take this same donor’s raw counts through quality control, normalization, feature selection, and dimensionality reduction to produce an analysis-ready object. Both project tracks start from that object:
- Pseudobulk analysis: repeat this loading process over donors, then perform per-donor pseudobulk aggregation.
- Trajectory analysis: run PCA and UMAP on your chosen cell type, then anchor the
slingshottrajectory in low-pathology cells.
Bring your variable dictionary to the next check-in.