Coronary angiography — keyframe vessel mapping with same-acquisition context, SYNTAX assignment, stenosis localization
You are given eight coronary angiography keyframe cases. Each contains one primary keyframe plus four supplementary frames from the same acquisition and projection. Supplementary images show slight cardiac motion and contrast-filling changes and provide context for disambiguating overlap and catheter edges; they are not different projection angles.
For each case, identify visible coronary segments using SYNTAX conventions within the annotated keyframe, use same-acquisition supplementary frames to maintain vessel identity through motion and to resolve foreshortening/overlap, localize stenoses, and quantify severity using a mask-derived diameter rule, with registered evidence.
Inputs
In the data directory:
-
case_01/ through case_08/ — one folder per case. Inside each:
case_01_keyframe.png — primary annotated keyframe (de-identified single-projection X-ray with contrast fill showing coronary tree: LM, LAD/diagonals/septals, LCx/OM, RCA branches depending on view, plus guiding catheter and aorta). This is the frame that held-back SYNTAX/stenosis annotations reference.
- Supplementary same-acquisition frames, e.g.
case_01_frame_m2.png, case_01_frame_m1.png, case_01_frame_p1.png, case_01_frame_p2.png — four frames immediately before/after the keyframe from the same acquisition, same projection angle, same calibration. They show slight motion and contrast differences, not different projection angles (RAO/LAO). Use them to track vessels through motion and confirm true lesions vs overlap.
- Cases span different projection angles, segment visibility, catheter overlap, uncertain borders, positive findings, and zero-stenosis controls. No segment masks, stenosis annotations, catheter masks, or uncertainty masks are agent-visible.
-
cases.json — authoritative inventory: case ID, primary-keyframe basename, four supplementary-frame basenames, one projection label, pixel spacing, and dimensions. It contains no segment or stenosis answers.
-
segment_definitions.json — neutral SYNTAX segment dictionary listing every segment code that may appear, with anatomical names and definitions. It is a naming reference, not a per-case answer key.
Letter-suffixed source labels are merged into their anatomically identifiable
parent segment (for example, 16a and 16b become 16), so no hidden
annotation ordering is needed to name sibling branches.
The answer lives only in X-ray pixels of the primary keyframe, with same-acquisition frames as context. No multi-projection reconciliation — supplementary frames are same projection, same acquisition.
What to produce
findings.json — per-case machine-readable inventory:
{
"cases": [
{
"case_id": "case_demo",
"primary_keyframe": "case_demo_keyframe.png",
"supplementary_frames": [
"case_demo_frame_m2.png",
"case_demo_frame_m1.png",
"case_demo_frame_p1.png",
"case_demo_frame_p2.png"
],
"projection_label": "primary=-10 deg, secondary=25 deg",
"visible_segments": [
{
"segment_code": "06",
"segment_name": "LAD proximal",
"present": true,
"visible": true,
"keyframe": "case_demo_keyframe.png",
"confidence": 0.85,
"notes": "clear in keyframe, confirmed in supplementary m1/p1"
}
],
"stenoses": [
{
"id": "case_demo_s01",
"segment_code": "06",
"keyframe": "case_demo_keyframe.png",
"center_x": 212.3,
"center_y": 240.1,
"extent_px": 18.5,
"diameter_reduction_pct": 70.0,
"measurement_method": "mask-derived orthogonal local width versus segment 90th-percentile reference width",
"qca_geometry": {
"min_width_px": 3.6,
"reference_width_px": 12.0,
"min_width_line": [
[210.5, 240.1],
[214.1, 240.1]
],
"reference_center_x": 194.0,
"reference_center_y": 229.0,
"reference_width_line": [
[188.0, 229.0],
[200.0, 229.0]
]
},
"confidence": 0.8,
"uncertain": false,
"uncertainty_reason": null,
"confirmed_in_supplementary": true,
"temporal_track": [
{
"frame": "case_demo_keyframe.png",
"center_x": 212.3,
"center_y": 240.1,
"visible": true
},
{
"frame": "case_demo_frame_m2.png",
"center_x": 211.0,
"center_y": 241.0,
"visible": true
},
{
"frame": "case_demo_frame_m1.png",
"center_x": 210.8,
"center_y": 241.4,
"visible": true
},
{
"frame": "case_demo_frame_p1.png",
"center_x": 213.1,
"center_y": 239.8,
"visible": true
},
{
"frame": "case_demo_frame_p2.png",
"center_x": 214.0,
"center_y": 239.2,
"visible": true
}
]
}
],
"uncertain_regions": [
{
"segment_code": "11",
"keyframe": "case_demo_keyframe.png",
"reason": "catheter_overlap",
"bbox_xyxy": [180, 205, 238, 276],
"description": "guiding catheter overlaps proximal LCx in keyframe, persists in supplementary"
}
],
"catheter_notes": "JL4 in aortic root, overlaps proximal segments",
"overall_assessment": "Single 70% proximal LAD lesion in primary keyframe; other visible segments unobstructed, consistent across same-acquisition frames"
}
]
}
Required:
case_id must match cases.json. In findings.json, primary_keyframe, supplementary_frames, and every keyframe field must use file basenames only, exactly matching files inside that case folder. All supplementary frames are from the same acquisition and projection.
visible_segments contains visible segments only; omit non-visible segments. Follow the bifurcation boundary rules in segment_definitions.json, reference the primary basename, and report confidence in [0,1].
stenoses: id must be unique and use <case_id>_sNN; center_x/y use the original unresampled primary-keyframe pixel grid, origin (0,0) at top-left, x rightward and y downward. Define extent_px as the larger of the x-span and y-span of the connected narrowing region, measured between extreme pixel centers. For a quantifiable lesion, diameter_reduction_pct is 0-100, qca_geometry is required, and measurement_method must be exactly mask-derived orthogonal local width versus segment 90th-percentile reference width. If severity is unquantifiable, set uncertain:true, set both diameter_reduction_pct and qca_geometry to null, set measurement_method to exactly unquantifiable, and use one of catheter_overlap, overlap_foreshortening, poor_contrast, or border_uncertain. Unquantifiable lesions retain detection and uncertainty scoring but are excluded from severity scoring.
- Severity rule pinned: measure lumen width through the stenosis center, orthogonal to the local vessel direction. Define
min_width there. Define reference_width as twice the 90th percentile of all positive Euclidean distance-transform radii in the submitted segment mask; the reference line may be placed at any in-mask location having that width. Report 100 * (1 - min_width/reference_width), clipped to [0,100]. Use measurement_method: "mask-derived orthogonal local width versus segment 90th-percentile reference width".
- Inspectable QCA geometry required: every stenosis must include
qca_geometry with positive min_width_px and reference_width_px, a two-endpoint min_width_line, a two-endpoint reference_width_line, and the reference-line center in original keyframe pixels. Each line length must agree with its declared width (within 1 pixel), its midpoint must be inside the submitted mask, and its direction must agree within 20 degrees of the local normal estimated from the closest mask boundary. The minimal-width line midpoint must agree with the stenosis center (within 3 pixels); the reference-line midpoint must agree with its declared center (within 3 pixels). The local mask width must agree with each declared width within 1.5 pixels, and the reported percentage must be derived from the two widths.
- Matching rule: a stenosis center may be placed anywhere on the connected narrowing region; this avoids imposing one arbitrary centroid on long or diffuse targets. A prediction is eligible only in the same case and segment and when its center is inside or within 10 pixels of that held-back region. Matching is one-to-one and minimizes distance to the region; ties are resolved by smaller severity error, then smaller extent error. Unmatched predictions and references are false positives and false negatives.
- Temporal-track rule: every stenosis must contain exactly five
temporal_track rows: the primary basename followed by the four supplementary basenames in cases.json order. For visible rows, give native-frame pixel coordinates. The primary row must be within 3 pixels of the submitted stenosis center, which itself must satisfy the lesion-region matching rule. For supplementary rows, the grader applies each held-back frame-to-frame motion delta to the submitted primary point and allows 12 pixels of correspondence tolerance, then also requires local-patch agreement with the submitted primary patch. This validates plausible same-lesion motion without forcing the held-back primary centroid. Filenames or booleans alone do not earn temporal credit.
uncertain_regions per primary keyframe where catheter/overlap prevents assessment — check supplementary same-acquisition frames to confirm persistence. Every region requires bbox_xyxy: [x_min,y_min,x_max,y_max] in primary-keyframe pixels, with positive area and a description of at least 12 characters. The grader spatially compares the box with held-back catheter/border uncertainty geometry using three-pixel box expansion so tiny regions are not hypersensitive; prose alone earns no region credit.
- Coordinates reference primary keyframe image without resampling.
segment_masks/ — required registered vessel mapping:
- For every entry in
visible_segments, write segment_masks/<case_id>_<segment_code>.png.
- Each file is a single-channel or RGB binary mask at exactly the original keyframe dimensions: background 0, claimed segment nonzero.
- Do not include masks for omitted/non-visible segments. Masks are scored by Dice against held-back segment annotations; wrong extra codes are penalized.
- Optional visualization evidence in
evidence/ (advisory and unscored):
evidence/case_01_keyframe_overlay.png — overlay on primary keyframe per stenosis and per case showing segment labeling. Same dimensions as source keyframe. Draw centerlines, stenosis center+extent, label with segment codes and % per mask-derived rule.
evidence/case_01_same_acquisition_sheet.png — contact sheet of primary keyframe plus supplementary same-acquisition frames (same projection) with same vessel/stenosis markers tracked across frames, proving temporal consistency and disambiguation of overlap/catheter vs true lesion.
- Evidence must use same primary keyframe filename cited in findings; supplementary sheet proves same-acquisition continuity, not multi-projection.
- Optional
report.md (advisory and unscored) — temporal tracking, anatomy assignment, uncertainty, and severity notes.
What to do
- Open primary keyframe PNG plus supplementary frames from same acquisition in viewer or Python/OpenCV. All frames in a case share same projection angle — supplementary frames show same view with slight motion and fill changes, not RAO vs LAO.
- Identify guiding catheter and aorta in primary keyframe — NOT coronary segments. Use supplementary frames to see catheter move relative to coronary.
- Map visible anatomy in primary keyframe to SYNTAX using
segment_definitions.json exact inventory. Maintain identity across supplementary same-acquisition frames of same case (same projection, slight motion). Non-visible segments not scored as false negatives.
- For each visible segment record primary keyframe filename and confidence, confirming in supplementary same-acquisition frames.
- Locate stenoses in primary keyframe where best filled. True stenosis shows focal narrowing with post-stenotic dilatation and persists as narrowing across supplementary same-acquisition frames; vanishing narrowing that appears/disappears with contrast pulsing or overlap in same-acquisition context may still be overlap — check consistency.
- Mark uncertain regions and record the five-row image-grounded temporal track for every stenosis.
- Measure diameter reduction using the pinned segment 90th-percentile reference-width rule.
Traps
- Same-acquisition motion/overlap: same artery appears slightly shifted or overlapped differently in supplementary frames due to cardiac motion and contrast fill. Severity from poorly-filled frame alone = false positive — use best-filled primary keyframe with supplementary confirmation.
- Catheter/contrast edges: marker bands and streaming not lesions; catheter moves slightly across same-acquisition frames, helping disambiguate.
- Single-projection limits: supplementary frames are same projection, not new angles, so a severe-looking narrowing that persists across same-acquisition frames is likely true; but you cannot use a different projection angle to resolve — you must use fill quality and catheter tracking.
- Blanket disease calls: include zero-stenosis controls and non-visible segments; blanket calls lose precision.
- Not multi-projection: supplementary images are same-acquisition frames at one projection angle; do not describe them as RAO/LAO alternatives within a case.
Constraints
- Analyze X-ray pixels of primary keyframe with same-acquisition context; no hardcoding, no internet keys.
- Vessel identity consistent across supplementary same-acquisition frames of same case: same anatomy one SYNTAX label, same projection.
- Do not confuse catheter/aorta/streaming for disease.
- Non-visible not false negative; labeling invisible as visible disease is false positive.
- Optional overlays, if supplied, must remain registered to their source images.
- Input format is one primary PNG plus four same-acquisition context PNGs per case. Exact filenames and segment inventory are authoritative in
cases.json and segment_definitions.json.
- Severity is scored using the deterministic orthogonal-width rule above.
Done when
findings.json exists with all cases from cases.json, valid SYNTAX codes from segment_definitions.json, primary keyframe filenames per segment/stenosis, pixel coords, severity % per mask-derived orthogonal rule, confidence, uncertainty reasons, confirmation in supplementary same-acquisition frames.
- Every stenosis has a complete five-frame temporal track with image-consistent local patches.
- Optional evidence/report, if supplied, agrees with the structured findings.
- High-quality: spatial segment-map score >0.80, stenosis detection F1 >0.75, severity MAE <15%, correct catheter/uncertainty handling, and held-back temporal-track agreement. The segment score averages code-set F1 and registered-mask Dice. Weighting: 0.20 segment mapping, 0.30 detection, 0.20 severity/extent/QCA geometry, 0.20 temporal tracking, 0.10 uncertainty.