scan_image_service
Serves an already-resolved scan file as a ZIP of scaled WebP frames.
Resolution (scan_id/path → validated file path) is the repository's job; this
service takes a resolved path, reads or builds each cache layer the request
needs — the frames always, plus the masks and the vectors when those outputs
were asked for — and stitches them into one archive. The repository composes it
and dispatches to render.
Classes
ScanImageService
class ScanImageService( *, cache: ScanImageCache, default_width: int, quality: int, cache_getter: Callable[[], CacheProtocol] | None = None,):Renders a resolved scan file into a ZIP of scaled WebP frames, cached.
Arguments
cache: The encrypted on-disk image cache.default_width: Output width used when the request omits one.quality: WebP quality for encoding.cache_getter: A zero-arg callable returning the pod background cache, used to look up segmentation overlays.None(the default) leaves the overlay feature disabled, so requests are served images-only.
Store the cache and conversion parameters used to render scans.
Methods
render
def render( self, resolved_path: str, *, file_id: str, modality: str | None, laterality: str | None, width: int | None, refresh: bool, include_masks: bool = False, include_vectors: bool = False, segmentation_classes: list[str] | None = None,) ‑> bytes:Return the ZIP archive of converted frames for a resolved scan file.
With both overlay flags False (the default), no inference fingerprint is read and no overlay work is attempted, so an opt-out request touches neither the background cache nor model-inference storage.
Arguments
resolved_path: The already-resolved, allowlisted scan file path.file_id: The scan's raw ingested path, as recorded on its inference rows. Deliberately not the resolved real path: the rows key on the path ingest stored, which differs under a symlinked mount.modality: Optional series selector.laterality: Optional "L"/"R" series selector.width: Requested output width; None uses the configured default.refresh: When True, bypass and overwrite any cached entry.include_masks: Whether the archive should carry a rendered mask PNG per segmentation class.include_vectors: Whether the served index should carry each class's raw drawable instances, in the model's own pixel space. Costs no PNG encode, so it is the cheap way to overlay a scan.segmentation_classes: Optional class-name filter, applied after normalising each name (case/punctuation-insensitive) the same way a model's own class names are normalised. Ignored when neither overlay output was requested. A name that matches no class any model produced yields no output for it, never an error.
Returns The ZIP archive bytes.
Raises
ScanRequestError: Non-positive width, or an undecodable file.ScanNotFoundError: The resolved file is missing/unreadable (e.g. deleted or unmounted between resolution and rendering).
ScanNotFoundError
class ScanNotFoundError(*args, **kwargs):Raised when a scan_id/path cannot be resolved to an authorised file.
ScanRequestError
class ScanRequestError(*args, **kwargs):Raised for malformed requests (bad inputs, undecodable file).