backup materials and knowledge-base docs

This commit is contained in:
admin
2026-05-30 16:22:29 +08:00
commit 93e50e8fce
3024 changed files with 2994945 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
# Chart Selection
## Task-to-chart mapping
| Communication task | Preferred forms | Notes |
|---|---|---|
| Benchmark comparison | grouped scatter, bar, companion table | use table when exact values matter most |
| Ablation | grouped comparison, dumbbell, compact table | keep the dimension count small |
| Calibration / evaluation | calibration, ROC, PR, BlandAltman | choose what matches the evaluation claim |
| Distribution | box, violin, raincloud, histogram, density, ECDF, QQ | choose by whether shape or exact quantiles matter |
| Relationship | scatter, bubble, contour2d, hexbin | use hexbin/contour2d when overplotting is severe |
| Trend | line, area | line is usually the safer default |
| Diagnostic effect size | forest plot, volcano | match domain and inference style |
| Set/composition | UpSet, stacked ratio, donut, radial hierarchy | avoid decorative complexity unless it helps interpretation |
| Exact benchmark appendix | publication table | default to `pubtab` |
## Use X instead of Y
- Use **grouped scatter** or a **table** instead of a dense grouped bar when exact per-group values matter.
- Use **line** instead of bar for ordered progression over time or scale.
- Use **UpSet** instead of Venn-style thinking once the set count grows.
- Use **forest plot** instead of overloaded textual effect summaries.
- Use **table** instead of radar when precision and comparability matter more than shape.
- Use **hexbin** or **contour2d** instead of raw scatter when point overlap hides structure.
- Use **ECDF** when comparing cumulative distributions clearly is more important than showing a smoothed KDE.
## Anti-patterns
Avoid:
- pie/donut for exact quantitative comparison unless the composition story is primary and category count is small,
- radar for many categories or when axes are not semantically comparable,
- 3D effects,
- decorative color ramps without semantic purpose,
- overly dense legends that repeat axis information,
- mixed chart types that make the evidence harder to read,
- turning every result into a figure when a publication table would be cleaner.
## Selection heuristic
Ask in order:
1. What claim is the reader supposed to take away?
2. Does the reader need pattern perception or exact value lookup?
3. Are the groups ordered, categorical, repeated, hierarchical, or overlapping?
4. Is the result single-panel or likely part of a multi-panel figure?
5. Would a figure-only answer hide important exact values that should live in a table?

View File

@@ -0,0 +1,34 @@
# Composite Assembly
## Principle
Composite assembly is a **secondary branch**, not the default workflow.
Use it when:
- the user explicitly wants a multi-panel paper figure,
- panel-level maintenance matters,
- or the final paper figure needs finishing beyond a single exported plot.
## Default stance
- Single-panel figure → stay in `pubfig` normal export mode.
- Multi-panel figure with real assembly needs → use panel/composite export.
- Figma is optional and should not be introduced unless it solves a real assembly problem.
## pubfig routes
Relevant `pubfig` capabilities:
- `export_panel(...)`
- `export_panels(...)`
- `batch_export(...)`
- `save_figure(...)`
If the environment already uses a pubfig/Figma bridge workflow, keep `figure_id` stable across revisions.
## Practical rule
Escalate to composite assembly only after the panel content itself is strong.
Do not use Figma/composite assembly to hide weak chart choice, poor labels, or overloaded panels.

View File

@@ -0,0 +1,159 @@
# Execution and Verification
## Goal
Turn a high-level publication figure/table request into a route that is actually runnable in the current environment.
## Minimum environment probe
Prefer the lightest useful checks.
### Preferred bundled probe
```bash
python3 scripts/ensure_publication_tooling.py --require pubfig --json
python3 scripts/ensure_publication_tooling.py --require pubtab --json
```
The helper probes availability, force-installs missing dependencies into the active interpreter, and returns the post-install status.
### Equivalent manual checks
```bash
python -c "import pubfig; print(pubfig.__version__)"
python -c "import pubtab; print(pubtab.__version__)"
pubtab --help
```
Do not spend the whole turn on setup if the user primarily needs design guidance. Just identify whether the route is executable now or should degrade gracefully.
## Automatic installation policy
If a dependency is missing and the task requires real execution, install it automatically before continuing.
### Preferred bundled route
Use the bundled helper when it is present:
```bash
python3 scripts/ensure_publication_tooling.py --require pubfig
python3 scripts/ensure_publication_tooling.py --require pubtab
```
The helper chooses `uv pip install --python <active-python>` when the project is clearly `uv`-managed, and otherwise falls back to `python -m pip install ...`.
### Equivalent manual install commands
```bash
uv pip install --python "$VIRTUAL_ENV/bin/python" pubfig
uv pip install --python "$VIRTUAL_ENV/bin/python" pubtab
python -m pip install pubfig
python -m pip install pubtab
```
### Required follow-up
After installation:
1. re-run the availability probe,
2. report the updated environment status,
3. continue with the runnable figure/table workflow.
If installation fails, capture the exact error and then fall back to design/specification guidance.
## Route selection
### Use `pubfig` when
- the task is primarily a figure,
- the user already has Python data structures,
- the result is a plot family already covered by `pubfig`,
- export quality matters immediately.
### Use `pubtab` when
- the task is primarily a publication table,
- the input is an Excel workbook, a `.tex` table, or a file-driven workflow,
- the reader needs exact values,
- previewing the table before manuscript insertion matters.
### Use both when
- the figure carries the visual pattern,
- the table preserves exact benchmark values,
- the paper section benefits from one fast visual plus one exact-value artifact.
## First runnable verification
### `pubfig`
After generating a minimal figure route, the first useful verification is:
- can the code execute,
- does `save_figure(...)` or `batch_export(...)` produce the expected files,
- do output suffixes match the intended formats.
### `pubtab`
After generating a minimal table route, the first useful verification is:
- can `xlsx2tex` or `tex2xlsx` run,
- can `preview` render PNG or PDF,
- does the chosen backend (`tabular` or `tabularray`) match the manuscript need.
## Current practical notes
### `pubfig`
Useful export primitives include:
- `save_figure(...)`
- `batch_export(...)`
- `export_panel(...)`
- `export_panels(...)`
Use panel export only when multi-panel assembly is truly needed.
### `pubtab`
Useful file-oriented routes include:
- `pubtab xlsx2tex ...`
- `pubtab tex2xlsx ...`
- `pubtab preview ...`
Remember:
- `xlsx2tex` exports all sheets by default when `--sheet` is not set,
- `preview` can render PNG or PDF,
- `--latex-backend tabularray` should be chosen only when the manuscript/backend requires `tblr`,
- when preview reliability is the immediate priority, validate the table body first and add final `caption` / `label` in a separate manuscript-facing step if needed.
## Graceful degradation
If the tool is missing:
- first try the bundled auto-install helper,
- if that route is unavailable, use the manual install commands above,
- if installation still fails, provide:
- the artifact recommendation,
- the exact files the user should prepare,
- a draft CLI or Python route,
- the export targets,
- and the publication QA checklist.
## Default output wording
When the route is runnable now, say:
- what to run,
- what files should appear,
- what to inspect next.
When the route is not runnable now, say:
- what is missing,
- which helper command or install command was attempted,
- whether the install succeeded or failed,
- what the intended route will be after install,
- and what design decision can already be locked in today.

