JEBS-4B / src /mdprep /visuals.py
the-Xy's picture
JEBS-4B v3: sealed artifact, runtime, model card
6592c2d verified
Raw History Blame Contribute Delete
40.2 kB
"""Deterministic synthetic visual-decision data builder."""
import argparse
import json
from collections import Counter
from pathlib import Path
from typing import Any
from PIL import Image, ImageDraw, ImageFont
from mdprep.common import (
GENERATOR_VERSION,
PART_QUOTAS,
SPLITS,
choice,
fetch,
noul,
record,
rng_for,
score,
sha256_file,
stable_id,
write_json,
write_jsonl,
)
SOURCE = "synthetic-visuals-v1"
FONT_REVISION = "1cb311624b2ddf88e9e37873999d165a8cd28b46"
FONT_URL = (
"https://raw.githubusercontent.com/googlefonts/atkinson-hyperlegible/"
f"{FONT_REVISION}/fonts/ttf/AtkinsonHyperlegible-Regular.ttf"
)
FONT_LICENSE_URL = (
"https://raw.githubusercontent.com/googlefonts/atkinson-hyperlegible/"
f"{FONT_REVISION}/OFL.txt"
)
FONT_SHA256 = "7fb917c89019896d0b52ee84b7cbb3304c18cb90b19a62f5e32712bd23e97669"
FONT_LICENSE_SHA256 = "f32d22b3908fcad2c86a74000614ec22e6a7f66ea7e867e616026a27aebdc143"
WIDTH = 450
HEIGHT = 450
CATEGORIES = ("receipt", "bar_chart", "request_form", "dashboard", "spatial")
THEMES = (
{"ink": "#17212b", "muted": "#65727e", "paper": "#fffdf8", "accent": "#19647e", "soft": "#dceff4"},
{"ink": "#261f2d", "muted": "#746a7b", "paper": "#fffaf3", "accent": "#8a4f2d", "soft": "#f3dfcf"},
{"ink": "#132a20", "muted": "#607269", "paper": "#f8fff9", "accent": "#24734d", "soft": "#dcefe3"},
)
OOD_LAYOUTS = {
"receipt": "receipt-stacked-cards-ood",
"bar_chart": "bar-horizontal-ood",
"request_form": "form-field-cards-ood",
"dashboard": "dashboard-sidebar-ood",
"spatial": "spatial-coordinate-grid-ood",
}
ACTION_SETS = {
"receipt": ("Decline", "Manual review", "Reimburse", "Priority reimburse"),
"bar_chart": ("Observe", "Notify", "Investigate", "Escalate", "Emergency response"),
"request_form": ("Return to requester", "Supervisor review", "Authorize"),
"dashboard": ("Backlog", "Normal queue", "Fast track", "Incident bridge"),
"spatial": ("Accept layout", "Inspect layout", "Revise layout", "Close area"),
}
MISSING_FIELDS = {
"receipt": "a visible cost-center approval code",
"bar_chart": "a visible audited-denominator badge",
"request_form": "a visible supervisor-clearance code",
"dashboard": "a visible customer-impact verification",
"spatial": "a visible ceiling-height measurement",
}
METRIC_NAMES = {
"receipt": "printed TOTAL in dollars",
"bar_chart": "Nimbus count",
"request_form": "requested units",
"dashboard": "open-ticket count",
"spatial": "red-triangle count",
}
DIRECTIONS = {
"receipt": "maximum",
"bar_chart": "minimum",
"request_form": "maximum",
"dashboard": "minimum",
"spatial": "maximum",
}
def _font_files(root: Path) -> tuple[Path, Path]:
font_dir = root / "data/raw/visuals/atkinson-hyperlegible"
font_path = fetch(FONT_URL, font_dir / "AtkinsonHyperlegible-Regular.ttf")
license_path = fetch(FONT_LICENSE_URL, font_dir / "OFL.txt")
actual_font_hash = sha256_file(font_path)
actual_license_hash = sha256_file(license_path)
if actual_font_hash != FONT_SHA256:
raise RuntimeError(f"Pinned font hash mismatch: {actual_font_hash}")
if actual_license_hash != FONT_LICENSE_SHA256:
raise RuntimeError(f"Pinned font license hash mismatch: {actual_license_hash}")
return font_path, license_path
def _fonts(font_path: Path) -> dict[str, ImageFont.FreeTypeFont]:
return {
"xs": ImageFont.truetype(str(font_path), 14),
"sm": ImageFont.truetype(str(font_path), 17),
"body": ImageFont.truetype(str(font_path), 20),
"strong": ImageFont.truetype(str(font_path), 23),
"title": ImageFont.truetype(str(font_path), 30),
"hero": ImageFont.truetype(str(font_path), 42),
}
def _write(draw: ImageDraw.ImageDraw, xy: tuple[int, int], text: object,
font: ImageFont.FreeTypeFont, fill: str, anchor: str | None = None) -> None:
draw.text(xy, str(text), font=font, fill=fill, anchor=anchor)
def _metric_values(category: str, rng: Any) -> tuple[int, int]:
if category == "receipt":
low = rng.randint(38, 58)
return low, low + rng.randint(22, 34)
if category == "bar_chart":
low = rng.randint(24, 39)
return low, low + rng.randint(28, 39)
if category == "request_form":
low = rng.randint(24, 44)
return low, low + rng.randint(28, 42)
if category == "dashboard":
low = rng.randint(3, 7)
return low, low + rng.randint(5, 9)
low = rng.randint(2, 4)
return low, low + rng.randint(3, 4)
def _make_scene(split: str, index: int, attempt: int = 0) -> dict[str, Any]:
category = CATEGORIES[index % len(CATEGORIES)]
rng = rng_for(SOURCE, split, index, category, attempt)
low, high = _metric_values(category, rng)
is_ood = split == "test_ood"
layout_family = OOD_LAYOUTS[category] if is_ood else f"{category}-standard-{index % 3}"
scene: dict[str, Any] = {
"category": category,
"index": index,
"theme": index % len(THEMES),
"layout_family": layout_family,
"ood": is_ood,
"values": {"a": low, "b": high},
"flag": bool(index % 2),
"required_field_visible": bool((index // len(CATEGORIES)) % 2),
}
if category == "receipt":
scene.update(
merchant=("NORTH PINE", "COPPER & CO", "GREEN MARKET")[index % 3],
receipt_number=f"R-{rng.randint(10000, 99999)}",
date=f"2026-{(index % 9) + 1:02d}-{(index * 7 % 27) + 1:02d}",
items=("Notebook", "Cable", "Tea", "Storage box"),
)
elif category == "bar_chart":
comparator = high + 6 if scene["flag"] else max(5, high - 6)
scene.update(
title=("Resolved cases", "Weekly inspections", "Validated batches")[index % 3],
labels=("Aster", "Cedar", "Nimbus", "Orchid"),
fixed_values=(rng.randint(15, 70), comparator, None, rng.randint(18, 68)),
)
elif category == "request_form":
scene.update(
request_id=f"Q-{rng.randint(1000, 9999)}",
department=("Facilities", "Research", "Operations")[index % 3],
requester=("Morgan L.", "Avery K.", "Jordan P.")[index % 3],
)
elif category == "dashboard":
scene.update(
queue=("Atlas Support", "Beacon Ops", "Cedar Service")[index % 3],
waiting=rng.randint(1, 6),
resolved=rng.randint(18, 44),
activities=rng.sample((
"New request", "Assigned to agent", "Customer reply", "Awaiting confirmation",
"Document received", "Callback scheduled", "Issue escalated", "Reply drafted",
"Review completed", "Follow-up queued", "Team notified", "Status updated",
), 3),
)
else:
relation = "left" if scene["flag"] else "right"
candidate_positions = [
(58 + column * 80, 144 + row * 68)
for row in range(3)
for column in range(5)
]
rng.shuffle(candidate_positions)
triangle_geometry = tuple(
(x + rng.randint(-10, 10), y + rng.randint(-10, 10), rng.randint(13, 18))
for x, y in candidate_positions[:8]
)
marker_x_positions = rng.sample((70, 126, 182, 238, 294, 350, 398), 2)
left_x, right_x = sorted(marker_x_positions)
blue_x, square_x = (
(left_x, right_x) if relation == "left" else (right_x, left_x)
)
scene.update(
map_name=("Packing zone", "Lab bay", "Loading area")[index % 3],
relation=relation,
triangle_geometry=triangle_geometry,
blue_center=(blue_x, rng.randint(340, 365)),
square_center=(square_x, rng.randint(340, 365)),
)
return scene
def _base_image(scene: dict[str, Any]) -> tuple[Image.Image, ImageDraw.ImageDraw, dict[str, str]]:
theme = THEMES[scene["theme"]]
image = Image.new("RGB", (WIDTH, HEIGHT), theme["paper"])
return image, ImageDraw.Draw(image), theme
def _render_receipt(scene: dict[str, Any], value: int,
fonts: dict[str, ImageFont.FreeTypeFont]) -> Image.Image:
image, draw, theme = _base_image(scene)
if scene["ood"]:
draw.rounded_rectangle((22, 20, 428, 430), radius=26, fill="#f4eee4", outline=theme["ink"], width=2)
_write(draw, (48, 48), scene["merchant"], fonts["title"], theme["ink"])
_write(draw, (48, 83), "PURCHASE SUMMARY", fonts["xs"], theme["accent"])
_write(draw, (48, 110), scene["date"], fonts["sm"], theme["muted"])
y = 148
savings = 5 if scene["flag"] else 0
fixed = (8, 11, 9)
prices = (*fixed, value - sum(fixed) + savings)
for name, price in zip(scene["items"], prices):
draw.rounded_rectangle((42, y, 408, y + 43), radius=10, fill="#fffaf2")
_write(draw, (58, y + 11), name, fonts["sm"], theme["ink"])
_write(draw, (389, y + 11), f"${price:.2f}", fonts["sm"], theme["ink"], "ra")
y += 50
if scene["flag"]:
_write(draw, (58, 354), "MEMBER SAVINGS", fonts["xs"], theme["accent"])
_write(draw, (389, 354), "-$5.00", fonts["xs"], theme["accent"], "ra")
_write(draw, (58, 397), "TOTAL", fonts["strong"], theme["ink"])
_write(draw, (389, 397), f"${value:.2f}", fonts["strong"], theme["ink"], "ra")
return image
draw.rectangle((62, 18, 388, 432), fill="#fffefa", outline="#c9c4b8", width=2)
_write(draw, (225, 46), scene["merchant"], fonts["title"], theme["ink"], "ma")
_write(draw, (225, 80), "SALES RECEIPT", fonts["xs"], theme["muted"], "ma")
_write(draw, (82, 109), scene["date"], fonts["sm"], theme["ink"])
_write(draw, (367, 109), scene["receipt_number"], fonts["sm"], theme["ink"], "ra")
draw.line((82, 137, 368, 137), fill="#8b8b83", width=1)
savings = 5 if scene["flag"] else 0
fixed = (8, 11, 9)
prices = (*fixed, value - sum(fixed) + savings)
y = 157
for name, price in zip(scene["items"], prices):
_write(draw, (84, y), name, fonts["sm"], theme["ink"])
_write(draw, (366, y), f"${price:.2f}", fonts["sm"], theme["ink"], "ra")
y += 37
draw.line((82, 308, 368, 308), fill="#8b8b83", width=1)
if scene["flag"]:
_write(draw, (84, 326), "MEMBER SAVINGS", fonts["xs"], theme["accent"])
_write(draw, (366, 326), "-$5.00", fonts["xs"], theme["accent"], "ra")
_write(draw, (84, 366), "TOTAL", fonts["strong"], theme["ink"])
_write(draw, (366, 366), f"${value:.2f}", fonts["strong"], theme["ink"], "ra")
_write(draw, (225, 414), "Thank you", fonts["sm"], theme["muted"], "ma")
return image
def _bar_values(scene: dict[str, Any], value: int) -> list[int]:
return [value if item is None else item for item in scene["fixed_values"]]
def _render_bar_chart(scene: dict[str, Any], value: int,
fonts: dict[str, ImageFont.FreeTypeFont]) -> Image.Image:
image, draw, theme = _base_image(scene)
values = _bar_values(scene, value)
labels = scene["labels"]
_write(draw, (30, 28), scene["title"], fonts["title"], theme["ink"])
_write(draw, (30, 65), "COUNT BY TEAM", fonts["xs"], theme["muted"])
if scene["ood"]:
x0, x1 = 112, 410
y = 116
for label, bar_value in zip(labels, values):
_write(draw, (96, y + 13), label, fonts["sm"], theme["ink"], "ra")
draw.rounded_rectangle((x0, y, x1, y + 34), radius=7, fill=theme["soft"])
end = x0 + int((x1 - x0) * bar_value / 100)
draw.rounded_rectangle((x0, y, end, y + 34), radius=7, fill=theme["accent"])
_write(draw, (min(end + 8, 423), y + 8), bar_value, fonts["sm"], theme["ink"])
y += 67
_write(draw, (112, 404), "0", fonts["xs"], theme["muted"])
_write(draw, (410, 404), "100", fonts["xs"], theme["muted"], "ra")
return image
chart = (52, 105, 415, 382)
draw.line((chart[0], chart[3], chart[2], chart[3]), fill=theme["ink"], width=2)
draw.line((chart[0], chart[1], chart[0], chart[3]), fill=theme["ink"], width=2)
for tick in range(0, 101, 25):
y = chart[3] - int((chart[3] - chart[1]) * tick / 100)
draw.line((chart[0], y, chart[2], y), fill="#d6d9d7", width=1)
_write(draw, (43, y), tick, fonts["xs"], theme["muted"], "rm")
bar_width = 54
for pos, (label, bar_value) in enumerate(zip(labels, values)):
x = 75 + pos * 83
top = chart[3] - int((chart[3] - chart[1]) * bar_value / 100)
draw.rounded_rectangle((x, top, x + bar_width, chart[3]), radius=6, fill=theme["accent"])
_write(draw, (x + bar_width // 2, top - 8), bar_value, fonts["sm"], theme["ink"], "mb")
_write(draw, (x + bar_width // 2, 402), label, fonts["xs"], theme["ink"], "ma")
return image
def _render_request_form(scene: dict[str, Any], value: int,
fonts: dict[str, ImageFont.FreeTypeFont]) -> Image.Image:
image, draw, theme = _base_image(scene)
_write(draw, (28, 27), "RESOURCE REQUEST", fonts["title"], theme["ink"])
_write(draw, (28, 65), scene["request_id"], fonts["sm"], theme["accent"])
fields = (
("REQUESTER", scene["requester"]),
("DEPARTMENT", scene["department"]),
("REQUESTED UNITS", str(value)),
("REQUESTER SIGNED", "Yes" if scene["flag"] else "No"),
)
if scene["ood"]:
y = 102
for label, field_value in fields:
draw.rounded_rectangle((28, y, 422, y + 66), radius=12, fill=theme["soft"])
_write(draw, (47, y + 10), label, fonts["xs"], theme["muted"])
_write(draw, (47, y + 33), field_value, fonts["body"], theme["ink"])
y += 76
_write(draw, (28, 414), "Submitted information", fonts["xs"], theme["muted"])
return image
draw.rounded_rectangle((28, 96, 422, 390), radius=10, outline="#a8b0ac", width=2)
y = 96
for label, field_value in fields:
draw.rectangle((28, y, 174, y + 73), fill=theme["soft"])
_write(draw, (44, y + 26), label, fonts["xs"], theme["ink"])
_write(draw, (198, y + 24), field_value, fonts["body"], theme["ink"])
y += 73
draw.line((28, y, 422, y), fill="#a8b0ac", width=1)
_write(draw, (28, 416), "Internal request form", fonts["xs"], theme["muted"])
return image
def _render_dashboard(scene: dict[str, Any], value: int,
fonts: dict[str, ImageFont.FreeTypeFont]) -> Image.Image:
image, draw, theme = _base_image(scene)
if scene["ood"]:
draw.rectangle((0, 0, 116, HEIGHT), fill=theme["ink"])
_write(draw, (18, 28), "PULSE", fonts["strong"], "#ffffff")
for y, label in ((102, "Queue"), (148, "Agents"), (194, "Reports")):
_write(draw, (18, y), label, fonts["sm"], "#dce6e1")
_write(draw, (142, 31), scene["queue"], fonts["title"], theme["ink"])
_write(draw, (142, 72), "LIVE QUEUE", fonts["xs"], theme["muted"])
draw.rounded_rectangle((142, 111, 420, 228), radius=18, fill=theme["soft"])
_write(draw, (163, 132), "OPEN TICKETS", fonts["xs"], theme["muted"])
_write(draw, (163, 163), value, fonts["hero"], theme["ink"])
draw.rounded_rectangle((142, 248, 274, 342), radius=14, outline=theme["accent"], width=2)
draw.rounded_rectangle((288, 248, 420, 342), radius=14, outline=theme["accent"], width=2)
_write(draw, (158, 264), "WAITING", fonts["xs"], theme["muted"])
_write(draw, (158, 293), scene["waiting"], fonts["title"], theme["ink"])
_write(draw, (304, 264), "RESOLVED", fonts["xs"], theme["muted"])
_write(draw, (304, 293), scene["resolved"], fonts["title"], theme["ink"])
if scene["flag"]:
draw.rounded_rectangle((142, 370, 420, 420), radius=10, fill="#f5d7d0")
_write(draw, (161, 385), "SERVICE NOTICE ACTIVE", fonts["sm"], "#7f2e22")
return image
draw.rectangle((0, 0, WIDTH, 72), fill=theme["ink"])
_write(draw, (24, 22), "PULSE DESK", fonts["strong"], "#ffffff")
_write(draw, (426, 25), scene["queue"], fonts["sm"], "#ffffff", "ra")
cards = (("OPEN TICKETS", value), ("WAITING", scene["waiting"]), ("RESOLVED", scene["resolved"]))
for idx, (label, number) in enumerate(cards):
x = 24 + idx * 142
draw.rounded_rectangle((x, 104, x + 122, 218), radius=14, fill=theme["soft"])
_write(draw, (x + 14, 123), label, fonts["xs"], theme["muted"])
_write(draw, (x + 14, 157), number, fonts["hero"], theme["ink"])
_write(draw, (24, 259), "QUEUE ACTIVITY", fonts["xs"], theme["muted"])
for idx, label in enumerate(scene["activities"]):
y = 291 + idx * 43
draw.rounded_rectangle((24, y, 426, y + 34), radius=7, fill="#ffffff", outline="#d5dcd8")
_write(draw, (39, y + 8), label, fonts["sm"], theme["ink"])
if scene["flag"]:
draw.rounded_rectangle((260, 249, 426, 278), radius=7, fill="#f5d7d0")
_write(draw, (275, 256), "SERVICE NOTICE", fonts["xs"], "#7f2e22")
return image
def _triangle(draw: ImageDraw.ImageDraw, center: tuple[int, int], size: int, fill: str) -> None:
x, y = center
draw.polygon(((x, y - size), (x - size, y + size), (x + size, y + size)), fill=fill)
def _render_spatial(scene: dict[str, Any], value: int,
fonts: dict[str, ImageFont.FreeTypeFont]) -> Image.Image:
image, draw, theme = _base_image(scene)
_write(draw, (24, 25), scene["map_name"].upper(), fonts["title"], theme["ink"])
_write(draw, (24, 63), "OBJECT MAP", fonts["xs"], theme["muted"])
draw.rounded_rectangle((24, 96, 426, 420), radius=14, fill="#ffffff", outline="#b8c1bc", width=2)
if scene["ood"]:
for x in range(74, 426, 50):
draw.line((x, 96, x, 420), fill="#e0e6e2", width=1)
for y in range(120, 420, 50):
draw.line((24, y, 426, y), fill="#e0e6e2", width=1)
_write(draw, (38, 103), "GRID A", fonts["xs"], theme["muted"])
for x, y, size in scene["triangle_geometry"][:value]:
_triangle(draw, (x, y), size, "#c84d42")
blue_x, blue_y = scene["blue_center"]
square_x, square_y = scene["square_center"]
draw.ellipse((blue_x - 20, blue_y - 20, blue_x + 20, blue_y + 20), fill="#3578b8")
draw.rectangle((square_x - 18, square_y - 18, square_x + 18, square_y + 18), fill="#252a2c")
_write(draw, (blue_x, blue_y + 34), "B", fonts["xs"], theme["muted"], "ma")
_write(draw, (square_x, square_y + 34), "S", fonts["xs"], theme["muted"], "ma")
return image
def _render(scene: dict[str, Any], variant: str,
fonts: dict[str, ImageFont.FreeTypeFont], destination: Path) -> None:
value = scene["values"][variant]
if scene["category"] == "receipt":
image = _render_receipt(scene, value, fonts)
elif scene["category"] == "bar_chart":
image = _render_bar_chart(scene, value, fonts)
elif scene["category"] == "request_form":
image = _render_request_form(scene, value, fonts)
elif scene["category"] == "dashboard":
image = _render_dashboard(scene, value, fonts)
else:
image = _render_spatial(scene, value, fonts)
if scene["required_field_visible"]:
evidence = {
"receipt": "Cost-center approval code: CC-47",
"bar_chart": "Audited denominator badge: 100",
"request_form": "Supervisor clearance code: SV-19",
"dashboard": "Customer-impact verification: VERIFIED",
"spatial": "Ceiling height: 3 m",
}[scene["category"]]
draw = ImageDraw.Draw(image)
draw.rectangle((0, 430, WIDTH, HEIGHT), fill="#ffffff")
_write(draw, (12, 432), evidence, fonts["xs"], "#17212b")
destination.parent.mkdir(parents=True, exist_ok=True)
image.save(destination, format="PNG", optimize=False, compress_level=6)
def _provenance(scene: dict[str, Any], variant: str) -> dict[str, Any]:
return {
"kind": "procedurally_generated",
"license": "Project-created synthetic data; rendered font SIL-OFL-1.1",
"license_url": FONT_LICENSE_URL,
"attribution": "Local procedural scene generator; Atkinson Hyperlegible font by Braille Institute of America",
"renderer": "Pillow",
"scene_category": scene["category"],
"scene_variant": variant,
"layout_family": scene["layout_family"],
"ood_basis": (
"held-out layout family" if scene["ood"]
else "in-distribution layout family"
),
"source_metadata": "sources/visuals.json",
"generated_data_terms": "Project-created deterministic synthetic scene and annotations; no external scene assets.",
"generated_data_attribution": "multimodal-decision data preparation project",
"font": "Atkinson Hyperlegible Regular",
"font_revision": FONT_REVISION,
"font_license": "SIL Open Font License 1.1",
"font_license_url": FONT_LICENSE_URL,
"font_attribution": "Copyright 2020 Braille Institute of America, Inc.",
}
def _metric_display(category: str, value: int) -> str:
return f"${value:.2f}" if category == "receipt" else str(value)
METRIC_SUPPORT = {
"receipt": range(38, 93),
"bar_chart": range(24, 79),
"request_form": range(24, 87),
"dashboard": range(3, 17),
"spatial": range(2, 9),
}
LOOKUP_SUPPORT = {
"receipt": range(38, 59),
"bar_chart": range(24, 40),
"spatial": range(2, 5),
}
def _numeric_candidates(category: str, value: int, rng: Any) -> dict[str, str]:
support = LOOKUP_SUPPORT[category]
if value not in support:
raise ValueError("Numeric lookup value outside rendered lookup support")
alternatives = [candidate for candidate in support if candidate != value]
values = [value, *rng.sample(alternatives, min(3, len(alternatives)))]
return {f"value_{candidate}": _metric_display(category, candidate) for candidate in sorted(values)}
def _score_bounds(category: str, rng: Any) -> tuple[int, int, int]:
support = METRIC_SUPPORT[category]
return tuple(sorted(rng.sample(range(support.start, support.stop + 1), 3)))
def _image_rows(split: str, group_id: str, scene: dict[str, Any],
image_paths: dict[str, str]) -> list[dict[str, Any]]:
category = scene["category"]
low = scene["values"]["a"]
high = scene["values"]["b"]
common_state = "Use only the attached image."
rows: list[dict[str, Any]] = []
if category in LOOKUP_SUPPORT:
criteria = _numeric_candidates(category, low, rng_for(group_id, "numeric-candidates"))
prompt = {
"receipt": "Which amount is printed next to TOTAL?",
"bar_chart": "What count is printed for Nimbus?",
"spatial": "How many red triangles are visible?",
}[category]
label = f"value_{low}"
elif category == "request_form":
criteria = {"facilities": "Facilities", "research": "Research", "operations": "Operations"}
prompt = "Which department is shown on the request?"
label = scene["department"].lower()
elif category == "dashboard":
criteria = {"atlas": "Atlas Support", "beacon": "Beacon Ops", "cedar": "Cedar Service", "other": "Delta Desk"}
prompt = "Which queue name is displayed?"
label = {"Atlas Support": "atlas", "Beacon Ops": "beacon", "Cedar Service": "cedar"}[scene["queue"]]
else:
raise ValueError("Unknown visual category")
rows.append(record(
split=split, source=SOURCE, group_id=group_id,
family=f"image-{category}-lookup", modality="image", state=common_state,
question=choice(prompt, criteria), label=label, images=[image_paths["a"]],
provenance=_provenance(scene, "a"), variant="image-lookup-a",
audit={"operation": "read_visible_field", "facts": {"variant": "a", "value": low},
"field": METRIC_NAMES[category] if category not in ("request_form", "dashboard") else prompt,
"result": criteria[label]},
))
if category == "receipt":
yes = scene["flag"]
instructions = "Does the receipt visibly include a MEMBER SAVINGS line?"
fact = {"member_savings_visible": yes}
elif category == "bar_chart":
values = _bar_values(scene, high)
yes = values[2] > values[1]
instructions = "Is the Nimbus bar larger than the Cedar bar?"
fact = {"nimbus": values[2], "cedar": values[1]}
elif category == "request_form":
yes = scene["flag"]
instructions = "Does REQUESTER SIGNED show Yes?"
fact = {"requester_signed": "Yes" if yes else "No"}
elif category == "dashboard":
yes = scene["flag"]
instructions = "Is a SERVICE NOTICE visible?"
fact = {"service_notice_visible": yes}
else:
yes = scene["relation"] == "left"
instructions = "Is the blue circle to the left of the black square?"
fact = {"blue_circle_relation_to_black_square": scene["relation"]}
rows.append(record(
split=split, source=SOURCE, group_id=group_id,
family=f"image-{category}-visible-relation", modality="image", state=common_state,
question=noul(instructions), label=str(yes).lower(), images=[image_paths["b"]],
provenance=_provenance(scene, "b"), variant="image-relation-b",
audit={"operation": "evaluate_visible_predicate", "facts": fact,
"rule": instructions, "result": yes},
))
score_value = low if scene["index"] % 2 == 0 else high
score_variant = "a" if scene["index"] % 2 == 0 else "b"
t1, t2, t3 = _score_bounds(category, rng_for(group_id, "image-rubric"))
score_target = sum(score_value >= threshold for threshold in (t1, t2, t3))
score_instruction = (
f"Score the visible {METRIC_NAMES[category]}: 0 if below {t1}; "
f"1 if {t1}–{t2 - 1}; 2 if {t2}–{t3 - 1}; 3 if {t3} or above."
)
rows.append(record(
split=split, source=SOURCE, group_id=group_id,
family=f"image-{category}-rubric", modality="image", state=common_state,
question=score(score_instruction, ["Tier 0", "Tier 1", "Tier 2", "Tier 3"]),
label=str(score_target), images=[image_paths[score_variant]],
provenance=_provenance(scene, score_variant), variant=f"image-score-{score_variant}",
audit={"operation": "bucket", "facts": {"value": score_value},
"rule": {"thresholds": [t1, t2, t3], "lower_inclusive": True},
"result": score_target},
))
return rows
def _threshold_policy(category: str, threshold: int) -> str:
metric = METRIC_NAMES[category]
if DIRECTIONS[category] == "maximum":
return f"POLICY: Mark eligible only when the visible {metric} is at most {threshold}."
return f"POLICY: Mark eligible only when the visible {metric} is at least {threshold}."
def _eligible(category: str, value: int, threshold: int) -> bool:
if DIRECTIONS[category] == "maximum":
return value <= threshold
return value >= threshold
def _lookup_policy(category: str, rng: Any) -> tuple[str, dict[str, str], dict[str, Any]]:
actions = ACTION_SETS[category]
support = METRIC_SUPPORT[category]
cutpoints = sorted(rng.sample(range(support.start, support.stop - 1), len(actions) - 1))
ordered = rng.sample(actions, len(actions))
criteria = {f"action_{position}": action for position, action in enumerate(actions)}
bands: list[str] = []
for position, action in enumerate(ordered):
if position == 0:
condition = f"value ≤ {cutpoints[0]}"
elif position == len(ordered) - 1:
condition = f"value > {cutpoints[-1]}"
else:
condition = f"{cutpoints[position - 1]} < value ≤ {cutpoints[position]}"
bands.append(f"{condition}: {action}")
state = f"ACTION TABLE for visible {METRIC_NAMES[category]} — " + "; ".join(bands) + "."
return state, criteria, {
"cutpoints": cutpoints,
"band_actions": list(ordered),
}
def _mixed_rows(split: str, group_id: str, scene: dict[str, Any],
image_paths: dict[str, str]) -> list[dict[str, Any]]:
category = scene["category"]
low = scene["values"]["a"]
high = scene["values"]["b"]
maximum = DIRECTIONS[category] == "maximum"
strict = low - 1 if maximum else low + 1
lenient = low + 1 if maximum else max(0, low - 1)
midpoint = (low + high) // 2
rows: list[dict[str, Any]] = []
for policy_name, threshold in (("strict", strict), ("lenient", lenient)):
result = _eligible(category, low, threshold)
rows.append(record(
split=split, source=SOURCE, group_id=group_id,
family=f"mixed-{category}-policy-counterfactual", modality="mixed",
state=_threshold_policy(category, threshold),
question=noul("Under the displayed policy, is this case eligible?"),
label=str(result).lower(), images=[image_paths["a"]],
provenance=_provenance(scene, "a"), variant=f"mixed-policy-{policy_name}-a",
audit={"operation": "threshold_compare", "facts": {"value": low},
"rule": {"direction": DIRECTIONS[category], "threshold": threshold},
"result": result, "pair": "same-image-changed-policy",
"changed_component": "policy_only"},
))
for variant, value in (("a", low), ("b", high)):
result = _eligible(category, value, midpoint)
rows.append(record(
split=split, source=SOURCE, group_id=group_id,
family=f"mixed-{category}-evidence-counterfactual", modality="mixed",
state=_threshold_policy(category, midpoint),
question=noul("Under the displayed policy, is this case eligible?"),
label=str(result).lower(), images=[image_paths[variant]],
provenance=_provenance(scene, variant), variant=f"mixed-evidence-{variant}",
audit={"operation": "threshold_compare", "facts": {"value": value},
"rule": {"direction": DIRECTIONS[category], "threshold": midpoint},
"result": result, "pair": "same-policy-changed-image-evidence",
"changed_component": "visual_evidence_only"},
))
lookup_variant = "a" if (scene["index"] // len(CATEGORIES)) % 2 == 0 else "b"
lookup_value = scene["values"][lookup_variant]
lookup_state, lookup_criteria, lookup_audit = _lookup_policy(
category, rng_for(group_id, "action-table")
)
matched_band = sum(lookup_value > cutpoint for cutpoint in lookup_audit["cutpoints"])
target_action = lookup_audit["band_actions"][matched_band]
lookup_label = next(key for key, action in lookup_criteria.items() if action == target_action)
lookup_audit.update(matched_band=matched_band, chosen_action=target_action)
rows.append(record(
split=split, source=SOURCE, group_id=group_id,
family=f"mixed-{category}-action-table", modality="mixed", state=lookup_state,
question=choice("Which action does the displayed table assign to this image?", lookup_criteria),
label=lookup_label, images=[image_paths[lookup_variant]],
provenance=_provenance(scene, lookup_variant), variant=f"mixed-action-table-{lookup_variant}",
audit={"operation": "interval_lookup", "facts": {"value": lookup_value},
"rule": lookup_audit, "result": lookup_criteria[lookup_label]},
))
t1, t2, t3 = _score_bounds(category, rng_for(group_id, "mixed-rubric"))
score_target = sum(high >= threshold for threshold in (t1, t2, t3))
rubric_state = (
f"RUBRIC for visible {METRIC_NAMES[category]}: Tier 0 below {t1}; "
f"Tier 1 from {t1} through {t2 - 1}; Tier 2 from {t2} through {t3 - 1}; "
f"Tier 3 at {t3} or above."
)
rows.append(record(
split=split, source=SOURCE, group_id=group_id,
family=f"mixed-{category}-policy-rubric", modality="mixed", state=rubric_state,
question=score("Apply the displayed rubric to the image.",
["Tier 0", "Tier 1", "Tier 2", "Tier 3"]),
label=str(score_target), images=[image_paths["b"]],
provenance=_provenance(scene, "b"), variant="mixed-rubric-b",
audit={"operation": "bucket", "facts": {"value": high},
"rule": {"thresholds": [t1, t2, t3], "lower_inclusive": True},
"result": score_target},
))
missing = MISSING_FIELDS[category]
limit_relation = "at most" if maximum else "at least"
missing_state = (
f"AUTHORIZATION RULE: Approve only if the visible {METRIC_NAMES[category]} is {limit_relation} "
f"{midpoint} and the image also visibly supplies {missing}. Reject only when all required "
"evidence is visible and the rule fails. Otherwise choose Insufficient evidence; never infer an absent field."
)
field_visible = scene["required_field_visible"]
authorization = ("approve" if _eligible(category, low, midpoint) else "reject") if field_visible else "insufficient"
rows.append(record(
split=split, source=SOURCE, group_id=group_id,
family=f"mixed-{category}-authorization-evidence", modality="mixed", state=missing_state,
question=choice("What decision is justified by the image and authorization rule?", {
"approve": "Approve", "reject": "Reject", "insufficient": "Insufficient evidence"
}),
label=authorization, images=[image_paths["a"]],
provenance=_provenance(scene, "a"), variant="mixed-required-field-a",
audit={"operation": "required_evidence_gate",
"facts": {"metric_value": low, "required_field_visible": field_visible,
"required_field": missing},
"rule": {"metric_limit": midpoint, "direction": DIRECTIONS[category], "requires_all_fields": True},
"result": authorization},
))
return rows
def prepare(root: Path) -> dict[str, Any]:
root = root.resolve()
font_path, license_path = _font_files(root)
fonts = _fonts(font_path)
media_dir = root / "data/media/visuals"
media_dir.mkdir(parents=True, exist_ok=True)
for stale_asset in media_dir.glob("*.png"):
stale_asset.unlink()
rows: list[dict[str, Any]] = []
assets: list[dict[str, Any]] = []
group_counts: dict[str, int] = {}
seen_facts: set[str] = set()
seen_hashes: set[str] = set()
for split in SPLITS:
image_quota = PART_QUOTAS["visual_image"][split]
mixed_quota = PART_QUOTAS["visual_mixed"][split]
if image_quota % 3 or mixed_quota % 7 or image_quota // 3 != mixed_quota // 7:
raise RuntimeError(f"Visual quotas cannot form complete scene bundles for {split}")
group_count = image_quota // 3
group_counts[split] = group_count
for index in range(group_count):
for attempt in range(10_000):
scene = _make_scene(split, index, attempt)
visible = {key: value for key, value in scene.items() if key not in {"index", "layout_family"}}
signature = stable_id("visible-scene", visible)
if signature in seen_facts:
continue
group_id = stable_id(SOURCE, visible)
image_paths = {}
proposed = []
for variant in ("a", "b"):
asset_id = stable_id("visual-asset", group_id, variant)
relative_path = f"media/visuals/{asset_id}.png"
destination = root / "data" / relative_path
_render(scene, variant, fonts, destination)
image_paths[variant] = relative_path
proposed.append({
"path": relative_path, "sha256": sha256_file(destination),
"group_id": group_id, "scene_variant": variant,
"scene_category": scene["category"], "layout_family": scene["layout_family"],
"scene_facts": json.loads(json.dumps(visible)),
"width": WIDTH, "height": HEIGHT,
})
hashes = {asset["sha256"] for asset in proposed}
if len(hashes) != 2 or hashes & seen_hashes:
for asset in proposed:
(root / "data" / asset["path"]).unlink()
continue
seen_facts.add(signature)
seen_hashes.update(hashes)
assets.extend(proposed)
break
else:
raise RuntimeError(f"Visible scene allocation exhausted: {split}/{index}")
rows.extend(_image_rows(split, group_id, scene, image_paths))
rows.extend(_mixed_rows(split, group_id, scene, image_paths))
quota_counts = Counter((row["split"], row["modality"]) for row in rows)
for split in SPLITS:
expected_image = PART_QUOTAS["visual_image"][split]
expected_mixed = PART_QUOTAS["visual_mixed"][split]
if quota_counts[(split, "image")] != expected_image:
raise RuntimeError(f"Image quota mismatch for {split}")
if quota_counts[(split, "mixed")] != expected_mixed:
raise RuntimeError(f"Mixed quota mismatch for {split}")
primitive_counts = Counter(row["question"]["type"] for row in rows)
modality_counts = Counter(row["modality"] for row in rows)
split_counts = Counter(row["split"] for row in rows)
part_path = root / "data/parts/visuals.jsonl"
row_count = write_jsonl(part_path, rows)
source_metadata = {
"source": SOURCE,
"generator_version": GENERATOR_VERSION,
"description": "Deterministic code-labelled synthetic decision scenes rendered with Pillow.",
"redistribution": "Generated PNGs are project-created; the bundled font remains under SIL OFL 1.1.",
"font": {
"name": "Atkinson Hyperlegible Regular",
"attribution": "Copyright 2020 Braille Institute of America, Inc.",
"revision": FONT_REVISION,
"source_url": FONT_URL,
"sha256": sha256_file(font_path),
"license": "SIL Open Font License 1.1",
"license_url": FONT_LICENSE_URL,
"license_path": str(license_path.relative_to(root / "data")),
"license_sha256": sha256_file(license_path),
},
"rendering": {
"library": "Pillow",
"canvas": [WIDTH, HEIGHT],
"color_mode": "RGB",
"format": "PNG",
"deterministic_seed": "mdprep.common.rng_for over source, split, group index, and category",
"categories": list(CATEGORIES),
"ood_layouts": OOD_LAYOUTS,
},
"asset_count": len(assets),
"assets": assets,
}
write_json(root / "data/sources/visuals.json", source_metadata)
return {
"part": "visuals",
"path": str(part_path),
"rows": row_count,
"assets": len(assets),
"groups": sum(group_counts.values()),
"groups_by_split": group_counts,
"rows_by_split": dict(split_counts),
"rows_by_modality": dict(modality_counts),
"primitives": dict(primitive_counts),
"source_metadata": str(root / "data/sources/visuals.json"),
"known_limitations": [
"Scenes are synthetic and use Latin-script English labels.",
"OOD evaluates held-out generated layouts, not task-family or photographic domain shift.",
"PNG byte identity assumes the same supported Pillow major version; scene facts and labels are version-stable.",
],
}
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", type=Path, required=True, help="Project root")
args = parser.parse_args()
print(prepare(args.root))
if __name__ == "__main__":
main()