Source Detection (pyobs.images.processors.detection)

DaophotSourceDetection

class DaophotSourceDetection(fwhm: float = 3.0, threshold: float = 4.0, bkg_sigma: float = 3.0, bkg_box_size: Tuple[int, int] = (50, 50), bkg_filter_size: Tuple[int, int] = (3, 3), **kwargs: Any)

Detect astronomical point sources using a DAOPhot-style algorithm via photutils.

This processor estimates and removes the background of a pyobs.images.Image, computes robust image statistics, and then detects point-like sources using photutils.detection.DAOStarFinder. The resulting source table is converted into a pyobs catalog and attached to the image. Pixel data are not modified in the returned image.

Parameters:
  • fwhm (float) – Estimated point-spread-function full width at half maximum (FWHM) in pixels. Used by DAOStarFinder to construct its matched filter. Default: 3.0.

  • threshold (float) – Detection threshold in units of the background standard deviation (sigma). The effective pixel threshold passed to DAOStarFinder is threshold * std where std is measured from the background-subtracted image. Default: 4.0.

  • bkg_sigma (float) – Sigma for kappa–sigma clipping in background estimation and statistics. Passed to the internal background remover. Default: 3.0.

  • bkg_box_size (tuple[int, int]) – Box size (ny, nx) in pixels for the background estimation grid used by the background remover. Default: (50, 50).

  • bkg_filter_size (tuple[int, int]) – Smoothing filter size (ny, nx) in pixels applied to the coarse background map. Default: (3, 3).

  • kwargs – Additional keyword arguments forwarded to pyobs.images.processors.detection.SourceDetection.

Behavior

  • If the input image has no data (image.safe_data is None), a warning is logged and the image is returned unchanged.

  • Background is estimated and subtracted using pyobs.images.processors.detection._DaoBackgroundRemover with the configured bkg_sigma, bkg_box_size, and bkg_filter_size.

  • Robust statistics are computed on the background-corrected data via astropy.stats.sigma_clipped_stats() (with sigma=3.0) to obtain median and standard deviation.

  • The median is subtracted from the background-corrected data, and photutils.detection.DAOStarFinder is run with fwhm=self.fwhm and threshold=self.threshold * std.

  • DAOStarFinder execution is offloaded to a thread executor to avoid blocking the event loop.

  • The resulting astropy.table.Table is converted to a pyobs pyobs.images.catalog._SourceCatalog, FITS 1-based origin convention is applied to coordinates, and the catalog is attached to the image with the keys ["x", "y", "flux", "peak"].

Input/Output

  • Input: pyobs.images.Image with 2D pixel data.

  • Output: pyobs.images.Image with a source catalog attached. Pixel data are unchanged; catalog entries typically include positions and flux measures.

Configuration (YAML)

Minimal example:

class: pyobs.images.processors.detection.DaophotSourceDetection
fwhm: 3.0
threshold: 4.0

Tune background estimation and sensitivity:

class: pyobs.images.processors.detection.DaophotSourceDetection
fwhm: 2.5
threshold: 5.0
bkg_box_size: [64, 64]
bkg_filter_size: [3, 3]

Notes

  • fwhm must be given in pixels. An accurate FWHM improves detection quality, especially in crowded fields or variable seeing.

  • threshold is a global sigma threshold referenced to the measured background noise; very low values may increase false positives.

  • The background remover’s exact behavior (e.g., clipping strategy, box tiling, and filtering) is defined by pyobs.images.processors.detection._DaoBackgroundRemover.

  • Very bright/saturated sources or artifacts (cosmic rays, bleed trails) may produce spurious detections; consider pre-masking if necessary.

SepSourceDetection

class SepSourceDetection(threshold: float = 1.5, minarea: int = 5, deblend_nthresh: int = 32, deblend_cont: float = 0.005, clean: bool = True, clean_param: float = 1.0, **kwargs: Any)

Detect astronomical sources using SEP (Source Extractor for Python).

This processor performs background estimation and subtraction on a pyobs.images.Image, then extracts sources with sep.extract(). It converts the resulting array into a pyobs catalog, augments it with additional statistics, and attaches it to the image. Pixel data are not modified in the returned image.

Parameters:
  • threshold (float) – Detection threshold in units of the background RMS (sigma). Passed to sep.extract() as thresh, with per-pixel error set to the global background RMS. Default: 1.5.

  • minarea (int) – Minimum number of connected pixels above threshold required for a detection. Default: 5.

  • deblend_nthresh (int) – Number of sub-thresholds used in multi-threshold deblending. Default: 32.

  • deblend_cont (float) – Minimum contrast ratio for deblending; lower values produce more aggressive splitting of blended objects. Default: 0.005.

  • clean (bool) – Whether to perform cleaning of spurious detections (as in SExtractor). Default: True.

  • clean_param (float) – Cleaning parameter controlling how aggressively detections are merged/removed. See SExtractor manual. Default: 1.0.

  • kwargs – Additional keyword arguments forwarded to pyobs.images.processors.detection.SourceDetection.