View File

@@ -0,0 +1,104 @@
# pubfig Recipes
`pubfig` is the default engine for scientific figures.
## Core route
Typical minimal workflow:
```python
import pubfig as pf
fig = pf.line(data, x=x, series_names=["A", "B"])
pf.save_figure(fig, "figure1.pdf")
```
## Common figure families
| Need | Preferred `pubfig` functions |
|---|---|
| benchmark comparison | `bar_scatter`, `grouped_scatter`, `bar`, `line` |
| ablation | `bar_scatter`, `dumbbell`, `paired`, `bar` |
| distribution | `box`, `violin`, `raincloud`, `histogram`, `density`, `ecdf`, `qq` |
| relationship | `scatter`, `bubble`, `contour2d`, `hexbin` |
| trend | `line`, `area` |
| diagnostic / evaluation | `calibration`, `forest_plot`, `bland_altman`, `volcano`, `roc`, `pr_curve` |
| composition / hierarchy | `donut`, `upset`, `radial_hierarchy`, `circular_grouped_bar`, `circular_stacked_bar`, `stacked_ratio_barh` |
| matrix / map | `heatmap`, `corr_matrix`, `clustermap` |
## Export defaults
For a normal first pass:
```python
pf.save_figure(fig, "figure1.pdf")
```
For multiple formats:
```python
pf.batch_export(
fig,
"figure1",
formats=("pdf", "svg", "png"),
spec="nature",
width="single",
dpi=300,
)
```
## When to add export parameters
Only add more export controls when the task demands them:
- `spec` / `width` for venue-style export
- explicit SVG for vector-first downstream editing
- PNG for quick review or raster deliverables
- panel export when the user truly needs composite assembly
- `batch_export(...)` when the same figure needs several publication-style outputs
## Panel export branch
Use these only when multi-panel assembly is genuinely needed:
- `export_panel(...)`
- `export_panels(...)`
Do not default to panel export for single figures.
## Minimal recipe patterns
### Benchmark comparison
```python
fig = pf.grouped_scatter(values, category_names=category_names, group_names=model_names)
pf.save_figure(fig, "benchmark.pdf")
```
### Ablation
```python
fig = pf.dumbbell(baseline, improved, category_names=labels)
pf.save_figure(fig, "ablation.pdf")
```
### Calibration
```python
fig = pf.calibration(prob_true, prob_pred)
pf.save_figure(fig, "calibration.pdf")
```
### Forest plot
```python
fig = pf.forest_plot(effect, lower, upper, labels=labels, reference=1.0)
pf.save_figure(fig, "forest.pdf")
```
### Heatmap
```python
fig = pf.heatmap(matrix)
pf.save_figure(fig, "heatmap.pdf")
```

View File

@@ -0,0 +1,47 @@
# Publication QA Checklist
## Figure QA
Check:
- Is the chart family appropriate for the scientific claim?
- Are axes labeled clearly, with units when needed?
- Is category ordering meaningful and stable?
- Are color choices readable in grayscale or for color-deficient readers?
- Are fonts, line weights, and marker sizes internally consistent?
- Is the legend necessary, and if so, is it compact?
- Does the figure stay readable after downscaling to likely paper width?
- If multi-panel, are labels, spacing, and styling consistent across panels?
- Does the caption need exact numbers that should instead live in a table?
## Table QA
Check:
- Is a table actually the right artifact, or should a companion figure exist?
- Are row/column labels short but unambiguous?
- Are important values easy to locate?
- Is the caption specific enough to stand alone?
- Is the table too dense for the main paper and better suited to appendix?
- If two-column format matters, was width/span considered explicitly?
- Was a preview rendered before treating the table as final?
## Mixed deliverable QA
If both a figure and table are present:
- Does each have a distinct role?
- Is the figure carrying pattern perception?
- Is the table preserving exact values?
- Is there duplication that should be reduced?
## Revision questions
If the artifact is weak, ask:
- Should the chart family change?
- Should exact values move into a table?
- Should the artifact split into two panels?
- Should labels or legends be simplified?
- Should export width/format change?
- Should the artifact move from figure-first to table-first, or the reverse?

View File

