Module-by-module description
Each leaf module under picmaker has one responsibility. The
summary below describes that responsibility and links to the API
reference for each public symbol.
picmaker (src/picmaker/__init__.py)
Top-level package. Re-exports the public API surface from the leaf
modules, defines __all__, and resolves __version__
from importlib.metadata (with a fallback to the
setuptools_scm-generated _version.py when the package is run
from a source checkout that has not been installed). New code
should import from here (from picmaker import images_to_pics)
rather than from the individual leaf modules.
picmaker.cli (src/picmaker/cli.py)
The argparse-based command-line entry point. picmaker.cli.main()
parses sys.argv, dispatches to picmaker.pipeline.process_images(),
and converts --versions FILE into a list of normalized option
dicts. Each CLI phase lives in its own private helper:
_build_parser() (argparse setup),
_separate_files_and_dirs() (positional-arg classification),
_normalize_and_validate() (mutex / value-validity checks),
_collect_option_dicts() (--versions re-parse loop), and
_process_directory() (per-directory walk). They are
unit-tested directly in tests/test_cli_unit.py and
tests/test_cli_helpers.py.
picmaker.pipeline (src/picmaker/pipeline.py)
The orchestration layer. picmaker.pipeline.process_images()
walks the input list (with optional --movie mode that shares a
stretch across frames) and dispatches each file to
picmaker.pipeline.images_to_pics(). The per-image work is split
across three module-private helpers:
_pds3_resolve_pointer() (PDS3 .LBL pointer resolution),
_hst_mosaic_rgb() (HST ACS/WFC and WFPC2 mosaic assembly,
with _hst_wfpc2_mosaic() and _hst_acs_panel_mosaic() as
geometry sub-helpers), and _process_one_image() (the per-file
read → slice → colormap → write chain). Each helper has direct
unit-test coverage in tests/test_pipeline_helpers.py.
picmaker.pipeline.find_common_path() is a small directory-walking
helper used to derive the output tree’s root when --recursive is
set.
picmaker.options (src/picmaker/options.py)
PicmakerOptions is the dataclass that owns
all post-normalization mutex / value-validity invariants. Both
picmaker.cli._normalize_and_validate() (early, at CLI parse
time) and picmaker.pipeline.images_to_pics() (late, at library
call time) build a PicmakerOptions from
their kwargs and call
validate() so the invariants
live in exactly one place.
picmaker.io (src/picmaker/io.py)
The file-reader cascade and output-path helpers. The cascade lives in
picmaker.io.read_one_image_array() and tries each known format
in turn (pickle → numpy .npy → VICAR → FITS → PIL → PDS3-label);
the first match returns a ReadResult
typing.NamedTuple of (array3d, default_is_up, filter_info).
read_image_array() is the multi-file variant that
stacks the per-file results along the band axis.
read_pds_labeled_image_array() is the PDS3 label
parser.
get_outfile() builds the output path, honoring
the replace= policy.
The module’s name shadows the stdlib io; use absolute imports
(from picmaker.io import …) and never write import io inside
the picmaker package. A rename to picmaker.readers is tracked
in issue #14.
picmaker.enhance (src/picmaker/enhance.py)
Intensity-space operations. get_limits()
chooses the stretch endpoints from the array, optional masks, and the
--limits / --percentiles / --trim / --footprint
options. apply_colormap() maps a 2-D array to
RGB through a named or per-instrument tint.
apply_gamma() is the final power-law
correction. fill_zebra_stripes() is the
optional pre-stretch cleanup for legacy spacecraft compression
artifacts.
picmaker.geometry (src/picmaker/geometry.py)
Shape-space operations. slice_array() selects
the sample / line / band range from the raw 3-D input.
crop_array() strips constant-valued borders.
rotate_array_rgb() applies the requested
flip / rotation. get_size() is the resize
planner that consumes --size / --scale / --frame /
--wrap-ratio and returns the final dimensions plus wrap geometry.
resize_image(),
wrap_image(), and
pad_image() execute the plan against a PIL
image. circle_mask() is a small helper used
by the median-filter footprint option in enhance.
picmaker.color (src/picmaker/color.py)
Mission-agnostic tint dispatch. tinted_colormap()
takes the filter_info triple from the reader cascade, normalizes
the HST CL1 / CL2 / CLEAR* / N/A quirks, then
delegates to the per-instrument modules in
picmaker.instruments. The wavelength-to-RGB lookup tables
(picmaker._rgb.RGB_BY_NM, picmaker._rgb.RFUNC,
picmaker._rgb.GFUNC, picmaker._rgb.BFUNC) are
re-exported here for convenience but live in picmaker._rgb.
picmaker.pil_utils (src/picmaker/pil_utils.py)
The bridge between numpy arrays and PIL images.
array_to_pil() converts an
(lines, samples, bands) array into a PIL image (or a list of three
PIL images for 16-bit RGB). pil_to_array()
is the inverse. write_pil() writes a PIL
image to disk and routes 16-bit output through
picmaker.tiff16.WriteTiff16().
picmaker._filters (src/picmaker/_filters.py)
A thin dispatch around PIL’s PIL.ImageFilter presets.
picmaker._filters.FILTER_DICT maps the case-folded filter
name to the ImageFilter instance;
filter_image() applies one to a PIL image
(or raises ValueError for the 16-bit-RGB-as-list path,
which is not supported).
picmaker._rgb (src/picmaker/_rgb.py)
The wavelength → RGB table that the HST tint inferer uses. Private to
the package; re-exported via picmaker.color.
picmaker.tiff16 (src/picmaker/tiff16.py)
Hand-rolled 16-bit TIFF reader and writer. Used because Pillow’s
16-bit support is uneven across grayscale / RGB / palette modes.
WriteTiff16() and
ReadTiff16() keep their PascalCase names for
backward compatibility (the one remaining per-file ruff ignore for
this module is the N802 allow).
picmaker.colornames (src/picmaker/colornames.py)
The X11 color-name table (~800 entries) plus a normalizing lookup
helper. Used by the --pad-color / --gap-color / colormap
options.
picmaker.instruments (src/picmaker/instruments/)
Per-mission detectors and tint chains. Each module under this
subpackage exposes the same four-function protocol described in
Adding a new instrument.
picmaker.instruments.lookup() picks the right instrument module
given a host string;
VICAR_INSTRUMENTS and
FITS_INSTRUMENTS are the per-format
dispatch lists that picmaker.io.read_one_image_array() iterates.