Downloading Xenium data#
spatialrefinery.download_xenium_study fetches a 10x Genomics Xenium study’s raw asset bundle from a manifest of curl -O <url> lines – the same manifest 10x’s dataset pages let you copy when you choose the “curl” download option. It retries transient failures, writes atomically (an interrupted download never leaves a truncated file behind), downloads in parallel, and unzips *_outs.zip archives in place (while always skipping the large *_xe_outs.zip Xenium Explorer bundles, which aren’t needed for SpatialData conversion).
This notebook uses Human Kidney Preview Data (Xenium Human Multi-Tissue and Cancer Panel), kidney cancer (PRCC) section, as its worked example – study Xenium_V1_hKidney_cancer_section.
What you need: a manifest file for the study you want. Runtime: the dry run below is instant; the real download depends on your network – for this study it’s ~3.4 GB for the outs bundle plus ~0.5 GB for the H&E image, so a few minutes on a decent connection.
from pathlib import Path
from spatialrefinery import download_xenium_study
The manifest format#
A manifest is a plain text file with one curl -O <url> line per asset. 10x’s dataset pages (10xgenomics.com/datasets/...) offer this as a download option next to the individual file links – copy it into a .txt file and pass that path as source.
The cell below writes the manifest for Human Kidney Preview Data (Xenium Human Multi-Tissue and Cancer Panel) – the kidney cancer (PRCC) section, study Xenium_V1_hKidney_cancer_section, Xenium Onboard Analysis v1.5.0 – exactly as 10x lists it: the main outputs bundle, the post-Xenium H&E image, and the H&E alignment CSV. Swap in the URLs from your own study to use a different dataset.
Manifests for other studies may also list a *_xe_outs.zip line (the Xenium Explorer bundle, often tens of GB). download_xenium_study never auto-extracts those, and you can drop them from a download entirely with the kinds filter shown below.
DATA_DIR = Path("xenium_example")
DATA_DIR.mkdir(exist_ok=True)
manifest_path = DATA_DIR / "manifest.txt"
manifest_path.write_text(
"""\
curl -O https://cf.10xgenomics.com/samples/xenium/1.5.0/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_outs.zip
curl -O https://cf.10xgenomics.com/samples/xenium/1.5.0/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_he_image.ome.tif
curl -O https://cf.10xgenomics.com/samples/xenium/1.5.0/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_he_imagealignment.csv
"""
)
print(manifest_path.read_text())
curl -O https://cf.10xgenomics.com/samples/xenium/1.5.0/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_outs.zip
curl -O https://cf.10xgenomics.com/samples/xenium/1.5.0/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_he_image.ome.tif
curl -O https://cf.10xgenomics.com/samples/xenium/1.5.0/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_he_imagealignment.csv
Dry run: see what would be downloaded#
dry_run=True resolves the manifest and reports the plan – study names, asset kinds, destinations – without any network activity. Useful to sanity-check a manifest before committing to a multi-GB download.
plan = download_xenium_study(manifest_path, outdir=DATA_DIR / "raw", dry_run=True)
for result in plan:
print(f"{result.asset.study:40s} {result.asset.kind:15s} -> {result.path}")
INFO Fetching 3 asset(s) with up to 8 parallel workers.
Xenium_V1_hKidney_cancer_section he_alignment -> xenium_example/raw/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_he_imagealignment.csv
Xenium_V1_hKidney_cancer_section outs -> xenium_example/raw/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_outs.zip
Xenium_V1_hKidney_cancer_section he_image -> xenium_example/raw/Xenium_V1_hKidney_cancer_section/Xenium_V1_hKidney_cancer_section_he_image.ome.tif
Each entry is a DownloadResult: .status ("downloaded", "cached", "skipped", or "failed"), .ok (a bool convenience property), .asset (the source RemoteAsset, with .url, .study, .filename, .kind), and .error when a download failed.
Downloading a subset#
Restrict to specific asset kinds to avoid pulling everything. Here we take the main "outs" bundle (transcripts, cell/nucleus boundaries, morphology image) plus the H&E image and its alignment CSV – everything the next tutorial needs. That’s all three assets for this study, but on a manifest that also lists a Xenium Explorer bundle the same filter would leave "xe_outs" on the server.
raw_dir = DATA_DIR / "raw"
results = download_xenium_study(
manifest_path,
outdir=raw_dir,
kinds=["outs", "he_image", "he_alignment"],
max_workers=8,
)
failed = [r for r in results if not r.ok]
if failed:
print(f"{len(failed)}/{len(results)} asset(s) failed:")
for r in failed:
print(f" - {r.asset.url}: {r.error}")
else:
print(f"Downloaded {len(results)} asset(s) to {raw_dir}")
INFO Fetching 3 asset(s) with up to 8 parallel workers.
Downloaded 3 asset(s) to xenium_example/raw
Output layout#
Assets land under outdir/<study>/<filename>, where <study> is the second-to-last path segment of the URL. *_outs.zip is unzipped in place – 10x’s outs archives have no top-level folder, so their contents extract directly into the study directory, alongside the downloaded files:
raw/
└── Xenium_V1_hKidney_cancer_section/
├── Xenium_V1_hKidney_cancer_section_outs.zip
├── Xenium_V1_hKidney_cancer_section_he_image.ome.tif
├── Xenium_V1_hKidney_cancer_section_he_imagealignment.csv
├── experiment.xenium
├── gene_panel.json
├── metrics_summary.csv
├── analysis_summary.html
├── transcripts.parquet
├── cells.parquet
├── cell_boundaries.parquet
├── nucleus_boundaries.parquet
├── cell_feature_matrix.h5
├── morphology.ome.tif
├── morphology_focus.ome.tif
└── morphology_mip.ome.tif
(Plus the .csv.gz, .tar.gz, and .zarr.zip equivalents 10x ships for the same tables.) The directory holding experiment.xenium is what you pass as dataset_path in the next tutorial.
Running this as a script#
python scripts/xenium_download.py --input_file manifest.txt --outdir raw_files --workers 8
What’s next#
Continue to Xenium to SpatialData zarr to convert the downloaded bundle into a SpatialData zarr store.