Misc (pyobs.images.processors.misc)

AddMask

class AddMask(masks: dict[str, dict[str, ndarray[tuple[Any, ...], dtype[floating[Any]]] | str]], **kwargs: Any)

Attach a precomputed mask to an image based on instrument and binning.

This processor selects a mask from a user-provided dictionary keyed by instrument name and binning, and assigns it to image.mask in a returned copy of the image. Masks can be provided directly as NumPy arrays or as paths to FITS files, which are loaded via astropy.io.fits.getdata().

Parameters:
  • masks (dict[str, dict[str, numpy.ndarray | str]]) –

    Mapping of instrument name (matching INSTRUME) to a mapping of binning strings (e.g., "1x1", "2x2") to either:

    • a NumPy array mask, or

    • a string path to a FITS file containing the mask array.

    The selected mask must match the image shape for the given instrument and binning.

  • kwargs – Additional keyword arguments forwarded to pyobs.images.processor.ImageProcessor.

Behavior

  • Builds an internal lookup of masks during initialization:

    • If a value is a NumPy array, it is stored as-is.

    • If a value is a string, loads the mask array using fits.getdata(path).

    • Otherwise, raises ValueError("Unknown mask format.").

  • On processing:

    • Reads INSTRUME, XBINNING, and YBINNING from the FITS header.

    • Constructs the binning key as "%dx%d" % (XBINNING, YBINNING).

    • Retrieves a copy of the corresponding mask and assigns it to output_image.mask.

    • If no mask is found for the instrument/binning, logs a warning and returns the image unchanged.

  • Returns a copy of the input image; pixel data are not modified.

Input/Output

  • Input: pyobs.images.Image with FITS header keys INSTRUME, XBINNING, and YBINNING.

  • Output: pyobs.images.Image (copied) with mask set when available; pixel data and other headers are unchanged.

Configuration (YAML)

Provide masks for multiple instruments and binning modes, mixing arrays and files:

class: pyobs.images.processors.misc.AddMask
masks:
  CAM_A:
    "1x1": "/path/to/cam_a_1x1_mask.fits"
    "2x2": "/path/to/cam_a_2x2_mask.fits"
  CAM_B:
    "1x1": "/path/to/cam_b_1x1_mask.fits"

Notes

  • Ensure mask arrays have the same shape as the image data for the selected instrument and binning. If your images are color/multi-plane, provide masks matching the plane used downstream, or adapt prior processing accordingly.

  • Mask dtype can be boolean or numeric; downstream code typically treats non-zero values as masked. Use boolean masks for clarity.

  • The binning key must match the exact "%dx%d" format built from XBINNING and YBINNING in the image header.

  • Loaded FITS masks use the primary data returned by fits.getdata; if your mask resides in a different HDU, adjust accordingly.

CatalogCircularMask

class CatalogCircularMask(radius: float, center: Tuple[int, int] | Tuple[float, float] | Tuple[str, str] = ('CRPIX1', 'CRPIX2'), exclude_circle: bool = False, **kwargs: Any)

Filter a source catalog by keeping only entries inside a central circle (or outside it).

This processor applies a circular spatial filter to the catalog attached to a pyobs.images.Image. It either retains sources whose positions fall within a specified radius of a chosen center, or excludes them if exclude_circle is set. Pixel data are not modified; only the image catalog is filtered in place.

Parameters:
  • radius (float) – Radius of the circle in pixels used for filtering. Default: required.

  • center (tuple[int, int] | tuple[float, float] | tuple[str, str]) – Center of the circle. Either a pair of numeric pixel coordinates (x, y), or a pair of FITS header keywords whose values define the center (default: ("CRPIX1", "CRPIX2")). The center must use the same coordinate convention as the catalog (typically FITS 1-based indices in pyobs catalogs).

  • exclude_circle (bool) – If False, keep only sources inside the circle. If True, exclude sources inside the circle and keep those outside. Default: False.

  • kwargs – Additional keyword arguments forwarded to pyobs.images.processor.ImageProcessor.

