eyepiece
Plotting and animation primitives for astronomical imaging simulations.
What eyepiece is
eyepiece provides ax-first, stateless figure functions for the plots that
recur across direct-imaging work: log-scaled and diverging image displays,
side-by-side and A/B comparison panels, radial profiles and contrast curves,
corner plots, orbit and sky-track scenes, optical-train schematics, and a
multi-sink animation recorder that grabs frames once and writes them to any
combination of gif, mp4, and html. Every primitive takes plain arrays in and
returns a small result object holding the axes and the artists it drew, so
callers can update or extend a figure without re-deriving which line or
image object came from where.
Figure style (color, colormaps, and mode) is resolved through
hwostyle at call
time, not at import time. import eyepiece never activates a style or
touches matplotlib's rcParams. Without an active hwostyle mode, primitives
fall back to a fixed light-mode palette, so eyepiece also works as a
standalone plotting library.
What eyepiece is not
- Not a simulation library. eyepiece takes arrays and returns figures; it never imports a simulation, orbit, or optics package.
- Not a style engine. Color, colormap, and mode definitions live in hwostyle; eyepiece only reads them at call time.
- Not a data pipeline. Aggregating or transforming simulation output before plotting is the caller's job.
What is in it
Every name below is importable straight from eyepiece; the submodules that
implement them are internal organization.
- Images.
imshow_log(log scale clipped to a floor, so a zero-valued pixel cannot break the norm),imshow_diverging(symmetric norm about zero),show_field(amplitude and phase panels of a complex field),compare_row(several images sharing one norm and colorbar), andtriptych(A, B, and a ratio or residual comparison panel, side by side). - Distributions.
corner,corner_overlay(a second sample set laid over an existing triangle plot),hist_vs_pdf, andcov_ellipse. - Profiles.
plot_radial(a precomputed radial profile line),plot_contrast_curve(a contrast curve with inner/outer working angle shading and reference floor curves, drawn once per axes even across repeated calls, with each curve taking the next palette color so two calls on one axes are distinguishable), andradial_profile_plot(computes the profile viahwoutilsand plots it in one call, under the[hwo]extra). - Scenes.
trail(a 2D or 3D trajectory with depth-cued markers),sky_fan(weighted candidate sky tracks with an inner-working-angle disk), andfading_track. - Schematics.
rail(an optical-train diagram built from a plain(label, glyph)element list, over theGLYPHSvocabulary), andschematic, a preset wrapper overrailfor the imager and coronagraph trains that come up constantly. - Layout. Pixel-edge extent helpers (
extent_lod,extent_arcsec,extent_au, ...) with matching axis labelers, plusFrameandSourceStylesfor keeping several panels of one scene consistent. - Output.
save_figfor a styled write to disk,record(a context manager that opens every sink at once and takes frames from a loop the caller drives) andanimate(which binds a figure, a draw function, and a frame source into the publicAnimationtype it returns), andPRESETSof measured fps/dpi pairs.
Usage
import eyepiece as ep
result = ep.imshow_log(psf, extent=ep.extent_lod_from_pixels(psf.shape[0], 0.5))
ep.label_lod(result.ax)
ep.save_fig(result.fig, "psf")
Every primitive returns a small result object carrying the axes it drew on
and the artists it made (keyed by the ARTIST_KEYS vocabulary), so a caller
can keep working on the figure without hunting for the objects again. An
image primitive also returns an .update that redraws with new data through
the same transform, which is what makes animation a few lines:
frames = [cube[k] for k in range(len(cube))]
result = ep.imshow_log(frames[0])
def draw(fig, k):
result.update(frames[k])
ep.animate(result.fig, draw, len(frames), fps=10).save("run.mp4", "run.gif")
rail draws a miniature optical-train diagram from a plain element list, so
a physics panel can sit beside a reminder of which plane it shows:
import eyepiece as ep
result = ep.rail(
[("Pupil", "pupil"), ("FPM", "fpm"), ("Lyot", "lyot"), ("Focal", "focal")],
highlight="FPM",
)
ep.save_fig(result.fig, "coronagraph_rail")
Status
eyepiece is young: the primitives above are implemented and tested, and the public API may still shift before 1.0.
Installation
pip install eyepiece
Unit conversions used by a small number of layout helpers (arcsecond and AU
extents) and radial_profile_plot's profile computation are optional and
pull in hwoutils:
pip install eyepiece[hwo]
License
MIT
Metadata
Release files for eyepiece 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| eyepiece-0.3.0.tar.gz | 60.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| eyepiece-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 119.8 kB
Release files / eyepiece-0.3.0.tar.gz
| Download URL | eyepiece-0.3.0.tar.gz |
|---|---|
| Size | 60.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
346b7ffd25f0579874200c4c32661ce5d4bfe2809bb9ab79bc74fb96de0ef5f4
|
|
BLAKE2b-256 checksum How to use checksums |
f05036c7a4e1d351f0a7415879aa0755d92c25421e27b8246125db581ad69c14
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.
Transparency logRelease files / eyepiece-0.3.0-py3-none-any.whl
| Download URL | eyepiece-0.3.0-py3-none-any.whl |
|---|---|
| Size | 59.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1231b94f1c8d4d1c8e92a541f269102da042d2196a72470f26b76c22dc2e5d9b
|
|
BLAKE2b-256 checksum How to use checksums |
c19ca473c456b8e7e137a0fe2f45af239d51133215e488dad14022d2e4eee2d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.
Transparency log