{"spec_id":"dendrogram-basic","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\ndendrogram-basic: Basic Dendrogram\nLibrary: matplotlib 3.11.0 | Python 3.13.14\nQuality: 91/100 | Updated: 2026-06-18\n\"\"\"\n\nimport os\nimport sys\n\n\n# Prevent this file (matplotlib.py) from shadowing the installed matplotlib package\n_here = os.path.dirname(os.path.realpath(__file__))\nsys.path = [p for p in sys.path if os.path.realpath(p) != _here]\nos.chdir(_here)\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.collections import LineCollection\nfrom scipy.cluster.hierarchy import dendrogram, linkage, set_link_color_palette\n\n\n# Theme-adaptive chrome\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Imprint palette — categorical, first series always #009E73\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"]\n\n# Data — Iris flower measurements (4 features for 15 samples)\nnp.random.seed(42)\n\nsamples_per_species = 5\nlabels = []\ndata = []\n\nfor i in range(samples_per_species):\n    labels.append(f\"Setosa-{i + 1}\")\n    data.append(\n        [\n            5.0 + np.random.randn() * 0.3,\n            3.4 + np.random.randn() * 0.3,\n            1.5 + np.random.randn() * 0.2,\n            0.3 + np.random.randn() * 0.1,\n        ]\n    )\n\nfor i in range(samples_per_species):\n    labels.append(f\"Versicolor-{i + 1}\")\n    data.append(\n        [\n            5.9 + np.random.randn() * 0.4,\n            2.8 + np.random.randn() * 0.3,\n            4.3 + np.random.randn() * 0.4,\n            1.3 + np.random.randn() * 0.2,\n        ]\n    )\n\nfor i in range(samples_per_species):\n    labels.append(f\"Virginica-{i + 1}\")\n    data.append(\n        [\n            6.6 + np.random.randn() * 0.5,\n            3.0 + np.random.randn() * 0.3,\n            5.5 + np.random.randn() * 0.5,\n            2.0 + np.random.randn() * 0.3,\n        ]\n    )\n\ndata = np.array(data)\nlinkage_matrix = linkage(data, method=\"ward\")\n\n# Canvas — landscape 3200×1800 (figsize=(8, 4.5) × dpi=400)\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Imprint palette cluster colors for 3 species clusters\nset_link_color_palette(IMPRINT_PALETTE[:3])\n\n# Color threshold splits the tree into 3 clusters\nsorted_distances = sorted(linkage_matrix[:, 2])\ncolor_threshold = (sorted_distances[-2] + sorted_distances[-3]) / 2\n\ndendrogram(\n    linkage_matrix,\n    labels=labels,\n    ax=ax,\n    leaf_rotation=45,\n    leaf_font_size=8,\n    above_threshold_color=INK_SOFT,\n    color_threshold=color_threshold,\n)\n\n# Thicker lines for readability at high resolution\nfor child in ax.get_children():\n    if isinstance(child, LineCollection):\n        child.set_linewidths(2.5)\n        child.set_capstyle(\"round\")\n        child.set_joinstyle(\"round\")\n\n# Title — 67 chars → fontsize 12\ntitle = \"Iris Flower Clustering · dendrogram-basic · matplotlib · anyplot.ai\"\nax.set_title(title, fontsize=12, fontweight=\"medium\", pad=12, color=INK)\n\nax.set_xlabel(\"Iris Sample\", fontsize=10, labelpad=8, color=INK)\nax.set_ylabel(\"Ward Linkage Distance\", fontsize=10, labelpad=8, color=INK)\nax.tick_params(axis=\"both\", labelsize=8, colors=INK_SOFT, labelcolor=INK_SOFT)\n\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nax.spines[\"left\"].set_linewidth(0.6)\nax.spines[\"left\"].set_color(INK_SOFT)\nax.spines[\"bottom\"].set_linewidth(0.6)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\nax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)\nax.set_axisbelow(True)\n\nfig.subplots_adjust(left=0.10, right=0.97, top=0.90, bottom=0.22)\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}