@@ -0,0 +1,133 @@
# pubtab Recipes
`pubtab` is the default engine for publication-ready tables.
## Core routes
### Excel to LaTeX
```bash
pubtab xlsx2tex results.xlsx -o results.tex
```
### LaTeX to Excel
```bash
pubtab tex2xlsx tables.tex -o tables.xlsx
```
### Preview
```bash
pubtab preview results.tex -o results.png --dpi 300
pubtab preview results.tex --format pdf -o results.pdf
```
## Python route
```python
import pubtab
pubtab.xlsx2tex("results.xlsx", output="results.tex", theme="three_line")
pubtab.preview("results.tex", output="results.png", dpi=300)
```
## Route selection rule
Prefer the **CLI** when:
- the user already speaks in files,
- the source is Excel or `.tex`,
- the main need is export and preview.
Prefer the **Python API** when:
- the task already lives inside a notebook or script,
- the table generation is part of a larger reproducible pipeline.
## Current practical notes
- `xlsx2tex` exports **all sheets by default** when `--sheet` is not set.
- `preview` can render **PNG or PDF**.
- `--latex-backend tabularray` is useful only when the manuscript/backend really requires `tblr`.
- `preview` can auto-detect `tblr`, but explicit backend override is still fine when needed.
- for a robust preview-first workflow, preview the table body first and add the final `caption` / `label` in the manuscript or in a final non-preview export step when needed.
## When to use `tabularray`
Use `--latex-backend tabularray` when:
- the user explicitly wants `tblr`,
- the manuscript already uses `tabularray`,
- or the backend must match an existing paper template.
Example:
```bash
pubtab xlsx2tex results.xlsx -o results_tblr.tex --theme three_line --latex-backend tabularray
```
## Common publication controls
Use these when they are justified:
- `--caption`
- `--label`
- `--span-columns`
- `--preview`
- `--latex-backend`
- `--sheet`
- `--with-resizebox`
- `--without-resizebox`
- `--resizebox-width`
## Default guidance
- start with the smallest `xlsx2tex` route,
- preview before treating the table as final,
- use a publication table when exact values matter more than quick pattern perception,
- keep figure and table roles distinct in mixed deliverables.
## Minimal recipe patterns
### Benchmark table from Excel
```bash
pubtab xlsx2tex benchmark.xlsx -o benchmark.tex --caption "Main benchmark results." --label "tab:benchmark"
```
### Two-column table
```bash
pubtab xlsx2tex benchmark.xlsx -o benchmark.tex --span-columns
```
### Preview before submission
```bash
pubtab xlsx2tex benchmark.xlsx -o benchmark_preview.tex
pubtab preview benchmark_preview.tex -o benchmark.png --dpi 300
```
Use this route when the immediate goal is a reliable visual check of the table body.
Keep `caption` / `label` as a separate manuscript-facing step if the preview is the main verification target.
### Final manuscript-facing export
```bash
pubtab xlsx2tex benchmark.xlsx -o benchmark.tex --caption "Main benchmark results." --label "tab:benchmark"
```
### All-sheets export
```bash
pubtab xlsx2tex benchmark.xlsx -o out/benchmark.tex
```
### Native file-pipeline batch roundtrip
```bash
pubtab tex2xlsx ./tables_tex -o ./out/xlsx
pubtab xlsx2tex ./out/xlsx -o ./out/tex
pubtab preview ./out/tex -o ./out/png --format png --dpi 300
```

View File

@@ -0,0 +1,199 @@
# pubfig API map (source-driven)
This guide maps the public `pubfig` API from `pubfig/src/pubfig/__init__.py` to the underlying modules.
## 1. Stable entrypoint
The public contract is defined by re-exports in `pubfig.__init__`.
For agents, this means:
- if a symbol is re-exported there, it is a good default public entrypoint;
- if a helper only exists in deep internal modules, treat it as implementation detail unless there is a strong reason not to.
## 2. Public API groups
### Themes
Public re-exports:
- `set_default_theme`
- `get_default_theme`
- `get_theme`
- `register_theme`
Use these when the task is really about reusable visual policy.
Do not hardcode theme assumptions if a registry call is more appropriate.
### Colors and palettes
Public re-exports include:
- `DEFAULT`, `NATURE`, `SCIENCE`, `LANCET`, `JAMA`
- `get_palette`
- `register_palette`
- `color_to_rgba`
- `darken_color`
- `show_palette`
Source fact:
- palette registration and palette inspection are exposed from the package root.
Operational implication:
- treat palette selection and palette registration as public API usage, not as deep internal customization.
### Export
Public re-exports:
- `save_figure`
- `batch_export`
- `PanelExportRecord`
- `export_panel`
- `export_panels`
- `package_figma_bundle`
- `validate_figma_bundle`
- `inspect_figma_bundle`
Skill implication:
- normal paper figures should usually stop at `save_figure` or `batch_export`
- panel workflows should use `export_panel(s)`
- bundle helpers are for bridge/Figma handoff, not the default answer
### Figure specs
Public re-exports:
- `FigureSpec`
- `get_figure_spec`
- `register_figure_spec`
- `list_figure_specs`
Use this layer whenever the user asks for venue-aware width, journal defaults, or a custom export profile.
### Plot families
The public plot surface is broad, but the source still clusters naturally.
#### Comparison / summary figures
Representative public calls:
- `bar`
- `bar_scatter`
- `stacked_bar`
- `stacked_ratio_barh`
- `donut`
- `dumbbell`
- `forest_plot`
- `grouped_scatter`
- `upset`
Use these for benchmark, ablation, summary, composition, and set-overlap tasks.
#### Distribution figures
Representative public calls:
- `ecdf`
- `qq`
- `box`
- `density`
- `hexbin`
- `histogram`
- `raincloud`
- `strip`
- `ridgeline`
- `violin`
Use these when the scientific claim is about spread, calibration of assumptions, or cohort structure.
#### Trend / profile figures
Representative public calls:
- `line`
- `area`
- `parallel_coordinates`
- `radar`
- `radial_hierarchy`
- `circular_stacked_bar`
- `circular_grouped_bar`
Not all of these are equally strong for publication use. The skill should still apply chart-selection discipline before calling them.
#### Relationship / embedding figures
Representative public calls:
- `scatter`
- `volcano`
- `bubble`
- `contour2d`
- `paired`
- `heatmap`
- `corr_matrix`
- `clustermap`
- `dimreduce`
- `pca_biplot`
Use these for association, error structure, feature layout, and representation views.
#### Evaluation figures
Representative public calls:
- `roc`
- `pr_curve`
- `calibration`
- `bland_altman`
This cluster matters because the source gives them dedicated implementation in `plots/evaluation.py`, which is a sign that evaluation charts are a first-class use case.
## 3. Return-value contract
The source in `export/io.py` makes a subtle but important contract explicit:
- export functions accept a Matplotlib `Figure`,
- or an `Axes`,
- or any object exposing a `.figure` attribute that resolves to a `Figure`.
Source fact:
- the export layer accepts standard Matplotlib figure objects or figure-bearing wrappers.
Operational implication:
- keep the `Figure` handle available and route export through the standard Matplotlib-facing export path.
For the skill, the safest phrasing is:
- create the figure,
- keep a handle to the `Figure`,
- then export explicitly.
## 4. What is not the main stable plotting interface
From the source tree, the CLI is not where normal chart creation happens.
It is mostly an operational layer for Figma bundle and bridge actions.
So if a user says “generate a paper-ready figure,” the skill should not default to a CLI answer.
## 5. Safe public usage pattern
The most source-faithful pattern is:
1. choose a public plot function from `pubfig`
2. generate a `Figure`
3. export via `save_figure(...)` or `batch_export(...)`
4. only use panel/bundle helpers when composition is actually required
## 6. Source-guided caution points
- Do not mix up plot-time design sizing with export-time publication sizing.
- Do not use `save_figure(...)` as a multi-format exporter; the source now pushes that role to `batch_export(...)`.
- Do not route ordinary figure-generation tasks through the Figma bridge CLI.
- Do not assume all public plot families are equally appropriate; the skill must still filter by scientific communication quality.

