Metadata-Version: 2.4
Name: lusca
Version: 0.1.2
Summary: A Jupyter magic command for creating reproducible matplotlib figures.
Author-email: Evan McKinney <evmckinney9@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/evmckinney9/lusca
Project-URL: Repository, https://github.com/evmckinney9/lusca
Project-URL: Issues, https://github.com/evmckinney9/lusca/issues
Keywords: jupyter,ipython-magic,matplotlib,reproducibility,figures,scientific-plotting
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Plugins
Classifier: Framework :: IPython
Classifier: Framework :: Jupyter
Classifier: Framework :: Matplotlib
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: matplotlib
Provides-Extra: dev
Requires-Dist: ipykernel; extra == "dev"
Requires-Dist: pylatexenc; extra == "dev"
Requires-Dist: ipywidgets; extra == "dev"
Requires-Dist: pre-commit; extra == "dev"
Provides-Extra: format
Requires-Dist: pre-commit; extra == "format"
Requires-Dist: ruff; extra == "format"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Dynamic: license-file

# lusca

[![Python](https://img.shields.io/badge/Python-3.12-blue?logo=python&logoColor=white)](https://www.python.org/downloads/)
[![PyPI - Version](https://img.shields.io/pypi/v/lusca)](https://pypi.org/project/lusca/)
[![CI](https://github.com/evmckinney9/lusca/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/evmckinney9/lusca/actions/workflows/ci.yml)
[![Ruff](https://img.shields.io/badge/linter-ruff-green.svg)](https://github.com/astral-sh/ruff)

```bash
pip install lusca
```

`lusca` is a Python library for creating reproducible matplotlib figures using Jupyter magic commands. You often want to use Jupyter for experiments without rerunning the entire notebook to recreate a plot, and saving data alongside figures is essential for artifact generation and reproducibility.

______
### `%%mplfreeze`

```python
%%mplfreeze <name> [vars ...] [--outdir DIR]
```
- `<name>`: Base name for outputs (folder + files).
- `[vars ...]`: Variable names to save into the NPZ file.
- `[--outdir DIR]`: Parent output directory (default: `docs/figs`).

The magic command:
- Captures the data used in your plots and saves it in a compressed NPZ file.
- Exports your figures in PDF, PNG, and SVG.
- Generates a minimal standalone script that reproduces the figure.
- Snapshots Python/package versions and the git commit into `<name>.meta.json`.
- Statically checks the cell for unsaved free names *before* writing anything, then runs the generated replot in a subprocess to confirm the bundle actually reproduces the figure - if `%%mplfreeze` succeeds, the replot is guaranteed to work.
- Applies `lusca`'s built-in stylesheet.

______
### Example

```python
import matplotlib.pyplot as plt
import numpy as np
import lusca
%load_ext lusca
```

```python
x_data = np.linspace(-10, 10, 100)
sine = np.sin(x_data)
cosine = np.cos(x_data)
```

```python
%%mplfreeze trig_demo x_data sine cosine
with plt.style.context("lusca"):
    fig, ax = plt.subplots(1, 1, figsize=(3.5, 2.6), sharey=True)
    ax.plot(x_data, sine, label="Sine")
    ax.plot(x_data, cosine, label="Cosine")
    plt.show()
```

An example notebook is available in `src/demo.ipynb`. Generated plots are saved under `docs/figs/`:

```
name_stamp/
    name.npz             # saved variables
    name.pdf             # exported figure
    name.png
    name.svg
    name.meta.json       # python/package versions + git commit
    replot_name.py       # standalone replot script
```

______
> [!NOTE]
> If you are using VS Code, set the workspace root as the default directory for saving figures by adding the following to your `settings.json`. Otherwise, output paths will be relative to the notebook location.
> ```json
> "jupyter.notebookFileRoot": "${workspaceFolder}"
> ```
