{"spec_id":"audiogram-clinical","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\naudiogram-clinical: Clinical Audiogram\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 89/100 | Updated: 2026-06-15\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport matplotlib.ticker as ticker\nimport seaborn as sns\nfrom matplotlib.transforms import blended_transform_factory\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\"\n\n# Semantic color exception: clinical convention (right ear = red, left ear = blue)\nRIGHT_COLOR = \"#AE3030\"  # Imprint matte red\nLEFT_COLOR = \"#4467A3\"  # Imprint blue\n\n# Pure-tone audiometry — high-frequency sensorineural notch (noise-induced pattern)\nfrequencies = [125, 250, 500, 1000, 2000, 4000, 8000]\nthreshold_right = [10, 10, 15, 15, 20, 55, 65]  # dB HL, right ear\nthreshold_left = [10, 15, 15, 20, 30, 65, 75]  # dB HL, left ear\n\n# Severity bands [dB HL lo, hi, fill color, label]\nBANDS = [\n    (-10, 25, \"#009E73\", \"Normal\"),\n    (25, 40, \"#99B314\", \"Mild\"),\n    (40, 55, \"#BD8233\", \"Moderate\"),\n    (55, 70, \"#DDCC77\", \"Mod. Severe\"),\n    (70, 90, \"#AE3030\", \"Severe\"),\n    (90, 120, \"#954477\", \"Profound\"),\n]\nBAND_ALPHA = 0.09 if THEME == \"light\" else 0.16\n\n# Global seaborn theme\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.15,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Canvas — square (2400×2400 px); audiogram is a square clinical grid\nfig, ax = plt.subplots(figsize=(6, 6), dpi=400)\nfig.set_facecolor(PAGE_BG)\nax.set_facecolor(PAGE_BG)\nfig.subplots_adjust(left=0.11, right=0.80, top=0.92, bottom=0.12)\n\n# Severity band fills (drawn first, behind everything)\nfor y_lo, y_hi, color, _ in BANDS:\n    ax.axhspan(y_lo, y_hi, alpha=BAND_ALPHA, color=color, zorder=0)\n\n# Log x-scale and inverted y-axis\nax.set_xscale(\"log\")\nax.set_xlim(100, 9000)\nax.set_ylim(120, -10)\n\n# Right ear: red open circles, solid line\nsns.lineplot(\n    x=frequencies,\n    y=threshold_right,\n    color=RIGHT_COLOR,\n    linewidth=2.0,\n    linestyle=\"-\",\n    marker=\"o\",\n    markersize=9,\n    markerfacecolor=PAGE_BG,\n    markeredgecolor=RIGHT_COLOR,\n    markeredgewidth=2.0,\n    label=\"Right Ear (O)\",\n    zorder=4,\n    ax=ax,\n)\n\n# Left ear: blue crosses, dashed line\nsns.lineplot(\n    x=frequencies,\n    y=threshold_left,\n    color=LEFT_COLOR,\n    linewidth=2.0,\n    linestyle=\"--\",\n    marker=\"x\",\n    markersize=10,\n    markeredgewidth=2.5,\n    label=\"Left Ear (X)\",\n    zorder=4,\n    ax=ax,\n)\n\n# x-axis: audiometric frequencies only, log scale\nax.set_xticks(frequencies)\nax.xaxis.set_major_formatter(ticker.FixedFormatter([\"125\", \"250\", \"500\", \"1k\", \"2k\", \"4k\", \"8k\"]))\nax.xaxis.set_minor_locator(ticker.NullLocator())\n\n# y-axis: 10 dB steps from -10 to 120\nax.set_yticks(range(-10, 121, 10))\n\n# Grid on both axes (standard clinical audiogram appearance)\nax.set_axisbelow(True)\nax.xaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)\nax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)\n\n# Severity band labels in right margin\ntrans = blended_transform_factory(ax.transAxes, ax.transData)\nfor y_lo, y_hi, _, label in BANDS:\n    ax.text(\n        1.04,\n        (y_lo + y_hi) / 2,\n        label,\n        transform=trans,\n        va=\"center\",\n        ha=\"left\",\n        fontsize=7,\n        color=INK_MUTED,\n        style=\"italic\",\n        clip_on=False,\n    )\n\n# Axis labels and tick styling\nax.set_xlabel(\"Frequency (Hz)\", fontsize=10, color=INK, labelpad=8)\nax.set_ylabel(\"Hearing Level (dB HL)\", fontsize=10, color=INK, labelpad=8)\nax.tick_params(axis=\"both\", labelsize=8, colors=INK_SOFT, top=False, right=False)\n\n# Title\ntitle = \"audiogram-clinical · python · seaborn · anyplot.ai\"\nax.set_title(title, fontsize=12, fontweight=\"medium\", color=INK, pad=10)\n\n# Legend\nlegend = ax.legend(fontsize=8, loc=\"lower left\", facecolor=ELEVATED_BG, edgecolor=INK_SOFT, framealpha=0.9)\nfor text in legend.get_texts():\n    text.set_color(INK_SOFT)\n\n# Spines — seaborn idiom removes top/right; color remaining spines\nsns.despine(ax=ax)\nax.spines[\"left\"].set_color(INK_SOFT)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\n# Save\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\nplt.close()\n"}