Metadata-Version: 2.4
Name: quiltwright
Version: 0.10.1
Summary: Holographic output for Looking Glass displays: off-axis multi-view quilts from PyVista, POV-Ray or Blender Cycles scenes
License-Expression: BSD-3-Clause
License-File: LICENSE
Keywords: looking-glass,light-field,holographic-display,quilt,povray,blender,cycles,pyvista,stereoscopy
Author: Eric G. Suchanek, PhD
Author-email: suchanek@flux-frontiers.com
Requires-Python: >=3.12,<3.14
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Topic :: Multimedia :: Graphics :: 3D Rendering
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Provides-Extra: molecules
Provides-Extra: video
Provides-Extra: viz
Requires-Dist: click (>=8.1.0,<9)
Requires-Dist: imageio-ffmpeg (>=0.4) ; extra == "video"
Requires-Dist: numpy (>=1.26)
Requires-Dist: pillow (>=10.0)
Requires-Dist: pypdb2pov (>=0.1.1) ; extra == "molecules"
Requires-Dist: pyvista (>=0.44) ; extra == "viz"
Project-URL: Documentation, https://flux-frontiers.github.io/quiltwright/
Project-URL: Homepage, https://github.com/Flux-Frontiers/quiltwright
Project-URL: Issues, https://github.com/Flux-Frontiers/quiltwright/issues
Project-URL: Repository, https://github.com/Flux-Frontiers/quiltwright
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://raw.githubusercontent.com/Flux-Frontiers/quiltwright/v0.10.1/assets/logo_pack/quiltwright_logo_512.png" alt="Quiltwright" width="512"/>
</p>

