{"spec_id":"roc-curve","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// roc-curve: ROC Curve with AUC\n// Library: highcharts 12.6.0 | JavaScript 22.23.2\n// Quality: 91/100 | Created: 2026-09-05\n\n//# anyplot-orientation: square\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Two diagnostic tests for detecting a disease, evaluated across classifier\n// thresholds. tpr = fpr^(1/power) is concave and bows toward the top-left\n// corner for power > 1, mimicking a real ROC curve shape.\nconst numPoints = 101;\nconst falsePositiveRates = Array.from({ length: numPoints }, (_, i) => i / (numPoints - 1));\n\nconst rocCurve = (power) => falsePositiveRates.map((fpr) => Math.pow(fpr, 1 / power));\n\nconst areaUnderCurve = (tprValues) => {\n  let area = 0;\n  for (let i = 1; i < falsePositiveRates.length; i += 1) {\n    const dx = falsePositiveRates[i] - falsePositiveRates[i - 1];\n    area += (dx * (tprValues[i] + tprValues[i - 1])) / 2;\n  }\n  return area;\n};\n\nconst antibodyTestTpr = rocCurve(9);\nconst enzymeTestTpr = rocCurve(4);\nconst antibodyTestAuc = areaUnderCurve(antibodyTestTpr);\nconst enzymeTestAuc = areaUnderCurve(enzymeTestTpr);\n\nconst toPoints = (tprValues) =>\n  falsePositiveRates.map((fpr, i) => [fpr, tprValues[i]]);\n\n// Example decision threshold called out on the best-performing curve, so the\n// chart tells a concrete \"if you accept 10% false positives, you get this\n// sensitivity\" story instead of stopping at the raw curve shapes.\nconst thresholdIndex = 10; // falsePositiveRates[10] === 0.10 exactly\nconst thresholdFpr = falsePositiveRates[thresholdIndex];\nconst thresholdTpr = antibodyTestTpr[thresholdIndex];\n\n// --- Chart -------------------------------------------------------------------\nHighcharts.chart(\"container\", {\n  chart: {\n    type: \"line\",\n    backgroundColor: \"transparent\",\n    animation: false,\n    style: { fontFamily: \"inherit\" },\n  },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: {\n    text: \"roc-curve · javascript · highcharts · anyplot.ai\",\n    style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" },\n  },\n  xAxis: {\n    title: { text: \"False Positive Rate\", style: { color: t.inkSoft, fontSize: \"16px\" } },\n    min: 0,\n    max: 1,\n    tickInterval: 0.2,\n    minorTickInterval: 0.1,\n    lineColor: t.inkSoft,\n    tickColor: t.inkSoft,\n    gridLineColor: t.grid,\n    gridLineWidth: 1,\n    minorGridLineColor: t.grid,\n    minorGridLineWidth: 1,\n    minorGridLineDashStyle: \"Dot\",\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n    plotLines: [\n      {\n        value: thresholdFpr,\n        color: t.inkSoft,\n        dashStyle: \"ShortDash\",\n        width: 1.5,\n        zIndex: 5,\n        label: {\n          text: `FPR = ${thresholdFpr.toFixed(2)}`,\n          style: { color: t.inkSoft, fontSize: \"12px\" },\n          align: \"left\",\n          x: 6,\n          y: 14,\n        },\n      },\n    ],\n  },\n  yAxis: {\n    title: { text: \"True Positive Rate\", style: { color: t.inkSoft, fontSize: \"16px\" } },\n    min: 0,\n    max: 1,\n    tickInterval: 0.2,\n    minorTickInterval: 0.1,\n    gridLineColor: t.grid,\n    minorGridLineColor: t.grid,\n    minorGridLineWidth: 1,\n    minorGridLineDashStyle: \"Dot\",\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n  },\n  legend: {\n    itemStyle: { color: t.inkSoft, fontSize: \"14px\" },\n    itemHoverStyle: { color: t.ink },\n    verticalAlign: \"bottom\",\n  },\n  tooltip: {\n    valueDecimals: 2,\n  },\n  plotOptions: {\n    series: { animation: false, marker: { enabled: false } },\n  },\n  series: [\n    {\n      // Area fill turns \"AUC\" from a legend number into a visible shape: the\n      // filled region under the top curve literally is the area it names.\n      type: \"area\",\n      name: `Antibody test (AUC = ${antibodyTestAuc.toFixed(2)})`,\n      data: toPoints(antibodyTestTpr),\n      color: t.palette[0],\n      fillOpacity: 0.08,\n      threshold: 0,\n      lineWidth: 3,\n    },\n    {\n      name: `Enzyme test (AUC = ${enzymeTestAuc.toFixed(2)})`,\n      data: toPoints(enzymeTestTpr),\n      color: t.palette[1],\n      lineWidth: 3,\n    },\n    {\n      name: \"Random classifier (AUC = 0.50)\",\n      data: [\n        [0, 0],\n        [1, 1],\n      ],\n      color: t.ink,\n      dashStyle: \"Dash\",\n      lineWidth: 2,\n      enableMouseTracking: false,\n    },\n    {\n      // Callout marker for the example operating threshold above.\n      type: \"scatter\",\n      name: \"Example threshold\",\n      data: [[thresholdFpr, thresholdTpr]],\n      color: t.palette[0],\n      marker: { enabled: true, radius: 6, lineWidth: 2, lineColor: t.ink },\n      dataLabels: {\n        enabled: true,\n        format: `TPR = ${thresholdTpr.toFixed(2)}`,\n        style: { color: t.ink, fontSize: \"12px\", fontWeight: \"600\", textOutline: \"none\" },\n        y: -14,\n      },\n      showInLegend: false,\n      enableMouseTracking: false,\n    },\n  ],\n});\n"}