Skip to content
Skills Library
Science & research · Building & coding

visual-engineer

/visual-engineer

Academic-quality visualization for MCM/ICM competitions. Use when creating figures for papers requiring publication-standard formatting (Times New Roman, 300 DPI, proper colormaps, clean layouts). Automatically saves to organized results directory. Essential for O-prize presentation quality.

Licence
MIT
Last repository change
27.06.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 27.06.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Academic-quality visualization for MCM/ICM competitions. Use when creating figures for papers requiring publication-standard formatting (Times New Roman, 300 DPI, proper colormaps, clean layouts). Automatically saves to organized results directory. Essential for O-prize presentation quality.

Original author description

Academic-quality visualization for MCM/ICM competitions. Use when creating figures for papers requiring publication-standard formatting (Times New Roman, 300 DPI, proper colormaps, clean layouts). Automatically saves to organized results directory. Essential for O-prize presentation quality.

How it works

  1. Core Principles
  2. Standard Configuration
  3. Common Plot Types
  4. Color Schemes
  5. LaTeX Integration
  6. File Organization
  7. Quality Checklist
  8. Common Mistakes to Avoid
  9. Advanced: Animation
  10. Output Naming Convention
Original SKILL.md headings · 425 lines, 1,096 words
SKILL.md preview
---
name: visual-engineer
description: Academic-quality visualization for MCM/ICM competitions. Use when creating figures for papers requiring publication-standard formatting (Times New Roman, 300 DPI, proper colormaps, clean layouts). Automatically saves to organized results directory. Essential for O-prize presentation quality.
---

# Visual-Engineer

Create publication-quality figures that meet academic standards for mathematical modeling competitions.

## Core Principles

1. **Clarity over decoration**: Every element must serve a purpose
2. **Accessibility**: Colorblind-friendly palettes, readable fonts
3. **Consistency**: Same style across all figures
4. **Reproducibility**: All figures generated from code, not manual editing

## Standard Configuration

### Global Matplotlib Settings

```python
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# Set publication-quality defaults
plt.rcParams.update({
    # Font
    'font.family': 'serif',
    'font.serif': ['Times New Roman', 'DejaVu Serif'],
    'font.size': 11,
    'axes.titlesize': 14,
    'axes.labelsize': 12,
    'xtick.labelsize': 10,
    'ytick.labelsize': 10,
    'legend.fontsize': 10,
    
    # Figure
    'figure.figsize': (8, 6),
    'figure.dpi': 100,
    'savefig.dpi': 300,
    'savefig.bbox': 'tight',
    'savefig.pad_inches': 0.1,
    
    # Lines and markers
    'lines.linewidth': 2,
    'lines.markersize': 6,
    
    # Axes
    'axes.linewidth': 1.2,
    'axes.grid': True,
    'grid.alpha': 0.3,
    'grid.linestyle': '--',
    
    # Legend
    'legend.frameon': True,
    'legend.framealpha': 0.8,
    'legend.edgecolor': 'black',
    
    # Colors
    'axes.prop_cycle': plt.cycler('color', 
        ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', 
         '#9467bd', '#8c564b', '#e377c2', '#7f7f7f'])
})

# Seaborn style for cleaner look
sns.set_style("whitegrid")
sns.set_context("paper")
```

## Common Plot Types

### 1. Time Series Plot

```python
def plot_time_series(time, data, labels=None, title='Time Series', 
                     xlabel='Time', ylabel='Value', 
                     filename='results/time_series.png'):
    """
    Plot one or more time series
    
    Parameters:
    - time: 1D array of time points
    - data: 2D array (n_series, n_points) or 1D array
    - labels: List of series names
    """
    
    fig, ax = plt.subplots(figsize=(10, 6))
    
    # Handle single series
    if data.ndim == 1:
        data = data.reshape(1, -1)
        labels = [labels] if labels else ['Series']
    
    # Plot each series
    for i, series in enumerate(data):
        label = labels[i] if labels else f'Series {i+1}'
        ax.plot(time, series, linewidth=2, label=label, marker='o', 
                markersize=4, markevery=max(1, len(time)//20))
    
    ax.set_xlabel(xlabel, fontweight='bold')
    ax.set_ylabel(ylabel, fontweight='bold')
    ax.set_title(title, fontweight='bold', pad=15)
    ax.legend(loc='best', frameon=True)
    ax.grid(True, alpha=0.3, linestyle='--')
    
    plt.tight_layout()
    plt.savefig(filename, dpi=300, bbox_inches='tight')
    plt.close()
    
    print(f"Saved: {filename}")
```

