Skip to content

sopa.utils.polygon_crop

sopa.utils.polygon_crop.polygon_selection(sdata, intermediate_image=None, intermediate_polygon=None, channels=None, scale_factor=10, margin_ratio=0.1)

Crop an image based on a user-defined polygon (interactive mode).

Parameters:

Name Type Description Default
sdata SpatialData

A SpatialData object

required
intermediate_image str | None

Path to the intermediate image, with a .zip extension. Use this only if the interactive mode is not available

None
intermediate_polygon str | None

Path to the intermediate polygon, with a .zip extension. Use this locally, after downloading the intermediate_image

None
channels list[str] | None

List of channel names to be displayed. Optional if there are already only 1 or 3 channels.

None
scale_factor float

Resize the image by this value (high value for a lower memory usage)

10
margin_ratio float

Ratio of the image margin on the display (compared to the image size)

0.1
Source code in sopa/utils/polygon_crop.py
def polygon_selection(
    sdata: SpatialData,
    intermediate_image: str | None = None,
    intermediate_polygon: str | None = None,
    channels: list[str] | None = None,
    scale_factor: float = 10,
    margin_ratio: float = 0.1,
):
    """Crop an image based on a user-defined polygon (interactive mode).

    Args:
        sdata: A `SpatialData` object
        intermediate_image: Path to the intermediate image, with a `.zip` extension. Use this only if the interactive mode is not available
        intermediate_polygon: Path to the intermediate polygon, with a `.zip` extension. Use this locally, after downloading the `intermediate_image`
        channels: List of channel names to be displayed. Optional if there are already only 1 or 3 channels.
        scale_factor: Resize the image by this value (high value for a lower memory usage)
        margin_ratio: Ratio of the image margin on the display (compared to the image size)
    """
    if intermediate_polygon is None:
        image_key, image = _prepare(sdata, channels, scale_factor)

        if intermediate_image is not None:
            log.info(f"Resized image will be saved to {intermediate_image}")
            with zarr.ZipStore(intermediate_image, mode="w") as store:
                g = zarr.group(store=store)
                g.attrs.put({ROI.SCALE_FACTOR: scale_factor, ROI.IMAGE_KEY: image_key})
                g.array(ROI.IMAGE_ARRAY_KEY, image, dtype=image.dtype, chunks=image.shape)
            return

        polygon = _draw_polygon(image, scale_factor, margin_ratio)
    else:
        log.info(f"Reading polygon at path {intermediate_polygon}")
        z = zarr.open(intermediate_polygon, mode="r")
        polygon = Polygon(z[ROI.POLYGON_ARRAY_KEY][:])
        image_key = z.attrs[ROI.IMAGE_KEY]

        image = get_spatial_image(sdata, image_key)

    geo_df = gpd.GeoDataFrame(geometry=[polygon])

    geo_df = ShapesModel.parse(geo_df, transformations=get_transformation(sdata[image_key], get_all=True).copy())
    sdata.shapes[ROI.KEY] = geo_df
    if sdata.is_backed():
        sdata.write_element(ROI.KEY, overwrite=True)

    log.info(f"Polygon saved in sdata['{ROI.KEY}']")