Astrometry
Astrometry turns a list of star positions into a pixel-to-sky transformation (WCS)
Install / Use
/learn @neuromorphicsystems/AstrometryREADME
- Astrometry
- Get started
- Examples
- Use the solver without
with - Provide size and position hints
- Print progress information (download and solve)
- Print field stars metadata
- Calculate field stars pixel positions with astropy
- Print series description and size (without downloading them)
- Disable tune-up and distortion
- Stop the solver early using the log-odds callback
- Use the solver without
- Choosing series
- Documentation
- Contribute
Astrometry
Astrometry turns a list of star positions into a pixel-to-sky transformation (WCS) by calling C functions from the Astrometry.net library (https://astrometry.net).
Astrometry.net star index files ("series") are automatically downloaded when required.
This package is useful for solving plates from a Python script, comparing star extraction methods, or hosting a simple local version of Astrometry.net with minimal dependencies. See https://github.com/dam90/astrometry for a more complete self-hosting solution.
Unlike Astrometry.net, Astrometry does not include FITS parsing or image pre-processing algorithms. Stars must be provided as a list of pixel positions.
This library works on Linux and macOS but it requires WSL on Windows.
We are not the authors of the Astrometry.net library. You should cite works from https://astrometry.net/biblio.html if you use the Astrometry.net algorithm via this package.
Get started
python3 -m venv .venv
source .venv/bin/activate
pip install astrometry
import astrometry
with astrometry.Solver(
astrometry.series_5200.index_files(
cache_directory="astrometry_cache",
scales={6},
)
) as solver:
stars = [
[388.9140568247906, 656.5003281719216],
[732.9210858972549, 473.66395545775106],
[401.03459504299843, 253.788113189415],
[312.6591868096163, 624.7527729425295],
[694.6844564647456, 606.8371776658344],
[741.7233477959561, 344.41284826261443],
[867.3574610200455, 672.014835980283],
[1063.546651153479, 593.7844603550848],
[286.69070190952704, 422.170016812049],
[401.12779619355155, 16.13543616977013],
[205.12103484692776, 698.1847350789413],
[202.88444768690894, 111.24830187635557],
[339.1627757703069, 86.60739435924549],
]
solution = solver.solve(
stars=stars,
size_hint=None,
position_hint=None,
solution_parameters=astrometry.SolutionParameters(),
)
if solution.has_match():
print(f"{solution.best_match().center_ra_deg=}")
print(f"{solution.best_match().center_dec_deg=}")
print(f"{solution.best_match().scale_arcsec_per_pixel=}")
solve is thread-safe. It can be called any number of times from the same Solver object.
Examples
Use the solver without with
import astrometry
solver = astrometry.Solver(...)
solver.solve(...) # solve can be called multiple times
solver.close() # close the index files used by the solver
Provide size and position hints
import astrometry
with astrometry.Solver(...) as solver:
solution = solver.solve(
stars=...,
size_hint=astrometry.SizeHint(
lower_arcsec_per_pixel=1.0,
upper_arcsec_per_pixel=2.0,
),
position_hint=astrometry.PositionHint(
ra_deg=65.7,
dec_deg=36.2,
radius_deg=1.0,
),
solution_parameters=...
)
Print progress information (download and solve)
import astrometry
import logging
logging.getLogger().setLevel(logging.INFO)
with astrometry.Solver(...) as solver:
solution = solver.solve(...)
Print field stars metadata
Astrometry extracts metadata from the star index ("series"). See Choosing series for a description of the available data.
import astrometry
with astrometry.Solver(...) as solver:
solution = solver.solve(...)
if solution.has_match():
for star in solution.best_match().stars:
print(f"{star.ra_deg}º, {star.dec_deg}º:", star.metadata)
Calculate field stars pixel positions with astropy
import astrometry
with astrometry.Solver(...) as solver:
solution = solver.solve(...)
if solution.has_match():
wcs = solution.best_match().astropy_wcs()
pixels = wcs.all_world2pix(
[[star.ra_deg, star.dec_deg] for star in solution.best_match().stars],
0,
)
# pixels is a len(solution.best_match().stars) x 2 numpy array of float values
astropy.wcs.WCS provides many more functions to probe the transformation properties and convert from and to pixel coordinates. See https://docs.astropy.org/en/stable/api/astropy.wcs.WCS.html for details. Astropy (https://pypi.org/project/astropy/) must be installed to use this method.
Print series description and size (without downloading them)
import astrometry
print(astrometry.series_5200_heavy.description)
print(astrometry.series_5200_heavy.size_as_string({2, 3, 4}))
See Choosing Series for a list of available series.
Disable tune-up and distortion
import astrometry
with astrometry.Solver(...) as solver:
solution = solver.solve(
stars=...,
size_hint=...,
position_hint=...,
solution_parameters=astrometry.SolutionParameters(
sip_order=0,
tune_up_logodds_threshold=None,
),
)
Stop the solver early using the log-odds callback
Return after the first match
import astrometry
with astrometry.Solver(...) as solver:
solution = solver.solve(
stars=...,
size_hint=...,
position_hint=...,
solution_parameters=astrometry.SolutionParameters(
logodds_callback=lambda logodds_list: astrometry.Action.STOP,
),
)
Return early if the best log-odds are larger than 100.0
import astrometry
with astrometry.Solver(...) as solver:
solution = solver.solve(
stars=...,
size_hint=...,
position_hint=...,
solution_parameters=astrometry.SolutionParameters(
logodds_callback=lambda logodds_list: (
astrometry.Action.STOP
if logodds_list[0] > 100.0
else astrometry.Action.CONTINUE
),
),
)
Return early if there are at least ten matches
import astrometry
with astrometry.Solver(...) as solver:
solution = solver.solve(
stars=...,
size_hint=...,
position_hint=...,
solution_parameters=astrometry.SolutionParameters(
logodds_callback=lambda logodds_list: (
astrometry.Action.STOP
if len(logodds_list) >= 10.0
else astrometry.Action.CONTINUE
),
),
)
Return early if the three best matches are similar
import astrometry
def logodds_callback(logodds_list: list[float]) -> astrometry.Action:
if len(logodds_list) < 3:
return astrometry.Action.CONTINUE
if logodds_list[1] > logodds_list[0] - 10 and logodds_list[2] > logodds_list[0] - 10:
return astrometry.Action.STOP
return astrometry.Action.CONTINUE
with astrometry.Solver(...) as solver:
solution = solver.solve(
stars=...,
size_hint=...,
position_hint=...,
solution_parameters=astrometry.SolutionParameters(
logodds_callback=logodds_callback,
),
)
Choosing series
This library downloads series from http://data.astrometry.net. A solver can be instantiated with multiple series and scales as follows:
import astrometry
with astrometry.Solver(
astrometry.series_5200.index_files(
cache_directory="astrometry_cache",
scales={4, 5, 6},
)
+ astrometry.series_4200.index_files(
cache_directory="astrometry_cache",
scales={6, 7, 12},
)
) as solver:
...
Astrometry.net gives the following recommendations to choose a scale:
Each index file contains a large number of “skymarks” (landmarks for the sky) that allow our solver to identify your images. The skymarks contained in each index file have sizes (diameters) within a narrow range. You probably want to download index files whose quads are, say, 10% to 100% of the sizes of the images you want to solve.
For example, let’s say you have some 1-degree square images. You should grab index files that contain skymarks of size 0.1 to 1 degre
Related Skills
node-connect
351.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
110.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
351.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
351.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