### 2. Scatter Plot with Regression

```python
def plot_scatter_regression(x, y, title='Scatter Plot', 
                            xlabel='X', ylabel='Y',
                            filename='results/scatter.png'):
    """Scatter plot with regression line and statistics"""
    
    from scipy import stats
    
    fig, ax = plt.subplots(figsize=(8, 6))
    
    # Scatter
    ax.scatter(x, y, alpha=0.6, s=50, edgecolors='black', linewidth=0.5)
    
    # Regression line
    slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
    line_x = np.array([x.min(), x.max()])
    line_y = slope * line_x + intercept
    ax.plot(line_x, line_y, 'r-', linewidth=2, 
            label=f'y = {slope:.3f}x + {intercept:.3f}')
    
    # Statistics box
    textstr = f'R² = {r_value**2:.4f}\np-value = {p_value:.4e}'
    props = dict(boxstyle='round', facecolor='wheat', alpha=0.8)
    ax.text(0.05, 0.95, textstr, transform=ax.transAxes, 
            fontsize=10, verticalalignment='top', bbox=props)
    
    ax.set_xlabel(xlabel, fontweight='bold')
    ax.set_ylabel(ylabel, fontweight='bold')
    ax.set_title(title, fontweight='bold', pad=15)
    ax.legend(loc='lower right')
    ax.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig(filename, dpi=300)
    plt.close()
    
    print(f"Saved: {filename}")
```

### 3. Heatmap

```python
def plot_heatmap(data, row_labels=None, col_labels=None, 
                 title='Heatmap', cmap='viridis',
                 filename='results/heatmap.png'):
    """
    Create annotated heatmap
    
    Parameters:
    - data: 2D array
    - cmap: 'viridis', 'RdYlGn', 'coolwarm', 'Blues'
    """
    
    fig, ax = plt.subplots(figsize=(10, 8))
    
    im = ax.imshow(data, cmap=cmap, aspect='auto')
    
    # Colorbar
    cbar = plt.colorbar(im, ax=ax)
    cbar.ax.set_ylabel('Value', rotation=270, labelpad=20, fontweight='bold')
    
    # Ticks
    if row_labels is not None:
        ax.set_yticks(np.arange(len(row_labels)))
        ax.set_yticklabels(row_labels)
    if col_labels is not None:
        ax.set_xticks(np.arange(len(col_labels)))
        ax.set_xticklabels(col_labels, rotation=45, ha='right')
    
    # Annotations (for small matrices)
    if data.shape[0] <= 10 and data.shape[1] <= 10:
        for i in range(data.shape[0]):
            for j in range(data.shape[1]):
                text = ax.text(j, i, f'{data[i, j]:.2f}',
                             ha="center", va="center", color="white" 
                             if data[i, j] > data.max()/2 else "black")
    
    ax.set_title(title, fontweight='bold', pad=15)
    
    plt.tight_layout()
    plt.savefig(filename, dpi=300)
    plt.close()
    
    print(f"Saved: {filename}")
```

### 4. Bar Chart with Error Bars

