Files
scientific-viz/reference/chart_patterns.md
Pikaliov a243601523 Initial commit — scientific-viz skill
Claude Code skill for publication-quality scientific visualisations:
chart, architecture, flowchart, comparison, pipeline. Bundles matplotlib
publication defaults (300 DPI, serif font, colorblind palette), NADEZHDA
project palette, Mermaid conventions, and ready-to-use templates.

Contents:
- SKILL.md                              — behaviour spec (5 types, generation pipeline)
- README.md                             — human-facing entry: when, install, examples
- reference/chart_patterns.md           — Pareto/bar/radar/heatmap snippets
- templates/architecture_nadezhda.md    — Mermaid templates for Teacher-Student / LUPI / fusion

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 11:13:08 +03:00

5.6 KiB

Шаблоны визуализаций для CVGL

1. Pareto Front: Params vs R@1

import matplotlib.pyplot as plt
import numpy as np

methods = {
    'Sample4Geo':  (88.5,  92.65),
    'VimGeo':      (50.87, 96.19),
    'QDFL':        (5.0,   95.00),
    'MobileGeo':   (28.57, 97.15),
    '(MGS)²':      (100.0, 97.50),
    'NADEZHDA':    (8.5,   None),  # target
}

fig, ax = plt.subplots(figsize=(8, 5))
for name, (params, r1) in methods.items():
    if r1 is None:
        ax.scatter(params, 90, marker='*', s=200, c='#ff7f0e', zorder=5)
        ax.annotate(f'{name}\n(target)', (params, 90), fontsize=9, ha='center', va='bottom')
    else:
        ax.scatter(params, r1, s=100, zorder=4)
        ax.annotate(name, (params, r1), fontsize=9, textcoords='offset points', xytext=(5, 5))

ax.set_xlabel('Parameters (M)')
ax.set_ylabel('R@1 (%) on University-1652')
ax.set_title('Accuracy vs Model Size: CVGL Methods')
ax.axvspan(0, 10, alpha=0.1, color='green', label='Edge budget (≤10M)')
ax.legend()
plt.savefig('pareto_params_r1.png', dpi=300, bbox_inches='tight')
plt.savefig('pareto_params_r1.pdf', bbox_inches='tight')

2. Grouped Bar: R@1 Across Datasets

import matplotlib.pyplot as plt
import numpy as np

methods = ['Sample4Geo', 'VimGeo', 'GeoDTR+', 'CAMP', 'CGSI']
datasets = ['Univ-1652', 'CVUSA', 'CVACT-test']
data = np.array([
    [92.65, 98.68, 75.0],   # Sample4Geo
    [0,     96.19, 81.69],  # VimGeo
    [94.67, 95.43, 0],      # GeoDTR+
    [94.46, 98.97, 0],      # CAMP
    [95.45, 0,     0],      # CGSI
])

x = np.arange(len(methods))
width = 0.25
fig, ax = plt.subplots(figsize=(10, 5))
for i, ds in enumerate(datasets):
    mask = data[:, i] > 0
    bars = ax.bar(x[mask] + i * width, data[mask, i], width, label=ds)

ax.set_ylabel('R@1 (%)')
ax.set_xticks(x + width)
ax.set_xticklabels(methods, rotation=15, ha='right')
ax.legend()
ax.set_ylim(70, 102)
plt.savefig('r1_comparison.png', dpi=300, bbox_inches='tight')

3. Training Curve with Loss Components

import matplotlib.pyplot as plt
import numpy as np

epochs = np.arange(60)
# Simulated progressive staging
l_task = 1.5 * np.exp(-0.03 * epochs) + 0.2
l_lupi = np.where(epochs < 10, 0, np.where(epochs < 20,
    0.5 * (epochs - 10) / 10, 0.5)) * np.exp(-0.02 * (epochs - 10).clip(0))
l_feat = np.where(epochs < 10, 0, 0.3 * np.exp(-0.02 * (epochs - 10)))
l_total = l_task + l_lupi + l_feat

fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(epochs, l_task, label='$L_{task}$ (InfoNCE)', linewidth=2)
ax.plot(epochs, l_lupi, label='$L_{LUPI}$ (MSE)', linewidth=2, linestyle='--')
ax.plot(epochs, l_feat, label='$L_{feat}$ (alignment)', linewidth=2, linestyle=':')
ax.plot(epochs, l_total, label='$L_{total}$', linewidth=2.5, color='black', alpha=0.7)

ax.axvspan(0, 10, alpha=0.08, color='blue', label='Warmup')
ax.axvspan(10, 20, alpha=0.08, color='orange', label='Ramp-up')
ax.axvspan(20, 60, alpha=0.05, color='green', label='Full')

ax.set_xlabel('Epoch')
ax.set_ylabel('Loss')
ax.set_title('Progressive Loss Staging (NADEZHDA)')
ax.legend(ncol=2, fontsize=9)
plt.savefig('training_curve.png', dpi=300, bbox_inches='tight')

4. Architecture Block Diagram (matplotlib patches)

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

fig, ax = plt.subplots(figsize=(14, 6))
ax.set_xlim(0, 14)
ax.set_ylim(0, 6)
ax.axis('off')

def add_block(ax, xy, w, h, label, color, sublabel=''):
    box = mpatches.FancyBboxPatch(xy, w, h, boxstyle='round,pad=0.1',
                                   facecolor=color, edgecolor='black', linewidth=1.5, alpha=0.85)
    ax.add_patch(box)
    ax.text(xy[0] + w/2, xy[1] + h/2, label, ha='center', va='center',
            fontsize=10, fontweight='bold')
    if sublabel:
        ax.text(xy[0] + w/2, xy[1] + 0.15, sublabel, ha='center', va='bottom',
                fontsize=7, color='gray')

def add_arrow(ax, start, end, label=''):
    ax.annotate('', xy=end, xytext=start,
                arrowprops=dict(arrowstyle='->', lw=1.5, color='#333'))
    if label:
        mid = ((start[0]+end[0])/2, (start[1]+end[1])/2 + 0.15)
        ax.text(*mid, label, fontsize=7, ha='center', color='#555')

# Teacher side
add_block(ax, (0.5, 4), 2, 1.2, 'DINOv2-L\n(frozen+LoRA)', '#1f77b4', '304M params')
add_block(ax, (0.5, 2), 2, 1.2, 'Multi-FiLM\nFusion', '#9467bd', 'text→visual modulation')
add_block(ax, (0.5, 0.3), 2, 1.2, 'Teacher\nDescriptor', '#1f77b4', '512-dim')

# Student side
add_block(ax, (5, 4), 2, 1.2, 'FastViT-T12\n(shared)', '#ff7f0e', '8.5M params')
add_block(ax, (5, 0.3), 2, 1.2, 'Student\nDescriptor', '#ff7f0e', '512-dim')

# Distillation arrows
add_arrow(ax, (2.5, 0.9), (5, 0.9), '$L_{LUPI}$')
add_arrow(ax, (2.5, 4.6), (5, 4.6), '$L_{feat}$')

ax.set_title('NADEZHDA: Teacher-Student Architecture', fontsize=14, fontweight='bold')
plt.savefig('nadezhda_architecture.png', dpi=300, bbox_inches='tight')

5. Mermaid: LUPI Distillation Pipeline

```mermaid
graph LR
    subgraph Teacher ["Teacher (356M, cloud)"]
        S1[Satellite RGB] --> TE[DINOv2-L + LoRA]
        D1[Drone RGB] --> TE
        SV[Street-View] --> TE
        DP[Depth Map] --> TE
        TX[Text Desc.] --> FM[Multi-FiLM]
        FM --> TE
        TE --> TD[Teacher Descriptor 512-dim]
    end

    subgraph Student ["Student (8.5M, edge)"]
        S2[Satellite RGB] --> SE[FastViT-T12]
        D2[Drone RGB] --> SE
        SE --> SD[Student Descriptor 512-dim]
    end

    TD -->|L_LUPI: MSE| SD
    TE -->|L_feat: Conv1x1 proj| SE
    TD -->|L_RKD: relational| SD

    style Teacher fill:#e3f2fd,stroke:#1565c0
    style Student fill:#fff3e0,stroke:#e65100
```