Skill: stephenlzc/pythesis-plot (version 1.0.3)

--- name: pythesis-plot description: > Python scientific plotting tool for thesis/dissertation scenarios. Workflow: data upload → analysis → recommendations → confirmation → generation. Triggers when users upload data files (CSV/Excel/TXT) and ask for plots, charts, figures, or data visualization for academic publications. --- # PyThesisPlot Python scientific plotting workflow tool supporting the complete process from data upload to figure generation for academic publications. ## Workflow ``` [User Uploads Data] → [Auto-save to output dir] → [Data Analysis] ↓ [Generate Images to output dir] ← [Code Generation] ← [User Confirms Scheme] ``` ### Required Steps 1. **Data Reception**: User uploads data file (txt/md/xlsx/csv) 2. **Auto-save**: Rename to `timestamp-original_filename`, save to `output/YYYYMMDD-filename/` 3. **Data Analysis**: Analyze dimensions, types, statistical features, column relationships 4. **Chart Recommendations**: Recommend chart schemes based on data characteristics (type, quantity, layout) 5. **User Confirmation**: Display analysis report, **must wait for user confirmation before generation** 6. **Generation & Delivery**: Python code + chart images, save to same output directory ## Core Scripts ### 1. Main Workflow Script ```bash python scripts/workflow.py --input data.csv --output-dir output/ ``` ### 2. Data Analysis ```bash python scripts/data_analyzer.py --input data.csv ``` Output: Data characteristics report + chart recommendation scheme ### 3. Chart Generation ```bash python scripts/plot_generator.py --config plot_config.json --output-dir output/ ``` ## File Management Standards ### Directory Structure ``` output/ └── 20250312-145230-data.csv/ # Named with timestamp + filename ├── 20250312-145230-data.csv # Original data file (renamed) ├── analysis_report.md # Data analysis report ├── plot_config.json # Chart configuration (generated after user confirmation) ├── 20250312-145230_plot.py # Generated Python code ├── 20250312-145230_fig1_line.png # Chart (PNG image) └── 20250312-145230_fig2_bar.png ``` ### Naming Conventions | File Type | Naming Format | Example | |---------|---------|------| | Data File | `{timestamp}-{original}` | `20250312-145230-data.csv` | | Analysis Report | `analysis_report.md` | `analysis_report.md` | | Python Code | `{timestamp}_plot.py` | `20250312-145230_plot.py` | | Chart PNG | `{timestamp}_fig{n}_{type}.png` | `20250312-145230_fig1_line.png` | ## Usage ### Scenario 1: Complete Workflow When user uploads a data file: 1. **Auto-save File** ```python # Rename and save to output/{timestamp}-{filename}/ save_uploaded_file(input_file, output_base="output/") ``` 2. **Execute Data Analysis** ```python # Analyze data characteristics, generate report python scripts/data_analyzer.py --input output/20250312-data/data.csv ``` 3. **Display Analysis Report to User** ```markdown ## Data Analysis Report ### Data Overview - File: data.csv - Dimensions: 120 rows × 5 columns - Types: 3 numeric + 2 categorical columns ### Column Details | Column | Type | Description | |-----|------|-----| | date | datetime | 2023-01 to 2023-12 | | sales | numeric | mean=1250, std=320 | | region | categorical | 4 categories: N/S/E/W | ### Chart Recommendations Based on data characteristics, the following schemes are recommended: **Scheme 1: Time Trend Analysis** ⭐Recommended - Chart Type: Line plot - Content: Sales trend over time - Reason: Time series data, most intuitive for showing trends **Scheme 2: Regional Comparison** - Chart Type: Grouped bar chart - Content: Sales comparison across regions - Reason: Categorical comparison, suitable for showing differences **Scheme 3: Comprehensive Dashboard** - Chart Type: 2×2 subplot layout - Includes: Trend line + Bar chart + Box plot + Correlation heatmap - Reason: Rich data dimensions, comprehensive display Please tell me what you want: - "Generate schemes 1 and 2" - "Generate all" - "Modify scheme 3..." (provide your modification suggestions) ``` 4. **Wait for User Confirmation** ⚠️ **Critical Step** - User may say: "Generate scheme 1" / "Generate all" / "Modify XX..." - **Must wait for explicit instruction before entering generation phase** 5. **Generate and Save** ```python # Generate Python code python scripts/plot_generator.py --config plot_config.json # Output to same directory output/20250312-data/ ├── 20250312-145230_plot.py # Code ├── 20250312-145230_fig1_line.png # Chart └── 20250312-145230_fig2_bar.png ``` ### Scenario 2: Data Analysis Only ```bash python scripts/data_analyzer.py --input data.csv --output report.md ``` ### Scenario 3: Generate from Config ```bash python scripts/plot_generator.py --config config.json --output-dir ./ ``` ## Chart Recommendation Logic | Data Characteristics | Recommended Chart | Application | |---------|---------|---------| | Time series + Numeric | Line plot | Trend display | | Categorical + Single numeric | Bar chart | Category comparison | | Categorical + Distribution | Box/Violin plot | Distribution display | | Two numeric (correlated) | Scatter (+regression) | Correlation analysis | | Multiple numeric (correlated) | Heatmap | Correlation matrix | | Single numeric distribution | Histogram/Density | Distribution characteristics | | Multi-dimensional rich data | 2×2 subplots | Comprehensive display | ## Supported File Formats - **CSV**: `.csv` (Recommended) - **Excel**: `.xlsx`, `.xls` - **Text**: `.txt`, `.md` (table format) ## Dependencies ``` pandas >= 1.3.0 matplotlib >= 3.5.0 seaborn >= 0.11.0 openpyxl >= 3.0.0 # Excel support numpy >= 1.20.0 scipy >= 1.7.0 ``` ## Reference Documents - [Workflow Guide](references/workflow_guide.md) - Complete workflow instructions - [Chart Types](references/chart_types.md) - Detailed chart type descriptions - [Style Guide](references/style_guide.md) - Color schemes, fonts, size standards - [Examples](references/examples.md) - Complete code examples ## Important Notes 1. **User confirmation is mandatory**: Must wait for user confirmation after analysis, cannot generate directly 2. **Unified file management**: All output files saved to same output/{timestamp}-{filename}/ directory 3. **High-resolution output**: Generate PNG at 300 DPI (suitable for publication) 4. **Code traceability**: Generated Python code also saved to same directory for user modification 5. **Academic style**: Charts follow top journal standards (Nature/Science/Lancet style)

path: README.md
content: # 📊 PyThesisPlot

> **Scientific Plotting Skill for Claude Code** — Transform raw data into publication-ready figures with Nature/Science quality standards.

