Offsets (pyobs.images.processors.offsets)
AstrometryOffsets
- class AstrometryOffsets(**kwargs: Any)
Compute pixel offsets from WCS by comparing image reference coordinates to telescope pointing.
This processor requires a valid WCS in the FITS header (run an astrometry solver beforehand). It reads two sky-coordinate pairs from the header: the image/WCS reference sky position (CRVAL1/CRVAL2) and the telescope’s current sky position (TEL-RA/TEL-DEC), converts both to pixel coordinates using the WCS, and computes their difference. The resulting pixel offset dx = x_tel - x_ref, dy = y_tel - y_ref is stored in the image metadata as a PixelOffsets object. It also stores the on-sky angular separation between the two positions (OnSkyDistance). Pixel data and standard headers are not modified.
Prerequisite: must run after an astrometry processor so that the FITS header contains a valid WCS solution.
- Parameters:
kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
Copies the input image and constructs a
astropy.wcs.WCSfrom its header.Reads sky coordinates (in degrees, ICRS frame): - Reference: CRVAL1/CRVAL2 (the WCS reference world coordinates). - Telescope: TEL-RA/TEL-DEC (the telescope pointing).
Converts both sky positions to pixel coordinates via WCS.world_to_pixel.
Computes pixel offsets: - dx = x_telescope - x_reference - dy = y_telescope - y_reference
Computes on-sky angular distance between the two sky positions.
Stores results in image metadata: - PixelOffsets(dx, dy) - OnSkyDistance(angle)
Returns the modified copy of the image; pixel data and FITS headers are unchanged.
Input/Output
Input:
pyobs.images.Imagewith a valid WCS in the header and the keywords CRVAL1, CRVAL2, TEL-RA, TEL-DEC present (in degrees, ICRS).Output:
pyobs.images.Image(copied) with metadata entries for PixelOffsets and OnSkyDistance set.
Configuration (YAML)
Run after astrometric calibration to attach pixel offsets:
class: pyobs.images.processors.offsets.AstrometryOffsets
Notes
Sign convention: positive dx means the telescope pointing is at a larger x pixel coordinate than the WCS reference position; positive dy likewise for y. Ensure this convention matches the downstream module that applies the offsets.
For typical WCS, the CRVAL position maps near the CRPIX pixel; thus the offset is approximately the difference between the telescope pointing and the WCS reference pixel location.
TEL-RA/TEL-DEC must be in ICRS degrees; adjust or convert if your system uses a different frame or units.
BrightestStarGuiding
- class BrightestStarGuiding(center_header_cards: tuple[str, str] = ('CRPIX1', 'CRPIX2'), **kwargs: Any)
Compute guiding offsets by tracking the brightest star relative to an initial reference frame.
This processor implements a simple auto-guiding strategy based on the brightest detected star. On the first call, it initializes a reference position from the brightest star in the image catalog and returns without setting offsets. On subsequent calls, it finds the current brightest star, computes the pixel offset relative to the reference, stores it as PixelOffsets in metadata, and also computes the corresponding Alt/Az offsets (in arcseconds) using the image WCS and observer location/time. Pixel data and FITS headers are not modified.
- Parameters:
center_header_cards (tuple[str, str]) – Names of FITS header keywords for the image center (default: (“CRPIX1”, “CRPIX2”)). Provided for compatibility; the current implementation determines the reference from the brightest star and does not use these values directly.
kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
If the image has no catalog or the catalog is empty, logs a warning and returns the image unchanged.
Initialization:
If no reference is set yet, selects the brightest star by the largest “flux” and stores its (x, y) pixel position as the reference. Returns the image.
Guiding update:
Selects the brightest star in the current catalog and computes pixel offsets relative to the stored reference:
dx = x_current - x_ref, dy = y_current - y_ref
Stores PixelOffsets(dx, dy) in the image metadata.
Computes Alt/Az offsets:
Uses WCS from the FITS header to convert the reference and current star pixel positions to sky coordinates (RA/Dec).
Builds an observer frame using FITS header location/time: LATITUDE [deg], LONGITUD [deg], HEIGHT [m], DATE-OBS.
Transforms both positions to AltAz and computes spherical offsets from the reference to the current position.
Stores AltAzOffsets(dAlt_arcsec, dAz_arcsec) in metadata.
Returns the same image object with updated metadata.
Input/Output
Input:
pyobs.images.Imagewitha source catalog containing “x”, “y”, and “flux” columns,
a valid WCS solution in the header (for Alt/Az offsets),
site metadata: LATITUDE [deg], LONGITUD [deg], HEIGHT [m],
observation time: DATE-OBS.
Output:
pyobs.images.Imagewith metadata entries set:PixelOffsets(dx, dy) after reference initialization,
AltAzOffsets(dAlt_arcsec, dAz_arcsec) likewise.
Configuration (YAML)
Initialize guiding on first frame, then report offsets on subsequent frames:
class: pyobs.images.processors.offsets.BrightestStarGuiding center_header_cards: ["CRPIX1", "CRPIX2"] # optional, not used directly
Notes
Offset sign convention: - PixelOffsets are star minus reference (positive dx means the star is to the
right of the reference; positive dy means above, in the usual image axis sense).
AltAzOffsets are returned as (dAlt, dAz) in arcseconds; positive dAlt means the target is at higher altitude than the reference; positive dAz means larger azimuth (Astropy’s AltAz azimuth increases east of north).
Reference management: - The first invocation sets the reference star and does not emit offsets. - Call reset() to clear the reference and reinitialize on the next image.
Catalog coordinates should use the same origin and units consistently across images; pyobs catalogs often adopt FITS-like 1-based pixel conventions.
Accurate WCS and site/time metadata are required for reliable Alt/Az offsets.
BrightestStarOffsets
- class BrightestStarOffsets(center_header_cards: Tuple[str, str] = ('CRPIX1', 'CRPIX2'), **kwargs: Any)
Compute pixel offsets from the image center to the brightest star and store them in metadata.
This processor reads the image center from FITS header keywords (default CRPIX1/CRPIX2), finds the brightest star in the attached source catalog (by maximum flux), computes the pixel offset between the center and that star, and stores the result as a PixelOffsets metadata entry. It also computes the on-sky angular separation between the two positions using the image WCS and stores it as OnSkyDistance. Pixel data and standard headers are not modified.
- Parameters:
center_header_cards (tuple[str, str]) – Names of the FITS header keywords that give the x and y pixel coordinates of the image center (default: (“CRPIX1”, “CRPIX2”)).
kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
If the image has no catalog or the catalog is empty, logs a warning and returns the image unchanged.
Selects the brightest star as the catalog row with the largest “flux” value and reads its “x” and “y” pixel coordinates.
Reads the image center pixel coordinates from the specified header keywords.
Computes pixel offsets:
dx = x_star - x_center
dy = y_star - y_center
Uses WCS from the image header to convert both positions to sky coordinates and computes their angular separation.
Stores results in image metadata:
PixelOffsets(dx, dy)
OnSkyDistance(angle)
Returns the same image object with updated metadata.
Input/Output
Input:
pyobs.images.Imagewith:a source catalog containing “x”, “y”, and “flux” columns
FITS header keys for the center (e.g., CRPIX1/CRPIX2)
a valid WCS solution in the header for sky separation
Output:
pyobs.images.Imagewith PixelOffsets and OnSkyDistance set in metadata.
Configuration (YAML)
Use CRPIX center:
class: pyobs.images.processors.offsets.BrightestStarOffsets
Use custom center keywords:
class: pyobs.images.processors.offsets.BrightestStarOffsets center_header_cards: ["CX", "CY"]
Notes
The sign convention for offsets is star minus center: positive dx means the star lies to the right of the center, positive dy means it lies above the center, assuming standard image axes.
Ensure catalog coordinates and center header values use the same pixel origin and units (pyobs catalogs often use FITS-like 1-based coordinates).
A valid WCS in the header is required to compute on-sky separation.
DummyOffsets
- class DummyOffsets(offset_class: str, offset: float = 1.0, **kwargs: Any)
Attach a dummy offset metadata entry using a class resolved from its name, for testing or simple workflows.
This processor resolves an offset class from a string and instantiates it with the same offset value for both components, then attaches the instance to the image metadata via
image.set_meta(...). Typical use cases include testing pipelines that consume offsets (e.g., PixelOffsets, AltAzOffsets) without running a full measurement procedure. Pixel data and FITS headers are not modified.- Parameters:
offset_class (str) – The name of the offset class to instantiate. Must be resolvable by
get_class_from_stringand refer to a class whose constructor accepts two numeric positional arguments (e.g.,dx, dy). Examples includepyobs.images.processors.offsets.PixelOffsetsorpyobs.images.processors.offsets.AltAzOffsets.offset (float) – The numeric value to use for both components of the offset (e.g., dx = dy = offset). Units depend on the chosen class (pixels for PixelOffsets, arcseconds for AltAzOffsets). Default:
1.0.kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
Resolves
offset_classto a class object usingpyobs.utils.classes.get_class_from_string().Instantiates the class with
(offset, offset)and attaches the resulting object to the image viaimage.set_meta(...).Returns the same image object; pixel data and FITS headers remain unchanged.
Input/Output
Input:
pyobs.images.Image.Output:
pyobs.images.Imagewith a metadata entry set to the instantiated offset object.
Configuration (YAML)
Set dummy pixel offsets of +1 pixel on both axes:
class: pyobs.images.processors.offsets.DummyOffsets offset_class: "pyobs.images.processors.offsets.PixelOffsets" offset: 1.0
Set dummy Alt/Az offsets of +2.5 arcseconds on both axes:
class: pyobs.images.processors.offsets.DummyOffsets offset_class: "pyobs.images.processors.offsets.AltAzOffsets" offset: 2.5
Notes
The meaning and units of
offsetdepend on the chosen class. Ensure consistency with downstream modules that consume the metadata.This processor is intended for testing or simple workflows; for measured offsets, use dedicated processors that compute offsets from catalogs, WCS, or other data.
DummySkyOffsets
- class DummySkyOffsets(coord0: SkyCoord | Dict[str, Any], coord1: SkyCoord | Dict[str, Any], **kwargs: Any)
Attach a precomputed sky-coordinate offset to image metadata for testing or simple workflows.
This processor constructs a
SkyOffsetsobject from two sky coordinates and attaches a copy of it to the image metadata viaimage.set_meta. Coordinates can be provided directly asastropy.coordinates.SkyCoordinstances or as configuration dictionaries that are instantiated viapyobs.utils.classes.get_object(). Pixel data and FITS headers are not modified.- Parameters:
coord0 (SkyCoord | dict) – The reference sky position. Either a SkyCoord instance or a configuration dictionary that resolves to one via
get_object.coord1 (SkyCoord | dict) – The target sky position. Either a SkyCoord instance or a configuration dictionary that resolves to one via
get_object.kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
Resolves
coord0andcoord1toSkyCoordobjects usingget_object()if dictionaries are provided.Constructs a
SkyOffsetsinstance representing the offset fromcoord0tocoord1.Attaches a shallow copy of this SkyOffsets object to the image metadata with
image.set_meta(...).Returns the same image object; pixel data and header entries are unchanged.
Input/Output
Input:
pyobs.images.Image.Output:
pyobs.images.Imagewith aSkyOffsetsmetadata entry set.
Configuration (YAML)
Provide coordinates as configuration dicts:
class: pyobs.images.processors.offsets.DummySkyOffsets coord0: class: astropy.coordinates.SkyCoord ra: "10h00m00s" dec: "+20d00m00s" frame: icrs coord1: class: astropy.coordinates.SkyCoord ra: "10h00m30s" dec: "+20d00m00s" frame: icrs
Notes
Frames and units of the provided SkyCoord objects determine the semantics of the SkyOffsets. Ensure both coordinates use compatible frames (e.g., ICRS).
This processor does not consult the image WCS or header; it simply stores the provided offset object in metadata.
A copy of the SkyOffsets is stored to avoid shared state across images.
FitsHeaderOffsets
- class FitsHeaderOffsets(target: Tuple[str, str], center: Tuple[str, str] = ('DET-CPX1', 'DET-CPX2'), **kwargs: Any)
Compute a 2D offset from FITS header coordinates and store it in image metadata.
This processor reads two pairs of FITS header keywords representing a target position and a reference (center) position, computes the component-wise difference target − center, and stores the result as a GenericOffset metadata entry on a copy of the image. Pixel data and standard headers are not modified.
- Parameters:
target (tuple[str, str]) – Names of the FITS header keywords for the target coordinates (e.g., measured or desired position), given as (x_key, y_key). Required.
center (tuple[str, str]) – Names of the FITS header keywords for the reference (center) coordinates, given as (x_key, y_key). Default: (“DET-CPX1”, “DET-CPX2”).
kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
Validates at initialization that both
targetandcenterare 2-tuples.On call: - Reads the target and center values from the image header. - Computes the offset as (target_x − center_x, target_y − center_y). - Creates a copy of the input image and attaches the result as
GenericOffset(dx, dy)in the image metadata.Returns the modified copy; pixel data and header values are unchanged.
Input/Output
Input:
pyobs.images.Imagewith FITS header containing the specified target and center keywords, whose values are numeric.Output:
pyobs.images.Image(copied) with aGenericOffsetmetadata entry set to the computed (dx, dy).
Configuration (YAML)
Use default center keys and custom target keys:
class: pyobs.images.processors.offsets.FitsHeaderOffsets target: ["OBJX", "OBJY"]
Custom center and target keys:
class: pyobs.images.processors.offsets.FitsHeaderOffsets target: ["TEL-CPX1", "TEL-CPX2"] center: ["CRPIX1", "CRPIX2"]
Notes
Units and origin are inherited from the header values (typically pixels). The sign convention is target minus center: dx = target_x − center_x, dy = target_y − center_y.
Ensure the target and center coordinates use the same convention (e.g., both 0-based or both FITS-like 1-based) to avoid off-by-one errors.
GenericOffsetis a unit-agnostic offset container; downstream consumers must interpret the units appropriately.
Offsets
- class Offsets(**kwargs: Any)
Base class for determining offsets.
PixelOffset
- class PixelOffset(pixel_offset_x: float, pixel_offset_y: float, **kwargs: Any)
Attach desired pixel offsets to the image metadata for later application by an acquisition module.
This processor stores a pixel-offset request in the image metadata as a
pyobs.images.processors.offsets.PixelOffsetsobject. Downstream modules (e.g., acquisition/guiding) can read these offsets and apply the corresponding pointing shift. Pixel data and FITS headers are not modified.- Parameters:
pixel_offset_x (float) – Requested offset in pixels along the image x-axis (columns).
pixel_offset_y (float) – Requested offset in pixels along the image y-axis (rows).
kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
Creates a
PixelOffsetsinstance with the givendxanddyvalues.Calls
image.set_meta(...)to attach the offsets to the image metadata.Returns the same image object; pixel data and FITS headers remain unchanged.
Input/Output
Input:
pyobs.images.Image.Output:
pyobs.images.Imagewith aPixelOffsetsmetadata entry set.
Configuration (YAML)
Request a shift of +12 pixels in x and -8 pixels in y:
class: pyobs.images.processors.offsets.AddPixelOffset pixel_offset_x: 12.0 pixel_offset_y: -8.0
Notes
Offsets are stored as metadata only; applying them is the responsibility of a downstream acquisition or control module that understands
PixelOffsets.Coordinate conventions (sign and axis direction) must match those expected by the module that consumes these offsets.
ProjectedOffsets
- class ProjectedOffsets(**kwargs: Any)
Compute pixel offsets for guiding by correlating 1D projections of the current image with a reference frame.
This processor implements an auto-guiding method based on collapsing images along the x and y axes and cross-correlating these 1D profiles against a stored reference. On the first invocation, it initializes by storing the reference projections from the input image and returns. On subsequent calls, it computes the current projections, performs background (sky) subtraction, estimates sub-pixel shifts via cross-correlation and Gaussian peak fitting, and stores the resulting PixelOffsets(dx, dy) in the image metadata. Pixel data and FITS headers are not modified.
- Parameters:
kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
Reference initialization:
If no reference is set, processes the input image to obtain sky-subtracted 1D projections along x and y, stores them as the reference, and returns.
Per-image guiding update:
Processes the current image to obtain sky-subtracted 1D projections.
Computes dx and dy by cross-correlating current vs. reference projections and fitting a Gaussian to the correlation peak within a small window to obtain sub-pixel offsets.
If either axis fails to produce a valid offset, logs a warning and returns the image unchanged.
Otherwise, attaches PixelOffsets(dx, dy) to image metadata.
Cropping via TRIMSEC:
If the FITS header contains TRIMSEC in the form “[x0:x1,y0:y1]” (1-based, inclusive), the image is cropped to that rectangle before projection.
Projection and sky subtraction:
Collapses the image by summing rows and columns with NaN-safe summation.
Subtracts a smooth sky continuum from each 1D projection:
Divides the projection into sbin=10 bins.
For each bin, estimates the continuum level as the median of the upper fraction (frac=0.15) of values.
Fits a spline (UnivariateSpline) through these bin medians and subtracts the fitted continuum from the projection.
Input/Output
Input:
pyobs.images.Imagewith 2D pixel data; optional TRIMSEC header for cropping prior to projection.Output:
pyobs.images.Imagewith PixelOffsets(dx, dy) set in metadata after the reference is initialized; otherwise unchanged.
Configuration (YAML)
Initialize on first frame, then report offsets on subsequent frames:
class: pyobs.images.processors.offsets.ProjectedOffsets
Notes
Offset sign convention: positive dx indicates that the current image’s x-profile is shifted to larger pixel indices relative to the reference; similarly for dy. Ensure this matches the downstream module that applies the offsets.
The Gaussian fit is performed around the cross-correlation peak within a window of width fit_width=10 by default; failed fits or peaks outside the window result in no offset update.
Sky subtraction parameters (frac=0.15, sbin=10) are fixed in this implementation; adjust the code if your background structure requires different settings.
Call reset() to clear the stored reference projections and reinitialize on the next image.
SpilledLightGuiding
- class SpilledLightGuiding(fibers: str, radius_ratio: float = 2, max_relative_sigma: float = 0.1, section_angular_width: float = 36, section_angular_shift: float = 18, **kwargs: Any)
Estimate pixel guiding offsets from asymmetry of spilled light around a fiber using a ring analysis.
This processor analyzes the distribution of light in an annulus around a selected fiber to infer the direction and magnitude of a pointing offset. It queries an IMultiFiber provider for the current fiber’s pixel position and radius, builds a ring (inner = fiber radius, outer = radius_ratio × inner), divides the ring into angular sections, and evaluates their brightness. If the ring brightness is sufficiently non-uniform, the brightest direction and a contrast-derived relative shift are used to compute a pixel offset, which is stored in the image metadata as PixelOffsets.
Note: This processor subtracts the global mean from the image data in place before analysis.
- Parameters:
fibers (str) – Name/address of an IMultiFiber module that provides the currently selected fiber’s pixel position and radius via get_pixel_position() and get_radius().
radius_ratio (float) – Ratio of the ring’s outer radius to the inner radius (the fiber radius). The ring is defined on [inner_radius, inner_radius × radius_ratio]. Default: 2.0.
max_relative_sigma (float) – Threshold on the ratio (std/median) of ring intensities used by the Ring object to decide whether the ring is “uniform.” If uniform, no offset is applied. Default: 0.1.
section_angular_width (float) – Angular width of each ring section in degrees for directional analysis. Default: 36.
section_angular_shift (float) – Angular offset (phase) in degrees applied to the ring sections. Default: 18.
kwargs – Additional keyword arguments forwarded to
pyobs.images.processors.offsets.Offsets.
Behavior
Retrieve fiber geometry:
Acquires fiber pixel position (x, y) and inner radius from the IMultiFiber module.
Corrects both by the detector binning factor read from FITS header DET-BIN1 (assumes square binning).
Background leveling:
Subtracts the global mean of image.data in place to reduce background bias.
Subimage trimming:
Extracts a rectangular subimage centered on the fiber with half-size radius_ratio × inner_radius in both axes for focused analysis.
Re-expresses the fiber position in the trimmed subimage’s coordinates.
Ring construction and analysis:
Builds a Ring with inner_radius, outer_radius = inner_radius × radius_ratio, section_angular_width, section_angular_shift, and max_relative_sigma.
If the ring is_uniform(), sets offset to (0, 0).
Otherwise:
Determines the brightest direction (default: brightest section).
Computes a relative shift from the brightness ratio of the brightest and opposite sections using a logistic mapping, capped at 1.
Converts to pixel offset: total_offset = relative_shift × inner_radius, with components
x = total_offset × sin(angle_deg), y = − total_offset × cos(angle_deg).
Metadata:
Stores PixelOffsets(dx, dy) in the image metadata.
Returns the same image object; note that image.data has been mean-subtracted.
Input/Output
Input:
pyobs.images.Imagewith: - FITS header key DET-BIN1 (integer binning factor), - access to an IMultiFiber module named by fibers.Output:
pyobs.images.Imagewith PixelOffsets set in metadata. Pixel data are modified in place by global mean subtraction.
Configuration (YAML)
Example with default ring parameters:
class: pyobs.images.processors.offsets.SpilledLightGuiding fibers: "FiberModuleName" radius_ratio: 2.0 max_relative_sigma: 0.1 section_angular_width: 36 section_angular_shift: 18
Notes
Sign convention: Offsets are reported in image pixel axes with x = total_offset × sin(angle), y = − total_offset × cos(angle), where angle is the azimuth of the brightest section in degrees.
The logistic mapping from section brightness ratio to relative shift is relative_shift = 1 / (1 + exp(−(ratio − 0.8) × 5)), capped at 1.0.
The trimming window is computed from the fiber position and radius to restrict analysis to the neighborhood of the fiber; the fiber position is converted to the trimmed subimage’s coordinates internally.
The Ring object is expected to provide methods such as: is_uniform(), get_brightest_section_angle(), get_brightest_point(), get_angle_from_position(), and get_opposite_section_normalized_counts_ratio().