Behavior

  • If the image has no catalog (image.safe_catalog is None), the image is returned unchanged.

  • Determines the circle center:

    • If center is a pair of strings, reads their values from the FITS header.

    • If center is numeric, uses those pixel coordinates directly.

  • Builds a boolean mask on the catalog using Euclidean distance in pixel units:

    • Inside selection: (x - cx)^2 + (y - cy)^2 <= radius^2.

    • Outside selection (if exclude_circle): the inequality is reversed.

  • Applies the mask to the catalog and assigns the filtered catalog back to image.catalog.

  • Returns the original image object with a filtered catalog; pixel data and header are unchanged.

Input/Output

  • Input: pyobs.images.Image with a source catalog containing x and y columns, and optionally header keys for the center if center is given as strings.

  • Output: pyobs.images.Image with its catalog filtered by the circular criterion. Pixel data are unchanged.

Configuration (YAML)

Keep sources within 300 pixels of CRPIX center:

class: pyobs.images.processors.misc.CatalogCircularMask
radius: 300
center: ["CRPIX1", "CRPIX2"]
exclude_circle: false

Exclude a 100-pixel radius around a specified pixel center:

class: pyobs.images.processors.misc.CatalogCircularMask
radius: 100
center: [1024, 1024]
exclude_circle: true

Notes

  • Ensure the center coordinates and catalog positions use the same origin and units. Pyobs catalogs often store positions in FITS 1-based convention.

  • radius is interpreted in pixel units of the catalog/image.

  • The filtering operates solely on the catalog; it does not mask pixels in the image data.

CircularMask

class CircularMask(radius: float, center: Tuple[str, str] = ('CRPIX1', 'CRPIX2'), **kwargs: Any)

Mask an image by keeping only pixels inside a central circle of a given radius.

This processor reads the circle center from two FITS header keywords (e.g., CRPIX1/CRPIX2) and constructs a circular mask in pixel coordinates. Pixels outside the circle are set to zero by in-place multiplication; pixels inside the circle are preserved. The modified image is returned.

Parameters:
  • radius (float) – Radius of the circular pass region in pixels. Pixels with squared distance to the center less than or equal to radius**2 are kept.

  • center (tuple[str, str]) – Names of the FITS header keywords whose values give the x and y pixel coordinates of the circle center (default: ("CRPIX1", "CRPIX2")).

  • kwargs – Additional keyword arguments forwarded to pyobs.images.processor.ImageProcessor.

Behavior

  • Reads the circle center from image.header[center[0]] and image.header[center[1]].

  • Builds a boolean circular mask on the 2D pixel grid and applies it to image.data by element-wise multiplication, zeroing pixels outside the circle and keeping those inside (boundary inclusive).

  • Returns the same image object with modified pixel data; the FITS header and catalog are not changed.

Input/Output

Configuration (YAML)

Keep only pixels within a 500-pixel radius around CRPIX:

class: pyobs.images.processors.misc.CircularMask
radius: 500
center: ["CRPIX1", "CRPIX2"]

Use custom center keywords:

class: pyobs.images.processors.misc.CircularMask
radius: 250
center: ["CX", "CY"]

Notes

  • The center values must use the same pixel coordinate convention as the mask grid. FITS CRPIX values are typically 1-based; if your image indices are 0-based, ensure consistency to avoid off-by-one shifts.

  • The implementation operates on 2D images. Multi-plane/color images are not supported by this processor as written.

  • Masking is performed in place; if you need to preserve the original image data, copy the image before applying this processor.

CreateFilename

class CreateFilename(pattern: str | None, **kwargs: Any)

Format and set a filename for the image using a pattern, storing it in the FNAME header.

This processor uses a pyobs.utils.filenames.FilenameFormatter to render a filename string from image metadata and writes it into the FITS header key FNAME on a copy of the image. If no pattern is provided, a built-in default pattern is used.

The default pattern is: {SITEID}{TELID}-{INSTRUME}-{DAY-OBS|date:}-{FRAMENUM|string:04d}-{IMAGETYP|type}01.fits