View File

@@ -0,0 +1,190 @@
# pubfig architecture (source-driven)
This guide reads `pubfig` from the source tree rather than from high-level overview material.
Source root:
- `pubfig/src/pubfig/__init__.py`
- `pubfig/src/pubfig/plots/`
- `pubfig/src/pubfig/export/`
- `pubfig/src/pubfig/specs.py`
- `pubfig/src/pubfig/themes/`
- `pubfig/src/pubfig/colors/`
- `pubfig/src/pubfig/cli.py`
## 1. Start at `pubfig.__init__`
The stable user-facing surface is re-exported from `__init__.py`.
That file tells you the package is organized into five main layers:
1. **plot constructors** from `plots/`
2. **export helpers** from `export/`
3. **publication sizing** from `specs.py`
4. **theme and palette registries** from `themes/` and `colors/`
5. **Figma/bridge helpers** and related CLI support
For skill design, this is the most important architectural fact:
- figure generation lives in `plots/`
- figure export lives in `export/`
- venue sizing lives in `specs.py`
- multi-panel/Figma handoff is a separate downstream layer
The default mental model is **plot first, export second, compose third**.
## 2. Package boundaries
### `plots/`
This is the core figure-construction layer.
Representative files:
- `plots/line.py`
- `plots/comparison.py`
- `plots/evaluation.py`
- `plots/_grouped_scatter.py`
From the source, plot functions usually do the same sequence:
1. normalize/coerce input data,
2. enter `theme_context(theme)`,
3. resolve design-time size via `resolve_design_dpi(...)`,
4. allocate figure/axes via `get_fig_ax(...)`,
5. style axes/legends through helpers in `_style.py`,
6. return a Matplotlib `Figure`.
Interpretation from source:
- `pubfig` behaves as a **Matplotlib-first figure factory layer**, not as a separate scene-graph runtime.
### `export/`
This is intentionally separated from plotting.
Important files:
- `export/io.py`
- `export/panels.py`
`export/io.py` handles normal figure export:
- coerce Figure/Axes into a real `Figure`
- enforce explicit suffixes
- apply publication width/height rules
- write vector or raster output
Current source implication:
- `batch_export(...)` now belongs to the same publication-aware export layer, rather than to a simple multi-format `savefig` wrapper.
`export/panels.py` handles panel-level export for composite or Figma-oriented workflows:
- one panel at a time or many panels together
- optional publication-aware sizing
- optional title stripping
- metadata index generation (`panel-index.json`)
### `specs.py`
This file is the publication-sizing contract.
`FigureSpec` defines:
- `font_family`
- `design_dpi`
- `single_column_mm`
- `double_column_mm`
- `default_raster_dpi`
- `background_color`
Built-in registry entries include:
- `nature`
- `science`
- `cell`
The source shows a strong split between:
- **design size** used when constructing interactive figures,
- **physical export size** used when saving publication figures.
That split is why the skill should not treat `width` in plot calls and `width` in export calls as the same semantic layer.
### `themes/` and `colors/`
These are registries, not plain constants.
From `__init__.py`, the public surface includes:
- `get_theme`, `register_theme`, `set_default_theme`
- `get_palette`, `register_palette`, `show_palette`
Operational implication:
- treat theme and palette selection as first-class API configuration rather than as hardcoded styling trivia.
### `cli.py`
The current CLI is not the main figure-generation interface.
From the source, `cli.py` is mainly about:
- Figma bridge serving
- bundle packaging/inspection/validation
- sync job submission and waiting
- local bridge auto-start logic
So for this skill:
- **Python API is the primary route for figure generation**
- `pubfig.cli` is a secondary operational layer for bridge/Figma workflows
## 3. Plotting architecture pattern
From `line.py`, `comparison.py`, and `evaluation.py`, the recurring internal pattern is:
- input normalization is local to the chart family,
- shared visual behavior is delegated to internal helpers,
- returned artifact is still a standard Matplotlib figure.
This is why the skill should map requests to a chart family first, instead of jumping directly to export or panel assembly.
Examples from source:
- `line.py` groups time/trend style plots
- `comparison.py` groups comparison-style statistical displays like `dumbbell` and `forest_plot`
- `evaluation.py` groups metric/evaluation plots like `roc`, `pr_curve`, and `calibration`
- `_grouped_scatter.py` contains the more specialized placement/jitter/annotation logic behind grouped scatter layouts
## 4. Export architecture pattern
From `export/io.py` and `export/panels.py`, `pubfig` uses three distinct output modes:
1. **single explicit artifact** via `save_figure(...)`
2. **publication-aware multi-format artifact set** via `batch_export(...)`
3. **panel bundle workflow** via `export_panel(...)` / `export_panels(...)`
Those are different contracts, and the skill should keep them separate in its recommendations.
## 5. Reading order for deep debugging
When a skill or agent needs source-level certainty, use this order:
1. `pubfig/src/pubfig/__init__.py`
2. relevant chart-family module in `plots/`
3. `pubfig/src/pubfig/specs.py`
4. `pubfig/src/pubfig/export/io.py`
5. `pubfig/src/pubfig/export/panels.py`
6. `pubfig/src/pubfig/cli.py` only if the task involves bridge/Figma sync
## 6. Implications for this skill
This source layout implies the skill should:
- default to **Python plot API + explicit export call**,
- treat publication sizing as an export concern,
- treat panel/Figma work as optional downstream composition,
- avoid presenting the CLI as the main path for ordinary figure generation,
- keep chart selection logically ahead of export tuning.

