{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.10"
    }
  },
  "cells": [
    {
      "id": "scope",
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# concept reproduction check\n",
        "Run in the extracted bundle folder. Read README.md for provenance, prerequisites, and limitations. This is not full-paper replication.\n"
      ]
    },
    {
      "id": "check",
      "cell_type": "code",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "\"\"\"Re-render the reported held-out comparison, without fitting a classifier.\"\"\"\n",
        "import html\n",
        "import json\n",
        "from pathlib import Path\n",
        "\n",
        "ROOT = Path(__file__).resolve().parent if \"__file__\" in globals() else Path.cwd()\n",
        "METRICS = (\"auc\", \"precision\", \"f1\", \"brier\")\n",
        "\n",
        "\n",
        "def reproduce():\n",
        "    rows = json.loads((ROOT / \"source.json\").read_text(encoding=\"utf-8\"))\n",
        "    assert len(rows) == 4 and len({row[\"name\"] for row in rows}) == 4\n",
        "    for row in rows:\n",
        "        assert all(0 <= row[metric] <= 1 for metric in METRICS)\n",
        "    winners = {}\n",
        "    for metric in METRICS:\n",
        "        best = (min if metric == \"brier\" else max)(row[metric] for row in rows)\n",
        "        winners[metric] = [row[\"name\"] for row in rows if row[metric] == best]\n",
        "    fca = next(row for row in rows if row[\"name\"] == \"FCA model\")\n",
        "    return rows, {\"rows\": len(rows), \"winners\": winners,\n",
        "                  \"fca\": {metric: fca[metric] for metric in METRICS}}\n",
        "\n",
        "\n",
        "def render_table(rows):\n",
        "    svg = ['<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 760 1080\" role=\"img\">',\n",
        "           '<title>Published FCA benchmark, Table 1 re-rendered</title>',\n",
        "           '<rect width=\"760\" height=\"1080\" fill=\"#f7f8f2\"/>',\n",
        "           '<g font-family=\"Arial,sans-serif\" fill=\"#23383a\">',\n",
        "           '<text x=\"30\" y=\"35\" font-size=\"21\">Published held-out comparison</text>',\n",
        "           '<text x=\"30\" y=\"62\" font-size=\"14\">DOI: 10.1177/14604582261444612 \u00b7 Table 1 \u00b7 common scale 0\u20131</text>']\n",
        "    for index, metric in enumerate(METRICS):\n",
        "        top = 110 + index * 230\n",
        "        direction = \"lower is better\" if metric == \"brier\" else \"higher is better\"\n",
        "        svg.append(f'<text x=\"30\" y=\"{top}\" font-size=\"18\">{metric.upper()} \u00b7 {direction}</text>')\n",
        "        for i, row in enumerate(rows):\n",
        "            y, value = top + 35 + i * 42, row[metric]\n",
        "            name = html.escape(row[\"name\"])\n",
        "            svg.extend([f'<text x=\"30\" y=\"{y+13}\" font-size=\"14\">{name}</text>',\n",
        "                        f'<rect x=\"220\" y=\"{y}\" width=\"400\" height=\"16\" fill=\"#e0e6e0\"/>',\n",
        "                        f'<rect x=\"220\" y=\"{y}\" width=\"{value*400}\" height=\"16\" fill=\"#14655f\"/>',\n",
        "                        f'<text x=\"640\" y=\"{y+13}\" font-size=\"14\">{value:.4f}</text>'])\n",
        "    svg.extend(['<text x=\"30\" y=\"1050\" font-size=\"14\">Reported numbers re-rendered. No model refit or patient-level reproduction.</text>', '</g></svg>'])\n",
        "    (ROOT / \"figure.svg\").write_text(\"\\n\".join(svg), encoding=\"utf-8\")\n",
        "\n",
        "\n",
        "if __name__ == \"__main__\":\n",
        "    rows, result = reproduce()\n",
        "    expected = json.loads((ROOT / \"expected.json\").read_text(encoding=\"utf-8\"))\n",
        "    assert result == expected, (result, expected)\n",
        "    render_table(rows)\n",
        "    print(json.dumps(result, indent=2))\n",
        "    print(\"PASS: Table 1 checked and re-rendered to figure.svg; no model refit.\")\n"
      ]
    }
  ]
}