[![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
[![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD--3--Clause-blue.svg)](LICENSE)
[![PyPI](https://img.shields.io/pypi/v/quiltwright.svg)](https://pypi.org/project/quiltwright/)
[![Version](https://img.shields.io/badge/version-0.10.1-blue.svg)](https://github.com/Flux-Frontiers/quiltwright/releases)
[![Tests](https://github.com/Flux-Frontiers/quiltwright/actions/workflows/tests.yml/badge.svg)](https://github.com/Flux-Frontiers/quiltwright/actions/workflows/tests.yml)
[![Docs](https://img.shields.io/badge/docs-flux--frontiers.github.io-blue.svg)](https://flux-frontiers.github.io/quiltwright/)
[![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22180300-blue.svg)](https://doi.org/10.5281/zenodo.22180300)

**Quiltwright** -- holographic output for scientific visualization.

*Eric G. Suchanek, PhD -- Flux-Frontiers*

Quiltwright is the last stage of a scientific rendering pipeline -- any
pipeline that ends in a scene. It takes what you already have -- a PyVista or
VTK scene built in memory, a Blender file or an exported mesh, or a `.pov`
file written thirty years ago by someone who is no longer around to explain
it -- and puts it on holographic hardware in glasses-free depth. Nothing is
rewritten to get there: your scene file is never modified, the off-axis camera
is supplied per view, and each scene is rendered by the renderer it already
belongs to. Where that renderer is Blender's Cycles, the views are path-traced
on the GPU's ray-tracing cores if the hardware has them.

It is used that way by [WaveRider](https://github.com/Flux-Frontiers/waverider)
for geometric ML manifolds and by
[pypdb2pov](https://github.com/Flux-Frontiers/pypdb2pov) for molecular
structures, but neither is a prerequisite. If you can render it, you can hang it in the air.

![Eric's Science Museum, the canonical POV-Ray render](https://raw.githubusercontent.com/Flux-Frontiers/quiltwright/v0.10.1/gallery/museum.png)

*A career in structural biophysics, arranged as exhibits: B-DNA and Z-DNA
under bell jars, Ras and my original **DNA Under Glass** on the walls. The molecular
models were generated by pdb2pov in 1997; the room dates to 1995. Quiltwright
ray-traces it into a 48-view light-field quilt for Looking Glass light-field
panels, or into 2-D video for Hololuminescent displays. A third output -- a
23-view sweep for LitiHolo's desktop hologram printer -- is in development.*
[About the image](docs/about-the-image.md)

---

## Latest news

**v0.10.1 (2026-08-31).** Documentation gets a real home: the `docs/*.md`
guides now build into a GitHub Pages site at
[flux-frontiers.github.io/quiltwright](https://flux-frontiers.github.io/quiltwright/),
with an mkdocstrings API reference generated straight from the package's own
docstrings, so it can't drift from the code. `docs/architecture.md` replaces
the module-split proposal it outgrew -- the split it planned had already
landed -- and `docs/cli.md` is a full flag reference for every command. The
repository itself moved under the Flux-Frontiers org, matching the rest of
the fleet.

This cut also carries `bj_holo_2026.pov` -- "DNA Under Glass" with a bell
jar that finally refracts rather than just tinting, via a Fresnel
reflection and a real wall thickness -- and a fix for the vitrine exhibits,
which had been rendering at a 71.4-degree lens instead of the 44 degrees
they are composed at.

_Full history: [CHANGELOG.md](CHANGELOG.md) and
[releases](https://github.com/Flux-Frontiers/quiltwright/releases)._

---

## What it's for

```
     scene sources                  quiltwright                  outputs

  PyVista / VTK  -----+        +------------------+        +-->  LFD  light-field panels
   (WaveRider, TVB)   |        |  off-axis views  |        |          multi-view quilts
                      +------->|  depth budget    |------->+-->  HLD  hololuminescent
  POV-Ray  -----------+        |  quilt assembly  |        |          2-D video
   (pypdb2pov, PyMOL) |        |  view sweeps     |        +-->  LitiHolo  hogel sweeps
                      |        +------------------+                       (in development)
  Blender / meshes ---+
   (.blend, glTF, USD, OBJ)
```

Three backends share one assembler:

| Backend | Call | Input |
|---|---|---|
| PyVista / VTK | `render_quilt()` | In-memory plotter |
| POV-Ray | `render_pov_quilt()` | `.pov` on disk; original never modified |
| Cycles | `render_cycles_quilt()` | `.blend` and mesh files; GPU ray tracing where available |

`render_cycles_quilt_from_plotter()` takes the same PyVista plotter
`render_quilt()` does and path-traces it instead. WaveRider, [The Virtual
Brain](docs/tvb-data.md), PyVista example datasets, `quiltwright.povgen`, and a
plain `.pov` file on disk all feed the same path.

**Two display technologies.** *Light-field displays* (LFD -- Portrait, Go,
16"/27"/32"/65") consume **quilts**: N views tiled into one image.
`quiltwright.lfd` targets those. *Hololuminescent displays* (HLD --
16"/27"/86") play **ordinary 2-D video** behind a fixed holographic optic and
need dark-field styling rather than parallax; that is `quiltwright.hld`.

A third output is in development: `render_pov_views()` plus `LITIHOLO_SWEEP`
write a 23-view single-row sweep for LitiHolo's desktop hologram printer. Nothing
has yet passed through a printer's software;
[docs/lfd.md](docs/lfd.md#view-sweeps--when-the-consumer-is-not-a-panel)
records what remains open.

### Off-axis, not toe-in

Each view must use an **off-axis (asymmetric-frustum) projection**: the camera
slides sideways while continuing to face the same direction, with the image
plane sheared back onto the original view axis.

The intuitive alternative is to swivel each camera to keep the subject centered.
This "toe-in" approach introduces vertical parallax and keystone distortion, so
the display cannot fuse the views: you get ghosting instead of depth. It is the
single most common way light-field renders go wrong, and it produces output
that looks perfectly plausible in any individual frame.

---

## Install

```bash
pip install quiltwright                 # core: quilt geometry + Bridge control
pip install "quiltwright[viz]"          # + PyVista/VTK rendering backend
pip install "quiltwright[video]"        # + a bundled ffmpeg for video encoding
pip install "quiltwright[molecules]"    # + PDB and mmCIF, via pypdb2pov
```

Requires Python 3.12 or 3.13. Core depends only on numpy, pillow, and click.

POV-Ray, Blender, PyMOL, ffmpeg, and Looking Glass Bridge are external binaries,
not pip dependencies. Poetry groups, from-source install, and the rest of the
stack are in the [installation guide](docs/install.md).

---

## Quick start

```python
import pyvista as pv
from quiltwright import QUILT_PRESETS, render_quilt, save_quilt

p = pv.Plotter(off_screen=True)
p.add_mesh(pv.ParametricTorus())
spec = QUILT_PRESETS["portrait"]
save_quilt(render_quilt(p, spec), "torus", spec)   # -> torus_qs8x6a0.75.png
```

POV-Ray, Cycles, casting to Bridge, and hologram-printer sweeps:
[docs/usage.md](docs/usage.md). Shell targets and the CLI:
[docs/shell.md](docs/shell.md).

---

## Driving it from the shell

The `Makefile` covers the bundled 1993-99 scenes. The `quiltwright` CLI covers
hardware (`cast`, `weave`, `wallpaper`, `bridge`) and arbitrary input (`mesh`,
`cartoon`, `probe`). Worked exhibits stay in `scripts/`. Full tour:
[docs/shell.md](docs/shell.md).

```bash
make gallery                    # every reference still -> gallery/
make quilts                     # every bundled quilt, measured budgets dialled in
make preview-museum             # quarter-size, for iterating on composition

quiltwright cast renders/quilts/bell-jar-holo_qs8x6a1.77778.png
quiltwright bridge status       # is Bridge actually able to draw?
quiltwright weave ... && quiltwright wallpaper ...   # the no-Bridge path
quiltwright cartoon 2omf.cif.gz ompf_cartoon.inc     # molecular ribbon, via PyMOL
quiltwright mesh model.glb                           # any mesh file, camera auto-framed
quiltwright probe scene.pov --eye 0 35 -95 --aim 0 18 0   # measure its depth range

python scripts/make_exhibit.py 7AHL --quilt          # fetch -> convert -> render
```

`RENDER_THREADS` defaults to `ncpu - 2`. When the glass stays black, run
`quiltwright bridge status` first -- Bridge keeps answering HTTP after crashing
internally.

---

## The depth budget

Whether a hologram fuses comes down to **adjacent-view disparity**: how far a
feature moves between neighboring views. Roughly 4-5 px is the practical
ceiling; past ~8 px, hard edges ghost. The arithmetic API is in
[docs/usage.md](docs/usage.md#check-the-depth-budget); the results worth
knowing before you frame a shot -- each derived in
[docs/povray.md](docs/povray.md):

- **Content at the focal plane has zero disparity** -- it is welded to the glass.
- **The focal plane belongs at the harmonic mean** of the measured depth range,
  not the midpoint; near content is the expensive side.
- **A narrower field of view increases disparity.** The widely repeated
  "~14 degree FOV" advice is specific to object-centric scenes; applied to an
  interior it makes ghosting worse.
- **Interiors have a fourth trap no arithmetic warns about**: the camera sweep
  can run through a wall. Measure
  [sweep clearance](docs/povray.md#3-sweep-clearance--the-constraint-peculiar-to-interiors).
- **The depths themselves are measured, not guessed** -- `quiltwright probe`
  sweeps an opaque plane along the view axis and reports where content actually
  begins and ends.

---

## Supported devices

`QUILT_PRESETS` carries the official quilt settings for Portrait, Go, and the
16"/27"/32"/65" panels in both orientations. The 16" Gen3 Landscape entry is
verified against what Bridge reports for real hardware -- see
[docs/usage.md](docs/usage.md#device-presets).

---

## Documentation

| Document | Contents |
|----------|----------|
| [docs/install.md](docs/install.md) | Installing the full stack: package extras, POV-Ray, ffmpeg, Bridge, pypdb2pov |
| [docs/usage.md](docs/usage.md) | Library recipes: PyVista, POV-Ray, Cycles, casting to Bridge, printer sweeps, depth budget |
| [docs/shell.md](docs/shell.md) | Driving it from the shell: every make target, the parallelism model, run reports, and what each CLI command is for |
| [docs/cli.md](docs/cli.md) | Flag-by-flag reference for every `quiltwright` command |
| [docs/architecture.md](docs/architecture.md) | The module map, the off-axis invariant shared by all three backends, and why the geometry core stays free of VTK |
| [docs/lfd.md](docs/lfd.md) | Light-field output, Bridge/Studio setup, device presets, the PyVista path, view sweeps for hologram printers |
| [docs/pyvista-datasets.md](docs/pyvista-datasets.md) | PyVista dataset ideas for holograms: topography, the Allen mouse brain atlas, other strong-depth candidates |
| [docs/tvb-data.md](docs/tvb-data.md) | Brain geometry from The Virtual Brain: cortical surfaces, connectomes, parcellations, downloaded on demand |
| [docs/povray.md](docs/povray.md) | The POV-Ray backend: off-axis camera derivation, depth budget, sweep clearance, a worked case study |
| [docs/cycles.md](docs/cycles.md) | The Blender Cycles backend: hardware ray tracing (Metal/OptiX/HIP), mesh and .blend scenes, one process per sweep |
| [docs/mesh-import.md](docs/mesh-import.md) | Any 3D object file (glTF/GLB, OBJ, FBX, USD, …) to a quilt in one command, with the camera auto-framed from the mesh's bounds |
| [docs/povgen.md](docs/povgen.md) | Writing POV-Ray scenes from analytic primitives, so a scene composed in Python can be ray-traced rather than rasterized |
| [docs/pov-workflow.md](docs/pov-workflow.md) | The procedure: taking an archive scene from "won't parse" to a quilt that fuses, step by step |
| [docs/pdb2pov.md](docs/pdb2pov.md) | Rendering molecular structures as holograms with pypdb2pov, from the shell or in-process |
| [docs/hld.md](docs/hld.md) | Hololuminescent Displays, which play ordinary 2-D video rather than quilts |
| [docs/about-the-image.md](docs/about-the-image.md) | The museum scene: what is on display, and the thirty-year pipeline behind it |
| [docs/gallery.md](docs/gallery.md) | Every image in `gallery/`, which scene made it, and the aspect each must be rendered at |

---

## Testing

```bash
poetry install --with viz,dev    # or: pip install -e ".[viz]" && pip install pytest
pytest
```

Tests skip when their backend is absent. Headless CI: `xvfb-run -a pytest`.
Layered install and skip conditions are in the
[installation guide](docs/install.md#checking-the-stack).

---

## The pipelines this serves

- [WaveRider](https://github.com/Flux-Frontiers/waverider) -- manifold-aware
  geometric ML. Its voxel and manifold visualizer builds the PyVista scenes
  that `render_quilt()` sweeps.
- [pypdb2pov](https://github.com/Flux-Frontiers/pypdb2pov) -- PDB and mmCIF to
  POV-Ray. Reads mmCIF and compressed input, ships the atom textures inside
  the package, and imports, so a conversion and a quilt render fit in one
  script. Scenes are byte-identical to
  [pdb2pov](https://github.com/suchanek/pdb2pov), the 1993 C original.
- [proteusPy](https://github.com/suchanek/proteusPy) -- protein disulfide bond
  analysis and rendering.

## Citation

If you use Quiltwright in your work, please cite it. Citation metadata is in
[CITATION.cff](CITATION.cff); GitHub's "Cite this repository" button generates
BibTeX/APA from it, and the DOI badge above resolves to the archived release
on Zenodo.

```bibtex
@software{suchanek_quiltwright,
  author  = {Suchanek, Eric G.},
  title   = {Quiltwright: Holographic Output for Looking Glass Displays},
  url     = {https://github.com/Flux-Frontiers/quiltwright},
  doi     = {10.5281/zenodo.22180300},
  version = {0.10.1},
  year    = {2026}
}
```

## License

BSD 3-Clause. See [LICENSE](LICENSE).

