Skip to main content

ASTApy

Thin wrapper around ASTAP CLI for Python

Download ASTAP CLI and star database from: https://www.hnsky.org/astap.htm#astap_command_line

Installation

ASTAP CLI

  1. Go to: https://www.hnsky.org/astap.htm
  2. Download the CLI for your operating system
  3. Save the binary in a suitable location, for example: ~/.local/astap
  4. Add this location to PATH: export PATH=~/.local/astap:$PATH
  5. Rename the CLI executable to astap

Star Database

Download a star database (e.g., D50), unpack it, and store the data in the same directory as the ASTAP CLI executable.

Testing the CLI

Type astap --help to verify installation. It should display the help page.

ASTApy Python Package

Install ASTApy from PyPI: https://pypi.org/project/astapy/

pip install astapy

Note: It is recommended to install in a virtual environment.

Usage

Basic example:

from pathlib import Path
from astapy import Astapy, Angle

# Define the FITS file path
file = Path("./data/test.fit")

# Define initial coordinates for searching (optional, defaults to ra=0, dec=0)
dec = Angle.from_deg(d=29, m=39, s=49)
ra = Angle.from_hour(h=6, m=30, s=49)

# Field of view of the image (must be close to actual FOV for effective solving)
fov = Angle.from_deg(d=0.18)

# Search radius
r = Angle.from_deg(d=10)

# Initialize Astapy
a = Astapy(file=file, dec=dec, ra=ra, fov=fov, r=r)

# Run plate solving and show log
wcs = a.run(log=True)

# Print the WCS header values
for val in wcs:
    print(val)

Custom ASTAP CLI Location

If your ASTAP executable has a different name or location, configure it at the top level:

from astapy import config

config({
    'exe': 'astap_cli'
})

API Documentation

Angle

The Angle class wraps an angle value stored internally in decimal degrees. It provides class methods to construct angles from degrees/minutes/seconds or hours/minutes/seconds.

Constructor

Angle(_v: Optional[float] = 0.0)

Initializes an Angle object directly from a degree value.

Do not use directly. Instead, use .from_deg() or .from_hour().

Parameters:

Name Type Default Description
_v float 0.0 Internal angle value in degrees

Example:

a = Angle(45)
print(a.to_deg())  # 45.0

Class Methods

from_deg(d=0.0, m=0.0, s=0.0) -> Angle

Creates an Angle from degrees, minutes, and seconds.

To create a negative angle, add a negative sign to d only.

Parameters:

Name Type Default Description
d float 0.0 Degrees component
m float 0.0 Arcminutes component
s float 0.0 Arcseconds component

Returns: An instance of Angle

Example:

a = Angle.from_deg(10, 30, 0)
print(a.to_deg())  # 10.5
from_hour(h=0.0, m=0.0, s=0.0) -> Angle

Creates an Angle from hours, minutes, and seconds. One hour corresponds to 15 degrees (useful for right ascension).

Parameters:

Name Type Default Description
h float 0.0 Hours component
m float 0.0 Minutes component
s float 0.0 Seconds component

Returns: An instance of Angle

Example:

a = Angle.from_hour(1, 0, 0)
print(a.to_deg())  # 15.0

Instance Methods

to_deg() -> float

Returns the internal value in decimal degrees.

Example:

a = Angle.from_deg(12, 30, 0)
print(a.to_deg())  # 12.5

Complete Example

from astapy import Angle

# From degrees/minutes/seconds
a1 = Angle.from_deg(23, 26, 45)
print(a1)  # Angle(23.445833°)

# From hours/minutes/seconds
a2 = Angle.from_hour(2, 0, 0)
print(a2.to_deg())  # 30.0

Astapy

This module wraps the ASTAP command-line tool, allowing you to run it directly from Python.

Data Structures

Config

A TypedDict defining configuration fields.

Key Type Description
exe str Path or name of the ASTAP executable
Args

Optional ASTAP command-line arguments. See: https://www.hnsky.org/astap.htm#astap_command_line

AstapNotFound

Custom exception raised when the ASTAP executable is missing.

Constructor

Astapy(file: Path, r: Angle = 10°, ra: Angle = 0°, dec: Angle = 0°, fov: Angle = 1°)

Parameters:

Name Type Default Description
file Path - Path to the FITS or image file to solve
r Angle 10° Search radius around starting coordinate
ra Angle 0° Right ascension initial guess
dec Angle 0° Declination initial guess
fov Angle 1° Field of view

Example:

from pathlib import Path
from astapy import Astapy, Angle

