|
2 | 2 | from pathlib import Path |
3 | 3 |
|
4 | 4 | from spatialdata import SpatialData |
| 5 | +from spatialdata.transformations import Identity, set_transformation |
5 | 6 |
|
6 | 7 | from . import ( |
7 | 8 | write_cell_categories, |
|
13 | 14 | from .constants import FileNames, experiment_dict |
14 | 15 |
|
15 | 16 |
|
16 | | -def write(path: str, sdata: SpatialData, image_key: str, gene_column: str) -> None: |
| 17 | +def _order_instances(sdata: SpatialData, shapes_key: str): |
| 18 | + adata = sdata.table |
| 19 | + |
| 20 | + instance_key = adata.uns["spatialdata_attrs"]["instance_key"] |
| 21 | + region_key = adata.uns["spatialdata_attrs"]["region_key"] |
| 22 | + |
| 23 | + adata = adata[adata.obs[region_key] == shapes_key].copy() |
| 24 | + adata.obs.set_index(instance_key, inplace=True) |
| 25 | + adata = adata[sdata.shapes[shapes_key].index].copy() |
| 26 | + return adata |
| 27 | + |
| 28 | + |
| 29 | +def write( |
| 30 | + path: str, |
| 31 | + sdata: SpatialData, |
| 32 | + image_key: str, |
| 33 | + shapes_key: str, |
| 34 | + points_key: str, |
| 35 | + gene_column: str, |
| 36 | + layer: str | None = None, |
| 37 | +) -> None: |
| 38 | + """ |
| 39 | + Transform a SpatialData object into inputs for the Xenium Explorer. |
| 40 | + Currently only images of type MultiscaleSpatialImage are supported. |
| 41 | +
|
| 42 | + Args: |
| 43 | + path: Path to the directory where files will be saved. |
| 44 | + sdata: SpatialData object. |
| 45 | + image_key: Name of the image or interest. |
| 46 | + shapes_key: Name of the cell shapes. |
| 47 | + points_key: Name of the transcripts (key of `sdata.points`). |
| 48 | + gene_column: Column name of the points dataframe containing the gene names. |
| 49 | + layer: Layer of `sdata.table` where the gene counts are saved. If `None`, uses `sdata.table.X`. |
| 50 | + """ |
17 | 51 | path: Path = Path(path) |
18 | 52 | assert ( |
19 | 53 | not path.exists() or path.is_dir() |
20 | 54 | ), f"A path to an existing file was provided. It should be a path to a directory." |
21 | 55 |
|
22 | 56 | path.mkdir(parents=True, exist_ok=True) |
23 | 57 |
|
24 | | - adata = sdata.table |
| 58 | + adata = _order_instances(sdata, shapes_key) |
25 | 59 |
|
26 | | - EXPERIMENT = experiment_dict(..., ..., adata.n_obs) |
| 60 | + EXPERIMENT = experiment_dict(image_key, shapes_key, adata.n_obs) |
27 | 61 | with open(path / FileNames.METADATA, "w") as f: |
28 | 62 | json.dump(EXPERIMENT, f, indent=4) |
29 | 63 |
|
30 | | - write_gene_counts(path / FileNames.TABLE, adata) |
| 64 | + write_gene_counts(path / FileNames.TABLE, adata, layer) |
31 | 65 | write_cell_categories(path / FileNames.CELL_CATEGORIES, adata) |
32 | 66 |
|
33 | | - polygons = sdata.shapes["..."] |
34 | | - # TODO: transform polygon coords to pixel |
35 | | - write_polygons(path / FileNames.SHAPES, polygons) |
| 67 | + pixels_cs = "__pixels" |
| 68 | + set_transformation(sdata.images[image_key], Identity(), pixels_cs) |
| 69 | + |
| 70 | + gdf = sdata.transform_element_to_coordinate_system(sdata.shapes[shapes_key], pixels_cs) |
| 71 | + write_polygons(path / FileNames.SHAPES, gdf.geometry) |
36 | 72 |
|
37 | | - # TODO : make it memory efficient |
38 | 73 | write_multiscale(path / FileNames.IMAGE, sdata.images[image_key]) |
39 | 74 |
|
40 | | - df = sdata.points["..."] |
| 75 | + df = sdata.transform_element_to_coordinate_system(sdata.points[points_key], pixels_cs) |
41 | 76 | write_transcripts(path / FileNames.POINTS, df, gene_column) |
0 commit comments