This pattern typically expands to a string like: XXYY-CAM-20240130-0007-L101.fits

Parameters:
  • pattern (str | None) –

    A filename pattern understood by pyobs.utils.filenames.FilenameFormatter. If None, a default pattern is used. The pattern is a template with placeholders of the form {KEY} or {KEY|filter:params}, where KEY is usually a FITS header keyword and optional filters control formatting. Common filters include:

    • date:...: format a date/time value (e.g., from DATE-OBS or DAY-OBS) according to formatter defaults or supplied parameters.

    • string:fmt: format using a Python-style format specification (e.g., 04d to zero-pad integers).

    • type: map image type values to standardized tokens.

    See the FilenameFormatter documentation for the full set of supported filters and parameters.

  • kwargs – Additional keyword arguments forwarded to pyobs.images.processor.ImageProcessor.

Behavior

  • Creates a FilenameFormatter from the given pattern during initialization (or from the built-in default pattern if none was provided).

  • On call, creates a copy of the input image and invokes Image.format_filename(formatter)() to compute the filename and store it in the FITS header under FNAME.

  • Returns the modified copy; pixel data and other metadata remain unchanged.

Input/Output

  • Input: pyobs.images.Image with FITS header fields referenced by the chosen pattern (e.g., SITEID, TELID, INSTRUME, DAY-OBS or DATE-OBS, FRAMENUM, IMAGETYP).

  • Output: pyobs.images.Image (copied) with the FNAME header set to the formatted filename.

Configuration (YAML)

Use the default pattern:

class: pyobs.images.processors.misc.CreateFilename
pattern: null

Custom pattern with zero-padded sequence and date:

class: pyobs.images.processors.misc.CreateFilename
pattern: "{SITEID}-{DAY-OBS|date:%Y%m%d}-{FRAMENUM|string:05d}.fits"

Notes

  • Ensure the FITS header contains all keywords required by the pattern; otherwise the formatter may raise an error or leave fields empty, depending on its behavior.

  • The exact syntax and capabilities of filters (date, string, type, etc.) are defined by FilenameFormatter.

ImageSourceFilter

class ImageSourceFilter(min_dist_to_border: float, num_stars: int, min_pixels: int, max_ellipticity: float = 0.4, min_weber_contrast: float = 1.5, max_saturation: int = 50000)

Filter a source catalog by border distance, quality metrics, and brightness, selecting the top N stars.

This processor operates on the source catalog attached to a pyobs.images.Image after SEP-based detection. It removes sources too close to the image borders, rejects saturated or low-quality detections based on several criteria, and then keeps the brightest remaining sources by flux. Pixel data are not modified; the catalog is replaced in a returned copy of the image.

Parameters:
  • min_dist_to_border (float) – Minimum allowed distance from any image border, in pixels. Sources closer than this threshold on either axis are removed. Default: required.

  • num_stars (int) – Number of brightest sources to keep. If set to a positive value smaller than the number of valid sources, the catalog is truncated to that many entries; otherwise all valid sources are kept. Default: required.

  • min_pixels (int) – Minimum number of pixels (tnpix) required for a source to be considered valid. Default: required.

  • max_ellipticity (float) – Maximum allowed source ellipticity. Sources with ellipticity > max_ellipticity are removed. Default: 0.4.

  • min_weber_contrast (float) – Minimum required Weber contrast relative to the local background, computed as (peak - background) / background. Sources with contrast less than or equal to this value are removed. Default: 1.5.

  • max_saturation (int) – Saturation threshold in ADU. Sources with peak >= max_saturation are considered saturated and removed. Default: 50000.

  • kwargs – Additional keyword arguments forwarded to pyobs.images.processor.ImageProcessor.

