astra.pointer#

Astronomical pointing correction and plate solving utilities.

This module provides comprehensive tools for correcting telescope pointing errors by analyzing astronomical images and comparing detected stars with catalog data. The primary workflow involves star detection, world coordinate system (WCS) computation, and pointing offset calculation.

Key Features:
  • Multi-scale star detection algorithms for robust identification in noisy images

  • Gaia star catalog integration for precise astrometric reference

  • World Coordinate System (WCS) computation using the twirl library

  • Automatic pointing correction calculation and validation

  • Support for FITS file processing with metadata extraction

  • Background subtraction and image cleaning utilities

The module supports two main use cases:
  1. Real-time pointing correction during observations

  2. Post-processing analysis of astronomical images

Typical Workflow:
  1. Load or generate an astronomical image

  2. Detect stars using multi-scale algorithms

  3. Query Gaia catalog for reference stars in the field

  4. Compute WCS transformation between image and sky coordinates

  5. Calculate pointing correction based on target vs actual position

  6. Apply corrections to telescope pointing

Example

# Process a FITS file for pointing correction
pointing_correction, image_star_mapping, num_stars = (
    calculate_pointing_correction_from_fits(
        "observation.fits",
        target_ra=150.25,
        target_dec=2.18
    )
)

# Get the pointing offset
ra_offset = pointing_correction.offset_ra
dec_offset = pointing_correction.offset_dec

print(f"Pointing error: RA={ra_offset:.3f}°, Dec={dec_offset:.3f}°")

Functions

calculate_pointing_correction_from_fits(filepath)

Calculate pointing correction from a FITS file.

calculate_pointing_correction_from_image(...)

Calculate pointing correction from an image array.

find_stars(data[, threshold, fwhm])

Find stars using DAOStarFinder algorithm.

local_db_query(db, min_dec, max_dec, min_ra, ...)

Query astronomical database for objects within coordinate bounds.

local_gaia_db_query(center, fov[, limit, ...])

Query local Gaia database to retrieve RA-DEC coordinates of stars within a given field-of-view.

Classes

ImageStarMapping(wcs, stars_in_image, ...)

A class to handle the mapping of stars detected in an image to their corresponding Gaia star coordinates using World Coordinate System (WCS) transformations.

PointingCorrection(target_ra, target_dec, ...)

Class to store the pointing correction between the desired target center and the plating center.

Exceptions

PlateSolveError

Raised when twirl finds no solution, or no solution passes the checks.

astra.pointer.calculate_pointing_correction_from_fits(filepath: str | Path | None, dark_frame: str | Path | ndarray | None = None, target_ra: float | None = None, target_dec: float | None = None, filter_band: str | None = None, use_local_db: bool = False, logger: Logger | None = None)[source]#

Calculate pointing correction from a FITS file.

Performs the complete plate solving workflow from a FITS file, including metadata extraction, image cleaning, star detection, and pointing correction.

Parameters:
  • filepath (str or Path) – Path to the FITS file.

  • dark_frame (str, Path or np.ndarray, optional) – Dark frame for subtraction, as a path or as image data. Defaults to None.

  • target_ra (float, optional) – Target right ascension in degrees. If not provided, it’s read from FITS header. Defaults to None.

  • target_dec (float, optional) – Target declination in degrees. If not provided, it’s read from FITS header. Defaults to None.

  • filter_band (str, optional) – Filter band used for observation. Defaults to None.

  • use_local_db (bool, optional) – Whether to use the local Gaia database. Defaults to False.

  • logger (logging.Logger, optional) – Logger for progress messages, for example the observatory logger so the messages reach the UI. Defaults to the module logger.

Returns:

Tuple[PointingCorrection, ImageStarMapping, int] –

A tuple containing:
  • PointingCorrection: Object with computed pointing correction

  • ImageStarMapping: Mapping of image stars to Gaia stars

  • int: Number of stars used from the image for plate solving

Raises:
  • Exception – If insufficient stars are detected for plate solving, or if the offset is larger than the field of view.

  • PlateSolveError – If no solution passes the checks in _verify_plate_solve.

astra.pointer.calculate_pointing_correction_from_image(image: ndarray, target_ra: float, target_dec: float, dateobs: datetime, plate_scale: float, filter_band: str | None = None, use_local_db: bool = False, logger: Logger | None = None)[source]#

Calculate pointing correction from an image array.

Performs the complete plate solving workflow: image cleaning, star detection, Gaia catalog matching, WCS computation, and pointing correction calculation.

Parameters:
  • image (np.ndarray) – The 2D astronomical image data.

  • target_ra (float) – Target right ascension in degrees.

  • target_dec (float) – Target declination in degrees.

  • dateobs (datetime) – Observation date for proper motion corrections.

  • plate_scale (float) – Image plate scale in degrees per pixel.

  • filter_band (str, optional) – Filter band used for observation.

  • use_local_db (bool, optional) – Whether to use the local Gaia database. Defaults to False.

  • logger (logging.Logger, optional) – Logger for progress messages, for example the observatory logger so the messages reach the UI. Defaults to the module logger.