View File

@@ -0,0 +1,210 @@
# pubfig export flow (source-driven)
This guide explains how `pubfig` moves from a generated Matplotlib figure to paper-ready files.
Primary source files:
- `pubfig/src/pubfig/export/io.py`
- `pubfig/src/pubfig/export/panels.py`
- `pubfig/src/pubfig/specs.py`
## 1. Core export contract
`export/io.py` separates two concerns:
- **coercing a valid figure object**
- **writing explicit output files**
The helper `_coerce_mpl_figure(...)` accepts:
- a `Figure`
- an `Axes`
- an object with a `.figure` attribute pointing to a `Figure`
The export layer is standardized around Matplotlib figures, even if upstream plotting code returns a richer wrapper.
## 2. `save_figure(...)` is now single-target and suffix-explicit
A key source-level rule lives in `_resolve_save_figure_target(...)`:
- `save_figure(...)` now requires an explicit filename suffix,
- supported examples include `.pdf`, `.svg`, `.png`, `.jpg`, `.tif`, `.eps`, `.ps`,
- if there is no suffix, the function raises an error,
- if multiple outputs are wanted, the source tells you to use `batch_export(...)`.
Skill implication:
- always write `results/figure1.pdf` rather than `results/figure1`
- when you want several formats, recommend `batch_export(...)`, not legacy vector/raster format lists
## 3. Publication sizing path
`save_figure(...)` is publication-aware.
Internally it does the following:
1. load the chosen `FigureSpec` via `get_figure_spec(...)`
2. resolve width through `resolve_width_mm(...)`
3. resolve height through `resolve_height_mm(...)`
4. set the Matplotlib figure size in inches using mm-to-inch conversion
5. choose raster DPI from the spec unless overridden
6. save the explicit target file
7. restore original caller state afterward
Interpretation from source:
- export sizing is more than a file-write step; it can temporarily resize the figure to venue-oriented physical dimensions before output.
## 4. Width and height semantics
From `specs.py`:
- width can be `single`, `double`, or a numeric mm value
- the built-in registry contains `nature`, `science`, and `cell`
- height can be explicit `height_mm`
- otherwise height is derived from `aspect_ratio`
That yields a clean rule for the skill:
- if the user asks for publication width, use `save_figure(..., spec=..., width=...)`
- if the user only wants quick draft export, keep the recommendation minimal
## 5. `batch_export(...)`
`batch_export(...)` is the publication-aware multi-format lane.
Source behavior:
- it takes a `base_path`
- it accepts publication export controls such as `spec`, `width`, `height_mm`, `aspect_ratio`, and `dpi`
- appends each explicit suffix from `formats`
- relayouts the figure through `_export_with_publication_layout(...)` for each target format
- restores the original in-memory figure size/state after export
This is the right recommendation when the user needs, for example:
- `PDF` for manuscript submission
- `SVG` for downstream editing
- `PNG` for slides or issue threads
Operational implication:
- use `batch_export(...)` when the task needs multiple publication-style outputs from the same figure,
- do not describe it as a plain `savefig` loop.
## 6. What `_save_basic_figure(...)` still does
`_save_basic_figure(...)` is still relevant, but it is no longer the main multi-format path for `batch_export(...)`.
It remains the lower-level path used for:
- direct basic export helpers,
- size-preserving panel export in `export/panels.py`,
- and internal single-target save operations that do not need publication relayout.
From the source, it also handles:
- output directory creation
- vector-text rcParams (important for editable SVG/PDF text handling)
- post-layout legend alignment
- post-layout callbacks attached by plot code
- trim/tight bbox behavior
So export quality is partially centralized in the export layer, not only inside plot modules.
## 7. Panel export lane
`export/panels.py` defines the multi-panel handoff path.
Key components:
- `PanelExportRecord`
- `export_panel(...)`
- `export_panels(...)`
- `_write_panel_index(...)`
A `PanelExportRecord` stores:
- `panel_id`
- `path`
- `format`
- `exported_at`
- `figma_node_name`
- `pubfig_version`
- optional `title`
- optional `label`
This shows that panel export is not only file emission. It also preserves minimal sync metadata.
## 8. Title stripping is intentional
One subtle but important source behavior:
- `_temporarily_strip_titles(...)` removes figure/axes titles during panel export by default unless `include_title=True`
Operational implication:
- panel-first composite assembly usually wants clean panel artwork,
- whole-figure titles and layout labels are often handled later,
- prefer exporting clean panel art first and adding whole-figure titles or layout labels downstream when needed.
## 9. Publication-aware vs size-preserving panel export
`export_panel(...)` has two modes:
### Publication-aware mode
Triggered when any of these are supplied:
- `spec`
- `width`
- `height_mm`
Then it delegates to `save_figure(...)`.
### Size-preserving mode
If none of those are supplied, it falls back to `_save_basic_figure(...)` and preserves the figures current size.
Skill implication:
- for reproducible paper panels, specify publication export parameters
- for design review or quick composition, preserving current size may be acceptable
## 10. Multiple panel export
`export_panels(...)` does three main things:
1. normalize and validate panel ids,
2. resolve labels for each panel,
3. export each panel and optionally write `panel-index.json`.
Default recommendation:
- prefer this route when the user wants a structured panel directory rather than a single whole-figure asset.
## 11. Overwrite and safety behavior
From `_ensure_writable_target(...)`:
- an existing panel file raises unless `overwrite=True`
That is useful for skill guidance because it means refresh-in-place is an explicit decision.
## 12. Recommended source-faithful export patterns
### Single paper figure
- plot with `pubfig.<chart_family>(...)`
- save with `save_figure(fig, 'out/figure1.pdf', spec='nature', width='single')`
### Same figure in several formats
- plot once
- export with `batch_export(fig, 'out/figure1', formats=('pdf', 'svg', 'png'), spec='nature', width='single', dpi=300)`
### Multi-panel downstream assembly
- generate each panel as a separate `Figure`
- export with `export_panels(...)`
- use the index file for composite/Figma-aware downstream handling

