picmaker Module
The picmaker package is organized into a handful of leaf modules
plus an instruments subpackage; each symbol is
documented at its canonical leaf-module location below. Click any
function name to jump to its source via sphinx.ext.viewcode, or
follow the Source link under each section to view the file on
GitHub.
Public API
Every name listed below is re-exported from the top-level picmaker
package, so callers should import from there:
from picmaker import images_to_pics, read_one_image_array, PicmakerOptions
The per-leaf-module sections after this one are the authoritative documentation for each symbol; the entries here are short pointers arranged by topic.
Top-level pipeline and CLI
- images_to_pics(filenames: list[str], directory: str | None = None, verbose: bool = False, *, replace: str = 'all', proceed: bool = False, extension: str | None = 'jpg', suffix: str = '', strip: Any = None, quality: int = 75, twobytes: bool = False, bands: Any = None, lines: Any = None, samples: Any = None, obj: Any = None, pointer: Any = None, pds3_label_method: str = 'strict', size: Any = None, scale: Any = (100.0, 100.0), crop: Any = None, frame: Any = None, pad: bool = False, pad_color: Any = 'black', frame_max: int | None = None, wrap: bool = False, wrap_ratio: float | None = None, overlap: tuple[float, float] = (0.0, 0.0), gap_size: int = 1, gap_color: Any = 'white', hst: bool = False, valid: Any = None, limits: Any = None, percentiles: Any = None, trim: int = 0, trim_zeros: bool = False, footprint: int = 0, histogram: bool = False, colormap: Any = None, below_color: Any = None, above_color: Any = None, invalid_color: Any = None, gamma: float = 1.0, tint: bool = False, display_upward: bool = False, display_downward: bool = False, rotate: Any = None, filter_name: str = 'NONE', zebra: bool = False, reuse: Any = None) tuple[Any, Any, Any][source]
Convert one or more image files to picture files.
See
picmaker --helpfor the meaning of each keyword argument. The CLI’s--filterflag binds to thefilter_namekeyword on this function (the rename in 2026-05 dropped the legacy builtin-shadowingfilterkwarg).- Parameters:
filenames – List of image file names to convert.
directory – Output directory.
Nonewrites next to the input.verbose – Print each input filename as it is processed.
- Returns:
(low, high, reuse)— the lower / upper limits of the stretch and the reuse tuple if the caller wants to call again without re-reading the file.
- process_images(filenames: list[str], directory: str | None, movie: bool, option_dicts: list[dict[str, Any]], verbose: bool = False) None[source]
Process a list of images using a list of option dictionaries.
In movie mode, all frames are converted with the same stretch derived from the median of the per-frame limits.
- Parameters:
filenames – Files to process.
directory – Output directory (created if missing).
Noneto write next to the input.movie – Run as a movie (single shared stretch across frames).
option_dicts – A list of
option_dictdicts (one per--versionsline).verbose – Print each file as it is processed.
- find_common_path(directories: list[str]) str[source]
Return the longest directory prefix shared by every directory in the list.
Uses
os.path.commonpath()so the result honors the current platform’s separator (/on POSIX,\on Windows).- Parameters:
directories – A list of directory path strings.
- Returns:
The longest common directory path. An empty string if the list is empty or the directories share no common ancestor (e.g. paths on different drives on Windows, or a mix of absolute and relative paths).
- main() None[source]
Picmaker CLI entry point.
Argparse usage errors raise
SystemExit(passed through). Validation errors raiseValueError; the outerexcept Exceptionwrapper prints them viasys.excepthook()and exits with code 1.
- class PicmakerOptions(replace: str = 'all', proceed: bool = False, extension: str | None = 'jpg', suffix: str = '', strip: Any = None, quality: int = 75, twobytes: bool = False, bands: Any = None, lines: Any = None, samples: Any = None, obj: Any = None, pointer: Any = None, pds3_label_method: str = 'strict', size: Any = None, scale: Any = (100.0, 100.0), crop: Any = None, frame: Any = None, pad: bool = False, pad_color: Any = 'black', frame_max: int | None = None, wrap: bool = False, wrap_ratio: float | None = None, overlap: tuple[float, float] = (0.0, 0.0), gap_size: int = 1, gap_color: Any = 'white', hst: bool = False, valid: Any = None, limits: Any = None, percentiles: Any = None, trim: int = 0, trim_zeros: bool = False, footprint: int = 0, histogram: bool = False, colormap: Any = None, below_color: Any = None, above_color: Any = None, invalid_color: Any = None, gamma: float = 1.0, tint: bool = False, display_upward: bool = False, display_downward: bool = False, rotate: Any = None, filter_name: str = 'NONE', zebra: bool = False)[source]
Bases:
objectAll post-normalization knobs that drive the pipeline.
Each field’s default matches the corresponding kwarg default on
picmaker.pipeline.images_to_pics(). Callvalidate()once after construction (or after any in-place mutation) to enforce the cross-field invariants.The
to_kwargs()andfrom_kwargs()helpers let the legacy**option_dictcall form continue to work unchanged.
Image I/O
- read_image_array(filename: str | Sequence[str | PathLike[str]], labelfile: str | PathLike[str] | None, obj: int | str | list[int | str] | tuple[int | str, ...] | None = None, hst: bool = False, *, pds3_label_method: str = 'strict') ReadResult[source]
Read one or more image files and return a stacked 3-D array.
- Parameters:
filename – An input file name, or a list of file names whose arrays should be stacked together. Files can be in VICAR, FITS, TIFF,
.npy, or pickle format.labelfile – Optional path to a PDS3 label file.
obj – Index or name of the object to load when the file contains multiple image objects. If a list/tuple, multiple objects are stacked.
hst – True to mosaic an HST image involving multiple CCDs.
pds3_label_method – Forwarded to
pdsparser.PdsLabelas itsmethod=argument when a PDS3.LBLis parsed ('strict','loose','compound', or'fast').
- Returns:
array3d— 3-D numpy array.display_upward— True if the default display orientation is upward.filter_info— Optional(inst_host, inst_id, filter)tuple.
- Return type:
(array3d, display_upward, filter_info)
- read_one_image_array(filename: str | PathLike[str], labelfile: str | PathLike[str] | None, obj: int | str | list[int | str] | tuple[int | str, ...] | None = None, hst: bool = False, *, pds3_label_method: str = 'strict') ReadResult[source]
Read a single image array, trying each known format in turn.
The try-cascade is: pickle → numpy
.npy→ VICAR → FITS → PIL (or 16-bit TIFF) → PDS3 label. Each format is attempted in order and the first one that succeeds wins.- Parameters:
filename – Path to the input file.
labelfile – Optional path to a sibling PDS3 label file.
obj – Object index/name for multi-image files.
hst – True to mosaic an HST image involving multiple CCDs.
pds3_label_method – Forwarded to
pdsparser.PdsLabelas itsmethod=argument when the PDS3-label branch fires ('strict','loose','compound', or'fast').
- Returns:
(array3d, display_upward, filter_info).filter_infoisNoneif no instrument is detected.- Raises:
OSError – If none of the format readers succeed. The per-reader failure causes are attached via
__cause__as anExceptionGroupso callers can inspect what each reader rejected.
- read_pds_labeled_image_array(filename: str | PathLike[str], obj: int | str | list[int | str] | tuple[int | str, ...] | None = None, *, pds3_label_method: str = 'strict') ReadResult | None[source]
Read a PDS3-labeled image and return the same triple as
read_one_image_array().- Parameters:
filename – Path to a
.LBL(or matching) PDS3 label file.obj – Optional pointer name or index.
pds3_label_method – Forwarded to
pdsparser.PdsLabelas itsmethod=argument ('strict','loose','compound', or'fast').
- Returns:
(array3d, False, (inst_host, inst_name, filter_name))orNoneif no parseable label is found.
- read_pil(infile: str | PathLike[str]) Image | list[Image][source]
Read a PIL image (or 16-bit TIFF expanded to a PIL image) from a file.
- Parameters:
infile – Path to the input file.
- Returns:
A PIL image or a list of three PIL images (16-bit RGB).
- read_array(infile: str | PathLike[str], rescale: bool) ndarray[tuple[Any, ...], dtype[Any]][source]
Read a numpy array from a PIL-readable file (or a 16-bit TIFF).
- Parameters:
infile – Path to the input file.
rescale – True to scale values to the range 0-1.
- Returns:
A 2-D or 3-D numpy array. The dtype depends on the input format and on
rescale:uint8for 8-bit PIL inputs without rescaling,uint16for 16-bit TIFF, andfloat64wheneverrescaleis true.
- get_outfile(infile: str | PathLike[str], outdir: str | PathLike[str] | None = None, strip: Any = None, suffix: str | None = '', extension: str = 'jpg', replace: str = 'all') str[source]
Derive the output filename for one input.
- Parameters:
infile – Name of the input file.
outdir – Output directory, or
Nonefor the input’s directory.strip – A string or list of strings to strip from the input filename before adding the suffix.
Noneis equivalent to[''].suffix – Extra string added before the extension.
extension – Output file extension (e.g.
'jpg').replace – Replacement policy when the output already exists:
'all'(silent overwrite),'none'(skip silently),'warn'(warn and overwrite), or'error'.
- Returns:
The output file path, or an empty string when
replace='none'and the file already exists.- Raises:
OSError – If
replace='error'and the file already exists.
- Side Effects:
Creates the output directory tree if it does not exist.
- write_pil(image: Any, outfile: str | PathLike[str], quality: int = 75) None[source]
Write a PIL image (or list of RGB images) to a file.
- Parameters:
image – A PIL image or a list of three images.
outfile – The output file to write.
quality – Quality factor 0-100 to use for JPEG output.
- class ReadResult(array3d: ndarray[tuple[Any, ...], dtype[Any]], default_is_up: bool, filter_info: tuple[str, str, Any] | None)[source]
Bases:
NamedTupleTriple returned by the reader cascade.
A
typing.NamedTupleso callers can use either positional unpacking (array, up, info = read_one_image_array(...)) or attribute access (result.array3d) interchangeably.
The FilterInfo type alias is documented in the I/O
section below.
Enhancement
- get_limits(array2d: Any, mask: Any, limits: Any = None, percentiles: tuple[float, float] = (0.0, 100.0), *, assume_int: bool = False, trim: int = 0, trim_zeros: bool = False, footprint: int = 0) Any[source]
Compute stretch limits from numeric limits and/or percentiles.
- Parameters:
array2d – The 2-D numpy array, which may be masked.
mask – 2-D mask array (True for masked pixels), or
None.limits – Numeric
(lower, upper)to confine the histogram, orNonefor the full dynamic range.percentiles –
(lower%, upper%)corresponding to the returned limits.assume_int – Treat the array as integers even if it isn’t. Integer histograms extend from 0.5 below the minimum to 0.5 above the maximum.
trim – Number of pixels around the image edge to exclude.
trim_zeros – If True, trim exterior rows/columns that contain all zeros before calculating limits.
footprint – Size of the 2-D median filter applied as an alternative way to set limits.
- Returns:
The
(lower, upper)stretch limits.
- apply_gamma(array: Any, gamma: float) Any[source]
Apply a gamma curve to an array already scaled 0-1.
- Parameters:
array – A 2-D or 3-D numpy array.
gamma – Gamma factor.
> 1brightens midtones;< 1darkens.
- Returns:
The rescaled array.
- apply_colormap(array2d: Any, limits: tuple[Any, Any], histogram: bool = False, colormap: Any = None, invalid_mask: Any = None, below_color: Any = None, above_color: Any = None, invalid_color: Any = 'black') Any[source]
Apply a colormap to a grayscale image.
Produces a 3-D array with one band (grayscale) or three bands (RGB), in axis order
(line, sample, band).- Parameters:
array2d – A 2-D numpy array.
limits – The values that correspond to the first and last colors of the mapping.
histogram – True to use histogram shading (uniform DN distribution).
colormap – An N-tuple of colors or color names (e.g.
"red-blue").Nonekeeps the image grayscale.invalid_mask – Boolean mask of invalid pixels.
below_color – Color for pixels below the lower limit. Defaults to the first color of the colormap.
above_color – Color for pixels above the upper limit. Defaults to the last color of the colormap.
invalid_color – Color for invalid pixels.
- Returns:
A 3-D array in axis order
(line, sample, band)scaled 0-1.
- fill_zebra_stripes(array2d: Any) Any[source]
Fill zero zebra stripes around the edges of rows.
Fills lines of zeros at the beginning and end of each row when the rows immediately above and below have nonzero values at the same columns. This removes an artifact associated with some spacecraft compression procedures.
- Parameters:
array2d – A 2-D numpy array (modified in place).
- Returns:
The same array, modified in place.
- tinted_colormap(filter_info: Any) list[tuple[int, int, int]] | None[source]
Return a colormap based on filter info.
- Parameters:
filter_info – A tuple
(instrument_host, instrument_id, filter), wherefiltermay be a single name or a 2-tuple of names (e.g. HST/ACS).- Returns:
A colormap as a list of
(R, G, B)tuples (typically[black, tint, white]), orNoneif no colormap can be derived.
Geometry
- crop_array(array: Any, value: float = 0.0, samples: bool = True, lines: bool = True) Any[source]
Crop constant-valued borders from a 2-D or 3-D image.
- Parameters:
array – A 2-D image
(lines, samples)or 3-D image(bands, lines, samples).value – Constant pixel value to trim from the border.
samples – True to trim sample borders; False to leave them.
lines – True to trim line borders; False to leave them.
- Returns:
A view (or sliced copy) of the input with the constant border removed.
- slice_array(array3d: Any, samples: Any = None, lines: Any = None, bands: Any = None, valid: Any = None, crop: Any = None) tuple[Any, Any][source]
Return the requested slice of a 3-D array as a 2-D array.
- Parameters:
array3d – 3-D image array indexed
(bands, lines, samples).samples – Tuple
(s0, s1)selecting the sample range, orNonefor all samples.lines – Tuple
(l0, l1)selecting the line range, orNonefor all lines.bands – Tuple
(b0, b1)selecting the band range to average;Nonefor all bands.valid – Tuple
(vmin, vmax)of valid pixel values; pixels outside this range are masked.Nonekeeps all pixels valid.crop – Numeric value to crop from the border of the image (e.g.
0to crop zero borders).Nonedisables cropping.
- Returns:
(array2d, invalid_mask).array2dis the band-averaged 2-D array; invalid pixels are excluded from the average.invalid_maskmay beNoneif no pixels are masked.
- wrap_image(image: Any, wrapped_size: Any, sections: int, wrap_axis: int, gap_size: int, gap_color: Any) Any[source]
Wrap a PIL image into
sectionssub-images separated by gaps.- Parameters:
image – A PIL image.
wrapped_size –
(width, height)of the final wrapped image.sections – Number of sections to wrap.
wrap_axis – 0 for horizontal wrapping; 1 for vertical.
gap_size – Width of gap in pixels between sections.
gap_color – Gap color, either an X11 name or an
(R, G, B)triple.
- Returns:
A new PIL image of the requested size.
- pad_image(image: Any, frame: Any, pad_color: Any) Any[source]
Pad a PIL image to fill a target frame size.
- Parameters:
image – A PIL image.
frame –
(width, height)target frame size, orNoneto skip padding.pad_color – Gap fill color (X11 name or
(R, G, B)triple).
- Returns:
A padded PIL image of the requested size, or the original if no padding is needed.
- resize_image(image: Any, new_size: tuple[int, int]) Any[source]
Resize a PIL image or a list of three PIL images.
- Parameters:
image – A single PIL image or a list/tuple of three images.
new_size –
(width, height)of the output.
- Returns:
The resized image(s).
- rotate_array_rgb(array_rgb: Any, display_upward: bool, rotation_name: str | None) Any[source]
Apply an orientation to an RGB array.
- Parameters:
array_rgb – An RGB array.
display_upward – True to flip the image upward (top-of-image becomes top-of-display); False leaves it as is.
rotation_name – One of
'NONE','FLIPLR','FLIPTB','ROT90','ROT180','ROT270'. Case-insensitive.
- Returns:
The rotated array.
- Raises:
KeyError – If
rotation_nameis not one of the recognized choices.
- circle_mask(diameter: float) Any[source]
Return a boolean disk mask of the given diameter.
- Parameters:
diameter – The disk diameter in pixels.
- Returns:
A 2-D boolean numpy array where
Truemarks pixels inside the disk. The returned array is trimmed by one pixel on each side if the outer row is all-empty.
- get_size(array_shape: Any, size: Any = None, scale: Any = (100.0, 100.0), frame: Any = None, wrap: bool = False, wrap_ratio: float | None = None, overlap: tuple[float, float] = (0.0, 0.0), gap_size: int = 1, frame_max: int | None = None) tuple[Any, Any, int, int][source]
Compute the output image size and wrap properties.
- Parameters:
array_shape – Shape of the source numpy array
(lines, samples)or(lines, samples, bands).size – Target
(width, height). A scalar means square.Nonekeeps the array size.scale – Percentage scale to apply. A scalar applies to both axes; pass a tuple to scale width/height independently.
frame – Hard outer
(width, height)constraint.Nonefor no constraint.wrap – True to consider wrapping the image to reduce distortion.
wrap_ratio – Wrap if the width:height (or height:width) ratio exceeds this value.
overlap –
(min%, max%)allowed overlap between wrap sections.gap_size – Pixels of gap between wrap sections.
frame_max – Maximum percentage scale applied when frame is set and
wrapis False.
- Returns:
(unwrapped_size, wrapped_size, sections, wrap_axis).
Filters and conversion
- filter_image(image: Any, filter_name: str) Any[source]
Apply an arbitrary filter to a PIL image.
Two-byte (16-bit) images are not supported and raise
ValueError.- Parameters:
image – A PIL image as 8-bit RGB or grayscale.
filter_name – Name of the filter to be applied. Valid choices are the keys of
FILTER_DICT(case-insensitive).'NONE'returns the input image unchanged.
- Returns:
The filtered PIL image. For
filter_name='NONE'the input image is returned unchanged.- Raises:
ValueError – If
imageis a list (16-bit two-byte image).KeyError – If
filter_name(case-folded) is not a key ofpicmaker._filters.FILTER_DICT.
- array_to_pil(array: Any, twobytes: bool = False, rescale: bool = True) Any[source]
Convert an array to a PIL image.
For the special case of a 16-bit RGB image, the result is a list of three PIL images (one per channel).
- Parameters:
array – Image array containing one band of grayscale or three bands if RGB.
twobytes – True for 16-bit images, False for 8-bit.
rescale – True to scale values from unit; False to leave them alone.
- Returns:
A PIL image, or a list of three PIL images for 16-bit RGB.
- pil_to_array(image: Any, rescale: bool = True) Any[source]
Convert a PIL image (or list of RGB images) to a numpy array.
The shape of the returned array is
(lines, samples, bands)for an RGB image or(lines, samples)for a grayscale image.- Parameters:
image – A PIL image or list/tuple of three.
rescale – True to scale values to the range 0-1; False to leave them alone.
- Returns:
A numpy array.
Re-exported constants
The following module-level data names are re-exported from
picmaker and documented in their leaf-module sections below
(Color and Filters):
picmaker.color.RGB_BY_NMpicmaker.color.RFUNC,picmaker.color.GFUNC,picmaker.color.BFUNCpicmaker._filters.FILTER_DICT
Package
Source: src/picmaker/__init__.py.
rms-picmaker — convert PDS3/VICAR/FITS images to JPEG, TIFF, etc.
The package’s public surface is re-exported from this module so that consumers can write:
from picmaker import images_to_pics, read_one_image_array
The top-level pipeline entry point is
picmaker.pipeline.images_to_pics(); the single-image reader is
picmaker.io.read_one_image_array(). The full set of public
names is in this module’s __all__ list.
Backward-compatibility shim
Source: src/picmaker/picmaker.py.
Alternate import path that re-exports the full picmaker public API.
Every name surfaced here is the same object as the canonical
leaf-module symbol (verified by tests/test_api_compat.py), so
from picmaker.picmaker import images_to_pics and
from picmaker import images_to_pics resolve to the same function.
Wavelength → RGB tables
Source: src/picmaker/_rgb.py.
Wavelength → RGB lookup tables.
Maps wavelengths in the 380-750 nm range to an (R, G, B) triple
suitable for tinting a grayscale image. RGB_BY_NM holds the raw
table; RFUNC, GFUNC, and BFUNC are
tabulation.Tabulation splines that interpolate between
adjacent rows so the caller can query at any wavelength.
This module imports nothing from the rest of picmaker, which
lets picmaker.color and picmaker.instruments.hst both
read the same tables without forming an import cycle.
Pipeline
Source: src/picmaker/pipeline.py.
Top-level orchestration: walk directories, process one image, drive a movie.
process_images() and images_to_pics() are the CLI’s main
entry points; the module-private helpers
_pds3_resolve_pointer(), _hst_mosaic_rgb(), and
_process_one_image() each handle one phase of the per-image
pipeline so that images_to_pics() reads as a flat loop.
- find_common_path(directories: list[str]) str[source]
Return the longest directory prefix shared by every directory in the list.
Uses
os.path.commonpath()so the result honors the current platform’s separator (/on POSIX,\on Windows).- Parameters:
directories – A list of directory path strings.
- Returns:
The longest common directory path. An empty string if the list is empty or the directories share no common ancestor (e.g. paths on different drives on Windows, or a mix of absolute and relative paths).
- images_to_pics(filenames: list[str], directory: str | None = None, verbose: bool = False, *, replace: str = 'all', proceed: bool = False, extension: str | None = 'jpg', suffix: str = '', strip: Any = None, quality: int = 75, twobytes: bool = False, bands: Any = None, lines: Any = None, samples: Any = None, obj: Any = None, pointer: Any = None, pds3_label_method: str = 'strict', size: Any = None, scale: Any = (100.0, 100.0), crop: Any = None, frame: Any = None, pad: bool = False, pad_color: Any = 'black', frame_max: int | None = None, wrap: bool = False, wrap_ratio: float | None = None, overlap: tuple[float, float] = (0.0, 0.0), gap_size: int = 1, gap_color: Any = 'white', hst: bool = False, valid: Any = None, limits: Any = None, percentiles: Any = None, trim: int = 0, trim_zeros: bool = False, footprint: int = 0, histogram: bool = False, colormap: Any = None, below_color: Any = None, above_color: Any = None, invalid_color: Any = None, gamma: float = 1.0, tint: bool = False, display_upward: bool = False, display_downward: bool = False, rotate: Any = None, filter_name: str = 'NONE', zebra: bool = False, reuse: Any = None) tuple[Any, Any, Any][source]
Convert one or more image files to picture files.
See
picmaker --helpfor the meaning of each keyword argument. The CLI’s--filterflag binds to thefilter_namekeyword on this function (the rename in 2026-05 dropped the legacy builtin-shadowingfilterkwarg).- Parameters:
filenames – List of image file names to convert.
directory – Output directory.
Nonewrites next to the input.verbose – Print each input filename as it is processed.
- Returns:
(low, high, reuse)— the lower / upper limits of the stretch and the reuse tuple if the caller wants to call again without re-reading the file.
- process_images(filenames: list[str], directory: str | None, movie: bool, option_dicts: list[dict[str, Any]], verbose: bool = False) None[source]
Process a list of images using a list of option dictionaries.
In movie mode, all frames are converted with the same stretch derived from the median of the per-frame limits.
- Parameters:
filenames – Files to process.
directory – Output directory (created if missing).
Noneto write next to the input.movie – Run as a movie (single shared stretch across frames).
option_dicts – A list of
option_dictdicts (one per--versionsline).verbose – Print each file as it is processed.
Options
Source: src/picmaker/options.py.
Configuration dataclass for picmaker.pipeline.images_to_pics().
PicmakerOptions consolidates the ~45 keyword arguments accepted
by picmaker.pipeline.images_to_pics() into a single value object,
and owns the cross-field mutex / value-validity checks that previously
lived inline in both picmaker.cli._normalize_and_validate (the
private helper that builds the CLI’s option dict) and
picmaker.pipeline.images_to_pics().
The public function signature of
picmaker.pipeline.images_to_pics() is unchanged for backward
compatibility — internally it builds a PicmakerOptions and
calls PicmakerOptions.validate() so the duplicated mutex checks
live in exactly one place.
- class PicmakerOptions(replace: str = 'all', proceed: bool = False, extension: str | None = 'jpg', suffix: str = '', strip: Any = None, quality: int = 75, twobytes: bool = False, bands: Any = None, lines: Any = None, samples: Any = None, obj: Any = None, pointer: Any = None, pds3_label_method: str = 'strict', size: Any = None, scale: Any = (100.0, 100.0), crop: Any = None, frame: Any = None, pad: bool = False, pad_color: Any = 'black', frame_max: int | None = None, wrap: bool = False, wrap_ratio: float | None = None, overlap: tuple[float, float] = (0.0, 0.0), gap_size: int = 1, gap_color: Any = 'white', hst: bool = False, valid: Any = None, limits: Any = None, percentiles: Any = None, trim: int = 0, trim_zeros: bool = False, footprint: int = 0, histogram: bool = False, colormap: Any = None, below_color: Any = None, above_color: Any = None, invalid_color: Any = None, gamma: float = 1.0, tint: bool = False, display_upward: bool = False, display_downward: bool = False, rotate: Any = None, filter_name: str = 'NONE', zebra: bool = False)[source]
Bases:
objectAll post-normalization knobs that drive the pipeline.
Each field’s default matches the corresponding kwarg default on
picmaker.pipeline.images_to_pics(). Callvalidate()once after construction (or after any in-place mutation) to enforce the cross-field invariants.The
to_kwargs()andfrom_kwargs()helpers let the legacy**option_dictcall form continue to work unchanged.- classmethod from_kwargs(**kwargs: Any) PicmakerOptions[source]
Build a
PicmakerOptionsfrom a kwargs dict.
- to_kwargs() dict[str, Any][source]
Return a kwargs dict that unpacks into the pipeline entry point.
Specifically, the dict can be passed as
picmaker.pipeline.images_to_pics(**options.to_kwargs()).
- validate() None[source]
Run cross-field mutex / value-validity checks.
- Raises:
ValueError – When two options that cannot be set together are both set, or when
twobytesis combined with a non-TIFF extension or a non-trivial filter.
I/O
Source: src/picmaker/io.py.
File I/O helpers — read raw image arrays, write output, and label parsing.
This module is named io but it is NOT the stdlib io
module. To avoid the shadowing trap, always use absolute imports
(from picmaker.io import X) and never write import io inside the
picmaker package. The stdlib io module is reachable from any
non-picmaker file unchanged.
- class ReadResult(array3d: ndarray[tuple[Any, ...], dtype[Any]], default_is_up: bool, filter_info: tuple[str, str, Any] | None)[source]
Bases:
NamedTupleTriple returned by the reader cascade.
A
typing.NamedTupleso callers can use either positional unpacking (array, up, info = read_one_image_array(...)) or attribute access (result.array3d) interchangeably.
- get_outfile(infile: str | PathLike[str], outdir: str | PathLike[str] | None = None, strip: Any = None, suffix: str | None = '', extension: str = 'jpg', replace: str = 'all') str[source]
Derive the output filename for one input.
- Parameters:
infile – Name of the input file.
outdir – Output directory, or
Nonefor the input’s directory.strip – A string or list of strings to strip from the input filename before adding the suffix.
Noneis equivalent to[''].suffix – Extra string added before the extension.
extension – Output file extension (e.g.
'jpg').replace – Replacement policy when the output already exists:
'all'(silent overwrite),'none'(skip silently),'warn'(warn and overwrite), or'error'.
- Returns:
The output file path, or an empty string when
replace='none'and the file already exists.- Raises:
OSError – If
replace='error'and the file already exists.
- Side Effects:
Creates the output directory tree if it does not exist.
- read_array(infile: str | PathLike[str], rescale: bool) ndarray[tuple[Any, ...], dtype[Any]][source]
Read a numpy array from a PIL-readable file (or a 16-bit TIFF).
- Parameters:
infile – Path to the input file.
rescale – True to scale values to the range 0-1.
- Returns:
A 2-D or 3-D numpy array. The dtype depends on the input format and on
rescale:uint8for 8-bit PIL inputs without rescaling,uint16for 16-bit TIFF, andfloat64wheneverrescaleis true.
- read_image_array(filename: str | Sequence[str | PathLike[str]], labelfile: str | PathLike[str] | None, obj: int | str | list[int | str] | tuple[int | str, ...] | None = None, hst: bool = False, *, pds3_label_method: str = 'strict') ReadResult[source]
Read one or more image files and return a stacked 3-D array.
- Parameters:
filename – An input file name, or a list of file names whose arrays should be stacked together. Files can be in VICAR, FITS, TIFF,
.npy, or pickle format.labelfile – Optional path to a PDS3 label file.
obj – Index or name of the object to load when the file contains multiple image objects. If a list/tuple, multiple objects are stacked.
hst – True to mosaic an HST image involving multiple CCDs.
pds3_label_method – Forwarded to
pdsparser.PdsLabelas itsmethod=argument when a PDS3.LBLis parsed ('strict','loose','compound', or'fast').
- Returns:
array3d— 3-D numpy array.display_upward— True if the default display orientation is upward.filter_info— Optional(inst_host, inst_id, filter)tuple.
- Return type:
(array3d, display_upward, filter_info)
- read_one_image_array(filename: str | PathLike[str], labelfile: str | PathLike[str] | None, obj: int | str | list[int | str] | tuple[int | str, ...] | None = None, hst: bool = False, *, pds3_label_method: str = 'strict') ReadResult[source]
Read a single image array, trying each known format in turn.
The try-cascade is: pickle → numpy
.npy→ VICAR → FITS → PIL (or 16-bit TIFF) → PDS3 label. Each format is attempted in order and the first one that succeeds wins.- Parameters:
filename – Path to the input file.
labelfile – Optional path to a sibling PDS3 label file.
obj – Object index/name for multi-image files.
hst – True to mosaic an HST image involving multiple CCDs.
pds3_label_method – Forwarded to
pdsparser.PdsLabelas itsmethod=argument when the PDS3-label branch fires ('strict','loose','compound', or'fast').
- Returns:
(array3d, display_upward, filter_info).filter_infoisNoneif no instrument is detected.- Raises:
OSError – If none of the format readers succeed. The per-reader failure causes are attached via
__cause__as anExceptionGroupso callers can inspect what each reader rejected.
- read_pds_labeled_image_array(filename: str | PathLike[str], obj: int | str | list[int | str] | tuple[int | str, ...] | None = None, *, pds3_label_method: str = 'strict') ReadResult | None[source]
Read a PDS3-labeled image and return the same triple as
read_one_image_array().- Parameters:
filename – Path to a
.LBL(or matching) PDS3 label file.obj – Optional pointer name or index.
pds3_label_method – Forwarded to
pdsparser.PdsLabelas itsmethod=argument ('strict','loose','compound', or'fast').
- Returns:
(array3d, False, (inst_host, inst_name, filter_name))orNoneif no parseable label is found.
Enhancement
Source: src/picmaker/enhance.py.
Pixel-value enhancement: stretch limits, gamma, colormap lookup, zebra fill.
These functions take 2-D numpy arrays (post slicing/cropping) and adjust intensity or map intensity to color. None of them resize or rotate.
- apply_colormap(array2d: Any, limits: tuple[Any, Any], histogram: bool = False, colormap: Any = None, invalid_mask: Any = None, below_color: Any = None, above_color: Any = None, invalid_color: Any = 'black') Any[source]
Apply a colormap to a grayscale image.
Produces a 3-D array with one band (grayscale) or three bands (RGB), in axis order
(line, sample, band).- Parameters:
array2d – A 2-D numpy array.
limits – The values that correspond to the first and last colors of the mapping.
histogram – True to use histogram shading (uniform DN distribution).
colormap – An N-tuple of colors or color names (e.g.
"red-blue").Nonekeeps the image grayscale.invalid_mask – Boolean mask of invalid pixels.
below_color – Color for pixels below the lower limit. Defaults to the first color of the colormap.
above_color – Color for pixels above the upper limit. Defaults to the last color of the colormap.
invalid_color – Color for invalid pixels.
- Returns:
A 3-D array in axis order
(line, sample, band)scaled 0-1.
- apply_gamma(array: Any, gamma: float) Any[source]
Apply a gamma curve to an array already scaled 0-1.
- Parameters:
array – A 2-D or 3-D numpy array.
gamma – Gamma factor.
> 1brightens midtones;< 1darkens.
- Returns:
The rescaled array.
- fill_zebra_stripes(array2d: Any) Any[source]
Fill zero zebra stripes around the edges of rows.
Fills lines of zeros at the beginning and end of each row when the rows immediately above and below have nonzero values at the same columns. This removes an artifact associated with some spacecraft compression procedures.
- Parameters:
array2d – A 2-D numpy array (modified in place).
- Returns:
The same array, modified in place.
- get_limits(array2d: Any, mask: Any, limits: Any = None, percentiles: tuple[float, float] = (0.0, 100.0), *, assume_int: bool = False, trim: int = 0, trim_zeros: bool = False, footprint: int = 0) Any[source]
Compute stretch limits from numeric limits and/or percentiles.
- Parameters:
array2d – The 2-D numpy array, which may be masked.
mask – 2-D mask array (True for masked pixels), or
None.limits – Numeric
(lower, upper)to confine the histogram, orNonefor the full dynamic range.percentiles –
(lower%, upper%)corresponding to the returned limits.assume_int – Treat the array as integers even if it isn’t. Integer histograms extend from 0.5 below the minimum to 0.5 above the maximum.
trim – Number of pixels around the image edge to exclude.
trim_zeros – If True, trim exterior rows/columns that contain all zeros before calculating limits.
footprint – Size of the 2-D median filter applied as an alternative way to set limits.
- Returns:
The
(lower, upper)stretch limits.
Geometry
Source: src/picmaker/geometry.py.
Geometry helpers: slicing, cropping, rotation, sizing, wrapping, padding.
These functions take numpy arrays or PIL images and shape them — they do not change pixel values (rotation/flips notwithstanding) or apply colormaps.
- circle_mask(diameter: float) Any[source]
Return a boolean disk mask of the given diameter.
- Parameters:
diameter – The disk diameter in pixels.
- Returns:
A 2-D boolean numpy array where
Truemarks pixels inside the disk. The returned array is trimmed by one pixel on each side if the outer row is all-empty.
- crop_array(array: Any, value: float = 0.0, samples: bool = True, lines: bool = True) Any[source]
Crop constant-valued borders from a 2-D or 3-D image.
- Parameters:
array – A 2-D image
(lines, samples)or 3-D image(bands, lines, samples).value – Constant pixel value to trim from the border.
samples – True to trim sample borders; False to leave them.
lines – True to trim line borders; False to leave them.
- Returns:
A view (or sliced copy) of the input with the constant border removed.
- get_size(array_shape: Any, size: Any = None, scale: Any = (100.0, 100.0), frame: Any = None, wrap: bool = False, wrap_ratio: float | None = None, overlap: tuple[float, float] = (0.0, 0.0), gap_size: int = 1, frame_max: int | None = None) tuple[Any, Any, int, int][source]
Compute the output image size and wrap properties.
- Parameters:
array_shape – Shape of the source numpy array
(lines, samples)or(lines, samples, bands).size – Target
(width, height). A scalar means square.Nonekeeps the array size.scale – Percentage scale to apply. A scalar applies to both axes; pass a tuple to scale width/height independently.
frame – Hard outer
(width, height)constraint.Nonefor no constraint.wrap – True to consider wrapping the image to reduce distortion.
wrap_ratio – Wrap if the width:height (or height:width) ratio exceeds this value.
overlap –
(min%, max%)allowed overlap between wrap sections.gap_size – Pixels of gap between wrap sections.
frame_max – Maximum percentage scale applied when frame is set and
wrapis False.
- Returns:
(unwrapped_size, wrapped_size, sections, wrap_axis).
- pad_image(image: Any, frame: Any, pad_color: Any) Any[source]
Pad a PIL image to fill a target frame size.
- Parameters:
image – A PIL image.
frame –
(width, height)target frame size, orNoneto skip padding.pad_color – Gap fill color (X11 name or
(R, G, B)triple).
- Returns:
A padded PIL image of the requested size, or the original if no padding is needed.
- resize_image(image: Any, new_size: tuple[int, int]) Any[source]
Resize a PIL image or a list of three PIL images.
- Parameters:
image – A single PIL image or a list/tuple of three images.
new_size –
(width, height)of the output.
- Returns:
The resized image(s).
- rotate_array_rgb(array_rgb: Any, display_upward: bool, rotation_name: str | None) Any[source]
Apply an orientation to an RGB array.
- Parameters:
array_rgb – An RGB array.
display_upward – True to flip the image upward (top-of-image becomes top-of-display); False leaves it as is.
rotation_name – One of
'NONE','FLIPLR','FLIPTB','ROT90','ROT180','ROT270'. Case-insensitive.
- Returns:
The rotated array.
- Raises:
KeyError – If
rotation_nameis not one of the recognized choices.
- slice_array(array3d: Any, samples: Any = None, lines: Any = None, bands: Any = None, valid: Any = None, crop: Any = None) tuple[Any, Any][source]
Return the requested slice of a 3-D array as a 2-D array.
- Parameters:
array3d – 3-D image array indexed
(bands, lines, samples).samples – Tuple
(s0, s1)selecting the sample range, orNonefor all samples.lines – Tuple
(l0, l1)selecting the line range, orNonefor all lines.bands – Tuple
(b0, b1)selecting the band range to average;Nonefor all bands.valid – Tuple
(vmin, vmax)of valid pixel values; pixels outside this range are masked.Nonekeeps all pixels valid.crop – Numeric value to crop from the border of the image (e.g.
0to crop zero borders).Nonedisables cropping.
- Returns:
(array2d, invalid_mask).array2dis the band-averaged 2-D array; invalid pixels are excluded from the average.invalid_maskmay beNoneif no pixels are masked.
- wrap_image(image: Any, wrapped_size: Any, sections: int, wrap_axis: int, gap_size: int, gap_color: Any) Any[source]
Wrap a PIL image into
sectionssub-images separated by gaps.- Parameters:
image – A PIL image.
wrapped_size –
(width, height)of the final wrapped image.sections – Number of sections to wrap.
wrap_axis – 0 for horizontal wrapping; 1 for vertical.
gap_size – Width of gap in pixels between sections.
gap_color – Gap color, either an X11 name or an
(R, G, B)triple.
- Returns:
A new PIL image of the requested size.
Color
Source: src/picmaker/color.py.
Mission-agnostic colormap dispatch.
tinted_colormap() takes a (host, instrument, filter) triple
from the I/O cascade and returns a per-filter colormap (or None).
The mission-specific logic lives in picmaker.instruments; this
module’s only job is to normalize the filter description and forward
to picmaker.instruments.lookup().
The wavelength → RGB constants RGB_BY_NM, RFUNC, GFUNC, and
BFUNC are surfaced here as well as on picmaker._rgb, so that
from picmaker.color import RGB_BY_NM is a single short import.
- tinted_colormap(filter_info: Any) list[tuple[int, int, int]] | None[source]
Return a colormap based on filter info.
- Parameters:
filter_info – A tuple
(instrument_host, instrument_id, filter), wherefiltermay be a single name or a 2-tuple of names (e.g. HST/ACS).- Returns:
A colormap as a list of
(R, G, B)tuples (typically[black, tint, white]), orNoneif no colormap can be derived.
PIL utilities
Source: src/picmaker/pil_utils.py.
PIL image conversion + I/O helpers.
These wrap PIL.Image so callers can move between numpy arrays and
PIL images and write JPEG / TIFF / 16-bit TIFF without owning the
mode-specific details themselves.
- array_to_pil(array: Any, twobytes: bool = False, rescale: bool = True) Any[source]
Convert an array to a PIL image.
For the special case of a 16-bit RGB image, the result is a list of three PIL images (one per channel).
- Parameters:
array – Image array containing one band of grayscale or three bands if RGB.
twobytes – True for 16-bit images, False for 8-bit.
rescale – True to scale values from unit; False to leave them alone.
- Returns:
A PIL image, or a list of three PIL images for 16-bit RGB.
- pil_to_array(image: Any, rescale: bool = True) Any[source]
Convert a PIL image (or list of RGB images) to a numpy array.
The shape of the returned array is
(lines, samples, bands)for an RGB image or(lines, samples)for a grayscale image.- Parameters:
image – A PIL image or list/tuple of three.
rescale – True to scale values to the range 0-1; False to leave them alone.
- Returns:
A numpy array.
Filters
Source: src/picmaker/_filters.py.
PIL filter dispatch helpers.
- filter_image(image: Any, filter_name: str) Any[source]
Apply an arbitrary filter to a PIL image.
Two-byte (16-bit) images are not supported and raise
ValueError.- Parameters:
image – A PIL image as 8-bit RGB or grayscale.
filter_name – Name of the filter to be applied. Valid choices are the keys of
FILTER_DICT(case-insensitive).'NONE'returns the input image unchanged.
- Returns:
The filtered PIL image. For
filter_name='NONE'the input image is returned unchanged.- Raises:
ValueError – If
imageis a list (16-bit two-byte image).KeyError – If
filter_name(case-folded) is not a key ofpicmaker._filters.FILTER_DICT.
CLI
Source: src/picmaker/cli.py.
Command-line entry point for picmaker.
The main() function builds an argparse parser covering
every option documented in picmaker --help and dispatches to
picmaker.pipeline.process_images(). Each long flag also has an
underscore alias (--alt_strip for --alt-strip, etc.) so older
scripts that use the underscore spelling keep working.
Error handling follows three layers:
SystemExitraised by argparse’s own usage errors propagates through unchanged.Mutex / value-validity checks raise
ValueError; the outerexcept Exceptionwrapper prints the traceback viasys.excepthook()(so any plugin / IDE / profiler hook attached tosys.excepthookstill fires) and exits with code 1.KeyboardInterruptprints*** KeyboardInterrupt ***and exits with code 2.
The filter argparse dest deliberately shadows the builtin so the
option_dict it builds passes straight through to
picmaker.pipeline.images_to_pics(). The per-file A002 ruff
ignore lives in pyproject.toml.
- main() None[source]
Picmaker CLI entry point.
Argparse usage errors raise
SystemExit(passed through). Validation errors raiseValueError; the outerexcept Exceptionwrapper prints them viasys.excepthook()and exits with code 1.
Instruments
Source: src/picmaker/instruments/.
Instrument-specific detection and tint logic.
Each instrument module exposes a uniform 4-method protocol:
detect_vicar(vic) -> tuple[str, str, str] | None— returns(inst_host, inst_id, filter_name)for a VICAR file orNoneif the instrument does not own this label.detect_fits(hdulist) -> tuple[str, str, str] | None— same for FITS.matches(inst_host, inst_id) -> bool— host-level predicate.tint_for(inst_id, filter_name) -> list[tuple[int, int, int]] | None— returns the full colormap (NOT just the tint), orNonefor the HST unknown-wavelength case.
- ALL_INSTRUMENTS: list[ModuleType] = [<module 'picmaker.instruments.cassini' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/cassini.py'>, <module 'picmaker.instruments.voyager' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/voyager.py'>, <module 'picmaker.instruments.galileo' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/galileo.py'>, <module 'picmaker.instruments.hst' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/hst.py'>, <module 'picmaker.instruments.nh' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/nh.py'>]
Every registered instrument module.
- FITS_INSTRUMENTS: list[ModuleType] = [<module 'picmaker.instruments.hst' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/hst.py'>, <module 'picmaker.instruments.nh' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/nh.py'>]
Instrument modules whose
detect_fitsmay match a FITS input.
- VICAR_INSTRUMENTS: list[ModuleType] = [<module 'picmaker.instruments.cassini' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/cassini.py'>, <module 'picmaker.instruments.galileo' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/galileo.py'>, <module 'picmaker.instruments.voyager' from '/home/docs/checkouts/readthedocs.org/user_builds/rms-picmaker/checkouts/stable/src/picmaker/instruments/voyager.py'>]
Instrument modules whose
detect_vicarmay match a VICAR input.
- lookup(inst_host: str | None, inst_id: str | None) Any | None[source]
Return the first instrument whose
matches()returns True, else None.- Parameters:
inst_host – Instrument host string (e.g.
'CASSINI ORBITER').inst_id – Instrument id (e.g.
'ISS'). PassNoneif unknown.
- Returns:
The matching instrument module, or
Noneif no instrument matches.
Cassini ISS detection and tint.
- detect_fits(hdulist: Any) tuple[str, str, str] | None[source]
Cassini ISS is not delivered as FITS — always returns
None.- Parameters:
hdulist – An
astropy.io.fitsHDU list (unused).- Returns:
Always
None.
- detect_vicar(vic: Any) tuple[str, str, str] | None[source]
Detect a Cassini ISS VICAR image.
Looks at the
INSTRUMENT_HOST_NAMEandFILTER_NAMElabel fields; the filter is delivered as a 2-tuple of names that are joined with'+'.- Parameters:
vic – A
vicar.VicarImageinstance.- Returns:
('CASSINI', 'ISS', '<filter1>+<filter2>')if the label identifies a Cassini ISS image,Noneotherwise.
- matches(inst_host: str, inst_id: str) bool[source]
Host-level predicate; sub-instrument dispatch happens in
tint_for().- Parameters:
inst_host – Instrument host string (e.g.
'CASSINI ORBITER').inst_id – Instrument id (e.g.
'ISS').
- Returns:
Truefor any Cassini host.
- tint_for(inst_id: str, filter_name: Any) list[tuple[int, int, int]] | None[source]
Return the full
[black, tint, white]colormap for a Cassini filter.Non-ISS Cassini instruments fall through to the 2-element
[black, white]colormap (no tint).- Parameters:
inst_id – Instrument id (typically
'ISS').filter_name – The Cassini filter string from
detect_vicar().
- Returns:
[(0, 0, 0), tint, (255, 255, 255)]for an ISS filter or[(0, 0, 0), (255, 255, 255)]otherwise.
Voyager ISS detection and tint.
- detect_fits(hdulist: Any) tuple[str, str, str] | None[source]
Voyager ISS is not delivered as FITS — always returns
None.- Parameters:
hdulist – An
astropy.io.fitsHDU list (unused).- Returns:
Always
None.
- detect_vicar(vic: Any) tuple[str, str, str] | None[source]
Detect a Voyager ISS VICAR image.
Voyager VICAR labels carry their identifying string in
LAB02(aVGRprefix) and the filter name in characters 37..43 ofLAB03; trailing spaces are stripped.- Parameters:
vic – A
vicar.VicarImageinstance.- Returns:
('VOYAGER', 'ISS', filter_name)if the label identifies a Voyager ISS image,Noneotherwise.
- matches(inst_host: str, inst_id: str) bool[source]
Host-level predicate; sub-instrument dispatch happens in
tint_for().- Parameters:
inst_host – Instrument host string.
inst_id – Instrument id (e.g.
'ISS').
- Returns:
Truefor any host whose name starts with'VOYAGER'.
- tint_for(inst_id: str, filter_name: Any) list[tuple[int, int, int]] | None[source]
Return the full
[black, tint, white]colormap for a Voyager filter.Non-ISS Voyager instruments fall through to the 2-element
[black, white]colormap. Unknown filter names raiseKeyError(the caller is expected to surface that as a “no colormap” condition).- Parameters:
inst_id – Instrument id (typically
'ISS').filter_name – A key into
picmaker.instruments.voyager.FILTER_DICT.
- Returns:
[(0, 0, 0), tint, (255, 255, 255)]for an ISS filter or[(0, 0, 0), (255, 255, 255)]otherwise.- Raises:
KeyError – If
filter_nameis not inpicmaker.instruments.voyager.FILTER_DICTandinst_idis an ISS instrument.
Galileo SSI detection and tint.
- detect_fits(hdulist: Any) tuple[str, str, str] | None[source]
Galileo SSI is not delivered as FITS — always returns
None.- Parameters:
hdulist – An
astropy.io.fitsHDU list (unused).- Returns:
Always
None.
- detect_vicar(vic: Any) tuple[str, str, str] | None[source]
Detect a Galileo SSI VICAR image.
Two label conventions are tried in order: the
MISSIONkeyword with a numericFILTERindex intopicmaker.instruments.galileo.FILTER_NAMES, then aGLL/SSIprefix inLAB01withFILTER=<digit>somewhere inLAB03.- Parameters:
vic – A
vicar.VicarImageinstance.- Returns:
('GALILEO', 'SSI', filter_name)if the label identifies a Galileo SSI image,Noneotherwise.
- matches(inst_host: str, inst_id: str) bool[source]
Host-level predicate; sub-instrument dispatch happens in
tint_for().- Parameters:
inst_host – Instrument host string.
inst_id – Instrument id (e.g.
'SSI').
- Returns:
Truefor any host whose name starts with'GALILEO'.
- tint_for(inst_id: str, filter_name: Any) list[tuple[int, int, int]] | None[source]
Return the full
[black, tint, white]colormap for a Galileo filter.Only the SSI camera and the
SOLID-prefixed variants get a colored tint; every other Galileo instrument falls through to the 2-element[black, white]colormap.- Parameters:
inst_id – Instrument id.
filter_name – A key into
picmaker.instruments.galileo.FILTER_DICT.
- Returns:
[(0, 0, 0), tint, (255, 255, 255)]for an SSI filter or[(0, 0, 0), (255, 255, 255)]otherwise.- Raises:
KeyError – If
filter_nameis not inpicmaker.instruments.galileo.FILTER_DICTandinst_idselects the SSI path.
HST detection and wavelength-based tint.
- detect_fits(hdulist: Any) tuple[str, str, Any] | None[source]
Detect an HST FITS image.
The
TELESCOPkeyword identifies the host,INSTRUME(with an optionalDETECTORsuffix) identifies the instrument, and the filter name comes from one ofFILTER,FILTER1/FILTER2(HST/ACS), orFILTNAM1/FILTNAM2(HST/WFPC2).- Parameters:
hdulist – An
astropy.io.fitsHDU list.- Returns:
(inst_host, inst_id, filter_name)wherefilter_namemay be a string or a 2-tuple of strings, orNoneif the file is not an HST FITS image.
- detect_vicar(vic: Any) tuple[str, str, str] | None[source]
HST is not delivered as VICAR — always returns
None.- Parameters:
vic – A
vicar.VicarImageinstance (unused).- Returns:
Always
None.
- matches(inst_host: str, inst_id: str) bool[source]
Host-level predicate: accept any host that mentions HUBBLE or HST.
- Parameters:
inst_host – Instrument host string (e.g.
'HST'or'HUBBLE SPACE TELESCOPE').inst_id – Instrument id.
- Returns:
Trueif either substring appears ininst_host.
- tint_for(inst_id: str, filter_name: Any) list[tuple[int, int, int]] | None[source]
Return the full
[black, tint, white]colormap for an HST filter.The tint color comes from inferring a wavelength out of the numeric characters in
filter_name(e.g.'F606W'→ 606 nm) and looking that wavelength up inpicmaker._rgb.RGB_BY_NMvia thepicmaker._rgb.RFUNC/picmaker._rgb.GFUNC/picmaker._rgb.BFUNCsplines. Each detector family has its own correction:NICMOS scales the inferred number by 3.5 (its filter names encode tens of nm rather than nm).
WFC3/IR and ACS/SBC also scale by 3.5 when the inferred number is below 200.
WFPC2 quad-filters
FQUV*andFQCH4*are pinned to 300 nm and 900 nm respectively.NICMOS polarisers
POL0S/POL0Lare pinned to 110 nm and 220 nm before the NICMOS x3.5 scaling.
Broadband filters
F350LP,F606W, andLONG_PASSshort- circuit to a plain[black, white]colormap.- Parameters:
inst_id – Instrument id, possibly with detector suffix (e.g.
'WFC3/IR').filter_name – HST filter name; passed through as-is from
detect_fits().
- Returns:
[(0, 0, 0), (r, g, b), (255, 255, 255)]for a successfully inferred wavelength,[(0, 0, 0), (255, 255, 255)]for the broadband short-circuits, orNonewhen no wavelength can be inferred (a WARNING is logged).
New Horizons MVIC detection and tint.
- detect_fits(hdulist: Any) tuple[str, str, Any] | None[source]
Detect a New Horizons FITS image.
The
HOSTNAMEkeyword identifies the host andINSTRUidentifies the instrument; the filter name comes fromFILTERwhen present.- Parameters:
hdulist – An
astropy.io.fitsHDU list.- Returns:
(inst_host, inst_id, filter_name)if the file is an NH FITS image,Noneotherwise.filter_namemay beNoneif noFILTERkeyword is present.
- detect_vicar(vic: Any) tuple[str, str, str] | None[source]
NH is not delivered as VICAR — always returns
None.- Parameters:
vic – A
vicar.VicarImageinstance (unused).- Returns:
Always
None.
- matches(inst_host: str, inst_id: str) bool[source]
Host-level predicate; sub-instrument dispatch happens in
tint_for().- Parameters:
inst_host – Instrument host string.
inst_id – Instrument id.
- Returns:
Trueifinst_hostis'NEW HORIZONS'or'NH'.
- tint_for(inst_id: str, filter_name: Any) list[tuple[int, int, int]] | None[source]
Return the full
[black, tint, white]colormap for an NH filter.Only the MVIC camera gets a colored tint; every other New Horizons instrument falls through to the 2-element
[black, white]colormap.- Parameters:
inst_id – Instrument id (
'MVIC'/'MVI'for the color path).filter_name – A key into
picmaker.instruments.nh.FILTER_DICT.
- Returns:
[(0, 0, 0), tint, (255, 255, 255)]for an MVIC filter or[(0, 0, 0), (255, 255, 255)]otherwise.- Raises:
KeyError – If
filter_nameis not inpicmaker.instruments.nh.FILTER_DICTandinst_idselects the MVIC path.
TIFF 16
Source: src/picmaker/tiff16.py.
- ReadTiff16(filename: str, up: bool = False, transpose: Any = None) tuple[Any, Any][source]
Read a 16-bit TIFF file written by
WriteTiff16().No other TIFF file formats are supported.
- Parameters:
filename – The name of the file to read.
up – True for line numbers to increase upward; False (default) for downward.
transpose – Optional geometric transformation to undo on the image before returning. Choices match
PIL.Image.Transpose:FLIP_LEFT_RIGHT,FLIP_TOP_BOTTOM,ROTATE_90,ROTATE_180,ROTATE_270.
- Returns:
array— a numpy 2-D or 3-Duint16array indexed(line, sample, band). The third axis is present only for RGB inputs (size >= 3).palette— an optional(65536, 3)array. When present, the 0th band ofarrayindexes into the palette to derive each pixel’s(R, G, B)triple.Nonefor non-palette inputs.
- Return type:
(array, palette)
- WriteTiff16(filename: str, array: Any, palette: Any = None, up: bool = False, byteorder: str = 'native', translate: bool = True, transpose: Any = None) None[source]
Write a 16-bit TIFF file from a 2-D or 3-D numpy array.
Three TIFF formats are supported: grayscale, RGB, and palette.
- Parameters:
filename – The name of the file to write.
array – A numpy 2-D or 3-D array containing the image pixels. Values are converted to unsigned 16-bit if they are not already in that format. Indices are
(line, sample, band); the third axis is optional. If present with size>= 3and nopaletteis provided,array[:, :, 0:3]is interpreted as the(R, G, B)values for each pixel.palette – Optional
(65536, 3)array. When provided, the 0th band ofarrayindexes into the palette to derive each pixel’s(R, G, B)triple.up – True for line numbers to increase upward; False (default) for downward.
byteorder – One of
'native','little', or'big'. Default is'native'.translate – True to translate a palette image to RGB on write (default; many TIFF readers do not support 16-bit palettes). False writes the palette index plus the palette table.
transpose – Optional geometric transformation before writing. Choices match
PIL.Image.Transpose:FLIP_LEFT_RIGHT,FLIP_TOP_BOTTOM,ROTATE_90,ROTATE_180,ROTATE_270.
Color names
Source: src/picmaker/colornames.py.
- class ColorNames[source]
Bases:
objectStandard X11 color-name → RGB lookup.
Exposes the X11
rgb.txtcolor table asCOLOR_NAME_DICT(and the case-insensitive, whitespace-stripped variantCOLOR_NAME_LOWER_DICT) plus a single entry pointlookup()that resolves the following input forms:A canonical name (
'IndianRed','red','white smoke').A case-insensitive variant with spaces, dashes, or underscores stripped (
'INDIAN_RED','mint-cream').An RGB container expressed as
'(r, g, b)'or'[r, g, b]'.
The class has no instance state; every entry point is a
staticmethod().- static lookup(name: str) tuple[int, int, int][source]
Resolve a color name or RGB expression to a
(r, g, b)triple.- Parameters:
name – A canonical X11 color name (case-sensitive), a case-insensitive variant with spaces / dashes / underscores stripped, or an RGB container expressed as
'(r, g, b)'or'[r, g, b]'(parsed viaast.literal_eval()).- Returns:
The
(r, g, b)triple with each channel in[0, 255]. Bracketed'[r, g, b]'inputs are also returned as tuples (the parser normalizes lists to tuples on the way out).- Raises:
TypeError – If
nameis not a string.KeyError – If
namematches no known X11 color and no RGB expression in()/[].ValueError – If a parsed RGB component exceeds 255.