Returns:

Tuple[PointingCorrection, ImageStarMapping, int] –

A tuple containing:
  • PointingCorrection: Object with computed pointing correction

  • ImageStarMapping: Mapping of image stars to Gaia stars

  • int: Number of stars used from the image for plate solving

Raises:
  • Exception – If insufficient stars are detected for plate solving, or if the offset is larger than the field of view.

  • PlateSolveError – If no solution passes the checks in _verify_plate_solve.

astra.pointer.find_stars(data: ndarray, threshold: float = 5.0, fwhm: float = 3.0) → ndarray[source]#

Find stars using DAOStarFinder algorithm.

Uses the photutils DAOStarFinder algorithm to detect point sources in astronomical images. The function performs background subtraction and returns star coordinates sorted by brightness.

Parameters:
  • data (np.ndarray) – The 2D image data array.

  • threshold (float, optional) – Detection threshold in units of background standard deviation. Higher values detect fewer, brighter stars. Defaults to 5.0.

  • fwhm (float, optional) – Expected Full Width at Half Maximum of stars in pixels. Should match the typical seeing conditions. Defaults to 3.0.

Returns:

np.ndarray –

Array of detected star coordinates sorted by brightness.

Shape is (N, 2) where N is the number of stars, and each row is (x, y). Returns an empty array if no stars are found.

exception astra.pointer.PlateSolveError[source]#

Bases: Exception

Raised when twirl finds no solution, or no solution passes the checks.

class astra.pointer.PointingCorrection(target_ra: float, target_dec: float, plating_ra: float, plating_dec: float)[source]#

Bases: object

Class to store the pointing correction between the desired target center and the plating center.

Stores target and actual telescope pointing coordinates and provides methods to calculate offsets, angular separations, and proxy coordinates for correction. The proxy coordinates represent where the telescope should point to achieve the desired target position.

Properties:

offset_ra: RA offset (plating - target) in degrees :no-index: offset_dec: Dec offset (plating - target) in degrees :no-index: angular_separation: Angular distance between target and actual position :no-index: proxy_ra: RA coordinate to point telescope to reach target :no-index: proxy_dec: Dec coordinate to point telescope to reach target :no-index:

Example

>>> from astra.pointer import PointingCorrection
>>> pointing_correction = PointingCorrection(
...     target_ra=10.685, target_dec=41.269,
...     plating_ra=10.68471, plating_dec=41.26917
... )
>>> print(f"RA offset: {pointing_correction.offset_ra:.4f} degrees")
target_ra: float#

The declination of the target center in degrees.

target_dec: float#

The right ascension of the plating center in degrees.

plating_ra: float#

The declination of the plating center in degrees.

plating_dec: float#
property offset_ra#

Calculate the RA offset between plating and target coordinates.

Returns:

float –

RA offset (plating_ra - target_ra) in degrees. Positive values

indicate the telescope pointed east of the target.

property offset_dec#

Calculate the Dec offset between plating and target coordinates.

Returns:

float –

Dec offset (plating_dec - target_dec) in degrees. Positive values

indicate the telescope pointed north of the target.

property angular_separation: float#

Calculate the angular separation between target and plating coordinates.

Returns:

float –

Angular distance between target and actual position in degrees.

Always positive, represents the magnitude of the pointing error.

property proxy_ra#

Calculate the RA coordinate to point the telescope to reach the target RA.

This assumes that the offset is independent of the telescope’s position in the sky. The proxy coordinate compensates for the systematic pointing error.

Returns:

float –

RA coordinate in degrees where the telescope should point to

effectively arrive at the target RA.

See also

ConstantDistorter: Verify sign convention of correction.

property proxy_dec#

Calculate the Dec coordinate to point the telescope to reach the target Dec.

This assumes that the offset is independent of the telescope’s position in the sky. The proxy coordinate compensates for the systematic pointing error.

Returns:

float –

Dec coordinate in degrees where the telescope should point to

effectively arrive at the target Dec.

See also

ConstantDistorter: Verify sign convention of correction.

class astra.pointer.ImageStarMapping(wcs: WCS, stars_in_image: ndarray, gaia_stars_in_image: ndarray)[source]#

Bases: object

A class to handle the mapping of stars detected in an image to their corresponding Gaia star coordinates using World Coordinate System (WCS) transformations.

Manages the relationship between pixel coordinates of detected stars and their celestial coordinates from the Gaia catalog. Provides methods for coordinate transformations, star matching, and validation of the plate solving process.

wcs: WCS#

An array of detected star coordinates in the image, represented in pixel format (x, y).

stars_in_image: ndarray#

An array of Gaia star coordinates projected into the image’s pixel space using the WCS transformation.

gaia_stars_in_image: ndarray#
classmethod from_gaia_coordinates(stars_in_image: ndarray, gaia_stars: ndarray, plate_scale: float | None = None, logger: Logger | None = None)[source]#

Create an ImageStarMapping instance from detected stars and Gaia coordinates.

Computes the World Coordinate System (WCS) transformation using the twirl library to map between pixel and sky coordinates.

