Skip to content

feat(api): serve motion-corrected micrograph preview image (ADR 0021) #308

Description

@vredchenko

Important

Re-scoped by ADR 0021 (Micrograph Motion-Corrected Preview Image Ingestion and Serving; smartem-devtools PR #232).

The original proposal below — serve high_res_path via _render_image_png — is superseded. high_res_path is the raw multi-GB dose-fractionated movie stack: a 3D array PIL.Image.fromarray cannot encode, and loading it reproduces the atlas-page OOM. Unprocessed rows carry high_res_path = '.' (unset Path("")).

New scope: add GET /micrographs/{uuid}/micrograph_image that serves the motion-corrected artefacts ingested per ADR 0021 — JPEG-first (FileResponse, zero-render) -> MRC-fallback (_render_image_png, x,y,w,h crop) -> 404. The endpoint never reads high_res_path.

Gated behind #309 (schema migration + additive contract extension + consumer persistence). Real images require #310 (cryoem-services adapter supplies the paths); until then the endpoint correctly 404s.


Original proposal (historical, superseded above):

Context

The frontend can navigate the full acquisition hierarchy Atlas -> Grid Square -> Foil Hole -> Micrograph. The atlas and grid-square levels each have an image-serving endpoint, but the micrograph (exposure) level - the leaf, where the actual high-magnification data lives - has none. The foil-hole detail view therefore renders each micrograph as a grey placeholder tile, so the most scientifically meaningful image in the hierarchy is the one image the API cannot serve.

Current state

Two image endpoints exist and share a common rendering path:

  • GET /grids/{grid_uuid}/atlas_image - src/smartem_backend/api_server.py:2751 (supports an x,y,w,h crop query)
  • GET /gridsquares/{gridsquare_uuid}/gridsquare_image - src/smartem_backend/api_server.py:2774
  • Both resolve an on-disk MRC/image and render it to PNG via _render_image_png / _cached_image_response (api_server.py:2721-2748), returning image/png with a private cache header.

Micrograph rows carry high_res_path (plus image_size_x/y), but there is no corresponding image endpoint. The micrograph routes are metadata-only: /micrographs, /micrographs/{uuid}, /foilholes/{uuid}/micrographs.

Proposal

Add GET /micrographs/{micrograph_uuid}/micrograph_image (naming to match the existing convention) that:

  • resolves the micrograph's high_res_path on disk (subject to the same path-resolution/mount concerns already tracked for atlas/grid-square imagery),
  • renders to PNG via the existing _render_image_png / _cached_image_response helpers, optionally accepting the same x,y,w,h crop query the atlas endpoint has (useful for future zoom),
  • returns image/png with the same caching behaviour,
  • 404s cleanly when high_res_path is null or the file is absent.

Frontend impact

FoilholeDetail.tsx (smartem-frontend) currently renders each micrograph as a placeholder box. With this endpoint it would fetch the image as an authenticated blob -> object URL (the pattern already used for atlas and grid-square images) and show a real exposure preview.

Data observations from the current prod dump (context, not blockers)

Captured while confirming the gap - relevant to anyone testing the endpoint:

  • The grid used for FE testing (0Dim9CdRSrKjhWYcH2WRUQ) has 20,328 micrographs but 0 in a completed state; every foil hole there shows an unprocessed exposure.
  • Across the whole dump, PARTICLE_PICKING_COMPLETED micrographs (366,057) have high_res_path populated but all processing metrics (ctf_max_resolution_estimate, defocus, total_motion, average_motion, number_of_particles_*) are NULL. So the leaf level is currently untestable for metrics as well as imagery, independent of this endpoint.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions