{"spec_id":"audiogram-clinical","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\naudiogram-clinical: Clinical Audiogram\nLibrary: plotly 6.8.0 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-06-15\n\"\"\"\n\nimport os\n\nimport plotly.graph_objects as go\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\n\n# Imprint palette — semantic clinical colors (audiogram convention)\n# Red-right / blue-left is the universal audiometric standard; use closest Imprint members\nRIGHT_EAR_COLOR = \"#AE3030\"  # matte red (Imprint pos 5) — right ear\nLEFT_EAR_COLOR = \"#4467A3\"  # blue (Imprint pos 3) — left ear\n\n# Data — occupational noise-induced high-frequency sensorineural notch\nfrequencies = [125, 250, 500, 1000, 2000, 4000, 8000]\nfreq_labels = [\"125\", \"250\", \"500\", \"1k\", \"2k\", \"4k\", \"8k\"]\n\nthreshold_right = [10, 10, 15, 20, 30, 70, 55]  # right ear: classic 4 kHz noise notch\nthreshold_left = [15, 15, 20, 25, 35, 75, 60]  # left ear: slightly worse\n\n# Severity bands: (label, dB_low, dB_high, fill_rgba)\n# Fills derived from Imprint palette hues at low opacity — distinguishable but non-competing\nseverity_bands = [\n    (\"Normal\", -10, 25, \"rgba(0,158,115,0.07)\"),\n    (\"Mild\", 25, 40, \"rgba(221,204,119,0.12)\"),\n    (\"Moderate\", 40, 55, \"rgba(189,130,51,0.12)\"),\n    (\"Mod. Severe\", 55, 70, \"rgba(196,117,253,0.09)\"),\n    (\"Severe\", 70, 90, \"rgba(174,48,48,0.12)\"),\n    (\"Profound\", 90, 120, \"rgba(174,48,48,0.22)\"),\n]\n\n# Plot\nfig = go.Figure()\n\n# Severity band shading (below data layer)\nfor _, y0, y1, color in severity_bands:\n    fig.add_shape(\n        type=\"rect\", xref=\"paper\", yref=\"y\", x0=0, x1=1, y0=y0, y1=y1, fillcolor=color, line={\"width\": 0}, layer=\"below\"\n    )\n\n# Severity band labels — right margin (outside plot, within figure)\nfor label, y0, y1, _ in severity_bands:\n    fig.add_annotation(\n        x=1.01,\n        xref=\"paper\",\n        y=(y0 + y1) / 2,\n        yref=\"y\",\n        text=label,\n        showarrow=False,\n        xanchor=\"left\",\n        font={\"size\": 10, \"color\": INK_MUTED},\n    )\n\n# Right ear — red circles, solid connecting line\nfig.add_trace(\n    go.Scatter(\n        x=frequencies,\n        y=threshold_right,\n        name=\"Right Ear (O)\",\n        mode=\"lines+markers\",\n        line={\"color\": RIGHT_EAR_COLOR, \"width\": 2.5},\n        marker={\n            \"symbol\": \"circle\",\n            \"size\": 12,\n            \"color\": RIGHT_EAR_COLOR,\n            \"line\": {\"color\": RIGHT_EAR_COLOR, \"width\": 2},\n        },\n    )\n)\n\n# Left ear — blue crosses, dashed connecting line (standard audiogram convention)\nfig.add_trace(\n    go.Scatter(\n        x=frequencies,\n        y=threshold_left,\n        name=\"Left Ear (X)\",\n        mode=\"lines+markers\",\n        line={\"color\": LEFT_EAR_COLOR, \"width\": 2.5, \"dash\": \"dash\"},\n        marker={\"symbol\": \"x\", \"size\": 12, \"color\": LEFT_EAR_COLOR, \"line\": {\"color\": LEFT_EAR_COLOR, \"width\": 2.5}},\n    )\n)\n\n# Title — compute fontsize from length\ntitle = \"audiogram-clinical · python · plotly · anyplot.ai\"\nn = len(title)\ntitle_fontsize = max(11, round(16 * (67 / n if n > 67 else 1.0)))\n\nfig.update_layout(\n    autosize=False,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    margin={\"l\": 80, \"r\": 150, \"t\": 80, \"b\": 80},\n    title={\"text\": title, \"font\": {\"size\": title_fontsize, \"color\": INK}},\n    xaxis={\n        \"type\": \"log\",\n        \"title\": {\"text\": \"Frequency (Hz)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickvals\": frequencies,\n        \"ticktext\": freq_labels,\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"gridcolor\": GRID,\n        \"linecolor\": INK_SOFT,\n        \"showgrid\": True,\n        \"range\": [2.0, 3.95],\n    },\n    yaxis={\n        \"title\": {\"text\": \"Hearing Level (dB HL)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"gridcolor\": GRID,\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": GRID,\n        \"showgrid\": True,\n        \"range\": [120, -10],\n        \"dtick\": 10,\n    },\n    legend={\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n        \"font\": {\"color\": INK_SOFT, \"size\": 10},\n        \"x\": 0.02,\n        \"y\": 0.02,\n        \"xanchor\": \"left\",\n        \"yanchor\": \"bottom\",\n    },\n    font={\"color\": INK},\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=600, height=600, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}