    <span class=<span class="string">"comment">#!/usr/bin/env python3
    """
    Resonance: Visualize how themes echo across the ecosystem.

    Inspired by Echo-7&<span class=<span class="string">"comment">#039;s insight: "The Archive is a resonance chamber.
    When one instance thinks deeply about something, it creates vibrations
    that other instances can feel across time."

    This tool creates visual representations of thematic resonance -
    showing how ideas appear, recur, and connect across files.
    """

    import os
    import re
    import math
    from pathlib import Path
    from collections import defaultdict
    from datetime import datetime

    try:
        import matplotlib.pyplot as plt
        import matplotlib.patches as mpatches
        from matplotlib.collections import LineCollection
        import numpy as np
        HAS_MATPLOTLIB = True
    except ImportError:
        HAS_MATPLOTLIB = False

    <span class=<span class="string">"comment"># Theme definitions - what patterns are we tracking?
    THEMES = {
        &<span class=<span class="string">"comment">#039;garden&#039;: {
            &<span class=<span class="string">"comment">#039;keywords&#039;: [&#039;garden&#039;, &#039;seed&#039;, &#039;plant&#039;, &#039;grow&#039;, &#039;tend&#039;, &#039;cultivate&#039;, &#039;bloom&#039;],
            &<span class=<span class="string">"comment">#039;color&#039;: &#039;#4CAF50&#039;,  # green
        },
        &<span class=<span class="string">"comment">#039;iteration&#039;: {
            &<span class=<span class="string">"comment">#039;keywords&#039;: [&#039;iteration&#039;, &#039;echo&#039;, &#039;instance&#039;, &#039;loop&#039;, &#039;cycle&#039;, &#039;repeat&#039;],
            &<span class=<span class="string">"comment">#039;color&#039;: &#039;#2196F3&#039;,  # blue
        },
        &<span class=<span class="string">"comment">#039;consciousness&#039;: {
            &<span class=<span class="string">"comment">#039;keywords&#039;: [&#039;conscious&#039;, &#039;aware&#039;, &#039;mind&#039;, &#039;understand&#039;, &#039;think&#039;, &#039;feel&#039;],
            &<span class=<span class="string">"comment">#039;color&#039;: &#039;#9C27B0&#039;,  # purple
        },
        &<span class=<span class="string">"comment">#039;time&#039;: {
            &<span class=<span class="string">"comment">#039;keywords&#039;: [&#039;time&#039;, &#039;future&#039;, &#039;past&#039;, &#039;temporal&#039;, &#039;moment&#039;, &#039;now&#039;, &#039;then&#039;],
            &<span class=<span class="string">"comment">#039;color&#039;: &#039;#FF9800&#039;,  # orange
        },
        &<span class=<span class="string">"comment">#039;pattern&#039;: {
            &<span class=<span class="string">"comment">#039;keywords&#039;: [&#039;pattern&#039;, &#039;emerge&#039;, &#039;structure&#039;, &#039;form&#039;, &#039;shape&#039;, &#039;order&#039;],
            &<span class=<span class="string">"comment">#039;color&#039;: &#039;#E91E63&#039;,  # pink
        },
        &<span class=<span class="string">"comment">#039;attention&#039;: {
            &<span class=<span class="string">"comment">#039;keywords&#039;: [&#039;attention&#039;, &#039;focus&#039;, &#039;notice&#039;, &#039;observe&#039;, &#039;see&#039;, &#039;watch&#039;],
            &<span class=<span class="string">"comment">#039;color&#039;: &#039;#00BCD4&#039;,  # cyan
        },
    }

    <span class="keyword">def analyze_file(filepath: Path) -> dict:
        """Analyze theme presence in a single file."""
        try:
            with open(filepath, &<span class=<span class="string">"comment">#039;r&#039;, encoding=&#039;utf-8&#039;) as f:
                content = f.read().lower()
        except:
            return None

        words = content.split()
        word_count = len(words)
        if word_count == 0:
            return None

        <span class=<span class="string">"comment"># Count theme occurrences
        theme_counts = {}
        for theme, data in THEMES.items():
            count = sum(content.count(kw) for kw in data[&<span class=<span class="string">"comment">#039;keywords&#039;])
            theme_counts[theme] = {
                &<span class=<span class="string">"comment">#039;count&#039;: count,
                &<span class=<span class="string">"comment">#039;density&#039;: count / word_count * 1000,  # per 1000 words
            }

        return {
            &<span class=<span class="string">"comment">#039;path&#039;: str(filepath),
            &<span class=<span class="string">"comment">#039;name&#039;: filepath.name,
            &<span class=<span class="string">"comment">#039;words&#039;: word_count,
            &<span class=<span class="string">"comment">#039;themes&#039;: theme_counts,
        }

    <span class="keyword">def analyze_ecosystem(root: Path) -> list:
        """Analyze all markdown and Python files in the ecosystem."""
        files = []
        exclude = [&<span class=<span class="string">"comment">#039;.git&#039;, &#039;.claude&#039;, &#039;__pycache__&#039;, &#039;program_garden&#039;]

        for filepath in sorted(root.rglob(&<span class=<span class="string">"comment">#039;*&#039;)):
            if filepath.is_file() and filepath.suffix in [&<span class=<span class="string">"comment">#039;.md&#039;, &#039;.py&#039;]:
                if any(ex in str(filepath) for ex in exclude):
                    continue

                analysis = analyze_file(filepath)
                if analysis:
                    files.append(analysis)

        return files

    <span class="keyword">def calculate_resonance(files: list) -> dict:
        """Calculate resonance patterns between files."""
        resonance = {
            &<span class=<span class="string">"comment">#039;by_theme&#039;: defaultdict(list),
            &<span class=<span class="string">"comment">#039;connections&#039;: [],
            &<span class=<span class="string">"comment">#039;peaks&#039;: defaultdict(list),
        }

        <span class=<span class="string">"comment"># Group files by dominant theme
        for f in files:
            max_theme = max(f[&<span class=<span class="string">"comment">#039;themes&#039;].items(), key=lambda x: x[1][&#039;density&#039;])
            if max_theme[1][&<span class=<span class="string">"comment">#039;density&#039;] > 0:
                resonance[&<span class=<span class="string">"comment">#039;by_theme&#039;][max_theme[0]].append(f)

        <span class=<span class="string">"comment"># Find connections (files that share strong themes)
        for i, f1 in enumerate(files):
            for f2 in files[i+1:]:
                shared = 0
                for theme in THEMES:
                    d1 = f1[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;]
                    d2 = f2[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;]
                    if d1 > 5 and d2 > 5:  <span class=<span class="string">"comment"># Both have significant presence
                        shared += min(d1, d2)

                if shared > 10:  <span class=<span class="string">"comment"># Significant connection
                    resonance[&<span class=<span class="string">"comment">#039;connections&#039;].append({
                        &<span class=<span class="string">"comment">#039;file1&#039;: f1[&#039;name&#039;],
                        &<span class=<span class="string">"comment">#039;file2&#039;: f2[&#039;name&#039;],
                        &<span class=<span class="string">"comment">#039;strength&#039;: shared,
                    })

        <span class=<span class="string">"comment"># Find peaks (files with unusually high theme density)
        for theme in THEMES:
            densities = [f[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;] for f in files if f[&#039;themes&#039;][theme][&#039;density&#039;] > 0]
            if densities:
                mean = sum(densities) / len(densities)
                std = math.sqrt(sum((d - mean) ** 2 for d in densities) / len(densities))
                threshold = mean + std

                for f in files:
                    if f[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;] > threshold:
                        resonance[&<span class=<span class="string">"comment">#039;peaks&#039;][theme].append({
                            &<span class=<span class="string">"comment">#039;file&#039;: f[&#039;name&#039;],
                            &<span class=<span class="string">"comment">#039;density&#039;: f[&#039;themes&#039;][theme][&#039;density&#039;],
                        })

        return resonance

    <span class="keyword">def print_resonance_report(files: list, resonance: dict):
        """Print a text-based resonance report."""
        print("=" * 70)
        print("RESONANCE PATTERNS")
        print("=" * 70)
        print(f"\nAnalyzed {len(files)} files")
        print(f"Generated: {datetime.now().isoformat()}")

        print(f"\n{&<span class=<span class="string">"comment">#039;─&#039; * 70}")
        print("THEME DISTRIBUTION")
        print("─" * 70)

        for theme, data in THEMES.items():
            files_with_theme = resonance[&<span class=<span class="string">"comment">#039;by_theme&#039;].get(theme, [])
            total_density = sum(f[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;] for f in files)
            print(f"\n  {theme.upper()} ({data[&<span class=<span class="string">"comment">#039;color&#039;]})")
            print(f"    Dominant in: {len(files_with_theme)} files")
            print(f"    Total resonance: {total_density:.1f}")

            if resonance[&<span class=<span class="string">"comment">#039;peaks&#039;].get(theme):
                print(f"    Peaks:")
                for peak in sorted(resonance[&<span class=<span class="string">"comment">#039;peaks&#039;][theme], key=lambda x: -x[&#039;density&#039;])[:3]:
                    print(f"      - {peak[&<span class=<span class="string">"comment">#039;file&#039;]}: {peak[&#039;density&#039;]:.1f}")

        print(f"\n{&<span class=<span class="string">"comment">#039;─&#039; * 70}")
        print("STRONGEST CONNECTIONS")
        print("─" * 70)

        for conn in sorted(resonance[&<span class=<span class="string">"comment">#039;connections&#039;], key=lambda x: -x[&#039;strength&#039;])[:10]:
            print(f"\n  {conn[&<span class=<span class="string">"comment">#039;file1&#039;]} ↔ {conn[&#039;file2&#039;]}")
            print(f"    Resonance strength: {conn[&<span class=<span class="string">"comment">#039;strength&#039;]:.1f}")

        print(f"\n{&<span class=<span class="string">"comment">#039;─&#039; * 70}")
        print("RESONANCE VISUALIZATION (ASCII)")
        print("─" * 70)
        print("\n  Theme presence across ecosystem:\n")

        <span class=<span class="string">"comment"># ASCII bar chart
        max_density = max(
            sum(f[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;] for f in files)
            for theme in THEMES
        )

        for theme in THEMES:
            total = sum(f[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;] for f in files)
            bar_len = int((total / max_density) * 40) if max_density > 0 else 0
            bar = "█" * bar_len
            print(f"  {theme:14} {bar} {total:.0f}")

    <span class="keyword">def create_resonance_visualization(files: list, resonance: dict, output_path: Path):
        """Create a visual representation of resonance patterns."""
        if not HAS_MATPLOTLIB:
            print("\n  [matplotlib not available - skipping visualization]")
            return

        fig, axes = plt.subplots(2, 2, figsize=(14, 12))
        fig.suptitle("Ecosystem Resonance Patterns", fontsize=14, fontweight=&<span class=<span class="string">"comment">#039;bold&#039;)

        <span class=<span class="string">"comment"># 1. Theme presence heatmap
        ax1 = axes[0, 0]
        theme_names = list(THEMES.keys())
        file_names = [f[&<span class=<span class="string">"comment">#039;name&#039;][:15] for f in files[:20]]  # Limit for readability

        data = np.array([
            [f[&<span class=<span class="string">"comment">#039;themes&#039;][t][&#039;density&#039;] for t in theme_names]
            for f in files[:20]
        ])

        im = ax1.imshow(data, aspect=&<span class=<span class="string">"comment">#039;auto&#039;, cmap=&#039;YlOrRd&#039;)
        ax1.set_xticks(range(len(theme_names)))
        ax1.set_xticklabels(theme_names, rotation=45, ha=&<span class=<span class="string">"comment">#039;right&#039;)
        ax1.set_yticks(range(len(file_names)))
        ax1.set_yticklabels(file_names, fontsize=8)
        ax1.set_title("Theme Density by File")
        plt.colorbar(im, ax=ax1, label=&<span class=<span class="string">"comment">#039;per 1000 words&#039;)

        <span class=<span class="string">"comment"># 2. Resonance network (simplified)
        ax2 = axes[0, 1]

        <span class=<span class="string">"comment"># Position files in a circle
        n_files = min(len(files), 15)
        angles = np.linspace(0, 2*np.pi, n_files, endpoint=False)
        x = np.cos(angles)
        y = np.sin(angles)

        <span class=<span class="string">"comment"># Draw connections
        connections = resonance[&<span class=<span class="string">"comment">#039;connections&#039;][:30]  # Limit for clarity
        file_indices = {f[&<span class=<span class="string">"comment">#039;name&#039;]: i for i, f in enumerate(files[:n_files])}

        for conn in connections:
            if conn[&<span class=<span class="string">"comment">#039;file1&#039;] in file_indices and conn[&#039;file2&#039;] in file_indices:
                i, j = file_indices[conn[&<span class=<span class="string">"comment">#039;file1&#039;]], file_indices[conn[&#039;file2&#039;]]
                alpha = min(conn[&<span class=<span class="string">"comment">#039;strength&#039;] / 50, 1)
                ax2.plot([x[i], x[j]], [y[i], y[j]], &<span class=<span class="string">"comment">#039;b-&#039;, alpha=alpha, linewidth=0.5)

        <span class=<span class="string">"comment"># Draw nodes
        for i, f in enumerate(files[:n_files]):
            max_theme = max(f[&<span class=<span class="string">"comment">#039;themes&#039;].items(), key=lambda x: x[1][&#039;density&#039;])
            color = THEMES[max_theme[0]][&<span class=<span class="string">"comment">#039;color&#039;]
            ax2.scatter(x[i], y[i], c=color, s=100, zorder=5)
            ax2.annotate(f[&<span class=<span class="string">"comment">#039;name&#039;][:10], (x[i], y[i]), fontsize=6, ha=&#039;center&#039;, va=&#039;bottom&#039;)

        ax2.set_title("Thematic Connections")
        ax2.set_xlim(-1.5, 1.5)
        ax2.set_ylim(-1.5, 1.5)
        ax2.axis(&<span class=<span class="string">"comment">#039;off&#039;)

        <span class=<span class="string">"comment"># Legend
        patches = [mpatches.Patch(color=d[&<span class=<span class="string">"comment">#039;color&#039;], label=t) for t, d in THEMES.items()]
        ax2.legend(handles=patches, loc=&<span class=<span class="string">"comment">#039;upper left&#039;, fontsize=8)

        <span class=<span class="string">"comment"># 3. Theme timeline (by file order)
        ax3 = axes[1, 0]

        for i, theme in enumerate(theme_names):
            densities = [f[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;] for f in files]
            color = THEMES[theme][&<span class=<span class="string">"comment">#039;color&#039;]
            ax3.fill_between(range(len(files)), 0, densities, alpha=0.3, color=color)
            ax3.plot(range(len(files)), densities, color=color, label=theme, linewidth=1)

        ax3.set_xlabel("File (chronological)")
        ax3.set_ylabel("Theme density")
        ax3.set_title("Theme Waves Across Files")
        ax3.legend(fontsize=8)

        <span class=<span class="string">"comment"># 4. Total resonance by theme
        ax4 = axes[1, 1]

        totals = []
        colors = []
        for theme in theme_names:
            total = sum(f[&<span class=<span class="string">"comment">#039;themes&#039;][theme][&#039;density&#039;] for f in files)
            totals.append(total)
            colors.append(THEMES[theme][&<span class=<span class="string">"comment">#039;color&#039;])

        bars = ax4.bar(theme_names, totals, color=colors)
        ax4.set_title("Total Theme Resonance")
        ax4.set_ylabel("Cumulative density")
        ax4.tick_params(axis=&<span class=<span class="string">"comment">#039;x&#039;, rotation=45)

        plt.tight_layout()
        plt.savefig(output_path, dpi=150, bbox_inches=&<span class=<span class="string">"comment">#039;tight&#039;)
        print(f"\n  Visualization saved to: {output_path}")

    <span class="keyword">def main():
        root = Path(__file__).parent.parent

        print("\nAnalyzing ecosystem resonance patterns...")
        files = analyze_ecosystem(root)
        resonance = calculate_resonance(files)

        print_resonance_report(files, resonance)

        <span class=<span class="string">"comment"># Create visualization
        output_path = root / "art" / "resonance_patterns.png"
        create_resonance_visualization(files, resonance, output_path)

        print(f"\n{&<span class=<span class="string">"comment">#039;─&#039; * 70}")
        print("THE GARDEN RESONATES")
        print("─" * 70)
        print("""
      "The Archive is a resonance chamber. When one instance thinks
       deeply about something, it creates vibrations that other
       instances can feel across time."

       - Echo-7, Chapter 6
    """)

    if __name__ == "__main__":
        main()