This document describes the Application Programming Interface (API) for Path Foundation when deployed as an HTTPS service endpoint, referred to as the service in this document.
Overview
The
serving source code for Path Foundation
can be built and hosted on any API management system, but it's specially
designed to take advantage of
Vertex AI prediction endpoints.
Therefore, it conforms to Vertex AI's required API signature and implements a
predict
method.
The service is designed to support micro batching, not to be mistaken with batch jobs. For every pathology image patch in the request, if the processing is successful, the service returns a one-dimensional embedding vector in the same order as the image patches in the request. Refer to the sections on API request, response, and micro batching for details.
You can provide digital pathology image patches to the service either directly within the request (inlined) or by providing a reference to their location. Inlining the images in the request is not recommended for large-scale productions; read more. When using data storage links the service expects corresponding OAuth 2.0 bearer tokens to retrieve the data on your behalf. For detailed information on constructing API requests and the different ways to provide image data, refer to the API request section.
When given DICOM images from a DICOM store, the service expects the underlying DICOM storage system to conform to HAI-DEF DICOM store requirements. Furthermore, the service expects the pathology data to meet more detailed requirements.
To invoke the service, consult the request section, compose a
valid request JSON and send a POST
request to the endpoint. The following script shows a sample
cURL command which is initialized to
invoke our research endpoint. You can deploy Path Foundation using
Model Garden
and change LOCATION
, PROJECT_ID
and ENDPOINT_ID
to target your endpoint:
LOCATION="us-central1"
PROJECT_ID="hai-cd3-foundations"
ENDPOINT_ID="162"
REQUEST_JSON="path/to/your/request.json"
curl \
-X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/endpoints/${ENDPOINT_ID}:predict" \
-d "@${REQUEST_JSON}"
Request
An API request can include multiple instances, each conforming to this schema. Note that this schema is based on Vertex AI PredictSchemata standard and is a partial OpenAPI specification. The complete JSON request has the following structure:
{
"instances": [
{...},
{...}
]
}
Each request instance can include an optional extension dictionary that you can use to control certain service behaviour; read more about extensions.
The service accepts digital pathology image patches in two ways:
Directly within the HTTPS request: You can include image data as base64-encoded bytes using the
raw_image_bytes
JSON field; read more about inlined images.Indirectly via storage links: You can provide links to the images stored in GCS using the
image_file_uri
JSON field, or you can usedicom_path
to point to DICOM images stored in DICOMweb storage; read more about DICOM requirements.
To illustrate these methods, the following example JSON request shows
raw_image_bytes
, image_file_uri
, and dicom_path
all in one request. In a
real-world scenario, you'll typically only use one of these options for all
images within a single request:
{
"instances": [
{
"raw_image_bytes": "your base 64 encoded image bytes",
"patch_coordinates": [
{
"x_origin": 0,
"y_origin": 0,
"width": 224,
"height": 224
}
],
"extensions": {
"transform_imaging_to_icc_profile": "sRGB",
"require_patches_fully_in_source_image": true
}
},
{
"image_file_uri": "gs://your-bucket/path/to/image.png",
"bearer_token": "your-bearer-token",
"patch_coordinates": [
{
"x_origin": 0,
"y_origin": 0,
"width": 224,
"height": 224
}
],
"extensions": {
"transform_imaging_to_icc_profile": "sRGB"
}
},
{
"dicom_path": {
"series_path": "https://dicomweb-store.uri/studies/1.2.3.4.5.6.7.8.9/series/1.2.3.4.5.6.7.8.10",
"instance_uids": ["1.2.3.4.5.6.7.8.11", "1.2.3.4.5.6.7.8.12"],
}
"bearer_token": "your-bearer-token",
"patch_coordinates": [
{
"x_origin": 0,
"y_origin": 0,
"width": 224,
"height": 224
},
{
"x_origin": 500,
"y_origin": 500,
"width": 224,
"height": 224
}
],
"extensions": {
"transform_imaging_to_icc_profile": "sRGB"
}
}
]
}
Inlined images
You can inline the images in the API request as a base64-encoded
string in the raw_image_bytes
JSON field. However, keep in mind most API
management systems enforce a limit on the maximum size of the request payloads.
When Path Foundation is hosted as a Vertex AI Prediction endpoint,
Vertex AI quotas apply.
To optimize the request size, you should compress the images using common image compression codecs. If you require lossless compression, use PNG encoding. If lossy compression is acceptable, use JPEG encoding.
Here is a code snippet for converting compressed JPEG image files from local
file system into a base64-encoded
string:
import base64
def encode_file_bytes(file_path: str) -> str:
"""Reads a file and returns its contents as a base64-encoded string."""
with open(file_path, 'rb') as imbytes:
return base64.b64encode(imbytes.read())
Another code snippet for converting uncompressed image bytes into a lossless PNG
format and then converting it into a base64-encoded
string:
import base64
import io
import numpy as np
import PIL.Image
def convert_uncompressed_image_bytes_to_base64(image: np.ndarray) -> str:
"""Converts an uncompressed image array to a base64-encoded PNG string."""
with io.BytesIO() as compressed_img_bytes:
with PIL.Image.fromarray(image) as pil_image:
pil_image.save(compressed_img_bytes, 'png')
return base64.b64encode(compressed_img_bytes.getvalue())
Extensions
The API request supports an optional freeform dictionary for each instance. You can think of the extensions as server side configurations that you can control in your requests. The current list of supported extensions are as follows:
Key | Value type | Description |
---|---|---|
image_dimensions |
dictionary | You can instructe the service to resize the original image to a chosen height and width before dividing it into patches for processing. To do that you need to set the hight and width in pixels using the keys width_px and height_px . |
width_px |
number | A key in the image_dimensions dictionary specifying the chosen image width prior to patch generation. |
height_px |
number | A key in the image_dimensions dictionary specifying the chosen image height prior to patch generation. |
transform_imaging_to_icc_profile |
string | If your DICOM images include an ICC profile, you can have the service apply a color transformation to your images before generating embeddings. Choose from NONE , SRGB , ADOBERGB , or ROMMRGB . This transformation follows the DICOM Standard. To use this feature your images must be stored with the ICC profile. If the images are from DICOM store, they must meet the DICOM requirements. |
require_patches_fully_in_source_image |
boolean | You can control how the service handles patch overlap. Set this to True to instruct the service to fail if the patches don't completely fall within the image boundaries, or set it to False to allow partial overlaps with the understanding that uncovered areas will be filled with black (not recommended). If not set, the service assumes True . |
Response
An API response can include multiple predictions that correspond to the order of the instances in the request. Each prediction conforms to this schema. Note that this schema is based on Vertex AI PredictSchemata standard and is a partial OpenAPI specification. The complete JSON request has the following structure:
{
"predictions": [
{
// ... content of first prediction
},
{
// ... content of second prediction
}
],
"deployedModelId": "model-id",
"model": "model",
"modelVersionId": "version-id",
"modelDisplayName": "model-display-name",
"metadata": {
// ... content of metadata
}
}
Each request instance can independently succeed or fail. When succeeded, the
corresponding prediction JSON starts with a result
field and when failed with
an error
. Here is an example of a response to a request with two instances
where the first one has succeeded and the second one failed:
{
"predictions": [
{
"result": {
"patch_embeddings": [
{
"patch_coordinate": {
"x_origin": 100,
"y_origin": 200,
"width": 224,
"height": 224
},
"embedding_vector": [ 0.1, 0.2, 0.3]
}
]
}
},
{
"error": {
"code": "INCOMPATIBLE_PATCH_DIMENSIONS_ERROR",
"description": "Some actionable text."
}
}
],
"deployedModelId": "model-id",
"model": "model",
"modelVersionId": "version-id",
"modelDisplayName": "model-display-name",
"metadata": {
// ... content of metadata
}
}
Error codes
Category | Code | Description |
---|---|---|
General | INVALID_REQUEST_FIELD_ERROR |
There is an error in the request syntax. Construct a valid request and retry. |
General | INVALID_CREDENTIALS_ERROR |
The OAuth bearer token for retrieving data from the referenced data storage system was rejected or is missing. Provide a valid bearer token are retry. |
General | TOO_MANY_PATCHES_ERROR |
The total number of requested patches exceed the maximum limit supported by the service, refer to micro batching. |
General | INCOMPATIBLE_PATCH_DIMENSIONS_ERROR |
The specified patch dimensions are not supported. Provide 224x224 patches and retry. |
General | PATCH_OUTSIDE_OF_IMAGE_DIMENSIONS_ERROR |
The patch coordinates don't fall entirely within the image. Change the coordinates or use require_patches_fully_in_source_image extension to control the service behaviour. |
General | HTTP_ERROR |
An HTTP error occurred during transaction with the referenced data storage system. Ensure the data links are valid and retry. |
General | INVALID_ICC_PROFILE_TRANSFORM_ERROR |
The requested ICC profile transformation is not supported. Ensure your images conform with the DICOM requirements and use the transform_imaging_to_icc_profile extension to control the service behaviour. |
General | IMAGE_DIMENSION_ERROR |
The resize dimensions are invalid. Correct the image_dimensions extension and retry. |
Image | IMAGE_ERROR |
An error occurred while decoding the compressed image bytes. Ensure the provided encoded string is valid and retry. Refer to inlined images for assistance. |
Image | GCS_IMAGE_PATH_FORMAT_ERROR |
The GCS image URI is incorrcet. Retry with a valid URI starting with gs:// . |
DICOM | LEVEL_NOT_FOUND_ERROR |
The SOP instance UID is not found in the DICOM series. Ensure the provides UID exists and retry. |
DICOM | INSTANCES_NOT_CONCATENATED_ERROR |
Multiple SOP instance UIDs were listed, but listed instances were not concatenated. Retry with concatenated instances. |
DICOM | DICOM_TILED_FULL_ERROR |
The requested DICOM image has more than one frame and appears to be sparsly tiled. Retry with a different fully tiled image. |
DICOM | DICOM_IMAGE_DOWNSAMPLING_TOO_LARGE_ERROR |
Resizing the DICOM image downsamples it more than 8x times. Retry with a different image or change image_dimensions extension. |
DICOM | DICOM_ERROR |
A DICOM instance is missing required tags or formatted incorrectly. Retry with different images that meet the DICOM requirements. |
DICOM | DICOM_PATH_ERROR |
No DICOM series found. Ensure the series exists, the path is in a correct format: https://dicomweb-store.uri/studies/${STUDY-UID}/series/${SERIES-UID} , and retry. |
Configuration | UNAPPROVED_DICOM_STORE_ERROR |
This error is raised if the service is configured with an allowlist DICOM Stores and an API caller requests embeddings from a DICOM Store that is not on the allowlist. By default this configuration is not set. See APPROVED_DICOM_STORE_SOURCE_LIST_FLAG in the container configuration. |
Configuration | UNAPPROVED_GCS_BUCKET_ERROR |
This error is raised if the service is configured with an allowlist GCS buckets and an API caller requests embeddings from a bucket that is not on the allowlist. By default this configuration is not set. See APPROVED_GCS_SOURCE_LIST_FLAG in the container configuration. |
Micro batching
The API request supports micro batching. You can request embeddings for multiple image patches using different instances within the same JSON request:
{
"instances": [
{...},
{...}
]
}
Furthermore, within one request instance, you can request multiple magnification
levels of the same DICOM series, where each magnification level is represented
by a different instance_uids
:
"dicom_path": {
"series_path": "https://dicomweb-store.uri/studies/1.2.3.4.5.6.7.8.9/series/1.2.3.4.5.6.7.8.10",
"instance_uids": ["1.2.3.4.5.6.7.8.11", "1.2.3.4.5.6.7.8.12"],
}
Keep in mind that the total number of embeddings that you can request in one API
call is capped by the service to a fixed limit that is set using
_MAX_PATCHES_PER_REQUEST
.
DICOM requirements
To ensure compatibility with the service, digital pathology Whole Slide Images (WSI) must be represented in DICOM format according to the requirements detailed in this section, which complement the HAI-DEF DICOM store requirements for the underlying storage system:
Supported Information Object Definitions (IODs): The service only supports the following IODs:
Media Storage SOP Class UID / SOP Class UID Name 1.2.840.10008.5.1.4.1.1.77.1.6 VL Whole Slide Microscopy Image IOD 1.2.840.10008.5.1.4.1.1.77.1.2 VL Microscopic Image IOD 1.2.840.10008.5.1.4.1.1.77.1.3 VL Slide-coordinates Microscopic Image IOD The VL Whole Slide Microscopy Imaging is the most common microscopy DICOM IOD for storing and exchanging WSI, typically produced by high-resolution commercial slide scanners. These images are very large and organized as a multi-resolution pyramid within the DICOM file. This IOD can also include information like the slide's label, a thumbnail preview, and details about the scanned area.
The VL Microscopic Image IOD and VL Slide-coordinates Microscopic Image IOD are used for storing images from microscopes with digital cameras. These images are not tiled. They are captured as a single, complete frame and represented by a single DICOM file.
Single pyramid representation: DICOM series that contain VL Whole Slide Microscopy Image IOD must contain one and only one representation of the image pyramid. DICOM imaging represented in either the VL Microscopic Image IOD or the VL Slide-coordinates Microscopic Image IOD must not be represented in the same series as VL Whole Slide Microscopy Image IOD imaging.
Uniform ICC color profile: If an ICC color profile is defined, the same ICC profile must be applicable to all levels of the image pyramid.
Single fragment encapsulated transfers In multi-frame images with encapsulated transfer syntax each frame's compressed data must be in one piece (one fragment). In single-frame images with encapsulated transfer syntax all the compressed data must be in one fragment.
Single focal planes: Images encoded with multiple focal planes are not supported.
Single optical path sequence: Images must be acquired using a single optical path and have one optical path sequence. Refer to Optical Path Module Attributes for details.
Transfer syntax transcoding: The service relies on the Transfer Syntax UID to transcode the image pixels. The following table lists the supported transcodes. If the service can't transcode the images itself, it falls back on the capabilities of the underlying DICOM storage system. If the DICOMs are from a Google Cloud DICOM store, this document on supported transfer syntaxes for transcoding applies.
Supported UID Name 1.2.840.10008.1.2.4.50 (Recommended) JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8-bit Image Compression 1.2.840.10008.1.2.4.90 JPEG 2000 Image Compression (Lossless Only) 1.2.840.10008.1.2.4.91 JPEG 2000 Image Compression 1.2.840.10008.1.2.1 Uncompressed 1.2.840.10008.1.2 Uncompressed '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little-Endian '1.2.840.10008.1.2.4.110' JPEGXL_LOSSLESS (coming soon) '1.2.840.10008.1.2.4.111' JPEGXL_JPEG (coming soon) 1.2.840.10008.1.2.4.112' JPEGXL (coming soon) Required tags: The following tags are required:
Tag Name Note (0002,0010) TransferSyntraxUID
(0008,0008) ImageType
(0008,0060) Modality
(0008,0016) SOPClassUID
(0008,0018) SOPInstanceUID
(0020,000E) SeriesInstanceUID
(0020,000D) StudyInstanceUID
(0020,9161) ConcatenationUID
Required if instance is part of a concatenation (uncommon) (0020,9228) ConcatenationFrameOffsetNumber
Required if instance is part of a concatenation (uncommon) (0020,9331) DimensionalOrganizationType
Must be set to TILED_FULL
for all multi-frame instances. Refer to Multi-frame Dimension Module Attributes for details.(0028,0002) SamplesPerPixel
Must be set to 1
for monochrome or grayscale imaging and3
for color imaging. Refer to Image Pixel Modul Attributes for details.(0028,0010) Rows
(0028,0011) Columns
(0028,0100) BitsAllocated
Must be set to 8
indicating 8 bits per sample encoding. Refer to Image Pixel Module Attributes for details.(0028,0102) HighBit
Must be set to 7
indicating little-endian encoding. Refer to Image Pixel Module Attributes for details.(0028,2000) ICC Profile
Not a root level tag; expected in OpticalPathSequence (0048,0105) -> ICC_Profile (0028, 2000) (0028,9110) PixelSpacing
Not a root level tag; expected in: Shared Functional Group Sequence (5200, 9229) -> Pixel Measures Sequence (0028, 9110) -> PixelSpacing (0028, 9110). (0048,0001) ImagedVolumeWidth
(0048,0002) ImagedVolumeHeight
(0048,0006) TotalPixelMatrixColumns
(0048,0007) TotalPixelMatrixRows
(7FE0,0010) PixelData