View File

@@ -0,0 +1,216 @@
# pubtab architecture (source-driven)
This guide explains `pubtab` from the actual package layout under `pubtab/src/pubtab`.
Core files:
- `__init__.py`
- `cli.py`
- `models.py`
- `reader.py`
- `renderer.py`
- `config.py`
- `_preview.py`
- `tex_reader.py`
- `backends/`
- `themes/`
## 1. Start at `pubtab.__init__`
The public contract is defined in `__init__.py`.
Public exports are intentionally small:
- `xlsx2tex`
- `preview`
- `compile_pdf`
- `tex_to_excel`
- `SpacingConfig`
This is the key architectural signal: `pubtab` exposes a compact API, while the real complexity is pushed into reader/renderer/preview internals.
## 2. Core data model layer
`models.py` defines the structured table representation.
Important dataclasses:
- `CellStyle`
- `Cell`
- `TableData`
- `SpacingConfig`
- `ThemeConfig`
- `BackendConfig`
Source fact:
- the shared structured representation is `TableData`, not raw Excel cells or raw LaTeX text.
Forward and reverse conversions both pass through this structured table model.
## 3. Forward pipeline: Excel to LaTeX
The main forward path is:
1. `xlsx2tex(...)` in `__init__.py`
2. `read_excel(...)` in `reader.py`
3. `render(...)` in `renderer.py`
4. optional preview through `_preview.py`
This gives a clean source-driven decomposition:
- `reader.py` = file ingestion and structure recovery
- `renderer.py` = LaTeX generation
- `_preview.py` = compile and raster preview
## 4. Reverse pipeline: LaTeX to Excel
The reverse path is:
1. `tex_to_excel(...)` in `__init__.py`
2. `read_tex_multi(...)` from `tex_reader.py`
3. writer functions to `.xlsx`
So roundtrip support is not an afterthought. It is a real architecture branch.
## 5. `reader.py` is richer than a plain spreadsheet loader
From the source, `reader.py` does much more than “read cells”:
- supports `.xlsx` and `.xls`
- extracts rich text segments
- reconstructs merged cells and spans
- reads styling information
- trims only trailing globally empty columns
- reads pubtab metadata sheets
- restores group separators, multicolumn alignment hints, and math-script hints
Interpretation from source:
- `pubtab` is optimized for **publication table semantics**, rather than for plain tabular text dumping.
## 6. `renderer.py` is the central logic hub
`renderer.py` turns `TableData` into backend-specific LaTeX.
From the source, it handles:
- style/theme loading
- backend template loading
- spacing resolution
- column spec construction or projection
- tabular vs tabularray differences
- merged cells, row/column spans, header rules, vertical rules
- background colors and grouped separators
- final template rendering
This file is where most of the difficult publication logic lives.
For skill design, that means:
- backend choice is not a cosmetic toggle
- column spec and rule behavior are structural concerns
- preview/render bugs usually require reading `renderer.py`
## 7. Theme vs backend is a real split
The codebase separates:
- **themes** in `themes/`
- **LaTeX backends** in `backends/`
That is reflected in two dataclasses:
- `ThemeConfig`
- `BackendConfig`
And in two loaders:
- `load_theme(...)`
- `load_backend(...)`
This is a major architectural point for the skill:
- theme decides stylistic defaults,
- backend decides LaTeX environment/template behavior.
Do not explain them as if they were the same thing.
## 8. Config precedence is explicit
In `xlsx2tex(...)`, the source implements a clear precedence order:
1. hardcoded defaults
2. YAML config loaded by `config.py`
3. explicit function kwargs
4. in some roundtrip cases, values recovered from `TableData`
This is why user-facing guidance should say “CLI flags or function kwargs override YAML config.”
## 9. Multi-file and multi-sheet support are first-class
From `__init__.py`:
- directory input is supported for both forward and reverse paths
- sheet enumeration is supported when `sheet=None`
- multi-sheet export produces `*_sheetNN.tex`
The default skill guidance can therefore recommend batch/file-driven workflows, not only one-table-at-a-time usage.
## 10. Preview is a real compilation layer
`preview(...)` and `compile_pdf(...)` in `__init__.py` delegate into `_preview.py`.
That layer:
- finds or installs `pdflatex`
- builds a standalone document
- compiles the output
- retries missing packages through `tlmgr`
- converts PDF to PNG when requested
Preview is not a fake HTML-like snapshot. It is a real LaTeX compile pipeline.
## 11. `tex_reader.py` closes the roundtrip loop
`tex_reader.py` is substantial, not decorative.
From the source it supports parsing of:
- `tabular`
- `tblr`
- `longtblr`
- `talltblr`
It also handles:
- color parsing
- rule parsing
- multirow/multicolumn reconstruction
- metadata extraction
- grouped rows and placeholder cleanup
This makes `pubtab` suitable for source-aware roundtrip and migration tasks, rather than only one-way Excel export.
## 12. Reading order for source debugging
When you need source-level certainty, use this order:
1. `pubtab/src/pubtab/__init__.py`
2. `pubtab/src/pubtab/models.py`
3. `pubtab/src/pubtab/reader.py`
4. `pubtab/src/pubtab/renderer.py`
5. `pubtab/src/pubtab/_preview.py`
6. `pubtab/src/pubtab/tex_reader.py`
7. `pubtab/src/pubtab/backends/` and `themes/`
8. `pubtab/src/pubtab/cli.py` for flag-to-API mapping only
## 13. Implications for this skill
The source says the most faithful default workflow is:
- use `xlsx2tex(...)` or CLI `xlsx2tex` for forward generation,
- use `preview(...)` to verify actual compile output,
- use `tex_to_excel(...)` for roundtrip or migration tasks,
- explain theme/backend separately,
- escalate into renderer/source debugging only when table structure or LaTeX behavior is the real problem.

