{"spec_id":"heatmap-periodic-table","library":"makie","language":"julia","code":"# anyplot.ai\n# heatmap-periodic-table: Periodic Table Property Heatmap\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 88/100 | Created: 2026-06-15\n\nusing CairoMakie\nusing Colors\n\nconst THEME        = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG      = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst INK          = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT     = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst INK_MUTED    = THEME == \"light\" ? colorant\"#6B6A63\" : colorant\"#A8A79F\"\nconst TILE_MISSING = THEME == \"light\" ? colorant\"#D8D6CE\" : colorant\"#383834\"\n\n# Imprint sequential colormap: brand green → blue (single-polarity continuous data)\nconst ANYPLOT_SEQ = cgrad([colorant\"#009E73\", colorant\"#4467A3\"])\n\n# Element data: (symbol, atomic_number, display_col, display_row, pauling_electronegativity)\n# display_col 1–18; display_row 1–7 (main table), 8.5 (lanthanides), 9.5 (actinides)\n# NaN = no standard Pauling electronegativity value\nconst ELEMENTS = [\n    # Period 1\n    (\"H\",   1,  1, 1.0, 2.20), (\"He\",  2, 18, 1.0, NaN),\n    # Period 2\n    (\"Li\",  3,  1, 2.0, 0.98), (\"Be\",  4,  2, 2.0, 1.57),\n    (\"B\",   5, 13, 2.0, 2.04), (\"C\",   6, 14, 2.0, 2.55),\n    (\"N\",   7, 15, 2.0, 3.04), (\"O\",   8, 16, 2.0, 3.44),\n    (\"F\",   9, 17, 2.0, 3.98), (\"Ne\", 10, 18, 2.0, NaN),\n    # Period 3\n    (\"Na\", 11,  1, 3.0, 0.93), (\"Mg\", 12,  2, 3.0, 1.31),\n    (\"Al\", 13, 13, 3.0, 1.61), (\"Si\", 14, 14, 3.0, 1.90),\n    (\"P\",  15, 15, 3.0, 2.19), (\"S\",  16, 16, 3.0, 2.58),\n    (\"Cl\", 17, 17, 3.0, 3.16), (\"Ar\", 18, 18, 3.0, NaN),\n    # Period 4\n    (\"K\",  19,  1, 4.0, 0.82), (\"Ca\", 20,  2, 4.0, 1.00),\n    (\"Sc\", 21,  3, 4.0, 1.36), (\"Ti\", 22,  4, 4.0, 1.54),\n    (\"V\",  23,  5, 4.0, 1.63), (\"Cr\", 24,  6, 4.0, 1.66),\n    (\"Mn\", 25,  7, 4.0, 1.55), (\"Fe\", 26,  8, 4.0, 1.83),\n    (\"Co\", 27,  9, 4.0, 1.88), (\"Ni\", 28, 10, 4.0, 1.91),\n    (\"Cu\", 29, 11, 4.0, 1.90), (\"Zn\", 30, 12, 4.0, 1.65),\n    (\"Ga\", 31, 13, 4.0, 1.81), (\"Ge\", 32, 14, 4.0, 2.01),\n    (\"As\", 33, 15, 4.0, 2.18), (\"Se\", 34, 16, 4.0, 2.55),\n    (\"Br\", 35, 17, 4.0, 2.96), (\"Kr\", 36, 18, 4.0, 3.00),\n    # Period 5\n    (\"Rb\", 37,  1, 5.0, 0.82), (\"Sr\", 38,  2, 5.0, 0.95),\n    (\"Y\",  39,  3, 5.0, 1.22), (\"Zr\", 40,  4, 5.0, 1.33),\n    (\"Nb\", 41,  5, 5.0, 1.60), (\"Mo\", 42,  6, 5.0, 2.16),\n    (\"Tc\", 43,  7, 5.0, 1.90), (\"Ru\", 44,  8, 5.0, 2.20),\n    (\"Rh\", 45,  9, 5.0, 2.28), (\"Pd\", 46, 10, 5.0, 2.20),\n    (\"Ag\", 47, 11, 5.0, 1.93), (\"Cd\", 48, 12, 5.0, 1.69),\n    (\"In\", 49, 13, 5.0, 1.78), (\"Sn\", 50, 14, 5.0, 1.96),\n    (\"Sb\", 51, 15, 5.0, 2.05), (\"Te\", 52, 16, 5.0, 2.10),\n    (\"I\",  53, 17, 5.0, 2.66), (\"Xe\", 54, 18, 5.0, 2.60),\n    # Period 6 (col 3 left empty for f-block pointer tile)\n    (\"Cs\", 55,  1, 6.0, 0.79), (\"Ba\", 56,  2, 6.0, 0.89),\n    (\"Hf\", 72,  4, 6.0, 1.30), (\"Ta\", 73,  5, 6.0, 1.50),\n    (\"W\",  74,  6, 6.0, 2.36), (\"Re\", 75,  7, 6.0, 1.90),\n    (\"Os\", 76,  8, 6.0, 2.20), (\"Ir\", 77,  9, 6.0, 2.20),\n    (\"Pt\", 78, 10, 6.0, 2.28), (\"Au\", 79, 11, 6.0, 2.54),\n    (\"Hg\", 80, 12, 6.0, 2.00), (\"Tl\", 81, 13, 6.0, 1.62),\n    (\"Pb\", 82, 14, 6.0, 2.33), (\"Bi\", 83, 15, 6.0, 2.02),\n    (\"Po\", 84, 16, 6.0, 2.00), (\"At\", 85, 17, 6.0, 2.20),\n    (\"Rn\", 86, 18, 6.0, NaN),\n    # Period 7 (col 3 left empty for f-block pointer tile)\n    (\"Fr\", 87,  1, 7.0, 0.70), (\"Ra\", 88,  2, 7.0, 0.89),\n    (\"Rf\",104,  4, 7.0, NaN), (\"Db\",105,  5, 7.0, NaN),\n    (\"Sg\",106,  6, 7.0, NaN), (\"Bh\",107,  7, 7.0, NaN),\n    (\"Hs\",108,  8, 7.0, NaN), (\"Mt\",109,  9, 7.0, NaN),\n    (\"Ds\",110, 10, 7.0, NaN), (\"Rg\",111, 11, 7.0, NaN),\n    (\"Cn\",112, 12, 7.0, NaN), (\"Nh\",113, 13, 7.0, NaN),\n    (\"Fl\",114, 14, 7.0, NaN), (\"Mc\",115, 15, 7.0, NaN),\n    (\"Lv\",116, 16, 7.0, NaN), (\"Ts\",117, 17, 7.0, NaN),\n    (\"Og\",118, 18, 7.0, NaN),\n    # Lanthanides (f-block row 1, cols 3–17)\n    (\"La\", 57,  3, 8.5, 1.10), (\"Ce\", 58,  4, 8.5, 1.12),\n    (\"Pr\", 59,  5, 8.5, 1.13), (\"Nd\", 60,  6, 8.5, 1.14),\n    (\"Pm\", 61,  7, 8.5, NaN),  (\"Sm\", 62,  8, 8.5, 1.17),\n    (\"Eu\", 63,  9, 8.5, NaN),  (\"Gd\", 64, 10, 8.5, 1.20),\n    (\"Tb\", 65, 11, 8.5, NaN),  (\"Dy\", 66, 12, 8.5, 1.22),\n    (\"Ho\", 67, 13, 8.5, 1.23), (\"Er\", 68, 14, 8.5, 1.24),\n    (\"Tm\", 69, 15, 8.5, 1.25), (\"Yb\", 70, 16, 8.5, NaN),\n    (\"Lu\", 71, 17, 8.5, 1.27),\n    # Actinides (f-block row 2, cols 3–17)\n    (\"Ac\", 89,  3, 9.5, 1.10), (\"Th\", 90,  4, 9.5, 1.30),\n    (\"Pa\", 91,  5, 9.5, 1.50), (\"U\",  92,  6, 9.5, 1.38),\n    (\"Np\", 93,  7, 9.5, 1.36), (\"Pu\", 94,  8, 9.5, 1.28),\n    (\"Am\", 95,  9, 9.5, 1.30), (\"Cm\", 96, 10, 9.5, 1.30),\n    (\"Bk\", 97, 11, 9.5, 1.30), (\"Cf\", 98, 12, 9.5, 1.30),\n    (\"Es\", 99, 13, 9.5, 1.30), (\"Fm\",100, 14, 9.5, 1.30),\n    (\"Md\",101, 15, 9.5, 1.30), (\"No\",102, 16, 9.5, 1.30),\n    (\"Lr\",103, 17, 9.5, NaN),\n]\n\n# Colormap range over elements with a known EN value\nconst EN_VALS  = [en for (_, _, _, _, en) in ELEMENTS if !isnan(en)]\nconst EN_MIN   = minimum(EN_VALS)   # 0.70 (Fr)\nconst EN_MAX   = maximum(EN_VALS)   # 3.98 (F)\n\nfunction tile_color(en::Float64)\n    isnan(en) && return TILE_MISSING\n    t = clamp((en - EN_MIN) / (EN_MAX - EN_MIN), 0.0, 1.0)\n    return get(ANYPLOT_SEQ, t)\nend\n\nfunction text_color_for(c)\n    lum = 0.299 * Float64(red(c)) + 0.587 * Float64(green(c)) + 0.114 * Float64(blue(c))\n    return lum > 0.45 ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nend\n\n# --- Figure -----------------------------------------------------------------\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n    figure_padding  = 16,\n)\n\nax = Axis(\n    fig[1, 1];\n    title               = \"heatmap-periodic-table · julia · makie · anyplot.ai\",\n    titlesize           = 20,\n    titlecolor          = INK,\n    subtitle            = \"Pauling electronegativity: highest at F (3.98, top-right), lowest at Fr (0.70, bottom-left)\",\n    subtitlesize        = 11,\n    subtitlecolor       = INK_SOFT,\n    backgroundcolor     = PAGE_BG,\n    xticksvisible       = false,\n    yticksvisible       = false,\n    xticklabelsvisible  = false,\n    yticklabelsvisible  = false,\n    topspinevisible     = false,\n    rightspinevisible   = false,\n    leftspinevisible    = false,\n    bottomspinevisible  = false,\n    xgridvisible        = false,\n    ygridvisible        = false,\n)\n\nxlims!(ax, 0.5, 18.5)\nylims!(ax, 0.0, 10.1)\n\n# Flip y so period 1 appears at the top: dy = 10.5 - display_row\n# period 1 → dy=9.5 (near top), actinides → dy=1.0 (near bottom)\nflip_y(row) = 10.5 - row\n\n# --- Draw element tiles and labels ------------------------------------------\nconst TILE_HALF = 0.45f0   # half-side of each square tile (gap ≈ 0.10 per side)\n\nfor (sym, z, dx, row, en) in ELEMENTS\n    dy  = flip_y(row)\n    tc  = tile_color(en)\n    ltc = isnan(en) ? INK_MUTED : text_color_for(tc)\n\n    # Tile rectangle centred at (dx, dy)\n    poly!(ax, Rect2f(dx - TILE_HALF, dy - TILE_HALF, 2 * TILE_HALF, 2 * TILE_HALF);\n          color = tc)\n\n    # Atomic number — upper-left corner of tile (dy+0.22 is visually above centre)\n    text!(ax, dx - 0.33, dy + 0.22;\n          text      = string(z),\n          fontsize   = 7.5,\n          color      = ltc,\n          align      = (:left, :center))\n\n    # Element symbol — centred, slightly below the atomic number\n    text!(ax, dx, dy - 0.08;\n          text      = sym,\n          fontsize   = 9,\n          color      = ltc,\n          align      = (:center, :center))\nend\n\n# --- F-block pointer tiles at col 3 of periods 6 and 7 ---------------------\nfor row in (6.0, 7.0)\n    dy = flip_y(row)\n    poly!(ax, Rect2f(3 - TILE_HALF, dy - TILE_HALF, 2 * TILE_HALF, 2 * TILE_HALF);\n          color = TILE_MISSING)\n    text!(ax, 3.0, dy;\n          text      = \"*\",\n          fontsize   = 11,\n          color      = INK_MUTED,\n          align      = (:center, :center))\nend\n\n# --- F-block row annotations -----------------------------------------------\ntext!(ax, 2.0, flip_y(8.5); text = \"Ln\", fontsize = 7, color = INK_MUTED, align = (:center, :center))\ntext!(ax, 2.0, flip_y(9.5); text = \"An\", fontsize = 7, color = INK_MUTED, align = (:center, :center))\n\n# --- Colorbar ---------------------------------------------------------------\ncbar = Colorbar(fig[1, 2];\n    colormap        = ANYPLOT_SEQ,\n    limits          = (EN_MIN, EN_MAX),\n    label           = \"Pauling Electronegativity\",\n    labelcolor      = INK,\n    labelsize       = 12,\n    tickcolor       = INK_SOFT,\n    ticklabelcolor  = INK_SOFT,\n    ticklabelsize   = 10,\n    width           = 18,\n    flipaxis        = false,\n)\n\ncolsize!(fig.layout, 1, Relative(0.92))\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}