#!/usr/bin/env python3 """Render the long-form OrbitSight review proposal and its supporting charts.""" from __future__ import annotations import re import textwrap from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from matplotlib.backends.backend_pdf import PdfPages ROOT = Path(__file__).resolve().parents[1] SOURCE = ROOT / "docs" / "OrbitSight_Full_Technical_Proposal_Review.md" OUTPUT = ROOT / "docs" / "OrbitSight_Full_Technical_Proposal_Review.pdf" ASSETS = ROOT / "docs" / "full_proposal_assets" NAVY = "#15253b" BLUE = "#2274a5" CYAN = "#42b3c7" RED = "#b33a3a" GREY = "#5f6b76" LIGHT = "#eef3f6" def make_model_evolution() -> None: stages = [ "First honest\nbaseline", "Early\ntraining", "V5 + gates", "V7", "Heavy\nhybrid", "Initial\nstudent", "Final\nstudent", ] f1 = [0.0364, 0.5150, 0.6298, 0.5954, 0.6683, 0.6229, 0.6292] map_scores = [0.0096, 0.2200, 0.3804, 0.3585, 0.4895, 0.4608, 0.4645] x = range(len(stages)) fig, ax = plt.subplots(figsize=(11.2, 5.4)) fig.patch.set_facecolor("white") ax.plot(x, f1, marker="o", linewidth=2.5, color=BLUE, label="Leakage-free F1") ax.plot(x, map_scores, marker="o", linewidth=2.5, color=CYAN, label="Leakage-free mAP") for index, value in enumerate(f1): ax.text(index, value + 0.022, f"{value:.3f}", ha="center", fontsize=8, color=NAVY) for index, value in enumerate(map_scores): ax.text(index, value - 0.045, f"{value:.3f}", ha="center", fontsize=8, color=GREY) ax.set_xticks(list(x), stages) ax.set_ylim(0, 0.76) ax.set_ylabel("Score") ax.set_title("OrbitSight development: accuracy improved, then latency became the constraint", loc="left", fontweight="bold", color=NAVY) ax.grid(axis="y", alpha=0.22) ax.spines[["top", "right"]].set_visible(False) ax.legend(frameon=False, ncol=2, loc="upper left") ax.text( 0, -0.27, "Early-training 0.515/0.220 is a historical validation checkpoint and is not strictly comparable to the later locked evaluations.", transform=ax.transAxes, fontsize=8, color=GREY, ) fig.subplots_adjust(left=0.08, right=0.98, top=0.86, bottom=0.27) fig.savefig(ASSETS / "model_evolution.png", dpi=180, bbox_inches="tight") plt.close(fig) def make_heavy_vs_student() -> None: labels = ["Heavy V5/V7 hybrid", "Distilled CPU student"] params = [8_588_339, 135_111] latency = [383.0, 17.05] fig, axes = plt.subplots(1, 2, figsize=(11.2, 4.8)) fig.patch.set_facecolor("white") colors = [RED, BLUE] axes[0].barh(labels, params, color=colors) axes[0].set_xscale("log") axes[0].set_title("Parameters (log scale)", loc="left", fontweight="bold", color=NAVY) axes[0].set_xlabel("Parameters") for idx, value in enumerate(params): axes[0].text(value * 1.08, idx, f"{value:,}", va="center", fontsize=9) axes[1].barh(labels, latency, color=colors) axes[1].axvline(40, color=NAVY, linestyle="--", linewidth=1.5, label="40 ms requirement") axes[1].set_title("Measured CPU latency", loc="left", fontweight="bold", color=NAVY) axes[1].set_xlabel("Mean milliseconds per window") axes[1].legend(frameon=False, fontsize=8) for idx, value in enumerate(latency): axes[1].text(value + 6, idx, f"{value:.2f} ms", va="center", fontsize=9) for ax in axes: ax.grid(axis="x", alpha=0.2) ax.spines[["top", "right"]].set_visible(False) fig.suptitle("Distillation made the deployment constraint achievable", x=0.06, ha="left", fontweight="bold", color=NAVY, fontsize=14) fig.subplots_adjust(left=0.20, right=0.97, bottom=0.16, top=0.78, wspace=0.38) fig.savefig(ASSETS / "heavy_vs_student.png", dpi=180, bbox_inches="tight") plt.close(fig) def make_final_student_architecture() -> None: """Draw the exact deployed tensor path, including recurrent state and inactive heads.""" fig, ax = plt.subplots(figsize=(15.5, 8.6)) fig.patch.set_facecolor("white") ax.set_xlim(0, 15.5) ax.set_ylim(0, 8.6) ax.axis("off") def box(x, y, w, h, title, body, color=BLUE, dashed=False): patch = plt.Rectangle( (x, y), w, h, facecolor="white", edgecolor=color, linewidth=1.8, linestyle="--" if dashed else "-", joinstyle="round" ) ax.add_patch(patch) ax.text(x + 0.12, y + h - 0.18, title, va="top", fontsize=10, fontweight="bold", color=color) ax.text(x + 0.12, y + h - 0.55, body, va="top", fontsize=8.1, color=NAVY, linespacing=1.28) def arrow(x1, y1, x2, y2, color=NAVY, style="-"): ax.annotate("", xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle="->", color=color, lw=1.4, linestyle=style, shrinkA=2, shrinkB=2)) ax.text(0.35, 8.25, "Final OrbitSight CPU student — exact deployed architecture", fontsize=17, fontweight="bold", color=NAVY) ax.text(0.35, 7.88, "Solid boxes execute at inference; dashed boxes are stored/training-only.", fontsize=9, color=GREY) box(0.35, 5.25, 1.65, 1.35, "40 ms input", "3×640×640\npositive count\nnegative count\nrecency", CYAN) box(2.35, 5.25, 1.65, 1.35, "Stem · 120 p", "3×3 Conv 3→4\nBatchNorm + SiLU\n4×640×640") arrow(2.0, 5.93, 2.35, 5.93) stages = [ (4.35, "Stage 1", "down 4→4 · s2\nConvLSTM d1\n4×320×320\n1,324 p"), (6.35, "Stage 2", "down 4→8 · s2\nConvLSTM d2\n8×160×160\n4,952 p"), (8.35, "Stage 3", "down 8→16 · s2\nConvLSTM d4\n16×80×80\n19,696 p"), (10.35, "Stage 4", "down 16→32 · s2\nConvLSTM d8\n32×40×40\n78,560 p"), ] for x, title, body in stages: box(x, 5.05, 1.65, 1.75, title, body) for start in [4.0, 6.0, 8.0, 10.0]: arrow(start, 5.93, start + 0.35, 5.93) for x, label in [(5.0, "H,C\nstate"), (7.0, "H,C\nstate"), (9.0, "H,C\nstate"), (11.0, "H,C\nstate")]: ax.annotate(label, xy=(x + 0.17, 6.75), xytext=(x + 0.17, 7.52), ha="center", va="center", fontsize=7.5, color=RED, arrowprops=dict(arrowstyle="<->", color=RED, lw=1.1)) heads = [ (6.25, 2.55, "Stride-4 head", "8→16→16\nreg 4×160²\nobj 1×160²\n3,573 active p"), (8.25, 2.55, "Stride-8 head", "16→16→16\nreg 4×80²\nobj 1×80²\n4,725 active p"), (10.25, 2.55, "Stride-16 head", "32→16→16\nreg 4×40²\nobj 1×40²\n7,029 active p"), ] for x, y, title, body in heads: box(x, y, 1.75, 1.65, title, body, CYAN) arrow(7.15, 5.05, 7.15, 4.2) arrow(9.15, 5.05, 9.15, 4.2) arrow(11.15, 5.05, 11.15, 4.2) box(12.45, 2.55, 2.45, 1.65, "Exact top-one decoder", "33,600 scores → stable argmax\nthreshold 0.10\ndecode only winning cell\nno production NMS", RED) for x in [8.0, 10.0, 12.0]: arrow(x, 3.37, 12.45, 3.37) box(12.45, 5.05, 2.45, 1.75, "Native output path", "inverse area mapping\nDVX size ×0.98\nKalman/coast tracker\nsensor gate → integer row", BLUE) arrow(13.68, 4.2, 13.68, 5.05) box(0.35, 0.55, 3.45, 1.25, "Selective training objective", "human focal + pixel-inclusive CIoU + aux BCE\n+ matched-teacher confidence/box + empty-window negatives", GREY, dashed=True) box(4.15, 0.55, 3.45, 1.25, "Auxiliary segmentation · 9 p", "1×1 Conv on stride-4 feature → 1×160×160\nexecuted only while model.training", GREY, dashed=True) box(7.95, 0.55, 3.45, 1.25, "Compatibility classification · 15,123 p", "three stored cls towers/predictors\ncompute_cls=False; never scored", GREY, dashed=True) box(11.75, 0.55, 3.15, 1.25, "Checkpoint contract", "135,111 stored parameters\nquality head: off · sensor FiLM: off", GREY, dashed=True) fig.subplots_adjust(left=0.015, right=0.985, top=0.98, bottom=0.03) fig.savefig(ASSETS / "final_student_architecture.png", dpi=180, bbox_inches="tight") plt.close(fig) def clean_inline(value: str) -> str: value = re.sub(r"!\[[^]]*]\([^)]+\)", "", value) value = re.sub(r"\[([^]]+)]\([^)]+\)", r"\1", value) return value.replace("**", "").replace("__", "").replace("`", "") class Renderer: width = 8.27 height = 11.69 left = 0.085 right = 0.925 top = 0.925 bottom = 0.075 def __init__(self, pdf: PdfPages) -> None: self.pdf = pdf self.fig = None self.ax = None self.y = self.top self.page = 0 self.new_page() def new_page(self) -> None: if self.fig is not None: self.finish_page() self.page += 1 self.fig = plt.figure(figsize=(self.width, self.height), facecolor="white") self.ax = self.fig.add_axes([0, 0, 1, 1]) self.ax.axis("off") self.y = self.top def finish_page(self) -> None: self.fig.text(self.left, 0.035, "OrbitSight — Full Technical Proposal Review", fontsize=7, color=GREY) self.fig.text(self.right, 0.035, str(self.page), fontsize=7, color=GREY, ha="right") self.pdf.savefig(self.fig, bbox_inches=None) plt.close(self.fig) def ensure(self, needed: float) -> None: if self.y - needed < self.bottom: self.new_page() def rule(self, color: str = CYAN) -> None: self.ensure(0.025) self.ax.plot([self.left, self.right], [self.y, self.y], transform=self.fig.transFigure, color=color, linewidth=1.2) self.y -= 0.025 def text(self, value: str, *, size: float = 9.2, color: str = NAVY, bold: bool = False, indent: float = 0.0, before: float = 0.006, after: float = 0.008, mono: bool = False, prefix: str = "") -> None: value = clean_inline(value).strip() if not value: self.y -= after return chars = max(28, int((104 - indent * 95) * 9.2 / size)) subsequent = " " * len(prefix) lines = textwrap.wrap(prefix + value, width=chars, subsequent_indent=subsequent, break_long_words=False, break_on_hyphens=False) or [value] line_h = size / 850 needed = before + len(lines) * line_h + after self.ensure(needed) self.y -= before for line in lines: self.fig.text(self.left + indent, self.y, line, fontsize=size, color=color, fontweight="bold" if bold else "normal", family="DejaVu Sans Mono" if mono else "DejaVu Sans", va="top") self.y -= line_h self.y -= after def heading(self, value: str, level: int) -> None: if level == 1: self.ensure(0.14) self.text(value, size=21, bold=True, before=0.015, after=0.012) self.rule() elif level == 2: self.ensure(0.085) self.text(value, size=14.2, color=BLUE, bold=True, before=0.025, after=0.008) else: self.ensure(0.06) self.text(value, size=11.2, bold=True, before=0.018, after=0.006) def code(self, lines: list[str]) -> None: rendered: list[str] = [] for line in lines: rendered.extend(textwrap.wrap(line, width=96, subsequent_indent=" ", replace_whitespace=False) or [""]) line_h = 8.0 / 850 needed = len(rendered) * line_h + 0.028 self.ensure(needed) y_top = self.y - 0.006 y_bottom = y_top - len(rendered) * line_h - 0.012 self.ax.add_patch(plt.Rectangle((self.left - 0.008, y_bottom), self.right - self.left + 0.016, y_top - y_bottom, transform=self.fig.transFigure, facecolor=LIGHT, edgecolor="#d8e1e7", linewidth=0.6)) self.y = y_top - 0.008 for line in rendered: self.fig.text(self.left, self.y, line, fontsize=8, color=NAVY, family="DejaVu Sans Mono", va="top") self.y -= line_h self.y = y_bottom - 0.012 def table(self, lines: list[str]) -> None: rows = [] for line in lines: cells = [clean_inline(cell.strip()) for cell in line.strip().strip("|").split("|")] if all(re.fullmatch(r":?-{3,}:?", cell) for cell in cells): continue rows.append(cells) if not rows: return cols = max(len(row) for row in rows) normalized = [row + [""] * (cols - len(row)) for row in rows] max_width = 98 cell_width = max(10, max_width // cols - 2) formatted = [] for row_index, row in enumerate(normalized): wrapped = [textwrap.wrap(cell, width=cell_width, break_long_words=False) or [""] for cell in row] row_height = max(len(cell) for cell in wrapped) for line_index in range(row_height): values = [] for cell in wrapped: value = cell[line_index] if line_index < len(cell) else "" values.append(value.ljust(cell_width)) formatted.append(" ".join(values).rstrip()) if row_index == 0: formatted.append(" ".join("─" * cell_width for _ in range(cols))) self.code(formatted) def image(self, relative: str, alt: str) -> None: path = (SOURCE.parent / relative).resolve() if not path.exists(): self.text(f"[Image unavailable: {alt}]", color=RED) return data = plt.imread(path) ratio = data.shape[0] / data.shape[1] box_width = self.right - self.left box_height = min(0.39, box_width * ratio * self.width / self.height) self.ensure(box_height + 0.05) image_ax = self.fig.add_axes([self.left, self.y - box_height, box_width, box_height]) image_ax.imshow(data) image_ax.axis("off") self.y -= box_height + 0.006 self.text(alt, size=7.5, color=GREY, before=0.0, after=0.014) def close(self) -> None: if self.fig is not None: self.finish_page() self.fig = None def render_markdown() -> None: lines = SOURCE.read_text(encoding="utf-8").splitlines() with PdfPages(OUTPUT) as pdf: metadata = pdf.infodict() metadata["Title"] = "OrbitSight Full Technical Proposal Review" metadata["Author"] = "Team Simer" metadata["Subject"] = "Development history, architecture, evaluation, latency and deployment" renderer = Renderer(pdf) index = 0 in_code = False code_lines: list[str] = [] while index < len(lines): line = lines[index] if line.startswith("```"): if in_code: renderer.code(code_lines) code_lines = [] in_code = False else: in_code = True index += 1 continue if in_code: code_lines.append(line) index += 1 continue image_match = re.fullmatch(r"!\[([^]]*)]\(([^)]+)\)", line.strip()) if image_match: renderer.image(image_match.group(2), image_match.group(1)) index += 1 continue if line.startswith("|"): table_lines = [] while index < len(lines) and lines[index].startswith("|"): table_lines.append(lines[index]) index += 1 renderer.table(table_lines) continue heading_match = re.match(r"^(#{1,3})\s+(.+)$", line) if heading_match: renderer.heading(heading_match.group(2), len(heading_match.group(1))) elif re.match(r"^[-*]\s+", line): renderer.text(re.sub(r"^[-*]\s+", "", line), indent=0.018, prefix="• ") elif re.match(r"^\d+\.\s+", line): match = re.match(r"^(\d+\.)\s+(.+)$", line) renderer.text(match.group(2), indent=0.018, prefix=f"{match.group(1)} ") elif line.startswith(">"): renderer.text(line.lstrip("> "), color=RED, indent=0.018, bold=True) elif line.strip() in {"---", "***"}: renderer.rule(color="#c8d2da") elif line.strip(): paragraph = [line.strip()] while index + 1 < len(lines): nxt = lines[index + 1] if not nxt.strip() or nxt.startswith(("#", "|", "```", ">", "![")) or re.match(r"^[-*]\s+|^\d+\.\s+", nxt): break paragraph.append(nxt.strip()) index += 1 renderer.text(" ".join(paragraph)) else: renderer.y -= 0.006 index += 1 if code_lines: renderer.code(code_lines) renderer.close() def main() -> None: ASSETS.mkdir(parents=True, exist_ok=True) make_model_evolution() make_heavy_vs_student() make_final_student_architecture() render_markdown() print(f"Rendered {OUTPUT}") if __name__ == "__main__": main()