{"spec_id":"funnel-meta-analysis","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// funnel-meta-analysis: Meta-Analysis Funnel Plot for Publication Bias\n// Library: highcharts 12.6.0 | JavaScript 22.22.3\n// Quality: 90/100 | Created: 2026-06-10\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Data: 18 RCTs comparing antidepressant vs placebo, log odds ratios and standard errors\nconst pooledEffect = 0.40;\nconst seMax = 0.65;\n\nconst studies = [\n  [0.45, 0.15], [0.30, 0.22], [0.62, 0.18], [0.20, 0.35],\n  [0.55, 0.12], [-0.10, 0.40], [0.35, 0.28], [0.78, 0.55],\n  [0.15, 0.45], [0.50, 0.20], [0.25, 0.30], [0.70, 0.14],\n  [0.42, 0.38], [0.18, 0.50], [-0.08, 0.60], [0.65, 0.25],\n  [0.38, 0.16], [0.52, 0.32]\n];\n\n// Pseudo 95% CI funnel: apex at (pooled, SE=0), base at (pooled ± 1.96 * seMax, seMax)\nconst ci96 = 1.96 * seMax;\nconst funnelLeft  = [{ x: pooledEffect, y: 0 }, { x: pooledEffect - ci96, y: seMax }];\nconst funnelRight = [{ x: pooledEffect, y: 0 }, { x: pooledEffect + ci96, y: seMax }];\n\nHighcharts.chart(\"container\", {\n  chart: {\n    type: \"scatter\",\n    backgroundColor: \"transparent\",\n    animation: false,\n    plotBorderWidth: 0,\n    style: { fontFamily: \"inherit\" }\n  },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: {\n    text: \"funnel-meta-analysis · javascript · highcharts · anyplot.ai\",\n    style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" }\n  },\n  subtitle: {\n    text: \"Antidepressant vs Placebo · 18 Randomized Controlled Trials\",\n    style: { color: t.inkSoft, fontSize: \"14px\" }\n  },\n  xAxis: {\n    title: {\n      text: \"Log Odds Ratio\",\n      style: { color: t.inkSoft, fontSize: \"16px\" }\n    },\n    lineColor: t.inkSoft,\n    tickColor: t.inkSoft,\n    gridLineColor: t.grid,\n    gridLineWidth: 0.5,\n    min: -1.6,\n    max: 2.2,\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } }\n  },\n  yAxis: {\n    title: {\n      text: \"Standard Error (SE)\",\n      style: { color: t.inkSoft, fontSize: \"16px\" }\n    },\n    reversed: true,\n    min: 0,\n    max: 0.70,\n    lineColor: t.inkSoft,\n    tickColor: t.inkSoft,\n    gridLineColor: t.grid,\n    gridLineWidth: 0.5,\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } }\n  },\n  legend: {\n    itemStyle: { color: t.inkSoft, fontSize: \"14px\" },\n    itemHoverStyle: { color: t.ink }\n  },\n  tooltip: {\n    formatter: function () {\n      return \"<b>Log OR:</b> \" + this.x.toFixed(2) + \"<br><b>SE:</b> \" + this.y.toFixed(2);\n    }\n  },\n  plotOptions: {\n    series: { animation: false }\n  },\n  series: [\n    {\n      type: \"scatter\",\n      name: \"Studies (n = 18)\",\n      data: studies,\n      color: t.palette[0],\n      marker: {\n        radius: 7,\n        symbol: \"circle\",\n        lineColor: t.pageBg,\n        lineWidth: 1.5\n      },\n      zIndex: 5\n    },\n    {\n      // Pooled effect as a series for full lineWidth and label control\n      type: \"line\",\n      name: \"Pooled OR = 1.49\",\n      data: [\n        {\n          x: pooledEffect,\n          y: 0,\n          dataLabels: {\n            enabled: true,\n            format: \"Pooled OR = 1.49\",\n            rotation: 0,\n            align: \"left\",\n            x: 6,\n            y: 18,\n            style: {\n              color: t.ink,\n              fontSize: \"11px\",\n              fontWeight: \"700\",\n              textOutline: \"none\"\n            }\n          }\n        },\n        { x: pooledEffect, y: seMax }\n      ],\n      color: t.ink,\n      lineWidth: 3,\n      dashStyle: \"Solid\",\n      marker: { enabled: false },\n      enableMouseTracking: false,\n      zIndex: 4\n    },\n    {\n      type: \"line\",\n      name: \"95% CI Limits\",\n      data: funnelLeft,\n      color: t.inkSoft,\n      lineWidth: 1.5,\n      dashStyle: \"Dash\",\n      marker: { enabled: false },\n      enableMouseTracking: false,\n      zIndex: 3\n    },\n    {\n      type: \"line\",\n      data: funnelRight,\n      color: t.inkSoft,\n      lineWidth: 1.5,\n      dashStyle: \"Dash\",\n      marker: { enabled: false },\n      enableMouseTracking: false,\n      showInLegend: false,\n      zIndex: 3\n    },\n    {\n      // Null reference as a series for label control — no legend entry\n      type: \"line\",\n      data: [\n        {\n          x: 0,\n          y: 0,\n          dataLabels: {\n            enabled: true,\n            format: \"Null (OR = 1)\",\n            rotation: 0,\n            align: \"right\",\n            x: -6,\n            y: 18,\n            style: {\n              color: t.inkSoft,\n              fontSize: \"11px\",\n              fontWeight: \"400\",\n              textOutline: \"none\"\n            }\n          }\n        },\n        { x: 0, y: seMax }\n      ],\n      color: t.inkSoft,\n      lineWidth: 1.5,\n      dashStyle: \"ShortDash\",\n      marker: { enabled: false },\n      enableMouseTracking: false,\n      showInLegend: false,\n      zIndex: 2\n    }\n  ]\n});\n"}