Behavior

  • If the input image has no data (image.safe_data is None), a warning is logged and the image is returned unchanged.

  • A mask is obtained from image.mask if available; otherwise a zero-valued boolean mask is created.

  • Background is estimated with sep.Background using a grid of bw=32, bh=32 and smoothing fw=3, fh=3; the estimated background is subtracted from the image. If SEP raises an endianness-related ValueError, the data are byte-swapped and background estimation retried.

  • Sources are extracted via sep.extract() with: thresh=self.threshold, err=bkg.globalrms, minarea=self.minarea, deblend_nthresh=self.deblend_nthresh, deblend_cont=self.deblend_cont, clean=self.clean, clean_param=self.clean_param, and the computed mask. Extraction is offloaded to a thread executor to avoid blocking the event loop.

  • The resulting array is converted to a pyobs _SourceCatalog, initial detection flags are filtered, and additional SEP-based measurements are computed via PySepStatsCalculator. The detector gain is taken from the FITS header key DET-GAIN if present; otherwise gain-dependent metrics may be limited or use defaults.

  • Post-processing includes filtering by detection flags, wrapping rotation angles at 90 degrees, converting angles to degrees, and applying FITS 1-based origin conventions.

  • The catalog is attached to the image using the keys: ["x", "y", "peak", "flux", "fwhm", "a", "b", "theta", "ellipticity", "tnpix", "kronrad", "fluxrad25", "fluxrad50", "fluxrad75", "xwin", "ywin"].

Input/Output

  • Input: pyobs.images.Image with 2D pixel data; optional mask and header.

  • Output: pyobs.images.Image with a source catalog attached. Pixel data are unchanged; the FITS header may be read for gain (DET-GAIN).

Configuration (YAML)

Minimal example:

class: pyobs.images.processors.detection.SepSourceDetection
threshold: 1.5
minarea: 5

Aggressive deblending and cleaning:

class: pyobs.images.processors.detection.SepSourceDetection
threshold: 1.8
minarea: 9
deblend_nthresh: 64
deblend_cont: 0.001
clean: true
clean_param: 1.2

Notes

  • threshold is in sigma units relative to the background RMS. Very low values increase completeness but may raise false detections.

  • Provide a meaningful mask to exclude saturated stars, cosmic rays, and artifacts from background estimation and extraction.

  • Background parameters (bw, bh, fw, fh) are fixed in this wrapper; adjust here if you need finer control for highly structured backgrounds.

  • If DET-GAIN is absent, gain-dependent uncertainties and radii may be limited or use defaults in PySepStatsCalculator.

static remove_background(data: ndarray[tuple[Any, ...], dtype[floating[Any]]], mask: ndarray[tuple[Any, ...], dtype[floating[Any]]] | None = None) tuple[ndarray[tuple[Any, ...], dtype[floating[Any]]], Background][source]

Remove background from image in data.

Parameters:
  • data – Data to remove background from.

  • mask – Mask to use for estimating background.

Returns:

Image without background, Background

SimpleDisk

class SimpleDisk(threshold: int | float = 10.0, keyword_x: str = 'DISKPOS1', keyword_y: str = 'DISKPOS2', keyword_radius: str = 'DISKRAD', **kwargs: Any)

Detect a roughly circular bright disk by thresholding and distance transform.

This processor segments the image by a fixed intensity threshold, selects the largest connected component, fills internal holes, and computes the Euclidean distance transform to find the pixel farthest from the component boundary. That pixel is taken as the disk center, and its distance to the boundary as the disk radius (both in pixels). The results are written into the FITS header under configurable keyword names. Pixel data are not modified.

Parameters:
  • threshold (float | int) – Intensity threshold used to decide whether a pixel belongs to the disk (strictly data > threshold). Units must match the image pixel values. Default: 10.0.

  • keyword_x (str) – FITS header keyword to store the x-coordinate (column) of the detected disk center (zero-based pixel index). Default: "DISKPOS1".

  • keyword_y (str) – FITS header keyword to store the y-coordinate (row) of the detected disk center (zero-based pixel index). Default: "DISKPOS2".

  • keyword_radius (str) – FITS header keyword to store the disk radius in pixels. Default: "DISKRAD".

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

Behavior

  • Chooses the image plane: uses the first channel (image.data[0, :, :]) if the image is color, otherwise uses the full 2D array.

  • Creates a binary mask with mask = data > threshold.

  • Labels connected components in the mask and keeps the largest one; if none are found, returns the original image unchanged.

  • Fills holes within the selected component and computes the Euclidean distance transform of the filled mask.

  • Finds the pixel (y, x) with maximum distance; sets radius = dist[y, x].

  • Returns a copy of the input image with the FITS header fields:

    • keyword_y = y (row index, zero-based)

    • keyword_x = x (column index, zero-based)

    • keyword_radius = radius (float, pixels)

Input/Output

Configuration (YAML)

Basic detection with a custom threshold:

class: pyobs.images.processors.disk.SimpleDisk
threshold: 25.0

Customize FITS header keywords:

class: pyobs.images.processors.disk.SimpleDisk
threshold: 15.0
keyword_x: CX
keyword_y: CY
keyword_radius: CRAD

Notes

  • The algorithm assumes the disk is the largest bright connected region above the threshold. Choose threshold to robustly isolate the disk from background and other structures; pre-filtering or masking may help in noisy images.

  • The estimated radius is the in-mask inscribed-circle radius; for non-circular or partially occulted disks it represents the maximum interior distance to the boundary, not a best-fit circle.

  • Connectivity and hole filling use SciPy ndimage defaults; results may vary with image topology.

SourceDetection

class SourceDetection(**kwargs: Any)

Base class for source detection.