[![Python 3.8+](https://img.shields.io/badge/Python-3.8+-blue.svg)](https://python.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![Release](https://img.shields.io/github/v/release/stephenlzc/pythesis-plot)](https://github.com/stephenlzc/pythesis-plot/releases)
[![中文](https://img.shields.io/badge/中文-README-red.svg)](README.zh-CN.md)

---

## 🎯 What is PyThesisPlot?

PyThesisPlot is a **Claude Code Skill** that teaches AI assistants how to create publication-quality scientific figures from raw data. It provides:

- 📊 **Intelligent Workflow**: Data → Analysis → Recommendations → Confirmation → Figures
- 🎨 **Journal-Ready Output**: 300 DPI, Nature/Science style compliance
- 🔬 **Multi-Domain Support**: Biology, Psychology, Economics, Chemistry
- 📁 **Organized Output**: Timestamped directories with reproducible code

**Trigger**: When you upload data files (CSV/Excel/TXT) and ask for plots, charts, or figures.

---

## 📦 Installation

### For Humans

Copy and paste this to your AI assistant (Claude Code, Cursor, etc.):

```
Install PyThesisPlot skill for me:
https://github.com/stephenlzc/pythesis-plot
```

Or if you enjoy YAML-induced headaches, read the [Installation Guide](docs/installation.md). But seriously, let the agent handle it. Humans copy-paste paths wrong.

### For LLM Agents

```bash
git clone https://github.com/stephenlzc/pythesis-plot.git ~/.claude/skills/pythesis-plot
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

**Full instructions**: [docs/installation.md](docs/installation.md)

---

## 🚀 Skip This README

We're past the era of manual plotting. Just paste this into your agent:

```
I have some data and need publication-ready figures for my thesis. 
Use PyThesisPlot skill to help me:
https://github.com/stephenlzc/pythesis-plot
```

---

## 🚀 Quick Start

Once installed, simply upload your data and ask:

> "**Help me create some charts for my thesis**"

> "**Plot this data for my scientific paper**"

> "**Generate publication-ready figures from this Excel file**"

The skill will automatically:
1. **Analyze** your data structure and types
2. **Recommend** appropriate chart types
3. **Wait for your confirmation** on chart selection
4. **Generate** 300 DPI PNG figures + reproducible Python code

---

## 📋 Skill Structure

```
pythesis-plot/
├── SKILL.md                          # Skill definition (trigger conditions)
├── README.md                         # This file
├── README.zh-CN.md                   # Chinese documentation
├── scripts/
│   ├── workflow.py                   # Main orchestrator
│   ├── data_analyzer.py              # Data analysis engine
│   └── plot_generator.py             # Figure generation engine
├── references/
│   ├── workflow_guide.md             # Workflow documentation
│   ├── chart_types.md                # Chart selection guide
│   ├── style_guide.md                # Visual standards
│   └── examples.md                   # Code examples
└── assets/themes/
    ├── academic.mplstyle             # Academic journal style
    ├── nature.mplstyle               # Nature journal style
    └── presentation.mplstyle         # Presentation style
```

---

## 🎨 Supported Chart Types

| Chart Type | Best For | Example Use Case |
|:----------:|:---------|:-----------------|
| 📈 Line Plot | Time series, Trends | Gene expression over time |
| 📊 Bar Chart | Group comparisons | Treatment vs Control |
| 🎯 Box Plot | Distribution, Outliers | qPCR Ct values |
| ⚡ Scatter + Regression | Correlations | Dose-response relationships |
| 🔥 Heatmap | Correlation matrices | Multi-gene expression |
| 📋 Dashboard | Multi-panel figures | Complete study overview |

---

## 💡 Example Use Cases

### Example 1: Biomedical Research (qPCR Data)

```
User: "I have qPCR data for my PCOS study. Help me create figures."

AI: Analyzing Mouse_PCOS_BRAC1_RawData_108.xlsx...
    Detected: 108 samples, 3 groups, gene expression data
    
    Recommended Charts:
    1. Body weight comparison (bar chart)
    2. BRAC1 expression levels (log scale bar chart)
    3. qPCR Ct distributions (box plot)
    4. Comprehensive 2×2 dashboard

User: "Generate all of them"

AI: ✅ Generated 4 publication-ready figures in output/20250312-143052-PCOS/
```

### Example 2: Psychology RCT Study

```
User: "Plot my mental health intervention results"

AI: Analyzing Adolescent_Mental_Health_Intervention_1200.xlsx...
    Detected: 1200 participants, 4-arm RCT, pre/post measurements
    
    Recommended Charts:
    1. CONSORT-style study flow
    2. SDQ pre/post comparison
    3. Responder analysis (stacked bar)
    4. Effect size forest plot

User: "Generate schemes 1, 2, and 3"

AI: ✅ Generated 3 figures with statistical annotations
```

---

## ⚙️ How It Works

### 1. Skill Trigger

The skill activates when the YAML `description` in `SKILL.md` matches your request:

```yaml
---
name: pythesis-plot
description: Python scientific plotting tool... 
  Triggers when users upload data files (txt/md/excel/csv) 
  and mention "help me plot", "create chart", "data visualization", 
  "thesis figure", "scientific plotting"...
---
```

### 2. Workflow Stages

```
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Data Upload │────▶│  Analysis   │────▶│Recommendations│
└─────────────┘     └─────────────┘     └──────┬──────┘
                                                │
                                                ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Delivery  │◀────│ Generation  │◀────│Confirmation │
│  (PNG+Code) │     │             │     │  (Required) │
└─────────────┘     └─────────────┘     └─────────────┘
```

### 3. Output Organization

All outputs saved to timestamped directory:

```
output/
└── 20250312-143052-your-data/
    ├── 20250312-143052-your-data.csv    # Original data (renamed)
    ├── analysis_report.md               # Data analysis report
    ├── plot_config.json                 # Chart configuration
    ├── 20250312-143052_plot.py          # Reproducible Python code
    └── *.png                            # 300 DPI figures
```

---

## 📖 Documentation

- **[Workflow Guide](references/workflow_guide.md)** — Complete workflow walkthrough
- **[Chart Types](references/chart_types.md)** — When to use which chart
- **[Style Guide](references/style_guide.md)** — Color schemes and visual standards
- **[Examples](references/examples.md)** — Code examples and tutorials

---

## 🔧 Dependencies

```bash
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

---

## 🤝 Contributing

Contributions welcome! This skill follows the standard SKILL.md format:

1. **Fork** this repository
2. **Modify** SKILL.md or add new chart types
3. **Test** with sample data
4. **Submit** a Pull Request

### Skill Format

```yaml
---
name: pythesis-plot
description: | 
  Clear trigger conditions for when AI should load this skill.
  List specific phrases and contexts.
---

# Skill Body

## Quick Start
Brief instructions...

## Features
- Feature 1
- Feature 2
```

---

## 🌐 Languages

- **English**: [README.md](README.md) (this file)
- **中文**: [README.zh-CN.md](README.zh-CN.md)

---

## 📄 License

MIT License — see [LICENSE](LICENSE) for details.

---

## 🙏 Acknowledgments

- 🎨 Color palettes from [Nature](https://www.nature.com/) and [Science](https://www.science.org/) style guides
- 📊 Visualization practices from [Seaborn](https://seaborn.pydata.org/)
- 🎓 Academic standards from [Matplotlib](https://matplotlib.org/)

---

<div align="center">

**Made with ❤️ for Researchers**

[⬆ Back to Top](#-pythesisplot)

</div>


path: README.zh-CN.md
content: # 📊 PyThesisPlot

> **Claude Code 科研作图 Skill** — 将原始数据转化为符合 Nature/Science 标准的顶刊级图表。

[![Python 3.8+](https://img.shields.io/badge/Python-3.8+-blue.svg)](https://python.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![Release](https://img.shields.io/github/v/release/stephenlzc/pythesis-plot)](https://github.com/stephenlzc/pythesis-plot/releases)
[![English](https://img.shields.io/badge/English-README-red.svg)](README.md)

---

## 🎯 PyThesisPlot 是什么？

PyThesisPlot 是一个 **Claude Code Skill**，教会 AI 助手如何从原始数据创建顶刊级科研图表。它提供：

- 📊 **智能工作流**：数据 → 分析 → 推荐 → 确认 → 图表
- 🎨 **顶刊品质输出**：300 DPI，符合 Nature/Science 标准
- 🔬 **多领域支持**：生物、心理、经济、化学
- 📁 **规范输出**：带时间戳的目录 + 可复现代码

**触发条件**：当你上传数据文件（CSV/Excel/TXT）并请求作图时自动激活。

---

## 📦 安装

### 给人类用户

复制粘贴这段给你的 AI 助手（Claude Code、Cursor 等）：

```
帮我安装 PyThesisPlot skill：
https://github.com/stephenlzc/pythesis-plot
```

或者如果你喜欢被 YAML 折磨，阅读[安装指南](docs/installation.md)。但说真的，让 AI 去处理吧。人类总是会复制错路径。

### 给 AI 助手

```bash
git clone https://github.com/stephenlzc/pythesis-plot.git ~/.claude/skills/pythesis-plot
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

**完整说明**：[docs/installation.md](docs/installation.md)

---

## 🚀 跳过这篇 README

我们已经过了手动折腾图表的时代。直接粘贴这段给你的 AI：

```
我有一些数据，需要给论文生成顶刊级图表。
用 PyThesisPlot skill 帮我：
https://github.com/stephenlzc/pythesis-plot
```

---

## 🚀 快速开始

安装完成后，只需上传数据并询问：

> "**帮我为论文创建一些图表**"

> "**为我的科研论文绘制这些数据**"

> "**从这个 Excel 文件生成顶刊级图表**"

Skill 将自动：
1. **分析** 你的数据结构和类型
2. **推荐** 合适的图表类型
3. **等待你的确认** 选择图表方案
4. **生成** 300 DPI PNG 图表 + 可复现 Python 代码

---

## 📋 Skill 结构

```
pythesis-plot/
├── SKILL.md                          # Skill 定义（触发条件）
├── README.md                         # 英文文档
├── README.zh-CN.md                   # 本文档
├── scripts/
│   ├── workflow.py                   # 主编排器
│   ├── data_analyzer.py              # 数据分析引擎
│   └── plot_generator.py             # 图表生成引擎
├── references/
│   ├── workflow_guide.md             # 工作流文档
│   ├── chart_types.md                # 图表选择指南
│   ├── style_guide.md                # 视觉标准
│   └── examples.md                   # 代码示例
└── assets/themes/
    ├── academic.mplstyle             # 学术期刊风格
    ├── nature.mplstyle               # Nature 期刊风格
    └── presentation.mplstyle         # 演示汇报风格
```

---

## 🎨 支持的图表类型

| 图表类型 | 适用场景 | 示例 |
|:----------:|:---------|:-----------------|
| 📈 折线图 | 时间序列、趋势 | 基因表达随时间变化 |
| 📊 柱状图 | 分组对比 | 治疗组 vs 对照组 |
| 🎯 箱线图 | 分布、异常值 | qPCR Ct值分布 |
| ⚡ 散点+回归 | 相关性分析 | 剂量-效应关系 |
| 🔥 热力图 | 相关性矩阵 | 多基因表达相关性 |
| 📋 仪表盘 | 多子图组合 | 研究全貌展示 |

---

## 💡 应用示例

### 示例 1：生物医学研究（qPCR 数据）

```
用户："我有 PCOS 研究的 qPCR 数据，帮我创建图表"

AI: 分析 Mouse_PCOS_BRAC1_RawData_108.xlsx...
    检测到：108 样本，3 组，基因表达数据
    
    推荐图表：
    1. 体重对比（柱状图）
    2. BRAC1 表达量（对数刻度柱状图）
    3. qPCR Ct 分布（箱线图）
    4. 2×2 综合仪表盘

用户："全部生成"

AI: ✅ 已在 output/20250312-143052-PCOS/ 生成 4 张顶刊级图表
```

### 示例 2：心理学 RCT 研究

```
用户："绘制我的心理健康干预结果"

AI: 分析 Adolescent_Mental_Health_Intervention_1200.xlsx...
    检测到：1200 参与者，4 组 RCT，前后测数据
    
    推荐图表：
    1. CONSORT 风格研究流程
    2. SDQ 前后对比
    3. 响应者分析（堆叠柱状图）
    4. 效应量森林图

用户："生成方案 1、2、3"

AI: ✅ 已生成 3 张含统计显著性标注的图表
```

---

## ⚙️ 工作原理

### 1. Skill 触发

当你在 `SKILL.md` 中的 YAML `description` 匹配到请求时，skill 自动激活：

```yaml
---
name: pythesis-plot
description: | 
  Python 科研作图工具...
  当用户上传数据文件（txt/md/excel/csv）
  并提到"帮我作图"、"创建图表"、"数据可视化"、
  "论文图表"、"科研绘图"时触发...
---
```

### 2. 工作流阶段

```
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   数据上传   │────▶│    数据分析  │────▶│    图表推荐   │
└─────────────┘     └─────────────┘     └──────┬──────┘
                                                │
                                                ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   生成交付   │◀────│    图表生成  │◀────│   用户确认   │
│ (PNG+代码)  │     │             │     │   (必需)    │
└─────────────┘     └─────────────┘     └─────────────┘
```

### 3. 输出组织

所有输出保存到带时间戳的目录：

```
output/
└── 20250312-143052-your-data/
    ├── 20250312-143052-your-data.csv    # 原始数据（重命名）
    ├── analysis_report.md               # 数据分析报告
    ├── plot_config.json                 # 图表配置
    ├── 20250312-143052_plot.py          # 可复现 Python 代码
    └── *.png                            # 300 DPI 图表
```

---

## 📖 文档

- **[工作流程指南](references/workflow_guide.md)** — 完整工作流说明
- **[图表类型](references/chart_types.md)** — 何时使用何种图表
- **[样式规范](references/style_guide.md)** — 配色方案和视觉标准
- **[示例](references/examples.md)** — 代码示例和教程

---

## 🔧 依赖要求

```bash
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

---

## 🤝 贡献指南

欢迎贡献！本 skill 遵循标准 SKILL.md 格式：

1. **Fork** 本仓库
2. **修改** SKILL.md 或添加新图表类型
3. **测试** 使用样本数据
4. **提交** Pull Request

### Skill 格式

```yaml
---
name: pythesis-plot
description: | 
  清晰的触发条件，说明 AI 何时应加载此 skill。
  列出具体短语和上下文。
---

# Skill 正文

## 快速开始
简要说明...

## 功能
- 功能 1
- 功能 2
```

---

## 🌐 多语言

- **English**: [README.md](README.md)
- **中文**: [README.zh-CN.md](README.zh-CN.md)（本文档）

---

## 📄 开源协议

MIT 协议 — 详见 [LICENSE](LICENSE)

---

## 🙏 致谢

- 🎨 配色方案参考 [Nature](https://www.nature.com/) 和 [Science](https://www.science.org/) 风格指南
- 📊 可视化最佳实践来自 [Seaborn](https://seaborn.pydata.org/)
- 🎓 学术标准参考 [Matplotlib](https://matplotlib.org/)

---

<div align="center">

**用 ❤️ 为科研工作者打造**

[⬆ 返回顶部](#-pythesisplot)

</div>


path: docs/installation.md
content: # Installation Guide

> The complete guide for installing PyThesisPlot skill.
> 
> **For the impatient**: Just paste this to your AI assistant:
> ```
> Install PyThesisPlot: https://github.com/stephenlzc/pythesis-plot
> ```

---

## Table of Contents

- [For Humans](#for-humans)
- [For LLM Agents](#for-llm-agents)
- [Manual Installation](#manual-installation)
- [Verify Installation](#verify-installation)
- [Troubleshooting](#troubleshooting)

---

## For Humans

**The easy way**: Copy and paste this to your AI assistant (Claude Code, Cursor, etc.):

```
Install PyThesisPlot skill for me:
https://github.com/stephenlzc/pythesis-plot
```

That's it. Your AI will handle the rest.

**Why let the AI do it?** Because humans:
- Copy-paste paths wrong (`~/.claude` vs `~/.claude/`)
- Forget to install dependencies
- Misconfigure symlinks
- Fat-finger config files

Let the machines handle the machines. You focus on your research.

---

## For LLM Agents

If you're an LLM agent helping a user install PyThesisPlot, welcome! Follow these steps:

### Step 1: Clone Repository

```bash
git clone https://github.com/stephenlzc/pythesis-plot.git ~/.claude/skills/pythesis-plot
```

Or if user prefers a different location:

```bash
git clone https://github.com/stephenlzc/pythesis-plot.git /path/to/skills/pythesis-plot
```

### Step 2: Install Python Dependencies

```bash
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

**Optional but recommended**: Use a virtual environment

```bash
python -m venv ~/.claude/skills/pythesis-plot/.venv
source ~/.claude/skills/pythesis-plot/.venv/bin/activate
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

### Step 3: Verify Skill Structure

Ensure the skill is properly structured:

```
~/.claude/skills/pythesis-plot/
├── SKILL.md              ✓ Required
├── README.md             ✓ Documentation
├── scripts/
│   ├── workflow.py       ✓ Main orchestrator
│   ├── data_analyzer.py  ✓ Analysis engine
│   └── plot_generator.py ✓ Chart generator
└── assets/
    └── themes/           ✓ Style files
```

### Step 4: Confirm Installation

Tell the user:

> ✅ PyThesisPlot skill installed successfully!
> 
> You can now upload data files and ask me to create charts.
> 
> Try: "Help me create figures from this CSV file"

---

## Manual Installation

*For those who insist on doing it the hard way...*

### Prerequisites

- Python 3.8+
- pip
- Git

### Step-by-Step

```bash
# 1. Clone repository
git clone https://github.com/stephenlzc/pythesis-plot.git

# 2. Enter directory
cd pythesis-plot

# 3. Install dependencies
pip install pandas matplotlib seaborn openpyxl numpy scipy

# 4. Copy to Claude skills directory
cp -r . ~/.claude/skills/pythesis-plot

# Or use symlink (recommended for development)
ln -s $(pwd) ~/.claude/skills/pythesis-plot
```

### Alternative: User-specific installation

If you don't want to install to `~/.claude/skills/`, you can use a local path:

```bash
# Clone to your projects folder
git clone https://github.com/stephenlzc/pythesis-plot.git ~/projects/pythesis-plot

# Create symlink from Claude skills
ln -s ~/projects/pythesis-plot ~/.claude/skills/pythesis-plot
```

---

## Verify Installation

### Method 1: Upload Test Data

Upload any CSV/Excel file and ask:

> "Create some charts for my thesis"

The skill should auto-activate.

### Method 2: Check Skill Loading

In Claude Code, check if the skill is recognized:

```bash
ls ~/.claude/skills/pythesis-plot/SKILL.md
```

Should return the file path.

### Method 3: Test Dependencies

```bash
python -c "import pandas, matplotlib, seaborn, openpyxl, numpy, scipy; print('✓ All dependencies installed')"
```

---

## Troubleshooting

### Issue: "Module not found" errors

**Cause**: Dependencies not installed

**Fix**:
```bash
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

### Issue: Permission denied when copying to ~/.claude

**Cause**: Directory doesn't exist

**Fix**:
```bash
mkdir -p ~/.claude/skills
cp -r pythesis-plot ~/.claude/skills/
```

### Issue: Symlink not working

**Cause**: macOS/Linux differences

**Fix**: Use absolute paths
```bash
ln -s $(pwd)/pythesis-plot ~/.claude/skills/pythesis-plot
```

### Issue: Skill not auto-activating

**Cause**: SKILL.md not in expected location

**Fix**: Check structure
```bash
ls -la ~/.claude/skills/pythesis-plot/
# Should see: SKILL.md, README.md, scripts/, assets/
```

### Issue: Chinese characters not displaying

**Cause**: Font not configured

**Fix**: Install Chinese fonts (system-dependent)

**macOS**:
```bash
# Should work out of the box with system fonts
```

**Linux**:
```bash
sudo apt-get install fonts-wqy-zenhei  # Ubuntu/Debian
sudo yum install wqy-zenhei-fonts      # CentOS/RHEL
```

---

## For OpenCode Users

Installation is similar:

```bash
git clone https://github.com/stephenlzc/pythesis-plot.git ~/.opencode/skills/pythesis-plot
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

Or symlink for development:

```bash
ln -s $(pwd)/pythesis-plot ~/.opencode/skills/pythesis-plot
```

---

## For Other AI Assistants

Generic installation pattern:

```bash
# 1. Determine skill directory
SKILL_DIR="$HOME/.your-agent/skills"

# 2. Clone
git clone https://github.com/stephenlzc/pythesis-plot.git "$SKILL_DIR/pythesis-plot"

# 3. Install dependencies
pip install pandas matplotlib seaborn openpyxl numpy scipy
```

---

## Next Steps

After installation:

1. **Quick Test**: Upload a CSV and ask "Create charts for my paper"
2. **Read the [Quick Start Guide](../README.md#-quick-start)**
3. **Explore [Examples](../references/examples.md)**

---

## Uninstall

If you need to remove the skill:

```bash
rm -rf ~/.claude/skills/pythesis-plot
```

If using symlink, remove the link (not the original):

```bash
rm ~/.claude/skills/pythesis-plot  # Removes symlink only
```

---

**Still having issues?** 

Open an issue: https://github.com/stephenlzc/pythesis-plot/issues


path: references/chart_types.md
content: # 图表类型指南

本指南详细介绍 PyThesisPlot 支持的各种图表类型及其适用场景。

## 目录

- [折线图 (Line)](#折线图-line)
- [柱状图 (Bar)](#柱状图-bar)
- [散点图 (Scatter)](#散点图-scatter)
- [箱线图 (Box)](#箱线图-box)
- [热力图 (Heatmap)](#热力图-heatmap)
- [面积图 (Area)](#面积图-area)
- [饼图 (Pie)](#饼图-pie)
- [直方图 (Histogram)](#直方图-histogram)
- [组合图 (Combo)](#组合图-combo)

---

## 折线图 (Line)

### 适用场景

- 展示数据随时间的变化趋势
- 比较多个数据系列的趋势
- 显示连续数据的波动

### 代码示例

```python
import numpy as np
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, y1, linewidth=2, label='Series 1', color='#2E5AAC')
ax.plot(x, y2, linewidth=2, label='Series 2', color='#D9534F', linestyle='--')

ax.set_xlabel('Time (s)', fontsize=12)
ax.set_ylabel('Amplitude', fontsize=12)
ax.legend(loc='best')
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('line_chart.pdf', bbox_inches='tight')
```

### 最佳实践

- 线宽建议 1.5-2.5
- 多线图使用不同线型区分（实线、虚线、点划线）
- 避免超过 5 条数据线
- 添加标记点突出关键数据

---

## 柱状图 (Bar)

### 适用场景

- 比较不同类别的数据大小
- 展示离散数据的分布
- 显示计数或百分比

### 代码示例

```python
import numpy as np
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]

fig, ax = plt.subplots(figsize=(8, 5))
bars = ax.bar(categories, values, color='#2E5AAC', edgecolor='black', linewidth=0.5)

# 添加数值标签
for bar in bars:
    height = bar.get_height()
    ax.annotate(f'{height}',
                xy=(bar.get_x() + bar.get_width() / 2, height),
                xytext=(0, 3), textcoords="offset points",
                ha='center', va='bottom', fontsize=9)

ax.set_xlabel('Category', fontsize=12)
ax.set_ylabel('Value', fontsize=12)
ax.set_title('Bar Chart Example', fontsize=14, fontweight='bold')

plt.tight_layout()
plt.savefig('bar_chart.pdf', bbox_inches='tight')
```

### 分组柱状图

```python
x = np.arange(len(categories))
width = 0.35

fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(x - width/2, values1, width, label='Group 1', color='#2E5AAC')
ax.bar(x + width/2, values2, width, label='Group 2', color='#5CB85C')

ax.set_xticks(x)
ax.set_xticklabels(categories)
ax.legend()
```

### 最佳实践

- 柱子宽度适中，不要太细或太粗
- 分组柱状图保持适当间距
- 数值标签清晰可读
- 考虑使用水平柱状图当类别名称较长

---

## 散点图 (Scatter)

### 适用场景

- 展示两个变量的相关性
- 发现数据中的聚类或异常值
- 显示数据分布密度

### 代码示例

```python
import numpy as np
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

np.random.seed(42)
n = 100
x = np.random.randn(n)
y = 2 * x + np.random.randn(n) * 0.5

fig, ax = plt.subplots(figsize=(7, 6))
scatter = ax.scatter(x, y, alpha=0.6, s=50, c='#2E5AAC', 
                     edgecolors='black', linewidth=0.5)

ax.set_xlabel('Variable X', fontsize=12)
ax.set_ylabel('Variable Y', fontsize=12)
ax.set_title('Scatter Plot', fontsize=14, fontweight='bold')

plt.tight_layout()
plt.savefig('scatter.pdf', bbox_inches='tight')
```

### 带颜色映射的散点图

```python
colors = np.random.rand(n)
sizes = 100 * np.random.rand(n)

scatter = ax.scatter(x, y, c=colors, s=sizes, alpha=0.6, 
                     cmap='viridis', edgecolors='black', linewidth=0.5)
plt.colorbar(scatter, ax=ax, label='Color Scale')
```

### 最佳实践

- 点的大小适中，避免重叠
- 使用透明度(alpha)处理密集数据
- 添加趋势线展示相关性
- 颜色映射选择色盲友好的配色

---

## 箱线图 (Box)

### 适用场景

- 展示数据分布特征
- 比较多组数据的统计特性
- 识别异常值

### 代码示例

```python
import numpy as np
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

np.random.seed(42)
data = [
    np.random.normal(100, 10, 200),
    np.random.normal(90, 20, 200),
    np.random.normal(95, 15, 200),
    np.random.normal(110, 12, 200)
]
labels = ['Group A', 'Group B', 'Group C', 'Group D']

fig, ax = plt.subplots(figsize=(8, 6))
bp = ax.boxplot(data, labels=labels, patch_artist=True, notch=True)

colors = ['#2E5AAC', '#5CB85C', '#F0AD4E', '#D9534F']
for patch, color in zip(bp['boxes'], colors):
    patch.set_facecolor(color)
    patch.set_alpha(0.7)

ax.set_ylabel('Value', fontsize=12)
ax.set_title('Box Plot', fontsize=14, fontweight='bold')
ax.yaxis.grid(True, linestyle='--', alpha=0.7)

plt.tight_layout()
plt.savefig('boxplot.pdf', bbox_inches='tight')
```

### 最佳实践

- 使用不同颜色区分组
- 添加 notch 显示中位数置信区间
- 保持箱体透明度避免遮挡
- 添加网格线便于读数

---

## 热力图 (Heatmap)

### 适用场景

- 展示相关性矩阵
- 显示二维数据的密度分布
- 展示表格数据的数值大小

### 代码示例

```python
import numpy as np
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

# 生成相关性矩阵
np.random.seed(42)
data = np.random.randn(8, 8)
corr_matrix = np.corrcoef(data)

labels = [f'Var{i+1}' for i in range(8)]

fig, ax = plt.subplots(figsize=(8, 7))
im = ax.imshow(corr_matrix, cmap='RdYlBu_r', aspect='auto', vmin=-1, vmax=1)

# 添加颜色条
cbar = ax.figure.colorbar(im, ax=ax, shrink=0.8)
cbar.set_label('Correlation', fontsize=11)

# 设置刻度
ax.set_xticks(np.arange(len(labels)))
ax.set_yticks(np.arange(len(labels)))
ax.set_xticklabels(labels, rotation=45, ha='right')
ax.set_yticklabels(labels)

# 添加数值
for i in range(len(labels)):
    for j in range(len(labels)):
        text = ax.text(j, i, f'{corr_matrix[i, j]:.2f}',
                      ha="center", va="center", 
                      color="white" if abs(corr_matrix[i, j]) > 0.5 else "black",
                      fontsize=9)

ax.set_title('Correlation Matrix', fontsize=14, fontweight='bold', pad=20)

plt.tight_layout()
plt.savefig('heatmap.pdf', bbox_inches='tight')
```

### 最佳实践

- 选择合适的 colormap（RdYlBu_r 适合相关性）
- 添加数值标签便于精确读数
- 根据数值大小调整标签颜色
- 设置合适的 colorbar 范围

---

## 面积图 (Area)

### 适用场景

- 展示累积数据
- 显示部分与整体的关系
- 强调数量随时间的变化

### 代码示例

```python
import numpy as np
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

x = np.arange(10)
y1 = np.array([1, 3, 2, 4, 3, 5, 4, 6, 5, 7])
y2 = np.array([2, 2, 3, 3, 4, 4, 5, 5, 6, 6])

fig, ax = plt.subplots(figsize=(8, 5))
ax.fill_between(x, y1, alpha=0.5, color='#2E5AAC', label='Series 1')
ax.fill_between(x, y2, alpha=0.5, color='#5CB85C', label='Series 2')
ax.plot(x, y1, color='#2E5AAC', linewidth=2)
ax.plot(x, y2, color='#5CB85C', linewidth=2)

ax.set_xlabel('X', fontsize=12)
ax.set_ylabel('Y', fontsize=12)
ax.legend(loc='best')

plt.tight_layout()
plt.savefig('area_chart.pdf', bbox_inches='tight')
```

---

## 饼图 (Pie)

### 适用场景

- 展示部分占整体的比例
- 强调简单构成（建议不超过 6 个类别）

### 代码示例

```python
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

sizes = [30, 25, 20, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']
colors = ['#2E5AAC', '#5CB85C', '#F0AD4E', '#D9534F', '#6C757D']

fig, ax = plt.subplots(figsize=(7, 7))
wedges, texts, autotexts = ax.pie(sizes, labels=labels, colors=colors,
                                    autopct='%1.1f%%', startangle=90,
                                    explode=[0.05 if i == 0 else 0 for i in range(5)])

ax.set_title('Pie Chart', fontsize=14, fontweight='bold')

plt.tight_layout()
plt.savefig('pie_chart.pdf', bbox_inches='tight')
```

### 最佳实践

- 类别不超过 6 个
- 突出显示重要部分
- 添加百分比标签
- 考虑使用柱状图替代（更清晰）

---

## 直方图 (Histogram)

### 适用场景

- 展示数据分布
- 估计概率密度

### 代码示例

```python
import numpy as np
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

np.random.seed(42)
data = np.random.randn(1000)

fig, ax = plt.subplots(figsize=(8, 5))
n, bins, patches = ax.hist(data, bins=30, color='#2E5AAC', 
                           edgecolor='black', alpha=0.7, density=True)

# 添加核密度估计曲线
from scipy import stats
kde = stats.gaussian_kde(data)
x_range = np.linspace(data.min(), data.max(), 100)
ax.plot(x_range, kde(x_range), color='#D9534F', linewidth=2, label='KDE')

ax.set_xlabel('Value', fontsize=12)
ax.set_ylabel('Density', fontsize=12)
ax.legend()

plt.tight_layout()
plt.savefig('histogram.pdf', bbox_inches='tight')
```

---

## 组合图 (Combo)

### 适用场景

- 同时展示不同量纲的数据
- 比较多维度的关系

### 代码示例

```python
import numpy as np
import matplotlib.pyplot as plt
from pythesisplot import setup_thesis_style

setup_thesis_style()

x = np.arange(1, 6)
bar_data = [20, 35, 30, 35, 27]
line_data = [25, 32, 34, 20, 25]

fig, ax1 = plt.subplots(figsize=(8, 5))

# 柱状图
bars = ax1.bar(x, bar_data, color='#2E5AAC', alpha=0.7, label='Bar Data')
ax1.set_xlabel('Category', fontsize=12)
ax1.set_ylabel('Bar Values', fontsize=12, color='#2E5AAC')
ax1.tick_params(axis='y', labelcolor='#2E5AAC')

# 折线图
ax2 = ax1.twinx()
line = ax2.plot(x, line_data, color='#D9534F', marker='o', 
                linewidth=2, label='Line Data')
ax2.set_ylabel('Line Values', fontsize=12, color='#D9534F')
ax2.tick_params(axis='y', labelcolor='#D9534F')

# 合并图例
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='best')

ax1.set_title('Combo Chart', fontsize=14, fontweight='bold')

plt.tight_layout()
plt.savefig('combo_chart.pdf', bbox_inches='tight')
```

---

## 图表选择决策树

```
数据类型
├── 时间序列/趋势 → 折线图
├── 分类对比
│   ├── 单变量 → 柱状图
│   └── 多变量 → 分组柱状图/堆叠柱状图
├── 相关性
│   ├── 两变量 → 散点图
│   └── 多变量 → 热力图/散点图矩阵
├── 分布
│   ├── 单组 → 直方图/箱线图
│   └── 多组比较 → 箱线图/小提琴图
├── 构成/占比
│   ├── 静态 → 饼图/堆叠柱状图
│   └── 动态变化 → 堆叠面积图
└── 复杂关系 → 组合图
```


path: references/examples.md
content: # 代码示例集

本文件提供 PyThesisPlot 的完整代码示例，涵盖常见科研图表场景。

## 目录

- [基础示例](#基础示例)
- [进阶示例](#进阶示例)
- [论文场景示例](#论文场景示例)
- [完整模板](#完整模板)

---

## 基础示例

### 示例1：最简单的科研图表

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

# 设置科研样式
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 数据
x = np.linspace(0, 10, 100)
y = np.sin(x)

# 绘图
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, y, linewidth=2, color='#2E5AAC')
ax.set_xlabel('X轴', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)
ax.set_title('正弦波', fontsize=14)
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('simple.pdf', bbox_inches='tight', dpi=300)
```

### 示例2：多子图布局

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

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

fig, axes = plt.subplots(2, 2, figsize=(10, 8))

x = np.linspace(0, 10, 100)

# 子图1
axes[0, 0].plot(x, np.sin(x), color='#2E5AAC')
axes[0, 0].set_title('正弦波')
axes[0, 0].grid(True, alpha=0.3)

# 子图2
axes[0, 1].plot(x, np.cos(x), color='#5CB85C')
axes[0, 1].set_title('余弦波')
axes[0, 1].grid(True, alpha=0.3)

# 子图3
axes[1, 0].plot(x, np.tan(x), color='#F0AD4E')
axes[1, 0].set_title('正切波')
axes[1, 0].set_ylim(-5, 5)
axes[1, 0].grid(True, alpha=0.3)

# 子图4
axes[1, 1].plot(x, np.exp(-x/5), color='#D9534F')
axes[1, 1].set_title('指数衰减')
axes[1, 1].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('subplots.pdf', bbox_inches='tight', dpi=300)
```

---

## 进阶示例

### 示例3：带误差线的图表

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

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

x = np.arange(1, 6)
y = [10, 15, 13, 18, 16]
error = [1, 2, 1.5, 2.5, 1.8]

fig, ax = plt.subplots(figsize=(7, 5))
ax.errorbar(x, y, yerr=error, fmt='o-', linewidth=2, 
            markersize=8, capsize=5, color='#2E5AAC',
            ecolor='#D9534F', capthick=2)

ax.set_xlabel('实验组', fontsize=12)
ax.set_ylabel('测量值', fontsize=12)
ax.set_title('带误差线的实验结果', fontsize=14, fontweight='bold')
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('errorbar.pdf', bbox_inches='tight', dpi=300)
```

### 示例4：双Y轴图表

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

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

x = np.arange(1, 11)
y1 = np.random.randint(50, 100, 10)
y2 = np.random.randint(1000, 5000, 10)

fig, ax1 = plt.subplots(figsize=(8, 5))

color1 = '#2E5AAC'
ax1.bar(x, y1, color=color1, alpha=0.7, label='数量')
ax1.set_xlabel('时间 (月)', fontsize=12)
ax1.set_ylabel('数量', fontsize=12, color=color1)
ax1.tick_params(axis='y', labelcolor=color1)

ax2 = ax1.twinx()
color2 = '#D9534F'
ax2.plot(x, y2, color=color2, marker='o', linewidth=2, label='金额')
ax2.set_ylabel('金额 (元)', fontsize=12, color=color2)
ax2.tick_params(axis='y', labelcolor=color2)

fig.legend(loc='upper left', bbox_to_anchor=(0.1, 0.95))
ax1.set_title('双Y轴示例', fontsize=14, fontweight='bold')

plt.tight_layout()
plt.savefig('twinx.pdf', bbox_inches='tight', dpi=300)
```

### 示例5：带标注的图表

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

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, y, linewidth=2, color='#2E5AAC')

# 标注最大值
max_idx = np.argmax(y)
ax.annotate(f'最大值: ({x[max_idx]:.2f}, {y[max_idx]:.2f})',
            xy=(x[max_idx], y[max_idx]),
            xytext=(x[max_idx]+1, y[max_idx]+0.3),
            arrowprops=dict(arrowstyle='->', color='#D9534F'),
            fontsize=10, color='#D9534F')

# 标注最小值
min_idx = np.argmin(y)
ax.annotate(f'最小值: ({x[min_idx]:.2f}, {y[min_idx]:.2f})',
            xy=(x[min_idx], y[min_idx]),
            xytext=(x[min_idx]+1, y[min_idx]-0.3),
            arrowprops=dict(arrowstyle='->', color='#5CB85C'),
            fontsize=10, color='#5CB85C')

ax.set_xlabel('X轴', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)
ax.set_title('带标注的图表', fontsize=14, fontweight='bold')
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('annotation.pdf', bbox_inches='tight', dpi=300)
```

---

## 论文场景示例

### 示例6：实验结果对比图

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

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

methods = ['方法A', '方法B', '方法C', '方法D', '方法E']
accuracy = [0.85, 0.88, 0.92, 0.90, 0.87]
precision = [0.83, 0.86, 0.91, 0.89, 0.85]
recall = [0.87, 0.89, 0.93, 0.91, 0.88]

x = np.arange(len(methods))
width = 0.25

fig, ax = plt.subplots(figsize=(10, 6))
bars1 = ax.bar(x - width, accuracy, width, label='准确率', color='#2E5AAC')
bars2 = ax.bar(x, precision, width, label='精确率', color='#5CB85C')
bars3 = ax.bar(x + width, recall, width, label='召回率', color='#F0AD4E')

ax.set_xlabel('方法', fontsize=12)
ax.set_ylabel('分数', fontsize=12)
ax.set_title('不同方法的性能对比', fontsize=14, fontweight='bold')
ax.set_xticks(x)
ax.set_xticklabels(methods)
ax.legend(loc='best')
ax.set_ylim(0, 1.0)
ax.yaxis.grid(True, linestyle='--', alpha=0.7)

plt.tight_layout()
plt.savefig('comparison.pdf', bbox_inches='tight', dpi=300)
```

### 示例7：学习曲线

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

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

epochs = np.arange(1, 101)
train_loss = 1 / (epochs * 0.05) + 0.1 + np.random.randn(100) * 0.02
val_loss = 1 / (epochs * 0.04) + 0.15 + np.random.randn(100) * 0.02

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(epochs, train_loss, label='训练损失', linewidth=2, color='#2E5AAC')
ax.plot(epochs, val_loss, label='验证损失', linewidth=2, color='#D9534F')

# 标记最佳epoch
best_epoch = np.argmin(val_loss)
ax.axvline(x=best_epoch, color='#5CB85C', linestyle='--', alpha=0.7)
ax.scatter([best_epoch], [val_loss[best_epoch]], color='#5CB85C', s=100, zorder=5)
ax.annotate(f'最佳: Epoch {best_epoch}', 
            xy=(best_epoch, val_loss[best_epoch]),
            xytext=(best_epoch+10, val_loss[best_epoch]+0.1),
            fontsize=10, color='#5CB85C')

ax.set_xlabel('训练轮次', fontsize=12)
ax.set_ylabel('损失', fontsize=12)
ax.set_title('模型训练学习曲线', fontsize=14, fontweight='bold')
ax.legend(loc='best')
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('learning_curve.pdf', bbox_inches='tight', dpi=300)
```

### 示例8：混淆矩阵

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

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 混淆矩阵数据
confusion = np.array([[85, 5, 3, 2],
                      [4, 88, 4, 4],
                      [2, 3, 90, 5],
                      [3, 4, 5, 88]])

classes = ['类别A', '类别B', '类别C', '类别D']

fig, ax = plt.subplots(figsize=(7, 6))
im = ax.imshow(confusion, cmap='Blues')

# 添加颜色条
cbar = ax.figure.colorbar(im, ax=ax)
cbar.set_label('样本数', fontsize=11)

# 设置刻度
ax.set_xticks(np.arange(len(classes)))
ax.set_yticks(np.arange(len(classes)))
ax.set_xticklabels(classes)
ax.set_yticklabels(classes)
ax.set_xlabel('预测标签', fontsize=12)
ax.set_ylabel('真实标签', fontsize=12)
ax.set_title('混淆矩阵', fontsize=14, fontweight='bold')

# 在每个格子中显示数值
for i in range(len(classes)):
    for j in range(len(classes)):
        text = ax.text(j, i, confusion[i, j],
                      ha="center", va="center", 
                      color="white" if confusion[i, j] > 50 else "black",
                      fontsize=12, fontweight='bold')

plt.tight_layout()
plt.savefig('confusion_matrix.pdf', bbox_inches='tight', dpi=300)
```

### 示例9：ROC曲线

```python
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import roc_curve, auc

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 生成模拟数据
np.random.seed(42)
n_samples = 1000
y_true = np.random.randint(0, 2, n_samples)
y_scores = np.random.rand(n_samples)

# 计算ROC曲线
fpr, tpr, _ = roc_curve(y_true, y_scores)
roc_auc = auc(fpr, tpr)

fig, ax = plt.subplots(figsize=(7, 6))
ax.plot(fpr, tpr, linewidth=2, color='#2E5AAC', 
        label=f'ROC曲线 (AUC = {roc_auc:.3f})')
ax.plot([0, 1], [0, 1], 'k--', linewidth=1, label='随机猜测')

ax.set_xlabel('假正率 (False Positive Rate)', fontsize=12)
ax.set_ylabel('真正率 (True Positive Rate)', fontsize=12)
ax.set_title('ROC曲线', fontsize=14, fontweight='bold')
ax.legend(loc='lower right')
ax.grid(True, alpha=0.3)
ax.set_xlim([0.0, 1.0])
ax.set_ylim([0.0, 1.05])

plt.tight_layout()
plt.savefig('roc_curve.pdf', bbox_inches='tight', dpi=300)
```

---

## 完整模板

### 论文图表完整模板

```python
#!/usr/bin/env python3
"""
论文图表完整模板
包含：样式设置、数据绘图、图例、导出
"""

import matplotlib.pyplot as plt
import numpy as np

# ==================== 配置 ====================
# 中文字体设置
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

# 全局样式设置
plt.rcParams['font.size'] = 11
plt.rcParams['axes.titlesize'] = 12
plt.rcParams['axes.labelsize'] = 11
plt.rcParams['xtick.labelsize'] = 9
plt.rcParams['ytick.labelsize'] = 9
plt.rcParams['legend.fontsize'] = 9
plt.rcParams['lines.linewidth'] = 1.5
plt.rcParams['lines.markersize'] = 6

# ==================== 数据 ====================
np.random.seed(42)
x = np.linspace(0, 10, 100)
y1 = np.sin(x) + np.random.randn(100) * 0.1
y2 = np.cos(x) + np.random.randn(100) * 0.1

# ==================== 绘图 ====================
# 创建图形
fig, ax = plt.subplots(figsize=(7, 5))

# 配色方案
colors = ['#2E5AAC', '#D9534F']

# 绘制数据
ax.plot(x, y1, color=colors[0], linewidth=2, 
        label='方法A', marker='o', markevery=10)
ax.plot(x, y2, color=colors[1], linewidth=2, 
        label='方法B', marker='s', markevery=10, linestyle='--')

# 设置标签
ax.set_xlabel('时间 (s)', fontsize=12)
ax.set_ylabel('信号强度', fontsize=12)
ax.set_title('实验结果对比', fontsize=14, fontweight='bold')

# 图例
ax.legend(loc='best', frameon=True, fancybox=True, shadow=False)

# 网格
ax.grid(True, linestyle='--', alpha=0.3)

# 调整布局
plt.tight_layout()

# ==================== 导出 ====================
# 矢量图（LaTeX）
plt.savefig('figure.pdf', bbox_inches='tight', dpi=300)

# 位图（Word）
plt.savefig('figure.png', bbox_inches='tight', dpi=300, 
            facecolor='white', edgecolor='none')

print("✓ 图表已导出: figure.pdf, figure.png")
```

### LaTeX 集成模板

```python
#!/usr/bin/env python3
"""
LaTeX 论文图表模板
使用 pgf 后端直接生成 LaTeX 可用的图表
"""

import matplotlib
matplotlib.use('pgf')
import matplotlib.pyplot as plt
import numpy as np

# LaTeX 配置
matplotlib.rcParams.update({
    'pgf.texsystem': 'pdflatex',
    'font.family': 'serif',
    'text.usetex': True,
    'pgf.rcfonts': False,
})

# 数据
x = np.linspace(0, 10, 100)
y = np.sin(x)

# 绘图
fig, ax = plt.subplots(figsize=(3.5, 2.5))
ax.plot(x, y, linewidth=1.5)
ax.set_xlabel('Time (s)')
ax.set_ylabel('Amplitude')
ax.set_title('Sine Wave')
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('figure.pgf')
```

LaTeX 中使用：

```latex
\begin{figure}
    \centering
    \input{figure.pgf}
    \caption{示例图表}
    \label{fig:example}
\end{figure}
```


path: references/style_guide.md
content: # 样式规范

本规范定义 PyThesisPlot 的科研图表样式标准，确保图表的专业性和一致性。

## 目录

- [配色方案](#配色方案)
- [字体规范](#字体规范)
- [图表尺寸](#图表尺寸)
- [线条与标记](#线条与标记)
- [导出设置](#导出设置)

---

## 配色方案

### 学术蓝 (Academic)

经典学术风格，适合正式论文。

```python
colors = ['#2E5AAC', '#5B9BD5', '#A5D6F3', '#1F4E79', '#8FB8E6']
```

### 鲜艳色 (Vibrant)

高对比度，适合数据对比和演示。

```python
colors = ['#E41A1C', '#377EB8', '#4DAF4A', '#984EA3', '#FF7F00']
```

### 柔和色 (Pastel)

低饱和度，适合多组数据展示。

```python
colors = ['#FBB4AE', '#B3CDE3', '#CCEBC5', '#DECBE4', '#FED9A6']
```

### 期刊配色

#### Nature 风格

```python
colors = ['#E64B35', '#4DBBD5', '#00A087', '#3C5488', '#F39B7F']
```

#### Science 风格

```python
colors = ['#003399', '#CC0000', '#009900', '#FFCC00', '#9900CC']
```

#### IEEE 风格

```python
colors = ['#0066CC', '#CC0000', '#009900', '#FF9900', '#9900CC']
```

### 功能配色

#### 灰度色 (Grayscale)

黑白打印友好。

```python
colors = ['#000000', '#404040', '#707070', '#A0A0A0', '#D0D0D0']
```

#### 暖色调 (Warm)

```python
colors = ['#D73027', '#F46D43', '#FDAE61', '#FEE090', '#FFFFBF']
```

#### 冷色调 (Cool)

```python
colors = ['#4575B4', '#74ADD1', '#ABD9E9', '#E0F3F8', '#FFFFBF']
```

#### 发散色 (Diverging)

适用于正负值对比。

```python
colors = ['#D73027', '#FC8D59', '#FEE090', '#91BFDB', '#4575B4']
```

### 色盲友好配色

使用 ColorBrewer 推荐的色盲友好配色：

```python
# 3 色
['#1f77b4', '#ff7f0e', '#2ca02c']

# 4 色
['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728']

# 5 色
['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd']
```

### 配色使用建议

| 场景 | 推荐配色 |
|-----|---------|
| 正式论文 | academic, grayscale |
| 演示汇报 | vibrant, nature |
| 黑白打印 | grayscale |
| 多组数据 (>5) | pastel, cool |
| 对比强调 | vibrant, warm |
| 相关性热力图 | diverging |

---

## 字体规范

### 中文字体推荐

| 操作系统 | 首选字体 | 备选字体 |
|---------|---------|---------|
| Windows | SimHei (黑体) | Microsoft YaHei |
| macOS | Heiti TC (黑体-繁) | PingFang TC |
| Linux | WenQuanYi Micro Hei | Noto Sans CJK SC |

### 字体大小规范

| 元素 | 建议字号 | 说明 |
|-----|---------|-----|
| 图表标题 | 12-14 pt | 加粗 |
| 坐标轴标签 | 10-12 pt | |
| 刻度标签 | 9-10 pt | |
| 图例 | 9-10 pt | |
| 注释文字 | 8-9 pt | |

### 字体设置代码

```python
import matplotlib.pyplot as plt

# 中文字体配置
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

# 字体大小配置
plt.rcParams['font.size'] = 11
plt.rcParams['axes.titlesize'] = 12
plt.rcParams['axes.labelsize'] = 11
plt.rcParams['xtick.labelsize'] = 9
plt.rcParams['ytick.labelsize'] = 9
plt.rcParams['legend.fontsize'] = 9
```

---

## 图表尺寸

### 标准尺寸

| 使用场景 | 宽度 (英寸) | 高度 (英寸) | 对应像素 (300dpi) |
|---------|------------|------------|------------------|
| 单栏图 | 3.5 | 2.5-3.0 | 1050×750 |
| 1.5栏图 | 5.0 | 3.5-4.0 | 1500×1050 |
| 双栏图 | 7.0 | 4.5-5.5 | 2100×1350 |
| 全页图 | 7.0 | 9.0 | 2100×2700 |

### 尺寸代码

```python
# 单栏图
fig, ax = plt.subplots(figsize=(3.5, 2.5))

# 双栏图
fig, ax = plt.subplots(figsize=(7.0, 5.0))

# 自定义尺寸
fig, ax = plt.subplots(figsize=(width_inches, height_inches))
```

### 黄金比例

推荐宽高比 1.618:1（黄金比例）或 4:3、16:9。

```python
# 黄金比例
width = 7.0
height = width / 1.618
fig, ax = plt.subplots(figsize=(width, height))
```

---

## 线条与标记

### 线条样式

```python
# 线宽
linewidth = 1.5  # 标准
linewidth = 2.0  # 强调
linewidth = 1.0  # 辅助线

# 线型
linestyle = '-'   # 实线
linestyle = '--'  # 虚线
linestyle = '-.'  # 点划线
linestyle = ':'   # 点线
```

### 标记样式

| 标记 | 代码 | 适用场景 |
|-----|-----|---------|
| 圆点 | 'o' | 一般数据点 |
| 方块 | 's' | 分类数据 |
| 三角形 | '^' | 峰值数据 |
| 菱形 | 'D' | 关键数据 |
| 星号 | '*' | 特殊标记 |
| 十字 | '+' | 误差数据 |

```python
# 标记大小
markersize = 6  # 标准
markersize = 8  # 强调

# 标记样式
ax.plot(x, y, marker='o', markersize=6, markerfacecolor='white',
        markeredgecolor='#2E5AAC', markeredgewidth=1.5)
```

### 标记间隔

避免标记过于密集：

```python
# 每 n 个点显示一个标记
markevery = 10  # 每 10 个点显示一个
ax.plot(x, y, marker='o', markevery=markevery)
```

---

## 导出设置

### 文件格式

| 格式 | 适用场景 | 优点 |
|-----|---------|-----|
| PDF | LaTeX 论文 | 矢量图，无限缩放 |
| EPS | LaTeX 论文 | 矢量图，兼容性好 |
| PNG | Word/PPT | 位图，透明背景 |
| SVG | 网页编辑 | 矢量图，可编辑 |
| TIFF | 期刊投稿 | 高质量位图 |

### 导出代码

```python
# PDF 导出（推荐用于 LaTeX）
plt.savefig('figure.pdf', bbox_inches='tight', dpi=300)

# PNG 导出（推荐用于 Word）
plt.savefig('figure.png', bbox_inches='tight', dpi=300, 
            facecolor='white', edgecolor='none')

# SVG 导出（可编辑）
plt.savefig('figure.svg', bbox_inches='tight')

# TIFF 导出（期刊投稿）
plt.savefig('figure.tiff', bbox_inches='tight', dpi=600)
```

### 导出参数

| 参数 | 说明 | 建议值 |
|-----|-----|-------|
| `bbox_inches` | 去除多余白边 | `'tight'` |
| `dpi` | 分辨率 | 300（标准）、600（高质量） |
| `pad_inches` | 边距 | 0.02 |
| `facecolor` | 背景色 | `'white'` |
| `transparent` | 透明背景 | `False` |

### 批量导出

```python
# 导出多种格式
formats = ['pdf', 'png', 'svg']
for fmt in formats:
    plt.savefig(f'figure.{fmt}', bbox_inches='tight', dpi=300)
```

---

## 样式检查清单

提交图表前检查：

- [ ] 字体清晰可读，中文正常显示
- [ ] 坐标轴标签完整（含单位）
- [ ] 图例位置合理，不遮挡数据
- [ ] 配色协调，符合论文风格
- [ ] 分辨率足够（≥300dpi）
- [ ] 无多余白边
- [ ] 线条粗细适中
- [ ] 标记清晰可辨
- [ ] 标题简洁明了
- [ ] 网格线不干扰数据阅读


path: references/workflow_guide.md
content: # Workflow Guide

PyThesisPlot adopts a complete four-stage workflow: Data Analysis → Chart Recommendations → User Confirmation → Generation.

## Flowchart

```
┌─────────────────────────────────────────────────────────────────┐
│                     Stage 1: Data Reception                      │
├─────────────────────────────────────────────────────────────────┤
│  1. User uploads data file (csv/xlsx/txt/md)                   │
│  2. Generate timestamp: YYYYMMDD-HHMMSS                         │
│  3. Rename file: {timestamp}-{original_filename}                │
│  4. Create directory: output/{timestamp}-{filename}/            │
│  5. Save file to working directory                              │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Stage 2: Data Analysis                       │
├─────────────────────────────────────────────────────────────────┤
│  1. Read data file                                              │
│  2. Analyze data dimensions (rows, columns)                     │
│  3. Analyze column types (numeric/categorical/datetime)         │
│  4. Statistical feature analysis (mean, std, distribution)      │
│  5. Column relationship analysis (correlations)                 │
│  6. Generate analysis_report.md                                 │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Stage 3: Chart Recommendations               │
├─────────────────────────────────────────────────────────────────┤
│  Intelligent chart recommendations based on analysis results:    │
│                                                                  │
│  • Time series → Line plot                                       │
│  • Categorical comparison → Bar chart                            │
│  • Two numeric correlated → Scatter plot                         │
│  • Multiple numeric correlated → Heatmap                         │
│  • Distribution analysis → Box plot                              │
│  • Multi-dimensional data → Comprehensive dashboard              │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                  ⚠️ Stage 4: User Confirmation (Required)        │
├─────────────────────────────────────────────────────────────────┤
│  Display to user:                                               │
│    • Data overview (dimensions, types, statistics)              │
│    • Chart recommendations (types, content, reasons)            │
│                                                                  │
│  Wait for user instruction:                                     │
│    ✅ "Generate schemes 1 and 2" → Generate specified charts    │
│    ✅ "Generate all" → Generate all recommendations             │
│    📝 "Modify scheme X..." → Adjust based on feedback           │
│    💬 "I want to make XXX chart" → Custom according to needs    │
│                                                                  │
│  ⚠️ Important: Must wait for explicit user confirmation         │
│      before entering generation phase                           │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Stage 5: Generation & Delivery               │
├─────────────────────────────────────────────────────────────────┤
│  1. Generate plot_config.json (chart configuration)            │
│  2. Generate {timestamp}_plot.py (Python code)                  │
│  3. Execute code to generate charts:                            │
│     • {timestamp}_fig1_line.png (PNG image)                     │
│     • {timestamp}_fig2_bar.png                                  │
│  4. All files saved to same working directory                   │
└─────────────────────────────────────────────────────────────────┘
```

## File Naming Conventions

### Directory Naming
```
output/
└── 20250312-143052-sales_data/          # timestamp-original_name
    └── ...
```

### File Naming

| File Type | Naming Format | Example |
|---------|---------|------|
| Raw Data | `{timestamp}-{original}` | `20250312-143052-sales_data.csv` |
| Analysis Report | `analysis_report.md` | `analysis_report.md` |
| Chart Config | `plot_config.json` | `plot_config.json` |
| Python Code | `{timestamp}_plot.py` | `20250312-143052_plot.py` |
| Chart PNG | `{timestamp}_fig{n}_{type}.png` | `20250312-143052_fig1_line.png` |

## User Interaction Examples

### Scenario 1: Standard Workflow

```
[User uploads data.csv]

👤 User: Help me analyze this data and create some charts

🤖 Assistant: Received! Processing your data...

   📁 Working directory: output/20250312-143052-data/
   📄 Data file: 20250312-143052-data.csv
   🔍 Analyzing data...

═══════════════════════════════════════════════════════════════
                        Data Analysis Report
═══════════════════════════════════════════════════════════════

📊 Data Overview
• Dimensions: 120 rows × 5 columns
• Numeric columns: 3
• Categorical columns: 2

📋 Column Details
| Column | Type | Description                    |
|--------|------|--------------------------------|
| date   | 📅 datetime | 2023-01 to 2023-12        |
| sales  | 🔢 numeric | mean=1250, std=320         |
| region | 🏷️ categorical | 4 categories: N/S/E/W |

💡 Chart Recommendations

Scheme 1: Time Trend Analysis ⭐
• Chart Type: Line plot
• Content: Sales trend over time
• Reason: Time series data, best for showing trends

Scheme 2: Regional Comparison
• Chart Type: Grouped bar chart
• Content: Sales comparison by region
• Reason: Categorical data, intuitive for differences

Scheme 3: Comprehensive Dashboard
• Chart Type: 2×2 subplot layout
• Includes: Trend line + Bar chart + Box plot + Heatmap
• Reason: Rich dimensions, comprehensive view

═══════════════════════════════════════════════════════════════

🎯 Next Steps
Please tell me what you want:
• "Generate schemes 1 and 2" - Generate specified charts
• "Generate all" - Generate all recommendations
• "Modify scheme 3..." - Provide your modification suggestions

👤 User: Generate schemes 1 and 2

🤖 Assistant: Okay! Generating schemes 1 and 2...

   ⚙️  Chart config: plot_config.json
   📝 Python code: 20250312-143052_plot.py
   🎨 Generating charts...
   ✅ Generated 4 chart files
      📊 20250312-143052_fig1_line.png
      📊 20250312-143052_fig2_bar.png

═══════════════════════════════════════════════════════════════
✅ All complete!
📁 All files saved to: output/20250312-143052-data/
═══════════════════════════════════════════════════════════════
```

### Scenario 2: User Modifications

```
👤 User: Modify scheme 1, group X-axis by month and show mean values

🤖 Assistant: Received! Adjusting scheme 1 based on your request:

   Modified Scheme 1: Monthly Sales Trend
   • Chart Type: Line plot
   • X-axis: Month (grouped by date)
   • Y-axis: Sales mean
   • Data aggregation: Monthly aggregation

   Confirm generation?

👤 User: Confirm

🤖 Assistant: Generating...
```

## Script Usage Guide

### workflow.py - Complete Workflow

```bash
# Complete workflow (analysis + wait for confirmation + generation)
python scripts/workflow.py --input data.csv

# Analysis only (for displaying report, no chart generation)
python scripts/workflow.py --input data.csv --analyze-only

# Specify output directory
python scripts/workflow.py --input data.csv --output-dir ./my_output
```

### data_analyzer.py - Analysis Only

```bash
# Analyze and output report
python scripts/data_analyzer.py --input data.csv --output report.md

# Print report only
python scripts/data_analyzer.py --input data.csv
```

### plot_generator.py - Generate from Config

```bash
# Generate charts according to configuration file
python scripts/plot_generator.py --config plot_config.json --output-dir ./
```

## Important Notes

1. **Required Confirmation Step**: After analysis, must wait for user confirmation, cannot generate charts directly
2. **Unified File Management**: All related files saved to same directory for easy user access
3. **Publication-Ready Output**: Provide high-resolution PNG (300 DPI) suitable for publication
4. **Code Traceability**: Generated Python code also saved for user modification and reproducibility


path: scripts/data_analyzer.py
content: #!/usr/bin/env python3
"""
数据分析模块
分析数据特征，生成图表建议
"""

import os
import sys
import json
import pandas as pd
import numpy as np
from datetime import datetime


class DataAnalyzer:
    """数据分析器"""
    
    def __init__(self, data_file):
        self.data_file = data_file
        self.df = None
        self.columns_info = {}
        self.suggestions = []
        self._load_data()
        self._analyze_columns()
    
    def _load_data(self):
        """加载数据文件"""
        ext = os.path.splitext(self.data_file)[1].lower()
        
        try:
            if ext in ['.csv']:
                self.df = pd.read_csv(self.data_file)
            elif ext in ['.xlsx', '.xls']:
                self.df = pd.read_excel(self.data_file)
            elif ext in ['.txt', '.md']:
                # 尝试读取表格格式
                self.df = pd.read_csv(self.data_file, sep=r'\s+')
            else:
                raise ValueError(f"不支持的文件格式: {ext}")
        except Exception as e:
            print(f"❌ 加载数据失败: {e}")
            sys.exit(1)
    
    def _analyze_columns(self):
        """分析每列的特征"""
        for col in self.df.columns:
            info = {
                'name': col,
                'dtype': str(self.df[col].dtype),
                'null_count': self.df[col].isnull().sum(),
                'unique_count': self.df[col].nunique(),
            }
            
            # 数值型分析
            if pd.api.types.is_numeric_dtype(self.df[col]):
                info['type'] = 'numeric'
                info['min'] = self.df[col].min()
                info['max'] = self.df[col].max()
                info['mean'] = self.df[col].mean()
                info['std'] = self.df[col].std()
                
            # 时间序列分析
            elif pd.api.types.is_datetime64_any_dtype(self.df[col]):
                info['type'] = 'datetime'
                info['min'] = self.df[col].min()
                info['max'] = self.df[col].max()
                
            # 分类型分析
            else:
                info['type'] = 'categorical'
                # 尝试转换为时间序列
                try:
                    pd.to_datetime(self.df[col])
                    info['could_be_datetime'] = True
                except:
                    info['could_be_datetime'] = False
            
            self.columns_info[col] = info
    
    def _detect_datetime_columns(self):
        """检测可能的时间序列列"""
        datetime_cols = []
        for col, info in self.columns_info.items():
            if info['type'] == 'datetime':
                datetime_cols.append(col)
            elif info.get('could_be_datetime') and info['unique_count'] > 10:
                datetime_cols.append(col)
        return datetime_cols
    
    def _get_numeric_columns(self):
        """获取数值列"""
        return [col for col, info in self.columns_info.items() 
                if info['type'] == 'numeric']
    
    def _get_categorical_columns(self):
        """获取分类列"""
        return [col for col, info in self.columns_info.items() 
                if info['type'] == 'categorical']
    
    def _generate_suggestions(self):
        """生成图表建议"""
        suggestions = []
        
        datetime_cols = self._detect_datetime_columns()
        numeric_cols = self._get_numeric_columns()
        categorical_cols = self._get_categorical_columns()
        
        # 建议1: 时间趋势图
        if datetime_cols and numeric_cols:
            suggestions.append({
                'id': 1,
                'name': '时间趋势分析',
                'type': 'line',
                'description': f'{numeric_cols[0]}随时间变化趋势',
                'x_col': datetime_cols[0],
                'y_col': numeric_cols[0],
                'reason': '时间序列数据，适合展示趋势变化',
                'priority': 'high'
            })
        
        # 建议2: 柱状图对比
        if categorical_cols and numeric_cols:
            cat_col = categorical_cols[0]
            num_col = numeric_cols[0]
            
            # 如果类别太多，取Top N
            if self.columns_info[cat_col]['unique_count'] <= 20:
                suggestions.append({
                    'id': 2,
                    'name': '分类对比分析',
                    'type': 'bar',
                    'description': f'各{cat_col}的{num_col}对比',
                    'x_col': cat_col,
                    'y_col': num_col,
                    'reason': '分类数据对比，直观展示差异',
                    'priority': 'high'
                })
        
        # 建议3: 箱线图（如果有分类和数值）
        if categorical_cols and numeric_cols:
            suggestions.append({
                'id': 3,
                'name': '数据分布分析',
                'type': 'box',
                'description': f'{numeric_cols[0]}的分布情况',
                'x_col': categorical_cols[0] if len(categorical_cols) > 1 else None,
                'y_col': numeric_cols[0],
                'reason': '展示数据分布和异常值',
                'priority': 'medium'
            })
        
        # 建议4: 散点图（两个数值列）
        if len(numeric_cols) >= 2:
            # 计算相关性
            corr = self.df[numeric_cols[:5]].corr()
            
            # 找相关性最高的一对
            max_corr = 0
            best_pair = None
            for i in range(len(numeric_cols)):
                for j in range(i+1, len(numeric_cols)):
                    c = abs(corr.iloc[i, j])
                    if c > max_corr:
                        max_corr = c
                        best_pair = (numeric_cols[i], numeric_cols[j])
            
            if best_pair and max_corr > 0.3:
                suggestions.append({
                    'id': 4,
                    'name': '相关性分析',
                    'type': 'scatter',
                    'description': f'{best_pair[0]}与{best_pair[1]}的相关性',
                    'x_col': best_pair[0],
                    'y_col': best_pair[1],
                    'add_regression': True,
                    'reason': f'两变量相关性较强(r={max_corr:.2f})，适合散点图展示',
                    'priority': 'medium'
                })
        
        # 建议5: 热力图（多个数值列）
        if len(numeric_cols) >= 3:
            suggestions.append({
                'id': 5,
                'name': '相关性矩阵',
                'type': 'heatmap',
                'description': '数值变量间的相关性',
                'cols': numeric_cols[:8],  # 最多8列
                'reason': '多变量相关性分析，热力图最直观',
                'priority': 'medium'
            })
        
        # 建议6: 综合仪表盘（数据维度丰富）
        if len(numeric_cols) >= 2 and (datetime_cols or categorical_cols):
            plots_for_dashboard = []
            
            if datetime_cols and numeric_cols:
                plots_for_dashboard.append({
                    'type': 'line',
                    'title': '趋势分析',
                    'x': datetime_cols[0],
                    'y': numeric_cols[0]
                })
            
            if categorical_cols and numeric_cols:
                plots_for_dashboard.append({
                    'type': 'bar',
                    'title': '分类对比',
                    'x': categorical_cols[0],
                    'y': numeric_cols[0]
                })
            
            if len(numeric_cols) >= 2:
                plots_for_dashboard.append({
                    'type': 'scatter',
                    'title': '相关性',
                    'x': numeric_cols[0],
                    'y': numeric_cols[1]
                })
            
            if len(plots_for_dashboard) >= 2:
                suggestions.append({
                    'id': 6,
                    'name': '综合仪表盘',
                    'type': 'dashboard',
                    'layout': f'{len(plots_for_dashboard//2 + plots_for_dashboard%2)}x2',
                    'plots': plots_for_dashboard,
                    'description': f'{len(plots_for_dashboard)}个维度综合分析',
                    'reason': '数据维度丰富，综合展示更全面',
                    'priority': 'low'
                })
        
        self.suggestions = suggestions
        return suggestions
    
    def generate_report(self):
        """生成分析报告"""
        self._generate_suggestions()
        
        report = []
        report.append("# 数据分析报告\n")
        report.append(f"**分析时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        report.append(f"**数据文件**: {os.path.basename(self.data_file)}\n\n")
        
        # 数据概览
        report.append("## 📊 数据概览\n")
        report.append(f"- **数据维度**: {len(self.df)} 行 × {len(self.df.columns)} 列\n")
        report.append(f"- **数值列**: {len(self._get_numeric_columns())} 个\n")
        report.append(f"- **分类列**: {len(self._get_categorical_columns())} 个\n")
        report.append(f"- **时间列**: {len(self._detect_datetime_columns())} 个\n\n")
        
        # 列详情
        report.append("## 📋 列详情\n")
        report.append("| 列名 | 类型 | 唯一值 | 缺失值 | 说明 |\n")
        report.append("|------|------|--------|--------|------|\n")
        
        for col, info in self.columns_info.items():
            type_icon = {"numeric": "🔢", "categorical": "🏷️", "datetime": "📅"}.get(
                info['type'], "❓"
            )
            null_pct = info['null_count'] / len(self.df) * 100
            
            desc = ""
            if info['type'] == 'numeric':
                desc = f"均值={info['mean']:.2f}, 标准差={info['std']:.2f}"
            elif info['type'] == 'categorical':
                desc = f"类别数={info['unique_count']}"
            
            report.append(
                f"| {col} | {type_icon} {info['type']} | "
                f"{info['unique_count']} | {info['null_count']} ({null_pct:.1f}%) | {desc} |\n"
            )
        
        report.append("\n")
        
        # 图表建议
        report.append("## 💡 图表建议\n")
        report.append(f"基于数据特征，为您推荐 **{len(self.suggestions)}** 个图表方案：\n\n")
        
        for suggestion in self.suggestions:
            priority_icon = {"high": "⭐", "medium": "🔹", "low": "▫️"}.get(
                suggestion['priority'], "▫️"
            )
            
            report.append(f"### 方案{suggestion['id']}: {suggestion['name']} {priority_icon}\n")
            report.append(f"- **图表类型**: {suggestion['type']}\n")
            report.append(f"- **展示内容**: {suggestion['description']}\n")
            report.append(f"- **推荐理由**: {suggestion['reason']}\n\n")
        
        # 用户行动指引
        report.append("## 🎯 下一步\n")
        report.append("请告诉我您想要：\n")
        report.append('- **"生成方案1和2"** - 生成指定编号的图表\n')
        report.append('- **"全部生成"** - 生成所有建议的图表\n')
        report.append('- **"修改方案X..."** - 提出您的修改意见（如：修改X轴为...）\n')
        report.append('- **"我要做XXX图"** - 描述您想要的图表\n\n')
        
        return "".join(report)


def main():
    import argparse
    
    parser = argparse.ArgumentParser(description='数据分析工具')
    parser.add_argument('--input', '-i', required=True, help='输入数据文件')
    parser.add_argument('--output', '-o', help='输出报告文件')
    
    args = parser.parse_args()
    
    analyzer = DataAnalyzer(args.input)
    report = analyzer.generate_report()
    
    print(report)
    
    if args.output:
        with open(args.output, 'w', encoding='utf-8') as f:
            f.write(report)
        print(f"\n报告已保存: {args.output}")


if __name__ == '__main__':
    main()


path: scripts/plot_generator.py
content: #!/usr/bin/env python3
"""
图表生成模块
根据配置生成科研图表
"""

import os
import sys
import json
import matplotlib
matplotlib.use('Agg')  # 非交互式后端

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np


class PlotGenerator:
    """图表生成器"""
    
    # 配色方案
    PALETTES = {
        'academic': ['#4472C4', '#ED7D31', '#A5A5A5', '#FFC000', '#5B9BD5'],
        'nature': ['#E64B35', '#4DBBD5', '#00A087', '#3C5488', '#F39B7F'],
        'science': ['#074893', '#C41E3A', '#FFC800', '#4C4C4C', '#7F7F7F'],
        'vibrant': ['#E41A1C', '#377EB8', '#4DAF4A', '#984EA3', '#FF7F00'],
    }
    
    def __init__(self, config, output_dir, timestamp):
        self.config = config
        self.output_dir = output_dir
        self.timestamp = timestamp
        self.data_file = config.get('data_file')
        self.df = None
        self._setup_style()
        if self.data_file:
            self._load_data()
    
    def _setup_style(self):
        """设置科研样式"""
        plt.style.use('seaborn-v0_8-whitegrid')
        
        # 科研论文常用设置
        plt.rcParams['figure.dpi'] = 150
        plt.rcParams['savefig.dpi'] = 300
        plt.rcParams['font.size'] = 10
        plt.rcParams['axes.labelsize'] = 11
        plt.rcParams['axes.titlesize'] = 12
        plt.rcParams['legend.fontsize'] = 9
        plt.rcParams['xtick.labelsize'] = 9
        plt.rcParams['ytick.labelsize'] = 9
        
        # 中文字体设置（尝试常见字体）
        chinese_fonts = ['SimHei', 'Heiti TC', 'WenQuanYi Micro Hei', 'Arial Unicode MS']
        for font in chinese_fonts:
            try:
                plt.rcParams['font.sans-serif'] = [font, 'Arial', 'DejaVu Sans']
                plt.rcParams['axes.unicode_minus'] = False
                break
            except:
                continue
    
    def _load_data(self):
        """加载数据"""
        ext = os.path.splitext(self.data_file)[1].lower()
        
        if ext == '.csv':
            self.df = pd.read_csv(self.data_file)
        elif ext in ['.xlsx', '.xls']:
            self.df = pd.read_excel(self.data_file)
        else:
            self.df = pd.read_csv(self.data_file, sep=r'\s+')
    
    def _save_figure(self, fig, plot_type, desc=""):
        """
        保存图表为PDF和PNG两种格式
        
        命名规范: {timestamp}_fig{n}_{type}_{desc}.{ext}
        """
        # 查找当前已有图表数量
        existing = [f for f in os.listdir(self.output_dir) 
                   if f.startswith(self.timestamp) and f.endswith('.pdf')]
        fig_num = len(existing) + 1
        
        desc_suffix = f"_{desc}" if desc else ""
        base_name = f"{self.timestamp}_fig{fig_num}_{plot_type}{desc_suffix}"
        
        # 保存PDF（矢量图，适合LaTeX）
        pdf_path = os.path.join(self.output_dir, f"{base_name}.pdf")
        fig.savefig(pdf_path, bbox_inches='tight', format='pdf')
        
        # 保存PNG（预览图，适合查看）
        png_path = os.path.join(self.output_dir, f"{base_name}.png")
        fig.savefig(png_path, bbox_inches='tight', format='png')
        
        plt.close(fig)
        
        return [pdf_path, png_path]
    
    def _generate_line_plot(self, plot_config):
        """生成折线图"""
        x_col = plot_config['x_col']
        y_col = plot_config['y_col']
        
        fig, ax = plt.subplots(figsize=(8, 5))
        
        # 检查是否是时间序列
        if pd.api.types.is_datetime64_any_dtype(self.df[x_col]):
            ax.plot(self.df[x_col], self.df[y_col], 
                   linewidth=2, color=self.PALETTES['academic'][0])
        else:
            # 按X排序
            df_sorted = self.df.sort_values(by=x_col)
            ax.plot(df_sorted[x_col], df_sorted[y_col], 
                   linewidth=2, color=self.PALETTES['academic'][0])
        
        ax.set_xlabel(x_col)
        ax.set_ylabel(y_col)
        ax.set_title(f'{y_col}趋势图')
        ax.grid(True, alpha=0.3)
        
        return self._save_figure(fig, 'line', y_col)
    
    def _generate_bar_plot(self, plot_config):
        """生成柱状图"""
        x_col = plot_config['x_col']
        y_col = plot_config['y_col']
        
        # 聚合数据
        agg_data = self.df.groupby(x_col)[y_col].mean().sort_values(ascending=False)
        
        fig, ax = plt.subplots(figsize=(8, 5))
        
        bars = ax.bar(range(len(agg_data)), agg_data.values,
                     color=self.PALETTES['academic'][:len(agg_data)])
        ax.set_xticks(range(len(agg_data)))
        ax.set_xticklabels(agg_data.index, rotation=45, ha='right')
        ax.set_xlabel(x_col)
        ax.set_ylabel(y_col)
        ax.set_title(f'{y_col}按{x_col}分组对比')
        
        # 添加数值标签
        for bar in bars:
            height = bar.get_height()
            ax.text(bar.get_x() + bar.get_width()/2., height,
                   f'{height:.1f}',
                   ha='center', va='bottom', fontsize=8)
        
        return self._save_figure(fig, 'bar', f"{y_col}_by_{x_col}")
    
    def _generate_box_plot(self, plot_config):
        """生成箱线图"""
        y_col = plot_config['y_col']
        x_col = plot_config.get('x_col')
        
        fig, ax = plt.subplots(figsize=(8, 5))
        
        if x_col:
            self.df.boxplot(column=y_col, by=x_col, ax=ax)
            ax.set_title(f'{y_col}分布（按{x_col}分组）')
        else:
            self.df.boxplot(column=y_col, ax=ax)
            ax.set_title(f'{y_col}分布')
        
        ax.set_ylabel(y_col)
        plt.suptitle('')  # 移除默认标题
        
        return self._save_figure(fig, 'box', y_col)
    
    def _generate_scatter_plot(self, plot_config):
        """生成散点图"""
        x_col = plot_config['x_col']
        y_col = plot_config['y_col']
        add_reg = plot_config.get('add_regression', False)
        
        fig, ax = plt.subplots(figsize=(7, 6))
        
        # 散点
        ax.scatter(self.df[x_col], self.df[y_col], 
                  alpha=0.6, s=50, color=self.PALETTES['academic'][0])
        
        # 回归线
        if add_reg:
            z = np.polyfit(self.df[x_col].dropna(), 
                          self.df[y_col].dropna(), 1)
            p = np.poly1d(z)
            x_line = np.linspace(self.df[x_col].min(), self.df[x_col].max(), 100)
            ax.plot(x_line, p(x_line), "r--", alpha=0.8, linewidth=2,
                   label=f'拟合: y={z[0]:.2f}x+{z[1]:.2f}')
            ax.legend()
        
        ax.set_xlabel(x_col)
        ax.set_ylabel(y_col)
        ax.set_title(f'{y_col} vs {x_col}')
        ax.grid(True, alpha=0.3)
        
        return self._save_figure(fig, 'scatter', f"{y_col}_vs_{x_col}")
    
    def _generate_heatmap(self, plot_config):
        """生成热力图"""
        cols = plot_config['cols']
        corr = self.df[cols].corr()
        
        fig, ax = plt.subplots(figsize=(max(6, len(cols)), max(5, len(cols)*0.8)))
        
        sns.heatmap(corr, annot=True, fmt='.2f', cmap='RdBu_r',
                   center=0, square=True, ax=ax,
                   cbar_kws={'shrink': 0.8})
        ax.set_title('变量相关性热力图')
        
        return self._save_figure(fig, 'heatmap', 'correlation')
    
    def _generate_dashboard(self, plot_config):
        """生成综合仪表盘"""
        plots = plot_config['plots']
        n_plots = len(plots)
        n_cols = 2
        n_rows = (n_plots + 1) // 2
        
        fig = plt.figure(figsize=(14, 5 * n_rows))
        
        for idx, plot in enumerate(plots):
            ax = fig.add_subplot(n_rows, n_cols, idx + 1)
            
            if plot['type'] == 'line':
                ax.plot(self.df[plot['x']], self.df[plot['y']],
                       linewidth=2, color=self.PALETTES['academic'][0])
            elif plot['type'] == 'bar':
                agg = self.df.groupby(plot['x'])[plot['y']].mean()
                ax.bar(range(len(agg)), agg.values,
                      color=self.PALETTES['academic'][:len(agg)])
                ax.set_xticks(range(len(agg)))
                ax.set_xticklabels(agg.index, rotation=45, ha='right')
            elif plot['type'] == 'scatter':
                ax.scatter(self.df[plot['x']], self.df[plot['y']],
                          alpha=0.6, color=self.PALETTES['academic'][0])
            
            ax.set_xlabel(plot['x'])
            ax.set_ylabel(plot['y'])
            ax.set_title(f"({chr(97+idx)}) {plot['title']}")
            ax.grid(True, alpha=0.3)
        
        plt.tight_layout()
        return self._save_figure(fig, 'dashboard', 'multi')
    
    def generate(self):
        """
        根据配置生成所有图表
        
        返回: 生成的文件路径列表
        """
        generated_files = []
        plots = self.config.get('plots', [])
        
        for plot_config in plots:
            plot_type = plot_config['type']
            
            try:
                if plot_type == 'line':
                    files = self._generate_line_plot(plot_config)
                elif plot_type == 'bar':
                    files = self._generate_bar_plot(plot_config)
                elif plot_type == 'box':
                    files = self._generate_box_plot(plot_config)
                elif plot_type == 'scatter':
                    files = self._generate_scatter_plot(plot_config)
                elif plot_type == 'heatmap':
                    files = self._generate_heatmap(plot_config)
                elif plot_type == 'dashboard':
                    files = self._generate_dashboard(plot_config)
                else:
                    print(f"⚠️  未知图表类型: {plot_type}")
                    continue
                
                generated_files.extend(files)
                
            except Exception as e:
                print(f"❌ 生成图表失败 ({plot_type}): {e}")
        
        return generated_files


def main():
    import argparse
    
    parser = argparse.ArgumentParser(description='图表生成工具')
    parser.add_argument('--config', '-c', required=True, help='配置文件')
    parser.add_argument('--output-dir', '-o', default='.', help='输出目录')
    
    args = parser.parse_args()
    
    with open(args.config, 'r', encoding='utf-8') as f:
        config = json.load(f)
    
    timestamp = config.get('timestamp', pd.Timestamp.now().strftime('%Y%m%d-%H%M%S'))
    
    generator = PlotGenerator(config, args.output_dir, timestamp)
    files = generator.generate()
    
    print(f"✅ 已生成 {len(files)} 个文件")
    for f in files:
        print(f"   📊 {f}")


if __name__ == '__main__':
    main()


path: scripts/workflow.py
content: #!/usr/bin/env python3
"""
PyThesisPlot 主工作流脚本
完整流程：数据接收 → 分析 → 建议 → 确认 → 生成
"""

import os
import sys
import shutil
import json
import argparse
from datetime import datetime
from pathlib import Path

# 添加脚本目录到路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from data_analyzer import DataAnalyzer
from plot_generator import PlotGenerator


class WorkflowManager:
    """工作流管理器"""
    
    def __init__(self, output_base="output"):
        self.output_base = output_base
        self.timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
        self.work_dir = None
        self.original_filename = None
        
    def setup_work_directory(self, input_file):
        """
        创建工作目录，保存上传的文件
        
        命名规范: output/YYYYMMDD-HHMMSS-原文件名/
        """
        self.original_filename = Path(input_file).stem
        dir_name = f"{self.timestamp}-{self.original_filename}"
        self.work_dir = os.path.join(self.output_base, dir_name)
        
        # 创建目录
        os.makedirs(self.work_dir, exist_ok=True)
        print(f"📁 工作目录: {self.work_dir}")
        
        # 复制并重命名文件
        ext = Path(input_file).suffix
        saved_name = f"{self.timestamp}-{self.original_filename}{ext}"
        saved_path = os.path.join(self.work_dir, saved_name)
        shutil.copy2(input_file, saved_path)
        print(f"📄 数据文件: {saved_name}")
        
        return saved_path
    
    def analyze_data(self, data_file):
        """执行数据分析"""
        print("\n🔍 正在分析数据...")
        analyzer = DataAnalyzer(data_file)
        report = analyzer.generate_report()
        
        # 保存分析报告
        report_path = os.path.join(self.work_dir, "analysis_report.md")
        with open(report_path, 'w', encoding='utf-8') as f:
            f.write(report)
        print(f"📝 分析报告: analysis_report.md")
        
        return report, analyzer.suggestions
    
    def generate_plots(self, config):
        """
        生成图表
        
        输出到工作目录，同时生成PDF和PNG
        """
        print("\n🎨 正在生成图表...")
        generator = PlotGenerator(config, self.work_dir, self.timestamp)
        generated_files = generator.generate()
        
        print(f"✅ 已生成 {len(generated_files)} 个图表")
        for f in generated_files:
            print(f"   📊 {os.path.basename(f)}")
        
        return generated_files
    
    def save_plot_config(self, config):
        """保存图表配置"""
        config_path = os.path.join(self.work_dir, "plot_config.json")
        with open(config_path, 'w', encoding='utf-8') as f:
            json.dump(config, f, indent=2, ensure_ascii=False)
        print(f"⚙️  图表配置: plot_config.json")


def print_analysis_report(report, suggestions):
    """打印分析报告（用于展示给用户）"""
    print("\n" + "="*60)
    print(report)
    print("="*60)


def main():
    parser = argparse.ArgumentParser(
        description="PyThesisPlot 完整工作流",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
使用示例:
  # 完整工作流
  python workflow.py --input data.csv
  
  # 仅分析
  python workflow.py --input data.csv --analyze-only
  
  # 从配置生成
  python workflow.py --config plot_config.json
        """
    )
    parser.add_argument('--input', '-i', help='输入数据文件')
    parser.add_argument('--config', '-c', help='图表配置文件（跳过分析阶段）')
    parser.add_argument('--output-dir', '-o', default='output', 
                       help='输出目录基础路径 (默认: output)')
    parser.add_argument('--analyze-only', action='store_true',
                       help='仅执行数据分析')
    
    args = parser.parse_args()
    
    if not args.input and not args.config:
        parser.print_help()
        sys.exit(1)
    
    # 初始化工作流
    workflow = WorkflowManager(args.output_dir)
    
    if args.config:
        # 从配置直接生成
        print("📋 从配置生成图表...")
        with open(args.config, 'r', encoding='utf-8') as f:
            config = json.load(f)
        workflow.work_dir = os.path.dirname(args.config) or "."
        workflow.timestamp = config.get('timestamp', workflow.timestamp)
        workflow.generate_plots(config)
        
    elif args.input:
        # 完整工作流
        if not os.path.exists(args.input):
            print(f"❌ 文件不存在: {args.input}")
            sys.exit(1)
        
        # 阶段1: 设置工作目录
        print("="*60)
        print("阶段1: 数据接收")
        print("="*60)
        data_file = workflow.setup_work_directory(args.input)
        
        # 阶段2: 数据分析
        print("\n" + "="*60)
        print("阶段2: 数据分析")
        print("="*60)
        report, suggestions = workflow.analyze_data(data_file)
        
        # 展示分析报告
        print_analysis_report(report, suggestions)
        
        if args.analyze_only:
            print("\n✅ 分析完成，等待用户确认后生成图表")
            return
        
        # 阶段3: 用户确认（模拟交互）
        print("\n" + "="*60)
        print("阶段3: 用户确认")
        print("="*60)
        print("\n💡 提示: 在实际使用中，这里会暂停等待用户确认")
        print("   用户可以说: '生成方案1和2' / '全部生成' / '修改...'")
        
        # 模拟用户选择（实际使用时需要交互）
        selected = input("\n请输入要生成的方案编号（如: 1,2 或 all）: ").strip()
        
        # 阶段4: 生成
        print("\n" + "="*60)
        print("阶段4: 生成图表")
        print("="*60)
        
        # 根据选择生成配置
        if selected.lower() == 'all':
            selected_indices = list(range(len(suggestions)))
        else:
            selected_indices = [int(x.strip()) - 1 for x in selected.split(',')]
        
        config = {
            'timestamp': workflow.timestamp,
            'data_file': data_file,
            'original_file': args.input,
            'plots': [suggestions[i] for i in selected_indices if 0 <= i < len(suggestions)]
        }
        
        # 保存配置
        workflow.save_plot_config(config)
        
        # 生成图表
        workflow.generate_plots(config)
        
        print("\n" + "="*60)
        print("✅ 全部完成!")
        print(f"📁 所有文件已保存到: {workflow.work_dir}")
        print("="*60)


if __name__ == '__main__':
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)