```python
def plot_bar_chart(categories, values, errors=None, 
                   title='Bar Chart', ylabel='Value',
                   filename='results/bar_chart.png'):
    """Bar chart with optional error bars"""
    
    fig, ax = plt.subplots(figsize=(10, 6))
    
    x = np.arange(len(categories))
    bars = ax.bar(x, values, width=0.6, alpha=0.8, 
                  edgecolor='black', linewidth=1.2)
    
    # Error bars
    if errors is not None:
        ax.errorbar(x, values, yerr=errors, fmt='none', 
                   ecolor='black', capsize=5, capthick=2)
    
    # Value labels on bars
    for i, (bar, val) in enumerate(zip(bars, values)):
        height = bar.get_height()
        ax.text(bar.get_x() + bar.get_width()/2., height,
                f'{val:.2f}',
                ha='center', va='bottom', fontsize=9, fontweight='bold')
    
    ax.set_xticks(x)
    ax.set_xticklabels(categories, rotation=45, ha='right')
    ax.set_ylabel(ylabel, fontweight='bold')
    ax.set_title(title, fontweight='bold', pad=15)
    ax.grid(axis='y', alpha=0.3)
    
    plt.tight_layout()
    plt.savefig(filename, dpi=300)
    plt.close()
    
    print(f"Saved: {filename}")
```

### 5. Multi-Panel Figure

```python
def plot_multi_panel(data_dict, title='Multi-Panel Figure',
                     filename='results/multi_panel.png'):
    """
    Create figure with multiple subplots
    
    Parameters:
    - data_dict: {'subplot_title': (x, y), ...}
    """
    
    n_plots = len(data_dict)
    n_cols = min(2, n_plots)
    n_rows = (n_plots + n_cols - 1) // n_cols
    
    fig, axes = plt.subplots(n_rows, n_cols, figsize=(12, 4*n_rows))
    
    if n_plots == 1:
        axes = [axes]
    else:
        axes = axes.flatten()
    
    for ax, (subtitle, (x, y)) in zip(axes, data_dict.items()):
        ax.plot(x, y, linewidth=2, marker='o', markersize=4)
        ax.set_title(subtitle, fontweight='bold')
        ax.set_xlabel('X', fontweight='bold')
        ax.set_ylabel('Y', fontweight='bold')
        ax.grid(True, alpha=0.3)
    
    # Hide extra subplots
    for i in range(n_plots, len(axes)):
        axes[i].axis('off')
    
    fig.suptitle(title, fontsize=16, fontweight='bold', y=1.02)
    
    plt.tight_layout()
    plt.savefig(filename, dpi=300, bbox_inches='tight')
    plt.close()
    
    print(f"Saved: {filename}")
```

## Color Schemes

### Colorblind-Friendly Palettes

```python
# Sequential (for continuous data)
SEQUENTIAL = {
    'blue': 'Blues',
    'green': 'Greens',
    'orange': 'Oranges',
    'viridis': 'viridis',  # Perceptually uniform
    'plasma': 'plasma'
}

# Diverging (for data with meaningful center)
DIVERGING = {
    'red_blue': 'RdBu_r',
    'red_green': 'RdYlGn',
    'cool_warm': 'coolwarm'
}

# Qualitative (for categories)
QUALITATIVE = [
    '#1f77b4',  # Blue
    '#ff7f0e',  # Orange
    '#2ca02c',  # Green
    '#d62728',  # Red
    '#9467bd',  # Purple
    '#8c564b',  # Brown
    '#e377c2',  # Pink
    '#7f7f7f'   # Gray
]
```

## LaTeX Integration

### For LaTeX-rendered Text

```python
# Enable LaTeX rendering (requires LaTeX installation)
plt.rcParams.update({
    'text.usetex': True,
    'text.latex.preamble': r'\usepackage{amsmath}'
})

# Use in labels
ax.set_xlabel(r'$\alpha$ (growth rate)', fontsize=12)
ax.set_ylabel(r'$P(t)$ (population)', fontsize=12)
ax.set_title(r'Model: $\frac{dP}{dt} = \alpha P(1 - \frac{P}{K})$')
```

## File Organization

```python
import os

def ensure_results_dir():
    """Create organized results directory"""
    dirs = [
        'results/figures',
        'results/tables',
        'results/animations'
    ]
    for d in dirs:
        os.makedirs(d, exist_ok=True)

# Use at start of visualization script
ensure_results_dir()
```

## Quality Checklist

Before submitting figures:
- [ ] Font is Times New Roman or serif equivalent
- [ ] DPI is 300 or higher
- [ ] Axes are labeled with units
- [ ] Legend is present and clear
- [ ] Colors are colorblind-friendly
- [ ] Grid lines are subtle (alpha < 0.5)
- [ ] No unnecessary decorations (3D effects, shadows)
- [ ] File size is reasonable (< 5MB per figure)
- [ ] All text is readable when printed

