Metadata-Version: 2.4
Name: panel-compiler
Version: 0.1.0
Summary: Compose SVG figures and LaTeX equations into a panel template
Author-email: Matthias Függer <mfuegger@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: pyyaml
Description-Content-Type: text/markdown

# pc — Panel Compiler

Compose scientific figures from SVG plots, PDF figures, and LaTeX equations into a single SVG or PDF panel.

You define a panel template in Inkscape with named group placeholders (set via the layer/group label field), then write a small YAML config that maps each label to an SVG file, PDF, or a LaTeX string. `pc` scales each figure to fit its placeholder and writes the compiled panel.

## Example

Panel template `example/panel.svg` — 180×120mm, three rect placeholders (**a** formula, **b** linear, **c** log):

![panel template](example/panel.svg)

Input figures generated by `example/subfigures.py`:

| `logistic.svg` | `logistic_log.svg` |
|:--------------:|:------------------:|
| ![logistic](example/logistic.svg) | ![logistic_log](example/logistic_log.svg) |

`example/pc.yaml`:
```yaml
panel: panel.svg
output:
  - out.svg
  - panel.pdf

logistic_log:
  file: logistic_log.svg
  fit: contain

logistic:
  file: logistic.svg
  fit: contain

formula:
  tex: $\frac{dN}{dt} = rN\!\left(1 - \frac{N}{K}\right)$
  size: 10pt
```

Compiled result `example/out.svg`:

![compiled panel](example/out.svg)

```bash
cd example
python subfigures.py
pc pc.yaml
```

## Installation

```bash
uv tool install git+https://github.com/mfuegger/pc.git
```

or with pip:

```bash
pip install git+https://github.com/mfuegger/pc.git
```

For LaTeX rendering, `pdflatex` must be on your `PATH`. For PDF figures and PDF output, `pdf2svg` and `inkscape` must be on your `PATH`. On macOS: `brew install pdf2svg`.

## Usage

```
pc [config.yaml]
```

| Argument | Default | Description |
|---|---|---|
| `config.yaml` | `pc.yaml` | YAML config (see below) |

The output path is taken from the `output` key in the config. If omitted, it defaults to the config filename with `.svg` extension (e.g. `pc.yaml` → `pc.svg`).

## Config format

### Single panel

```yaml
panel: panel.svg    # required — path to the panel SVG, relative to this config file
output: out.svg     # optional — defaults to <config-stem>.svg if omitted
```

`output` can also be a list to produce multiple formats in one run:

```yaml
output:
  - out.svg
  - out.pdf
```

Each remaining key is a **label** that must match an element in the panel SVG. `pc` looks it up by `inkscape:label` first, then `label`, then `id`. The element can be a `<g>` group or a `<rect>` placeholder — a `<rect>` is automatically replaced by a `<g>` positioned at the rect's `x`/`y`.

### Figure entry (SVG or PDF)

```yaml
plot:
  file: results.svg   # path relative to this config file; .svg or .pdf  (alias: svg:)
  fit: contain        # contain | height | width  (default: contain)
  width: 200          # optional — override the target width  (SVG user units)
  height: 100         # optional — override the target height (SVG user units)
```

Fit strategies:
- `contain` — scale uniformly to fit within the placeholder box (default)
- `height` — scale to match the placeholder height exactly
- `width`  — scale to match the placeholder width exactly

Target dimensions come from `width`/`height` attributes on the group element in the panel SVG. The config `width`/`height` are used as a fallback when the group has no such attributes.

PDF files are converted via `pdf2svg` before embedding.

### LaTeX entry

```yaml
label:
  tex: $y = \sin(x)$   # any LaTeX — math mode, text, amsmath, …
  size: 12pt           # font size (default: 10pt); scales the rendered output
```

Rendered via `pdflatex` + `inkscape`. No fit scaling — the output is sized by `size` alone.

### Shorthand

A plain string value is treated as an SVG file path with `fit: contain`:

```yaml
other: path/to/fig.svg
```

### Multiple panels

Use a YAML list; each entry must have its own `output`:

```yaml
- panel: panel1.svg
  output: out1.svg
  plot:
    file: results.svg

- panel: panel2.svg
  output:
    - out2.svg
    - out2.pdf
  label:
    tex: $E = mc^2$
    size: 12pt
```

## License

Apache 2.0 — see [LICENSE](LICENSE).