If plate_scale is given, twirl first matches triangles of stars, which is fast. If that gives no solution, raises, or the solution fails _verify_plate_solve, it tries once more with quads of stars (the twirl defaults). Triangles can give wrong solutions that only the checks catch, so without plate_scale only quads are used and the solution is not checked.

Parameters:
  • stars_in_image (np.ndarray) – Array of detected star coordinates in pixels (x, y).

  • gaia_stars (np.ndarray) – Array of Gaia star coordinates in degrees (ra, dec).

  • plate_scale (float, optional) – Expected plate scale in degrees per pixel. If given, each solution must pass _verify_plate_solve.

  • logger (logging.Logger, optional) – Logger for the result of each attempt. Defaults to the module logger.

Returns:

ImageStarMapping – New instance with computed WCS and transformed coordinates.

Raises:

PlateSolveError – If no attempt gives a solution that passes the checks.

get_plating_center(image_shape: Tuple[int, int]) → Tuple[float, float][source]#

Calculate the sky coordinates of the image center (plating center).

Parameters:

image_shape (Tuple[int, int]) – Shape of the image as (height, width).

Returns:

Tuple[float, float] – RA and Dec coordinates of the image center in degrees.

skycoord_to_pixels(ra: float, dec: float) → Tuple[float, float][source]#

Convert sky coordinates to pixel coordinates using the WCS.

Parameters:
  • ra (float) – Right ascension in degrees.

  • dec (float) – Declination in degrees.

Returns:

Tuple[float, float] – Pixel coordinates (x, y) in the image.

pixels_to_skycoord(pixels: ndarray)[source]#

Convert pixel coordinates to sky coordinates using the WCS.

Parameters:

pixels (np.ndarray) – Array of pixel coordinates.

Returns:

Array of sky coordinates corresponding to the input pixels.

find_gaia_match()[source]#

Find the closest Gaia star match for each detected star in the image.

Calculates the distance between each detected star and all Gaia stars in pixel space, then returns the closest match and distance for each.

Returns:

Tuple[np.ndarray, np.ndarray] – - Matched Gaia star positions in pixel coordinates - Distances to the closest matches in pixels

number_of_matched_stars(pixel_threshold: float = 10)[source]#

Count the number of stars matched within a pixel threshold.

Parameters:

pixel_threshold (float, optional) – Maximum distance in pixels to consider a match valid. Defaults to 10.

Returns:

int – Number of detected stars that have a Gaia match within the threshold.

plot(ax=None, transpose=False, **kwargs)[source]#

Plot detected stars and their Gaia matches for visualization.

Parameters:
  • ax (matplotlib.axes.Axes, optional) – Axes to plot on. If None, creates new figure.

  • transpose (bool, optional) – If True, transpose x and y coordinates for plotting. Defaults to False.

  • **kwargs – Additional keyword arguments passed to scatter plot.

astra.pointer.local_gaia_db_query(center: Tuple[float, float] | SkyCoord, fov: float | Quantity, limit: int = 1000, tmass: bool = False, dateobs: datetime | None = None) → ndarray[source]#

Query local Gaia database to retrieve RA-DEC coordinates of stars within a given field-of-view.

Retrieves star positions from a local Gaia database within a rectangular region centered on the specified coordinates. Optionally applies proper motion corrections for a specific observation date and sorts by magnitude (Gaia G-band or 2MASS J-band).

Parameters:
  • center (tuple or SkyCoord) – The sky coordinates of the center of the FOV. If a tuple is given, it should contain the RA and DEC in degrees.

  • fov (float or Quantity) – The field-of-view size in degrees. If a float is given, it is assumed to be in degrees. Can be a single value (square FOV) or tuple (RA_fov, Dec_fov).

  • limit (int, optional) – The maximum number of sources to retrieve from the database. Defaults to 1000.

  • tmass (bool, optional) – Whether to sort by 2MASS J magnitudes instead of Gaia G magnitudes. Defaults to False.

  • dateobs (datetime, optional) – The date of the observation. If given, the proper motions of the sources will be applied to update positions from J2015.5 to the observation date. Defaults to None.

Returns:

np.ndarray –

An array of shape (n, 2) containing the RA-DEC coordinates

of the retrieved sources in degrees, sorted by magnitude (brightest first).

astra.pointer.local_db_query(db: str | Path, min_dec: float, max_dec: float, min_ra: float, max_ra: float, crosses_zero: bool = False) → DataFrame[source]#

Query astronomical database for objects within coordinate bounds.

Performs federated query across sharded SQLite database tables to retrieve astronomical catalog data within specified declination and right ascension ranges.

Parameters:
  • db (Union[str, Path]) – Path to the SQLite database file.

  • min_dec (float) – Minimum declination in degrees.

  • max_dec (float) – Maximum declination in degrees.

  • min_ra (float) – Minimum right ascension in degrees.

  • max_ra (float) – Maximum right ascension in degrees.

  • crosses_zero (bool, optional) – Whether the RA range crosses the 0-degree line. Defaults to False.

Returns:

pd.DataFrame – Combined results from all relevant database shards.