| |
| """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() |
|
|