solver = Astapy(
    Path("example.fits"),
    ra=Angle.from_hour(h=5),
    dec=Angle.from_deg(d=-10)
)

Methods

args(**kwargs) -> Astapy

Add additional ASTAP command-line arguments dynamically.

Parameters:

Name Type Description
**kwargs Any Command-line options without the leading dash

Supported args:

key type description
z int Down sample (binning) of the input image prior to solving. Specify "0" for auto selection..
s int Limits the number of star used for the solution. Typical value 500.
t float Tolerance used to compare quads. Typical value 0.007.
m float This setting could be used to filter out hot pixels.
check bool Apply a check pattern filter prior to solving. Use for raw OSC images only when binning is set 1x1
d str Specify a path to the star database
D str Specify a star database
sip bool Add SIP (Simple Image Polynomial) coefficients. Only required to deactivate SIP.
speed 'slow' | 'auto' "slow" is forcing more area overlap while searching to improve detection.
update bool Add the solution to the input fits/tiff file header. In case the input is a jpeg, png a new fits will be created.
log bool Write solver log to a .log text file.
analyse float Analyse only and report HFD. Windows: errorlevel is the median HFD * 100M + number of stars used. So the HFD is trunc(errorlevel/1M)/100. For Linux and macOS the info is send to stdout only.
extract float As analyse option but additionally export info of all detectable stars to a .csv file. The decimal separator is always a dot.
extract2 float Solve image and export info of all detectable stars to a .csv file including α, δ of each detection. SIP polynomial will be used for high precision positions. The decimal separator is always a dot. In versions after 2024-2-1
annotate bool Produce a deep sky annotated jpeg file with same name as input file extended with _annotated.
sqm float Measure the sky background value in magn/arcsec2 relative to the stars. The pedestal is the mean value of a dark. Also centalt and airmass are written to the header.

Not supported: -o, -debug, -tofits, -focus1, -stack

Example:

solver.args(z=3, sigma=4)
run(log=False, delete=True) -> list[Card | Comment]

Run the ASTAP alignment/plate-solving process.

Parameters:

Name Type Default Description
log bool False If True, print ASTAP output in real time
delete bool True Whether to delete temporary files after solving

Returns: WCS information as a list of Card or Comment objects

Raises:

  • AstapNotFound if the ASTAP executable cannot be found
  • FileNotFoundError if the image file does not exist

Example:

wcs = solver.run(log=True)
print(wcs)

Complete Example

from pathlib import Path
from astapy import Astapy, Angle

solver = Astapy(Path("image.fits")).args(z=2)
wcs = solver.run(log=True)

Log Output

Successful Solve

Running: astap -f test.fit -r 10.0 -ra 6.5136111111111115 -spd 119.66361111111111 -fov 0.18 -o temp -z 1 -log
astap -f test.fit -r 10.0 -ra 6.5136111111111115 -spd 119.66361111111111 -fov 0.18 -o temp -z 1 -log
Using star database D50
Database limit for this FOV is 203 stars.
ASTAP solver version CLI-2025.10.11
Search radius: 10.0 degrees,
Start position: 06: 30  49.0, +29d 39  49
Image height: 0.18 degrees
Binning: 1x1
Image dimensions: 1375x1100
Quad tolerance: 0.007
Minimum star size: 1.5"
Speed: normal
116 stars, 88 quads selected in the image. 112 database stars, 85 database quads required for the 0.20d square search window. Step size 0.18d. Oversize 1.10

