Work in progress · Unlisted example
This example is shared for feedback. Its analysis, layout, and APIs may change before it joins the documentation.
Aligned H&E in Celldega Landscape¶
Adds an aligned H&E image to a small Xenium DegaFiles example and views it in Landscape. The FLUORESCENCE / H&E control swaps the background; cells and transcripts stay in place.
Data: 2,000 × 500 px region of the 10x FFPE Human Lung Cancer dataset used in the SpatialData Xenium tutorial (Xenium 2.0.0, CC BY 4.0): 450 cells, 33,369 transcripts (QV ≥ 20), one display group.
Run this notebook from a Celldega repository checkout. It builds the example DegaFiles locally, so this page shows the code without outputs.
Setup (repository root; libvips required, e.g. brew install vips), then restart the kernel:
python -m pip install -e ".[pre]"
npm install && npm run build
import json
import os
from pathlib import Path
import runpy
import numpy as np
# Use the frontend built from this checkout; the released CDN bundle has no H&E selector.
os.environ["CELLDEGA_LOCAL_ESM"] = "1"
import celldega as dega
from celldega import pre
HERE = Path.cwd().resolve()
ROOT = next(p for p in (HERE, *HERE.parents) if (p / "scripts/prepare_xenium_he_example.py").is_file())
helpers = runpy.run_path(str(ROOT / "scripts/prepare_xenium_he_example.py"))
SOURCE_DIR = ROOT / "data/xenium_h_and_e"
DEGA_FILES = ROOT / "data/xenium_he_aligned_dega"
HE_IMAGE = SOURCE_DIR / f"{helpers['SAMPLE']}_he_image.ome.tif"
ALIGNMENT_CSV = SOURCE_DIR / f"{helpers['SAMPLE']}_he_imagealignment.csv"
1. Get the data and build the fluorescence DegaFiles¶
Downloads any 10x files not already in SOURCE_DIR (about 2 GB via HTTP byte ranges: the H&E image,
its alignment CSV and only the needed Xenium files), extracts them and checks the required files.
Then it reuses complete DegaFiles in DEGA_FILES or builds them with the pre module (DAPI, cells,
transcripts). For your own data, use your usual pre.main(...) output instead.
manifest_path = DEGA_FILES / "landscape_parameters.json"
# Reuses complete DegaFiles here, otherwise builds them with the pre module (no H&E yet).
helpers["ensure_dega_files"](SOURCE_DIR, DEGA_FILES, include_he=False)
example = json.loads((DEGA_FILES / "example.json").read_text())
x0, y0, width, height = example["crop_pixels"]
2. Add the aligned H&E¶
The 10x CSV maps H&E pixels to original morphology pixels ([x, y, 1] column vectors). Our DegaFiles
are a crop, so we compose it with a translation. pre.add_aligned_he() resamples H&E onto the DegaFiles
grid, writes an RGB tile pyramid and adds aligned_he to the manifest. Existing files are untouched, and an existing H&E is never overwritten.
The 10x alignment is affine, so it has small local errors; this step applies it and does not re-register.
For an existing DegaFiles folder, see the aligned H&E guide.
if "aligned_he" not in json.loads(manifest_path.read_text()):
he_to_crop = np.array([[1, 0, -x0], [0, 1, -y0], [0, 0, 1]], dtype=float) @ np.loadtxt(ALIGNMENT_CSV, delimiter=",")
pre.add_aligned_he(DEGA_FILES, HE_IMAGE, alignment=he_to_crop)
print(json.dumps(json.loads(manifest_path.read_text())["aligned_he"], indent=2))
3. Serve the DegaFiles locally¶
Starts a localhost server (Celldega's CORS handler) on a free port; keep the kernel running while viewing.
from functools import partial
from http.server import ThreadingHTTPServer
from threading import Thread
from celldega.viz.local_server import CORSHTTPRequestHandler
if "he_server" in globals(): # rerun: stop the previous server
he_server.shutdown()
he_server.server_close()
he_server = ThreadingHTTPServer(("127.0.0.1", 0), partial(CORSHTTPRequestHandler, directory=str(DEGA_FILES)))
Thread(target=he_server.serve_forever, daemon=True).start()
base_url = f"http://127.0.0.1:{he_server.server_port}"
4. View and toggle¶
Click the blue FLUORESCENCE text under IMG and choose H&E. IMG hides or shows the background; CELL and TRX control the overlays. Rerun this cell after changing the manifest.
dega.viz.Landscape(
technology="Xenium",
base_url=base_url,
dataset_name="Human lung cancer - aligned H&E",
ini_x=width / 2,
ini_y=height / 2,
ini_zoom=-1,
height=600,
)