goatpy.annotation
Add QuPath GeoJSON annotations to a SpatialData object produced by load_and_align().
The preferred workflow is to pass geojson_path directly to load_and_align() so annotations are transformed at registration time. Use add_qupath_annotations() when you want to add annotations to an already-built sdata object (e.g. loaded from disk).
The affine matrix stored in sdata[‘maldi_adata’].uns[‘he_transform’][‘affine_matrix’] is a 3x3 matrix mapping reg-resolution H&E coords -> buffer canvas coords. It was derived empirically by _fit_affine_from_pil() in auto_align.py, which fits a least-squares affine from a dense grid of point correspondences computed through PIL’s exact rotation geometry. This is robust to PIL’s internal conventions about expand=True, rotation centre, and canvas placement.
annotation.py then folds in the scale_to_reg and img_upscaling factors to produce the final native-H&E-pixel -> upscaled-canvas transform.
Functions
|
|
|
Add a categorical |
Module Contents
- goatpy.annotation.add_qupath_annotations(sdata, geojson_path, shapes_key='annotations', classification_key='classification', he_pixel_um=None)[source]
- goatpy.annotation.annotate_per_pixel(sdata: spatialdata.SpatialData, shapes_key: str = 'annotations', classification_key: str = 'classification', table_name: str = 'maldi_adata', obs_column: str = 'annotation', overlap: float = 0.0, other_label: str = 'other', priority: list[str] | None = None, inplace: bool = True) spatialdata.SpatialData[source]
Add a categorical
obs_columntomaldi_adata.obslabelling each pixel with its annotation class (orother_labelif none).- Parameters:
sdata (SpatialData) – Input spatial data object produced by
load_and_align.shapes_key (str) – Key in
sdata.shapescontaining the annotation GeoDataFrame. Default"annotations".classification_key (str) – Column in the annotation GeoDataFrame holding class labels. Default
"classification".table_name (str) – Table in
sdata.tablesto annotate. Default"maldi_adata".obs_column (str) – Name of the new column added to
adata.obs. Default"annotation".overlap (float) –
Minimum fractional overlap (0–1) required for a pixel to be assigned to a class.
0(default) — centroid-in-polygon test viaspatialdata.polygon_query. Fast.> 0— area-based test via Shapely intersection. A pixel is assigned only ifintersection_area / pixel_area >= overlap. E.g.overlap=0.5requires ≥ 50 % coverage. Slower.
other_label (str) – Label assigned to pixels that do not fall in any annotation. Default
"other".priority (list of str, optional) – Class names in ascending priority order. When a pixel overlaps multiple classes the last name in this list wins. If
None, classes are iterated in the order they appear in the GeoDataFrame.inplace (bool) – If True (default), modify
sdatain place and return it. If False, work on a shallow copy of the table only (the obs column is still added to the copy stored in sdata — set False if you want to avoid mutating the original adata object).
- Returns:
The input
sdatawithobs_columnadded tosdata[table_name].obs.- Return type:
SpatialData
Examples
>>> from goatpy.annotate import annotate_per_pixel
# Centroid-based (fast, default) >>> sdata = annotate_per_pixel(sdata)
# Area-based: pixel must be ≥ 50 % inside a polygon >>> sdata = annotate_per_pixel(sdata, overlap=0.5)
# Custom label for unannotated pixels >>> sdata = annotate_per_pixel(sdata, other_label=”background”)
# Control which class wins when polygons overlap >>> sdata = annotate_per_pixel(sdata, priority=[“Stroma”, “Tumor”])