Metadata-Version: 2.4
Name: lusca
Version: 0.1.1
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

![CI](https://github.com/evmckinney9/lusca/actions/workflows/ci.yml/badge.svg?branch=main) ![Python](https://img.shields.io/badge/python-3.12-blue.svg) ![Ruff](https://img.shields.io/badge/linter-ruff-green.svg)

`lusca` is a Python library for creating reproducible matplotlib figures using Jupyter magic commands.

Often, you want to use Jupyter for experiments but may not want to rerun the entire notebook to recreate plots. Additionally, saving data and figures is essential for artifact generation and reproducibility.

## 📊 `%%mplfreeze` Command

The `%%mplfreeze` magic command:
- Captures the data used in your plots and saves it in a compressed NPZ file.
- Automatically exports your figures in multiple useful formats.
- Creates 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.
- Leverages `lusca`'s built-in stylesheet.

Once you're satisfied with your plot, add the `%%mplfreeze` command to the cell.
```python
%%mplfreeze <name> [vars ...] [--outdir DIR]
```
- `<name>`: Base name for outputs (folder + files).
- `[vars ...]`: Variable names to save into the NPZ file.
- `[--outdir DIR]`: (Optional) Parent output directory (default: `docs/figs`).

### Example

1. Import and load the magic command
```python
import matplotlib.pyplot as plt
import numpy as np
import lusca
%load_ext lusca
```

2. Some data
```python
x_data = np.linspace(-10, 10, 100)
sine = np.sin(x_data)
cosine = np.cos(x_data)
```
3. Plot + save
```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`. The generated plots are saved in `docs/figs/` with the following structure:

```
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
```
## Installation

Install `lusca` directly from GitHub:

```bash
pip install -e git+https://github.com/evmckinney9/lusca#egg=lusca
```

#### Note

If you are using VS Code, you can set the workspace root as the default directory for saving figures by adding the following setting to your `settings.json` file. Otherwise, output paths will be relative to the notebook location.

```json
"jupyter.notebookFileRoot": "${workspaceFolder}"
```