View File

@@ -0,0 +1,201 @@
# pubtab backend and preview internals (source-driven)
This guide focuses on the two most important deeper layers in `pubtab`:
- backend/theme separation
- real preview/compile execution
Primary source files:
- `pubtab/src/pubtab/themes/__init__.py`
- `pubtab/src/pubtab/backends/__init__.py`
- `pubtab/src/pubtab/renderer.py`
- `pubtab/src/pubtab/_preview.py`
## 1. Theme and backend are different contracts
The source separates them cleanly.
### Theme layer
In `themes/__init__.py`, a theme resolves to `ThemeConfig`.
It carries style defaults such as:
- `column_sep`
- `font_size`
- `caption_position`
- `SpacingConfig`
### Backend layer
In `backends/__init__.py`, a backend resolves to:
- `BackendConfig`
- a Jinja template string
`BackendConfig` carries things like:
- package requirements
- preamble hints
- backend identity
Operational implication:
- theme = stylistic defaults
- backend = LaTeX environment/template machinery
## 2. Legacy normalization exists, but it is not the conceptual model
The source still supports legacy composite theme names like `_tabularray` suffixed themes.
Normalization happens in places like:
- `_normalize_theme_backend_choice(...)`
- `resolve_theme(...)`
But that compatibility layer should not define the skills main explanation.
The current conceptual model is still **separate theme + backend**.
## 3. What `render(...)` actually does
`renderer.py` is the core place where theme/backend decisions become concrete LaTeX.
Inside `render(...)`, the source does roughly this:
1. normalize theme/backend choice
2. load theme config
3. load backend config and template
4. merge default/theme/user spacing
5. compute or project column specs
6. branch into backend-specific row/cell rendering
7. render through Jinja
Backend choice changes the internal rendering algorithm, not only the final environment name.
## 4. `tabular` vs `tabularray` from the source perspective
The source suggests this practical distinction:
### `tabular`
- more classic LaTeX path
- column spec and rules are handled in the traditional environment
- when source `column_spec` exists, renderer tries to preserve classic rule structure
### `tabularray`
- dedicated `tblr`-style rendering path
- special handling for promoted vertical lines and grouped header boundaries
- extra sanitization in preview compile path
Interpretation from source:
- `tabularray` is a distinct renderer path with its own structural handling, not merely a cosmetic wrapper around `tabular`.
## 5. Why backend choice sometimes matters a lot
From `renderer.py`, backend differences affect:
- how colspec is interpreted
- how vertical rules are preserved or promoted
- how merged cells are encoded
- how row coloring and header boundaries are emitted
So if a table is structurally complex, the skill should not present backend choice as arbitrary.
## 6. Preview is a real LaTeX toolchain
`_preview.py` proves preview is a full execution pipeline.
Major steps:
1. locate `pdflatex`
2. install TinyTeX if missing
3. build a standalone document around the table
4. compile with `pdflatex`
5. auto-install missing LaTeX packages when possible
6. return PDF or convert to PNG
Preview is therefore a genuine verification step.
## 7. `pdflatex` discovery and TinyTeX fallback
The source checks:
- system `PATH`
- pubtab-managed TinyTeX under `~/.pubtab/TinyTeX`
If neither exists, it installs TinyTeX automatically.
This is why the skill can confidently describe preview as relatively self-healing, while still warning that first-run setup may download TeX assets.
## 8. Missing package retry
A particularly important source behavior:
- compile logs are scanned for missing `.sty`
- missing style names are mapped to `tlmgr` package names when needed
- `tlmgr install <pkg>` is run automatically
- compilation is retried
This is strong evidence that the recommended workflow should include preview, because preview can repair part of the environment on the way.
## 9. Standalone preview wrapping
`_build_standalone(...)` does more than wrap text in a document.
It also:
- imports backend-required packages
- preserves setup commands outside the `resizebox` body
- wraps the body in a preview-friendly standalone/minipage layout
- converts `\caption{...}` into `\captionof{table}{...}` during float stripping
This explains why preview output can differ from naive manual compilation if the user simply pastes a table fragment into a document incorrectly.
## 10. `tabularray` preview sanitization
Before compilation, `_sanitize_tblr_for_compile(...)` removes some commands that break inside `tblr` preview contexts, including certain row-color and `\cmidrule` forms.
So when debugging preview-vs-final-document differences, this source behavior matters.
## 11. PDF to PNG conversion fallback stack
For PNG previews, the source tries:
1. `pdf2image`
2. fallback to PyMuPDF (`fitz`)
Preview generation remains resilient even after PDF compilation succeeds.
## 12. Practical skill guidance from the source
### Recommend `tabular` when
- the table is simple/classic,
- the user wants conservative LaTeX output,
- compatibility matters more than modern layout features.
### Recommend `tabularray` when
- grouped headers and more complex structural layouts matter,
- the user is already targeting a `tblr`-capable workflow,
- the roundtrip/source table has rule structure that benefits from the dedicated renderer path.
### Recommend preview almost always when
- the table is intended for publication,
- the user is changing backend/theme/colspec,
- the task involves debugging table layout,
- the task depends on compile-time package correctness.
## 13. Failure triage order
When the generated table is wrong, debug in this order:
1. check theme/backend choice,
2. inspect `render(...)` inputs (`TableData`, colspec, span settings),
3. run preview/compile,
4. inspect missing package or backend-specific compile issues,
5. only then move into manuscript-level integration debugging.

View File