## Common Mistakes to Avoid

1. **Rainbow colormap**: Use 'viridis' instead of 'jet'
2. **Tiny fonts**: Minimum 10pt for readability
3. **No labels**: Always label axes with units
4. **Too much data**: Simplify or use sampling
5. **3D when 2D works**: 3D plots are hard to read
6. **Pie charts**: Use bar charts instead
7. **Default colors**: Customize for consistency
8. **Low DPI**: Always save at 300 DPI minimum

## Advanced: Animation

```python
from matplotlib.animation import FuncAnimation

def create_animation(data_over_time, filename='results/animation.mp4'):
    """Create animation of time-evolving data"""
    
    fig, ax = plt.subplots(figsize=(8, 6))
    
    line, = ax.plot([], [], linewidth=2)
    ax.set_xlim(0, len(data_over_time[0]))
    ax.set_ylim(data_over_time.min(), data_over_time.max())
    
    def init():
        line.set_data([], [])
        return line,
    
    def update(frame):
        x = np.arange(len(data_over_time[frame]))
        y = data_over_time[frame]
        line.set_data(x, y)
        ax.set_title(f'Time Step: {frame}', fontweight='bold')
        return line,
    
    anim = FuncAnimation(fig, update, frames=len(data_over_time),
                        init_func=init, blit=True, interval=100)
    
    anim.save(filename, writer='ffmpeg', fps=10, dpi=150)
    plt.close()
    
    print(f"Saved animation: {filename}")
```

## Output Naming Convention

Use descriptive, systematic names:
```
results/figures/
├── fig1_time_series_population.png
├── fig2_heatmap_parameter_sweep.png
├── fig3_scatter_correlation.png
└── fig4_bar_comparison.png
```

Not:
```
plot.png
figure_final_v3_FINAL.png
untitled.png
```

Versions

RepositoryScoreLicence
This page · SPIRAL-EDWIN/MCM-ICM-2601000100MIT
tranhieutt/software_development_department100MIT

Database snapshot: 13.11.2026 · package version 5147d5acd379 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100mcm-o-guide
    MCM/ICM 优秀论文写作全流程指南——基于 502 篇历年获奖论文(2004–2024)语料库的结构化分析与评委点评提炼。覆盖:摘要逐句模板、6 类题型模型选择矩阵、25 页页预算分配、图表黄金法则、灵敏度/稳健性分析范式、全文一致性检查清单。当用户准备美赛、写论文、打磨论文、查结构、选模型、做摘要、看评委标准、读优秀论文时使用。也适用于任何需要高质量数学建模论文写作的场景。
  • 100mcm-master
    Full-stack autonomous math modeling agent for MCM/ICM (美国大学生数学建模竞赛). Handles team control number, problem choice (A–F), English academic writing, mcmthesis LaTeX template, and optional practical deliverable (memo/letter/report). Use when the user provides an MCM/ICM problem and…
  • 95pdf
    MCM/ICM PDF Processing & Submission Handler. Use when the team needs to: (1) Extract text, equations, or tables from academic papers (PDFs) during literature review, (2) Merge the final submission PDF with the Code Appendix, (3) Validate submission compliance (page limits,…
  • 95auto-mcm
    AutoMCM-Pro industrial-grade math modeling agent (opencode binding). Supports AP (AI-led) and Manual (human-spec-led) dual modes with mandatory GitOps checkpoints, forced self-verification of all solver code before LaTeX inclusion, and structured human cross-validation at each…
  • 100ez-math-model
    Use when solving CUMCM, MCM, ICM, or other mathematical modeling tasks that need contest problem intake, model selection, Python solving, figures, paper writing, quality audit, and packaged deliverables.
  • 95latex-transformer
    Convert Markdown content to LaTeX format for MCM/ICM paper writing. Use when drafting content in Markdown and need to convert to LaTeX with proper formatting (equations, tables, citations, figures). Handles three-line tables, equation environments, and bibliography integration.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.