{"spec_id":"phase-diagram-pt","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nphase-diagram-pt: Thermodynamic Phase Diagram (Pressure-Temperature)\nLibrary: plotly 6.8.0 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-06-08\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme tokens (see prompts/default-style-guide.md)\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 — hybrid-v3 canonical order\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"]\n\n# Data — Water phase diagram with real Clausius-Clapeyron constants\n# Triple point: 273.16 K, 611.73 Pa | Critical point: 647.096 K, 22.064 MPa\ntriple_T = 273.16\ntriple_P = 611.73\ncritical_T = 647.096\ncritical_P = 22.064e6\nR = 8.314  # J/(mol·K)\n\n# Solid-gas boundary (sublimation curve) — triple point down to 200 K\nT_solid_gas = np.linspace(200, triple_T, 80)\nL_sub = 51059  # J/mol (sublimation enthalpy of water)\nP_solid_gas = triple_P * np.exp((L_sub / R) * (1 / triple_T - 1 / T_solid_gas))\n\n# Liquid-gas boundary (vaporization curve) — triple point to critical point\nT_liquid_gas = np.linspace(triple_T, critical_T, 100)\nL_vap = 40670  # J/mol (vaporization enthalpy of water)\nP_liquid_gas = triple_P * np.exp((L_vap / R) * (1 / triple_T - 1 / T_liquid_gas))\n\n# Solid-liquid boundary (melting curve) — negative slope unique to water\nP_solid_liquid = np.logspace(np.log10(triple_P), np.log10(1e10), 80)\ndT_dP = -7.4e-8  # K/Pa (anomalous negative slope for water)\nT_solid_liquid = triple_T + dT_dP * (P_solid_liquid - triple_P)\n\n# Axis bounds\nx_min, x_max = 180, 800\ny_log_min, y_log_max = 0, 10  # log10(Pa)\n\n# Title font size — scale down for long title\ntitle_str = \"Water P-T Phase Diagram · phase-diagram-pt · python · plotly · anyplot.ai\"\nn = len(title_str)\ntitle_fs = max(11, round(16 * (67 / n if n > 67 else 1.0)))\n\n# Plot\nfig = go.Figure()\n\n# Phase region fills using Imprint palette at low opacity\n# GAS region — below sublimation and vaporization curves\ngas_T = np.concatenate([[x_min], T_solid_gas, T_liquid_gas, [x_max, x_max, x_min]])\ngas_P = np.concatenate([[10**y_log_min], P_solid_gas, P_liquid_gas, [10**y_log_min, 10**y_log_min, 10**y_log_min]])\nfig.add_trace(\n    go.Scatter(\n        x=gas_T,\n        y=gas_P,\n        fill=\"toself\",\n        mode=\"lines\",\n        line={\"width\": 0},\n        fillcolor=\"rgba(189,130,51,0.10)\",  # Imprint ochre #BD8233 — warm/gas\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\n# SOLID region — left of melting curve, above sublimation curve\nsolid_T = np.concatenate([T_solid_gas[::-1], [x_min, x_min], T_solid_liquid[T_solid_liquid >= x_min][::-1]])\nsolid_P = np.concatenate(\n    [P_solid_gas[::-1], [P_solid_gas[0], 10**y_log_max], P_solid_liquid[T_solid_liquid >= x_min][::-1]]\n)\nfig.add_trace(\n    go.Scatter(\n        x=solid_T,\n        y=solid_P,\n        fill=\"toself\",\n        mode=\"lines\",\n        line={\"width\": 0},\n        fillcolor=\"rgba(68,103,163,0.12)\",  # Imprint blue #4467A3 — cold/solid\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\n# LIQUID region — between melting and vaporization curves\nliquid_mask = (T_solid_liquid >= x_min) & (P_solid_liquid <= critical_P)\nliquid_T = np.concatenate([T_liquid_gas, [critical_T], T_solid_liquid[liquid_mask][::-1]])\nliquid_P = np.concatenate([P_liquid_gas, [critical_P], P_solid_liquid[liquid_mask][::-1]])\nfig.add_trace(\n    go.Scatter(\n        x=liquid_T,\n        y=liquid_P,\n        fill=\"toself\",\n        mode=\"lines\",\n        line={\"width\": 0},\n        fillcolor=\"rgba(196,117,253,0.10)\",  # Imprint lavender #C475FD — liquid\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\n# Supercritical region — above and right of critical point\nfig.add_trace(\n    go.Scatter(\n        x=[critical_T, x_max, x_max, critical_T, critical_T],\n        y=[critical_P, critical_P, 10**y_log_max, 10**y_log_max, critical_P],\n        fill=\"toself\",\n        mode=\"lines\",\n        line={\"width\": 0},\n        fillcolor=\"rgba(221,204,119,0.15)\",  # Imprint amber #DDCC77 — supercritical\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\n# Phase boundary curves — Imprint palette positions 1→3\nfig.add_trace(\n    go.Scatter(\n        x=T_solid_gas,\n        y=P_solid_gas,\n        mode=\"lines\",\n        line={\"color\": IMPRINT[0], \"width\": 3.5},  # #009E73 green — sublimation\n        name=\"Sublimation curve\",\n        hovertemplate=\"<b>Sublimation</b><br>T: %{x:.1f} K<br>P: %{y:.2e} Pa<extra></extra>\",\n    )\n)\n\nfig.add_trace(\n    go.Scatter(\n        x=T_liquid_gas,\n        y=P_liquid_gas,\n        mode=\"lines\",\n        line={\"color\": IMPRINT[1], \"width\": 3.5},  # #C475FD lavender — vaporization\n        name=\"Vaporization curve\",\n        hovertemplate=\"<b>Vaporization</b><br>T: %{x:.1f} K<br>P: %{y:.2e} Pa<extra></extra>\",\n    )\n)\n\nfig.add_trace(\n    go.Scatter(\n        x=T_solid_liquid,\n        y=P_solid_liquid,\n        mode=\"lines\",\n        line={\"color\": IMPRINT[2], \"width\": 3.5},  # #4467A3 blue — melting\n        name=\"Melting curve\",\n        hovertemplate=\"<b>Melting</b><br>T: %{x:.1f} K<br>P: %{y:.2e} Pa<extra></extra>\",\n    )\n)\n\n# Triple point marker — Imprint matte red (semantic: special critical state)\nfig.add_trace(\n    go.Scatter(\n        x=[triple_T],\n        y=[triple_P],\n        mode=\"markers\",\n        marker={\n            \"size\": 16,\n            \"color\": IMPRINT[4],  # #AE3030 matte red\n            \"symbol\": \"diamond\",\n            \"line\": {\"color\": PAGE_BG, \"width\": 2},\n        },\n        name=\"Triple point\",\n        hovertemplate=\"Triple Point<br>T: 273.16 K<br>P: 611.73 Pa<extra></extra>\",\n    )\n)\n\n# Critical point marker — Imprint ochre (warm, distinct from red)\nfig.add_trace(\n    go.Scatter(\n        x=[critical_T],\n        y=[critical_P],\n        mode=\"markers\",\n        marker={\n            \"size\": 16,\n            \"color\": IMPRINT[3],  # #BD8233 ochre\n            \"symbol\": \"star\",\n            \"line\": {\"color\": PAGE_BG, \"width\": 2},\n        },\n        name=\"Critical point\",\n        hovertemplate=\"Critical Point<br>T: 647.1 K<br>P: 2.206×10⁷ Pa<extra></extra>\",\n    )\n)\n\n# Phase region labels — INK_MUTED so they sit behind the data visually\nlabel_font = {\"size\": 22, \"color\": INK_MUTED, \"family\": \"Arial Black\"}\n# annotation y uses log10 values because yaxis.type='log' uses log10 coordinate space\nfig.add_annotation(x=225, y=np.log10(3e4), text=\"SOLID\", font=label_font, showarrow=False, yref=\"y\")\nfig.add_annotation(x=430, y=np.log10(5e6), text=\"LIQUID\", font=label_font, showarrow=False, yref=\"y\")\nfig.add_annotation(x=450, y=np.log10(30), text=\"GAS\", font=label_font, showarrow=False, yref=\"y\")\nfig.add_annotation(\n    x=700,\n    y=9.75,\n    text=\"Supercritical<br>Fluid\",\n    font={\"size\": 16, \"color\": INK_MUTED, \"family\": \"Arial Black\"},\n    showarrow=False,\n    yref=\"y\",\n    xanchor=\"center\",\n)\n\n# Triple point annotation — placed right and above to avoid crowding with converging curves\nfig.add_annotation(\n    x=triple_T,\n    y=np.log10(triple_P),\n    yref=\"y\",\n    text=\"Triple Point<br>(273.16 K, 611.73 Pa)\",\n    font={\"size\": 12, \"color\": INK},\n    bgcolor=ELEVATED_BG,\n    bordercolor=IMPRINT[4],\n    borderwidth=1,\n    ax=90,\n    ay=-60,\n    arrowhead=2,\n    arrowsize=1.2,\n    arrowwidth=1.5,\n    arrowcolor=IMPRINT[4],\n)\n\n# Critical point annotation — points left into liquid region for space\nfig.add_annotation(\n    x=critical_T,\n    y=np.log10(critical_P),\n    yref=\"y\",\n    text=\"Critical Point<br>(647.1 K, 2.206×10⁷ Pa)\",\n    font={\"size\": 12, \"color\": INK},\n    bgcolor=ELEVATED_BG,\n    bordercolor=IMPRINT[3],\n    borderwidth=1,\n    ax=-120,\n    ay=-30,\n    arrowhead=2,\n    arrowsize=1.2,\n    arrowwidth=1.5,\n    arrowcolor=IMPRINT[3],\n)\n\n# Dashed supercritical boundary lines — vertical and horizontal from critical point\nfig.add_trace(\n    go.Scatter(\n        x=[critical_T, critical_T],\n        y=[critical_P, 1e10],\n        mode=\"lines\",\n        line={\"color\": IMPRINT[3], \"width\": 2, \"dash\": \"dot\"},\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\nfig.add_trace(\n    go.Scatter(\n        x=[critical_T, 800],\n        y=[critical_P, critical_P],\n        mode=\"lines\",\n        line={\"color\": IMPRINT[3], \"width\": 2, \"dash\": \"dot\"},\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\n# Layout — theme-adaptive chrome throughout\nfig.update_layout(\n    autosize=False,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    title={\"text\": title_str, \"font\": {\"size\": title_fs, \"color\": INK}, \"x\": 0.5, \"xanchor\": \"center\"},\n    xaxis={\n        \"title\": {\"text\": \"Temperature (K)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"range\": [x_min, x_max],\n        \"showgrid\": True,\n        \"gridwidth\": 1,\n        \"gridcolor\": GRID,\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": INK_SOFT,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Pressure (Pa)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"type\": \"log\",\n        \"range\": [y_log_min, y_log_max],\n        \"showgrid\": True,\n        \"gridwidth\": 1,\n        \"gridcolor\": GRID,\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": INK_SOFT,\n    },\n    legend={\n        \"font\": {\"size\": 10, \"color\": INK_SOFT},\n        \"x\": 0.02,\n        \"y\": 0.98,\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n    },\n    margin={\"l\": 100, \"r\": 80, \"t\": 80, \"b\": 80},\n    showlegend=True,\n    updatemenus=[\n        {\n            \"type\": \"buttons\",\n            \"direction\": \"left\",\n            \"x\": 0.98,\n            \"y\": -0.15,\n            \"xanchor\": \"right\",\n            \"buttons\": [\n                {\"label\": \"Log Scale\", \"method\": \"relayout\", \"args\": [{\"yaxis.type\": \"log\"}]},\n                {\"label\": \"Linear Scale\", \"method\": \"relayout\", \"args\": [{\"yaxis.type\": \"linear\"}]},\n            ],\n            \"font\": {\"size\": 10, \"color\": INK},\n            \"bgcolor\": ELEVATED_BG,\n            \"borderwidth\": 1,\n            \"bordercolor\": INK_SOFT,\n        }\n    ],\n)\n\n# Save — landscape 3200×1800 (width=800 height=450 scale=4)\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}