@@ -0,0 +1,178 @@
# pubtab CLI and API flow (source-driven)
This guide follows the actual control flow from `pubtab/src/pubtab/cli.py` into the public API and then into the internal pipeline.
## 1. Architectural headline
`cli.py` is a **thin Click wrapper** over the public API in `pubtab.__init__`.
Operational implication:
- command-line behavior should usually match Python API behavior,
- when docs disagree, the source of truth is `pubtab.__init__`, not CLI help text alone.
## 2. CLI commands exposed in `cli.py`
The main commands are:
- `pubtab xlsx2tex`
- `pubtab themes`
- `pubtab tex2xlsx`
- `pubtab preview`
There is also a hidden backward-compatible alias:
- `convert` -> `xlsx2tex`
## 3. `xlsx2tex` command flow
CLI entrypoint:
- `xlsx2tex_cmd(...)` in `cli.py`
Control flow:
1. validate input/output shape
2. coerce `--sheet` into int when possible
3. build kwargs only for explicitly provided options
4. call `pubtab.xlsx2tex(input_file, output, **kwargs)`
5. print output summary based on sheet count and preview mode
This thin-wrapper design matters because the CLI does **not** reimplement conversion logic.
## 4. `xlsx2tex(...)` API flow
The public API in `__init__.py` adds the real orchestration:
### Input modes
- single Excel file
- directory of Excel files
- single sheet
- all sheets (`sheet=None`)
### Output path behavior
- single-sheet export can target a direct `.tex` path
- directory input must target a directory
- multi-sheet export uses `*_sheetNN.tex`
This behavior is implemented by `_build_sheet_output_paths(...)` and directory iteration helpers.
## 5. Config precedence in the real API
Inside `xlsx2tex(...)`, the source builds parameters in this order:
1. defaults
2. YAML config via `load_config(...)`
3. explicit kwargs passed from CLI or Python
4. roundtrip-restored values where relevant
Operational rule:
- YAML config sets baseline behavior,
- CLI flags / Python kwargs override it.
## 6. Sheet expansion behavior
When `sheet is None`, the source does not simply choose the first sheet.
It calls `list_excel_sheets(...)` and expands all sheet names into separate outputs.
That is why a single workbook can generate:
- `table_sheet01.tex`
- `table_sheet02.tex`
- ...
The skill should explicitly mention this when users want appendix exports or workbook-wide conversion.
## 7. Read -> render -> write flow
For each selected sheet, `xlsx2tex(...)` does:
1. `read_excel(...)`
2. optional header or group-separator reconstruction
3. `render(...)`
4. write `.tex`
5. optional preview generation to `.png`
Preview is downstream of actual `.tex` generation, not an alternate renderer.
## 8. `preview` command flow
CLI entrypoint:
- `preview_cmd(...)`
The CLI again mostly validates paths and forwards to `pubtab.preview(...)`.
The public `preview(...)` API supports:
- raw LaTeX content
- a single `.tex` file
- a directory of `.tex` files
- `png` or `pdf` output
A key source detail: when backend is omitted, `preview(...)` may infer it from the LaTeX content using `_resolve_preview_inputs(...)`.
## 9. Backend inference path
`_infer_latex_backend(...)` checks for environments like:
- `tblr`
- `longtblr`
- `talltblr`
If found, backend becomes `tabularray`; otherwise `tabular`.
Operational implication:
- a preview or compile call can often resolve the correct backend without requiring an explicit `--latex-backend` flag.
## 10. `compile_pdf(...)` API flow
Public `compile_pdf(...)` in `__init__.py` does:
1. detect whether input is raw LaTeX or a file path,
2. infer theme/backend if needed,
3. delegate to `_preview.compile_pdf(...)`.
The compile path is still part of the public API, even though the heavy lifting is in `_preview.py`.
## 11. `tex2xlsx` command flow
CLI entrypoint:
- `tex2xlsx(...)` in `cli.py`
It forwards to `pubtab.tex_to_excel(...)`.
The public API then handles:
- single `.tex` file -> one `.xlsx`
- multi-table `.tex` -> one workbook with multiple sheets
- directory of `.tex` files -> one `.xlsx` per file
This keeps the reverse path operationally symmetric with the forward path.
## 12. Why the CLI should stay thin in this skill
Because the real logic is centralized in `pubtab.__init__`, the skill should:
- use CLI examples for file-driven shell workflows,
- use Python API examples for notebooks or scripted pipelines,
- avoid duplicating pseudo-logic that already exists in the library.
## 13. Recommended source-faithful routing
### Use CLI when
- the user already has Excel or `.tex` files on disk,
- the task is batch conversion,
- the user wants a terminal-first workflow.
### Use Python API when
- the user is in a notebook or script,
- the table needs custom preprocessing before render,
- the agent is composing a larger Python pipeline.

View File

@@ -0,0 +1,82 @@
# Workflow
## Default decision order
1. Identify the scientific communication goal.
2. Probe the environment and available assets lightly.
3. Decide whether the evidence should be a figure, a table, or a paired figure+table deliverable.
4. Choose the strongest representation family.
5. Route to `pubfig`, `pubtab`, or both.
6. Produce the smallest runnable implementation.
7. Specify export outputs explicitly.
8. Run publication QA.
9. Propose revisions if the result is weak.
## Handoff checklist
For every task, try to make these explicit:
- claim the artifact is supposed to support
- data shape and grouping structure
- target audience or venue expectations
- figure vs table role
- exact output filenames and formats
- whether the artifact is final, draft, or revision
- whether the current environment can execute the proposed route immediately
## Delivery contract
A strong response should make clear:
- which artifact type was chosen,
- why it was chosen,
- which tool owns each artifact,
- what the first runnable command/code path is,
- what output files should be produced,
- what still needs user input or upstream data.
## Default output priorities
Prioritize in this order:
1. clarity of claim
2. correct artifact type
3. minimal runnable implementation
4. publication-ready export
5. QA and revision guidance
## Graceful degradation when tools are missing
If `pubfig` or `pubtab` is not installed:
- keep the workflow going,
- provide installation guidance,
- provide pseudocode or draft commands,
- specify the recommended artifact structure,
- preserve the QA and revision guidance.
## Figure / table split rules
Use a **figure** when the reader needs to quickly perceive:
- trend
- distribution shape
- relationship
- calibration or diagnostic behavior
- composition or hierarchy
- visual comparison across a moderate number of groups
Use a **table** when the reader needs:
- exact numbers
- many metrics side by side
- benchmark grids
- ablation matrices
- appendix-style detail
- reproducible value lookup
Use **both** when:
- the figure carries the visual claim,
- the table preserves exact values,
- or the paper section benefits from a fast visual summary plus precise numeric evidence.