Behavior

  • Works on a copy of the input image and its catalog.

  • Removes sources near the borders:

    • Computes distance to the nearest border along both axes from the catalog coordinates x and y and the image shape.

    • Keeps sources whose minimum border distance exceeds min_dist_to_border.

  • Removes low-quality sources using these criteria:

    • Saturation: peak >= max_saturation.

    • Too small: tnpix < min_pixels.

    • Too large: tnpix > median(tnpix) + 2 * std(tnpix) (to reject extended artifacts).

    • High ellipticity: ellipticity > max_ellipticity.

    • Non-positive background: background <= 0.

    • Low contrast: Weber contrast (peak - background) / background <= min_weber_contrast.

  • Selects the brightest sources by sorting on flux in descending order and truncating to num_stars if positive and less than the number of remaining sources.

  • Returns the modified copy with the filtered catalog assigned.

Input/Output

  • Input: pyobs.images.Image with a source catalog containing at least x, y, flux, peak, tnpix, ellipticity, and background. The catalog is expected to use pixel coordinates consistent with the image shape.

  • Output: pyobs.images.Image (copied) with a filtered catalog. Pixel data and headers are unchanged.

Configuration (YAML)

Keep 20 high-quality stars, at least 10 pixels each, away from 25-pixel borders:

class: pyobs.images.processors.misc.ImageSourceFilter
min_dist_to_border: 25
num_stars: 20
min_pixels: 10
max_ellipticity: 0.4
min_weber_contrast: 1.5
max_saturation: 50000

Notes

  • Coordinate convention: pyobs catalogs often store x/y in FITS-like 1-based pixel coordinates. If necessary, convert to NumPy 0-based indexing before applying geometric filters; a helper method _fits2numpy is provided to subtract 1 from common pixel keys but is not invoked automatically here.

  • The border-distance calculation uses the image shape and source positions on each axis; ensure consistency between catalog coordinates and image dimensions.

  • The “too large” criterion uses a robust size cutoff based on tnpix median and standard deviation to reject extended artifacts or blends.

  • Weber contrast requires a positive background; sources with non-positive background are removed prior to contrast evaluation.

remove_bad_sources(sources: Table) Table[source]

Remove bad sources from table.

Parameters:

sources – Input table.

Returns:

Filtered table.

remove_sources_close_to_border(sources: Table, image_shape: tuple[int, ...]) Table[source]

Remove table rows from sources when source is closer than given distance from border of image.

Parameters:
  • sources – Input table.

  • image_shape – Shape of image.

Returns:

Filtered table.

.

RemoveBackground

class RemoveBackground(sigma: float = 3.0, box_size: Tuple[int, int] = (50, 50), filter_size: Tuple[int, int] = (3, 3), **kwargs: Any)

Estimate and subtract the background from an image using a DAOPhot-style method.

This processor applies robust background estimation and removes it from the image, producing a background-corrected result. The background is estimated on a grid with sigma-clipping and optional smoothing, then subtracted from the pixel data. The implementation delegates to pyobs.images.processors.detection._DaoBackgroundRemover.

Parameters:
  • sigma (float) – Sigma for kappa–sigma clipping used in background estimation. Default: 3.0.

  • box_size (tuple[int, int]) – Size of the grid boxes (ny, nx) in pixels over which the background is estimated. Default: (50, 50).

  • filter_size (tuple[int, int]) – Size (ny, nx) of the smoothing filter applied to the coarse background map. Default: (3, 3).

  • kwargs – Additional keyword arguments forwarded to pyobs.images.processor.ImageProcessor.

Behavior

  • Builds a background model using kappa–sigma clipping within tiles of size box_size and smooths the model with a filter of size filter_size.

  • Subtracts the estimated background from the image data.

  • Returns the background-corrected image; header and catalog are unchanged.

Input/Output

Configuration (YAML)

Basic background removal:

class: pyobs.images.processors.misc.RemoveBackground
sigma: 3.0
box_size: [50, 50]
filter_size: [3, 3]

Notes

  • Choose box_size large enough to capture slowly varying background while avoiding contamination by extended sources.

  • Increasing sigma reduces the influence of outliers on the background estimate.

  • If your image contains strong gradients or large-scale structures, consider tuning box_size and filter_size to avoid over-subtraction.