24 of 24 quads selected matching within 0.007 tolerance.
Solution["] x:=-0.574225*x+ -0.012891*y+ 401.578769,  y:=-0.013370*x+ 0.573890*y+ -306.168946
Solution found: 06: 30  48.2 +29d 39  49

Failed Solve

Running: astap -f test.fit -r 10.0 -ra 0.0 -spd 119.66361111111111 -fov 0.18 -o temp -z 1 -log
astap -f test.fit -r 10.0 -ra 0.0 -spd 119.66361111111111 -fov 0.18 -o temp -z 1 -log
Using star database D50
Database limit for this FOV is 203 stars.
ASTAP solver version CLI-2025.10.11
Search radius: 10.0 degrees,
Start position: 00: 00  00.0, +29d 39  49
Image height: 0.18 degrees
Binning: 1x1
Image dimensions: 1375x1100
Quad tolerance: 0.007
Minimum star size: 1.5"
Speed: normal
116 stars, 88 quads selected in the image. 112 database stars, 85 database quads required for the 0.20d square search window. Step size 0.18d. Oversize 1.10
0d,1d,1d,1d,1d,2d,2d,2d,2d,3d,3d,3d,3d,4d,4d,4d,4d,5d,5d,5d,5d,6d,6d,6d,6d,7d,7d,7d,7d,8d,8d,8d,9d,9d,9d,9d,10d,10d,10d,No solution found!  :(

WCS Header

The result of plate solving is a WCS header in the form of a list of Card or Comment objects.

Card

@dataclass
class Card:
    key: str
    value: str | float | bool
    comment: str | None = None

Represents a single key-value pair in the WCS header.

Attributes:

Name Type Description
key str Header keyword (e.g., CTYPE1, CRVAL1)
value str | float | bool Parsed header value, automatically converted when possible
comment str | None Optional comment following a / separator

Comment

@dataclass
class Comment:
    value: str

Represents a comment line in the header file (lines starting with COMMENT).

Attributes:

Name Type Description
value str The comment text

Example

solver = Astapy(file=file)
wcs = solver.run(log=True)
for val in wcs:
    print(val)

Output:

Card(key='CTYPE1  ', value=" 'RA---TAN'           ", comment=' first parameter RA,    projection TANgential')
Card(key='CTYPE2  ', value=" 'DEC--TAN'           ", comment=' second parameter DEC,  projection TANgential')
Card(key='CUNIT1  ', value=" 'deg     '           ", comment=' Unit of coordinates')
Card(key='CRPIX1  ', value='  6.880000000000E+002 ', comment=' X of reference pixel')
Card(key='CRPIX2  ', value='  5.505000000000E+002 ', comment=' Y of reference pixel')
Card(key='CRVAL1  ', value='  9.770093978531E+001 ', comment=' RA of reference pixel (deg)')
Card(key='CRVAL2  ', value='  2.966372471539E+001 ', comment=' DEC of reference pixel (deg)')
Card(key='CDELT1  ', value='  1.595471921033E-004 ', comment=' X pixel size (deg)')
Card(key='CDELT2  ', value='  1.594572697506E-004 ', comment=' Y pixel size (deg)')
Card(key='CROTA1  ', value=' -1.333831567642E+000 ', comment=' Image twist of X axis        (deg)')
Card(key='CROTA2  ', value=' -1.286801526764E+000 ', comment=' Image twist of Y axis        (deg)')
Card(key='CD1_1   ', value='  1.595039610045E-004 ', comment=' CD matrix to convert (x,y) to (Ra, Dec)')
Card(key='CD1_2   ', value='  3.713883671986E-006 ', comment=' CD matrix to convert (x,y) to (Ra, Dec)')
Card(key='CD2_1   ', value=' -3.580937559609E-006 ', comment=' CD matrix to convert (x,y) to (Ra, Dec)')
Card(key='CD2_2   ', value='  1.594170560590E-004 ', comment=' CD matrix to convert (x,y) to (Ra, Dec)')
Card(key='PLTSOLVD', value='                    T ', comment=' Astrometric solved by ASTAP_CLI v2025.10.11.')
Comment(value=' 7 Solved in 0.1 sec. Offset was 10.1".')
Comment(value=' cmdline:astap -f test.fit -r 1')
Comment(value=' 0.0 -ra 6.5136111111111115 -spd 119.66361111111111 -fov 0.18 -o')
Comment(value=' temp -z 1 -log')

License

See LICENSE file for details.

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Metadata

Release files for astapy 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for astapy 0.1.4
File Size Uploaded
astapy-0.1.4.tar.gz 14.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for astapy 0.1.4
File Interpreter ABI Platform
astapy-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 25.8 kB

Release files / astapy-0.1.4.tar.gz

Download URL astapy-0.1.4.tar.gz
Size 14.4 kB
Tags Source
SHA-256 checksum
How to use checksums
bc965f3265299055ac939c096474d2caa460c98ce7d5eb9b1a6e6a2430c78cbd
BLAKE2b-256 checksum
How to use checksums
71a98eac569c02b6d084bee6b0135976854502c81074ed42969a220bcf662553
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.18

Release files / astapy-0.1.4-py3-none-any.whl

Download URL astapy-0.1.4-py3-none-any.whl
Size 11.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
721a9de66f196b6da92a1debe412b03ae0cfdabde3573a393fe13a6df7b3abdf
BLAKE2b-256 checksum
How to use checksums
542dc33e7408253cddc65076aa5e19dd2261cc32dddd6a2b1d36d2e03d46c397
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.18

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page