Help us shape the future of Go! Take the 2026 Go Developer Survey

astro-recommender

command module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 16 Imported by: 0

README

astro-recommender

A small Go CLI that lists the best deep sky objects to image tonight from a given location. It looks at the whole of full astronomical night, from dusk to dawn (Sun below −18°).

It works like the deep sky part of uptonight, plus extras aimed at the Celestron Origin smart telescope:

  • a check that each object fits the Origin's frame and pixel scale (or any telescope's, with -fov/-scale)
  • moonlight and light-pollution handling, with optional narrowband filter support
  • cloud, transparency, dew and wind forecasts

Features

  • Tonight's window: astronomical dusk to dawn (Sun below −18°), found by searching from the site's own solar noon so time zones and polar nights can't cut it short. A run after midnight plans the rest of the night in progress; -date plans another evening and -from/-to narrow the window.
  • Observability per minute, following uptonight's rules: altitude between -alt-min and -alt-max, Moon separation of at least the illumination percentage in degrees (skipped while the Moon is below the horizon), and optionally above your measured local horizon profile (-horizon).
  • Ranking by an imaging score that sums, over every observable minute, the forecast sky quality × atmospheric extinction × a sky-brightness weight, with uptonight's observable fraction (FOTO) shown alongside. Mean altitude breaks ties.
  • Sky brightness and moonlight: the Krisciunas & Schaefer model of the moonless sky from -bortle or a measured -sqm value, brightened towards the horizon, plus scattered moonlight from the Moon's phase, altitude and distance to the target. Targets are weighted by sky-limited signal-to-noise.
  • Target-type sensitivity to sky glow: clusters count half of it, and with -filter emission-line targets (emission and planetary nebulae, supernova remnants, Wolf-Rayet nebulae, plus known mislabelled ones) count only -filter-k of it, which also relaxes their Moon-distance limit.
  • Extinction per hour from the site's elevation and the CAMS aerosol forecast (dust, smoke, haze), or a fixed -extinction; shown in the forecast table.
  • Weather: Open-Meteo cloud cover by layer (thin high cloud counts half), dew-point spread and wind gusts, and 7Timer transparency and seeing, in an hourly table and folded into the score minute by minute. Missing data counts as perfect sky with a warning, never silently.
  • Framing for the Celestron Origin (-origin) or any telescope (-fov, -scale): keeps only objects that fit the frame's short side and are at least -min-px across, scores how well they fill it, and shows their size in pixels.
  • Comets from the Minor Planet Center's daily elements, cached locally: two-body positions every minute (elliptic, parabolic and hyperbolic orbits), kept when brighter than -comet-mag, ranked like any other target.
  • Night plan (-plan 2h): one target per time block, chosen by a greedy pass followed by a local search that swaps and moves targets between blocks.
  • Nine built-in target lists (about 21,000 objects: Gary Imm's selection and full Compendium, Messier, Herschel 400, Pensack 500, NGC, IC, LBN, LDN) or your own uptonight-format YAML, with every object's constellation computed from the IAU boundaries.
  • Location handling: offline IANA time-zone lookup from the coordinates, reverse geocoding of the site name, coordinates rounded to about 1 km before any request, and a fully offline mode.
  • Terminal output: aligned, colour-coded tables with a legend; honours NO_COLOR, CLICOLOR_FORCE and TERM=dumb. Text from the network or from target files is stripped of control characters so it cannot inject terminal escape sequences.
  • Verified astronomy: the hand-rolled Sun, Moon, sidereal-time, precession and altitude formulas are checked against IAU SOFA in the test suite (see Accuracy); a single static binary with no API keys.

Install

go install github.com/dkorunic/astro-recommender@latest

Or from a checkout, using Task:

task build   # formats, then builds a static, PGO-optimised binary
task test
task lint    # golangci-lint

Plain go build . works too.

It needs Go 1.27+. The target catalogue is built into the binary.

Usage

astro-recommender -lat 45.815 -lon 15.982 -origin -filter -bortle 6 -n 5
Location: 45.8150, 15.9820 (Mjesni odbor Zrinjevac, Gradska četvrt Donji grad, Zagreb, Grad Zagreb, Hrvatska), Europe/Zagreb
Window:   2026-10-05 20:08 - 2026-10-06 05:22 (9h14m0s)
Moon:     24% illuminated, min separation 24°
Size:     4.1' - 45.0'
Targets:  GaryImm, 2 comets brighter than mag 12.0
Frame:    1.32° x 0.75°, 1.23"/px (3863 x 2195 px)
Sky:      Bortle 6 (zenith 18.80 mag/arcsec²), extinction 0.23-0.25 (elevation 126 m, aerosols) mag/airmass, filter k=0.25

HOUR   CLOUD  LOW/MID/HIGH  TRANSP  EXT   SEEING  DEW SPREAD  WIND/GUST
20:00  50%    0/0/100%      2/8     0.25  1.5-2"  6.0°C       5/13 km/h
21:00  50%    0/0/100%      2/8     0.24  1.5-2"  7.6°C       5/12 km/h
22:00  50%    0/0/100%      2/8     0.23  1.5-2"  7.6°C       4/10 km/h
23:00  54%    0/8/100%      2/8     0.23  1.5-2"  7.1°C       4/8 km/h
00:00  50%    0/0/100%      2/8     0.23  1.5-2"  6.7°C       4/8 km/h
01:00  50%    0/0/100%      2/8     0.23  1.5-2"  6.0°C       4/7 km/h
02:00  50%    0/0/100%      2/8     0.23  1.5-2"  5.9°C       3/7 km/h
03:00  7%     0/0/15%       2/8     0.23  1.5-2"  5.0°C       1/4 km/h
04:00  2%     0/0/3%        2/8     0.23  1.5-2"  3.3°C       1/1 km/h
05:00  0%     0/0/0%        2/8     0.23  1.5-2"  4.0°C       1/3 km/h

#  NAME      DESCRIPTION                  TYPE               CONSTELLATION  SIZE  FOTO  SCORE  MAX ALT      SKY   PX
1  NGC 281   PacMan Nebula                Emission Nebula    Cassiopeia     35'   1.00  0.24   79° @ 00:52  18.7  1707
2  IC 63     Gamma Cassiopeia Nebula      Emission Nebula    Cassiopeia     20'   1.00  0.24   75° @ 00:59  18.7  976
3  Sh2-173   Phantom of the Opera Nebula  Emission Nebula    Cassiopeia     25'   1.00  0.24   74° @ 00:20  18.7  1220
4  IC 1795   Fishhead Nebula              Emission Nebula    Cassiopeia     30'   1.00  0.24   74° @ 02:26  18.7  1463
5  Abell 85  CTB 1 or Garlic Nebula       Supernova Remnant  Cassiopeia     35'   1.00  0.23   73° @ 23:59  18.7  1707

The output ends with a legend explaining every column of the tables shown and the colours. In short:

  • FOTO: the fraction of the window during which the object meets the altitude, horizon and Moon-distance limits (uptonight's metric).
  • SCORE: imaging quality from 0 to 1, where 1 means a perfect minute for the whole window under a pristine dark sky. It accounts for weather, extinction, sky brightness and, with framing, how well the object fits the frame. This column decides the order.
  • MAX ALT: the object's highest altitude in the window, and when it occurs.
  • SKY: the average sky brightness at the object while it is observable, in V mag/arcsec². Higher is darker: about 22 is pristine and 18–19 is a suburb or a bright Moon. The filter isn't included.
  • PX: the object's size in pixels at the frame's pixel scale (the Origin's by default).

On a colour-capable terminal the output is colour-coded green/yellow/red. Colours are turned off when output is piped, when NO_COLOR is set or when TERM=dumb. CLICOLOR_FORCE=1 turns them on regardless.

Flags
Flag Default Description
-lat, -lon required Location in degrees, north and east positive
-tz from location IANA time zone used for all displayed times. By default it's looked up offline from -lat/-lon, falling back to the system zone
-date tonight Evening to plan, YYYY-MM-DD. Without it, a run after midnight plans the rest of the night in progress
-from, -to dusk, dawn Imaging window in local HH:MM, e.g. -from 22:00 -to 02:00. Times before noon mean the next morning. Always clamped to full astronomical night
-n 20 Number of objects to list
-plan 0 (off) Print a night plan with one target per block of this length, e.g. 2h
-horizon none Local horizon file (see below)
-origin off Framing for the Celestron Origin (1.32° × 0.75°, 1.23″/px): keep only objects that fit the frame and are at least -min-px across, and score how well they fill it
-fov, -scale Origin Framing for another telescope: field of view WxH in degrees up to 180 (e.g. 2.5x1.7) and pixel scale in ″/px between 0.01 and 1000. Either one turns framing on; the one you leave out uses the Origin's value. When both are given, a frame of more than 20,000 px across is rejected, which catches a field typed in arcminutes or a scale from another camera; with only one of them set there is nothing to compare and a field typed in arcminutes goes unnoticed, so check the Frame: line in the header
-min-px 200 With framing: minimum object size in pixels (≈4.1′ on the Origin); must be 0 or more even when framing is off
-filter off A dual- or tri-band nebula filter is in use
-filter-k 0.25 Fraction of sky glow the filter passes: ~0.15 for ≤4 nm bands, ~0.4 for wide ones
-bortle 0 (dark) Bortle class (1–9) of the site, which sets its zenith sky brightness
-sqm unset Measured zenith sky brightness in mag/arcsec², from an SQM meter or the World Atlas 2015 layer on lightpollutionmap.info. More precise than -bortle, which it overrides; the header shows the matching Bortle class. When neither is given and DARKSKYSITES_API_KEY is set, it is looked up on DarkSkySites; a free API key can be requested at darkskysites.com
-extinction auto Atmospheric extinction in magnitudes per airmass. By default it is estimated per hour from the site's elevation and the CAMS aerosol forecast. Setting it fixes the value; 0.2 is used when no estimate is available
-alt-min, -alt-max 30, 80 Altitude limits in degrees
-size-min, -size-max 10, 300 Object size limits in arcminutes, 0 or more; -size-min 0 means no minimum. Framing replaces them with -min-px × scale up to the frame's short side (4.1′–45.0′ on the Origin), since the size is the major axis and its orientation in the frame is unknown, unless you set them explicitly; a -size-max above the short side is an error, because such objects cannot be framed
-list GaryImm Built-in target list (see below)
-targets none Your own uptonight-format targets YAML file; overrides -list
-comet-mag 12 Include comets brighter than this total visual magnitude
-no-comets off Skip comets
-no-weather off Skip the Open-Meteo and 7Timer forecasts
-no-geocode off Skip the reverse geocoding of the location
-no-sqm off Skip the DarkSkySites sky brightness lookup
-version Print the version, commit and build time, then exit
Target lists

All eight uptonight target lists are built in, plus the full Gary Imm compendium. Pick one with -list; names aren't case-sensitive:

List Objects Contents
GaryImm (default) 206 Gary Imm's top astrophotography targets plus the top of his Deep Sky Compendium; sizes and positions checked against the 2026 (6th) edition
GaryImmFull 3145 All objects of Gary Imm's Deep Sky Compendium (2026, 6th edition), including his 0–5 rating (see below)
Messier 110 The Messier catalogue
Herschel400 400 The Astronomical League's Herschel 400
Pensack500 502 Don Pensack's 500 best deep sky objects
OpenNGC 8373 The NGC, from OpenNGC
OpenIC 5589 The IC, from OpenNGC
LBN 1116 Lynds' Catalogue of Bright Nebulae
LDN 1764 Lynds' Catalogue of Dark Nebulae

GaryImmFull.yaml is generated from the compendium spreadsheet by scripts/imm2yaml.py (Python standard library only):

scripts/imm2yaml.py IMM_Compendium_2026.xlsx > internal/catalog/targets/GaryImmFull.yaml

The script checks each decimal RA/Dec against the raw h/m/s and d/m/s cells, and uses the raw value when they disagree. In the 2026 edition this fixed NGC 4526, NGC 5985 and NGC 7094. It also fixes three Dec values typed without seconds (NGC 3813, NGC 3998, NGC 5473), which would otherwise put those Ursa Major galaxies on the celestial equator.

Objects with unknown size (-9999 in the list, or 0.0 in a few LDN entries) count as size 0: they are dropped by the default -size-min, and -size-min 0 keeps them (with no framing penalty, since there is nothing to judge).

The CONSTELLATION column is computed from the official IAU boundaries for every target, comets included, rather than taken from the list. Across all ~18,000 list entries the two agree except for spelling variants ("Ophiucus", "Se1") and five objects. Three of those are list errors, such as R Aquarii listed in Aquila; the other two sit right on a boundary.

Comets

Comets are added to whichever list you use, and ranked with the same scoring:

  • Data: orbital elements come from the Minor Planet Center's CometEls.txt. The file is cached for a day in your user cache directory (~/Library/Caches/astro-recommender on macOS), and a stale copy is used if the download fails.
  • Positions: computed every minute from a two-body orbit (elliptic, parabolic or hyperbolic). Checked against JPL Horizons, they agree to within 0.003–0.02° when MPC and JPL share the same orbit solution.
  • Which comets: those brighter than -comet-mag (default 12) at mid-window, using MPC's magnitude formula m = H + 5·log Δ + 2.5·K·log r. For 12P/Pons-Brooks at its 2024 perihelion this gives 4.42, matching JPL. Comet brightness predictions are uncertain by a magnitude or more, and MPC and JPL sometimes differ by several magnitudes for a given comet.
  • Display: comets show their magnitude and their distances from the Sun (r) and the Earth (Δ) as the description, with - for size and pixels. A coma has no catalogue size, so size limits and framing don't apply to comets.
Night plan

-plan 2h splits the window into 2-hour blocks, plus a shorter last block, and picks one target for each block. It prints the schedule above the ranked list:

TIME         NAME     DESCRIPTION          TYPE               SCORE  PEAK ALT
20:08-22:08  IC 1396  Elephant's Trunk     Dark Nebula        0.67   78° @ 21:37
22:08-00:08  Sh2-132  Lion Nebula          Wolf-Rayet Nebula  0.92   80° @ 22:17
00:08-02:08  NGC 281  PacMan Nebula        Emission Nebula    0.66   79° @ 00:50
02:08-04:08  IC 1795  Fishhead Nebula      Emission Nebula    0.44   74° @ 02:23
04:08-05:22  IC 405   Flaming Star Nebula  Emission Nebula    0.71   79° @ 05:13

First, each block in time order gets the unused target with the best score within that block, with mean altitude breaking ties. Then a local search, modelled on astrogo's SwapOptimizedStrategy, swaps targets between blocks, moves a target into an empty block or brings in an unused one, whenever that raises the total score. The result is a good plan for one night, though not guaranteed to be the best possible. Combine it with -from/-to to plan just part of the night.

Local horizon

-horizon horizon.txt replaces the fixed altitude floor with your real horizon. A minute counts only if the target is above both -alt-min and the horizon in its direction. The file lists azimuth (0 = north, 90 = east) and the minimum visible altitude, in degrees. Altitudes between the listed directions are interpolated, wrapping from 360° back to 0°:

# azimuth altitude
0    25
45   60   # house
90   35
180  20
270  40   # trees

To measure it, stand where the telescope sits and use a compass and an inclinometer app to note the top of each obstruction every 15–30°.

How objects are ranked

  1. Time window. Each minute from astronomical dusk to astronomical dawn is checked. The search runs for 24 hours from the site's solar noon, worked out from its longitude, so polar night is capped at 24 hours and the time zone can't cut the night short. Without -date, a run during the night (after dusk, before dawn) plans only what's left of the night in progress; otherwise it plans the coming evening. If full night never happens (for example at high latitudes in summer), the program says so and lists nothing. -from/-to narrow this to part of the night, but never extend it past dusk or dawn. A window that falls entirely outside the night is an error. Moon illumination is taken at the middle of the window.

  2. Observable minutes, following uptonight's rules:

    • the object is between 30° and 80° altitude (≥ 30° also covers uptonight's airmass ≤ 2 limit), and above the -horizon profile if given
    • it is at least Moon illumination % degrees from the Moon, e.g. 25% lit means 25° away
    • unlike uptonight, the Moon-distance rule is skipped while the Moon is below the horizon
  3. Sky glow sensitivity (k) is the fraction of sky glow that counts against a target:

    • galaxies, reflection nebulae and dark nebulae get k = 1
    • open and globular clusters are bright and compact: k = 0.5
    • with -filter, emission-line targets get k = -filter-k. These are emission nebulae, planetary nebulae, supernova remnants and Wolf-Rayet nebulae, plus a few hydrogen-emitting objects the catalogue mislabels, such as IC 1396 and the Cave Nebula.

    k also scales the Moon-distance limit.

  4. Weather, per minute:

    • clouds (Open-Meteo): low and mid cloud count in full; thin high cloud counts half
    • transparency (7Timer!, 1 best, 8 worst): weight goes from ×1.0 down to ×0.5
    • dew risk: when temperature minus dew point drops from 4 °C to 1 °C, weight goes from ×1.0 down to ×0.7
    • wind gusts: from 20 to 40 km/h, weight goes from ×1.0 down to ×0.5
    • seeing is shown for reference only; it matters little at the Origin's 1.23″/px

    Open-Meteo covers about 3 months back to 2 weeks ahead, and 7Timer about 3 days ahead. Outside those ranges, or if a service is down, the program warns and assumes perfect conditions.

  5. Extinction: the target's light dims by 10^(−0.4 · k · (airmass − 1)), using Pickering's (2002) airmass formula. With k = 0.2, that is about ×0.83 at 30° altitude and ×1.0 near the zenith. Unless -extinction is set, k is estimated for each hour as 0.1066 · e^(−elevation / 7996 m) (scattering by air molecules at 550 nm, less at higher sites) + 0.029 (ozone) + 1.086 · AOD₅₅₀ (aerosols: haze, dust, smoke). The aerosol optical depth (AOD) comes from the Open-Meteo Air Quality API, which relays the CAMS forecast up to about 5 days ahead; hours beyond that use a typical 0.1. The forecast table's EXT column shows k per hour. A dusty or smoky night pushes it up sharply, penalising low targets and spreading moonlight more widely.

  6. Sky brightness: the sky brightness at the target is computed each minute with the Krisciunas & Schaefer (1991) model:

    • the site's moonless zenith brightness: from -sqm, else the typical value for -bortle, else 22.0 mag/arcsec²
    • brightening towards the horizon
    • moonlight scattered towards the target, depending on Moon phase, Moon altitude, target altitude and the angle between Moon and target

    Imaging faint targets is limited by the sky, so the signal-to-noise ratio in a fixed exposure scales as 1/√sky. The weight is min(1, √(B_dark / (k · B))), where B_dark is a pristine 22.0 mag/arcsec² sky. A target 30° from a bright Moon therefore scores much lower than one 120° away, and with a filter, emission targets keep most of their score.

  7. Score = the sum over observable minutes of weather × extinction × sky weight, divided by the window length.

  8. Framing (-origin, -fov or -scale): objects filling 25–80% of the frame's short side score in full (11–36′ on the Origin). Smaller or tighter-fitting objects score less, and an object as large as the short side cannot be framed and is not listed.

  9. Results are sorted by score; mean altitude breaks ties.

Extinction and sky brightness come from published models. The weather ramps, the cluster k and the framing curve are simple heuristics. Treat SCORE as a way to order tonight's options rather than an absolute measure of quality.

Accuracy

The astronomy uses compact published formulas rather than a full ephemeris library. TestSOFA checks them against SOFA (through gofa, a test-only dependency) over 3000 random dates in 2000–2050; the limits it enforces are:

Quantity Formula Difference from SOFA
Sidereal time IAU GMST polynomial < 0.3″
Sun Astronomical Almanac low precision < 1′
Moon Astronomical Almanac low precision (geocentric) < 0.4°
Moon illumination from Sun–Moon elongation < 0.3 percentage points
Target altitude J2000 catalogue positions precessed to date (IAU 1976, Lieske 1977), GMST < 0.3′ against SOFA's full precession-nutation and apparent sidereal time (precession itself within 0.1″)
Earth position (for comets) Sun formula, corrected to J2000 < 0.0003 AU

The Moon's altitude is corrected for its mean horizontal parallax (57′), which otherwise lowers it by up to 1°; its position for the separation rule stays geocentric. Nutation (< 20″) and refraction (about 2′ at 30° altitude) are ignored. All of this is far tighter than the 30° altitude and tens-of-degrees Moon limits need.

Formulas and references

Everything below is implemented directly in Go from the cited source; no astronomy library is used at run time.

Positions and time (internal/astro)

Quantity Formula Source
Sun RA/Dec Mean longitude and anomaly, equation of centre to 2 terms, apparent ecliptic longitude The Astronomical Almanac, "Low-precision formulas for the Sun's coordinates" (section C)
Moon RA/Dec Ecliptic longitude (6 periodic terms) and latitude (4 terms), geocentric The Astronomical Almanac, low-precision Moon formulas (section D)
Obliquity of the ecliptic 23.439° − 0.0000004 n (n = days since J2000) The Astronomical Almanac, section C
Ecliptic → equatorial Rotation by the obliquity Standard (Meeus, Astronomical Algorithms, ch. 13)
Greenwich sidereal time 280.46061837° + 360.98564736629° · n, the linear terms of IAU 1982 GMST Aoki et al. (1982), A&A 105, 359, as given by Meeus eq. 12.4
Precession J2000 → date IAU 1976 angles ζ, z, θ and the three-rotation formula Lieske et al. (1977), A&A 58, 1; Meeus eqs. 21.2–21.4
Altitude and azimuth Spherical triangle from hour angle, declination and latitude Meeus eqs. 13.5–13.6
Angular separation Spherical law of cosines Meeus eq. 17.1
Moon illumination (1 − cos ψ)/2 from the Sun–Moon elongation ψ; phase angle ≈ 180° − ψ Meeus ch. 48
Moon altitude correction Mean horizontal parallax 57′ (0.9507°): alt − 0.9507° · cos alt The Astronomical Almanac; the Moon's distance variation (54′–61′) is ignored
Astronomical twilight Sun's geometric centre below −18° Standard definition (USNO)
Earth heliocentric position (for comets) Negated Sun vector, with general precession (1.3970°/century) removed to return to the J2000 frame Almanac Sun formula; Lieske et al. (1977) precession rate

Comets (internal/comets)

Quantity Formula Source
Elliptic orbits Kepler's equation E − e sin E = M by Newton–Raphson Standard (Meeus ch. 30)
Parabolic orbits Barker's equation, closed form via the cubic Meeus ch. 34
Hyperbolic orbits e sinh H − H = M by Newton–Raphson Standard
Orbit → ecliptic → equatorial Rotation by ω, Ω, i, then by the J2000 obliquity 23.4392911° Meeus ch. 33; MPC elements are J2000 ecliptic
Gaussian gravitational constant k = 0.01720209895 rad/day Gauss (1809), IAU 1976 system of constants
Total magnitude m₁ = H + 5 log₁₀ Δ + 2.5 K log₁₀ r Minor Planet Center magnitude parameters (K = 2.5 n)

Atmosphere and sky (internal/atmos)

Quantity Formula Source
Airmass X = 1 / sin(h + 244 / (165 + 47 h^1.1)) Pickering (2002), DIO 12, 1, §A
Extinction Transmission 10^(−0.4 k (X − 1)) relative to the zenith Standard
Extinction coefficient k Rayleigh 0.1066 · e^(−h / 7996 m) (τ = 0.098 at 550 nm, 8 km scale height) + ozone Chappuis band 0.029 (300 DU) + aerosols 1.086 · AOD₅₅₀ Rayleigh after Hayes & Latham (1975), ApJ 197, 593, consistent with Bucholtz (1995); ozone from the Chappuis cross-section; AOD from CAMS via Open-Meteo. 1.086 = 2.5 log₁₀ e
Surface brightness units B[nL] = 34.08 · e^(20.7233 − 0.92104 V) and its inverse Krisciunas & Schaefer (1991), PASP 103, 1033
Dark-sky brightness vs altitude Zenith brightness × 10^(−0.4 k (X − 1)) · X with the scattering airmass X = (1 − 0.96 sin² Z)^−½ Krisciunas & Schaefer (1991)
Scattered moonlight Scattering function f(ρ) = 10^5.36 (1.06 + cos² ρ) + 10^(6.15 − ρ/40), Moon brightness 10^(−0.4 (3.84 + 0.026 α + 4·10⁻⁹ α⁴)), attenuated by the Moon's airmass and scaled by 1 − 10^(−0.4 k X) Krisciunas & Schaefer (1991)
Bortle class ↔ zenith brightness Mid-points of the SQM ranges usually quoted per class (21.9 … 17.3 mag/arcsec²) Bortle (2001), Sky & Telescope, Feb 2001, with the common SQM mapping
Sky-limited SNR weight min(1, √(B_dark / (k · B))), B_dark = 22.0 mag/arcsec² Sky-limited imaging: SNR ∝ 1/√B

Heuristics (this project's own; see "How objects are ranked"): the weather ramps for cloud, transparency, dew spread and gusts; the sky-glow fractions k for clusters and filtered emission targets; the frame-fill curve (full credit at 25–80% of the short side); and the Moon-distance rule from uptonight.

Constellations (internal/constellation): IAU boundaries (Delporte 1930) at B1875.0 from CDS/VizieR VI/49 (Davenhall & Leggett 1989); the target is precessed to B1875.0 with the IAU 1976 formula and tested by ray casting, following Roman (1987), PASP 99, 695, with the table and test taken from astrogo.

Privacy

The program calls three free services, none of which need an API key: Open-Meteo (weather and air quality), 7Timer and OpenStreetMap Nominatim. With DARKSKYSITES_API_KEY set (and no -sqm/-bortle), it also asks DarkSkySites for the site's sky brightness (free API key on request at darkskysites.com). The comet elements download from the Minor Planet Center sends no location, and the time zone lookup runs offline. Before sending, it rounds your coordinates to two decimals (about 1 km). Reverse geocoding asks only for suburb-level detail. Use -no-weather -no-geocode -no-sqm -no-comets (or leave DARKSKYSITES_API_KEY unset) to run entirely offline.

Credits

  • Planning ideas (airmass weighting, sky-brightness scoring, swap-optimised scheduling) from astrogo by TuSKan (MIT).
  • uptonight by Markus Winkler (MIT): the observability rules and the built-in target lists in internal/catalog/targets/. The default GaryImm.yaml is based on Gary Imm's top astrophotography targets and his Deep Sky Compendium. Ten of its entries were corrected against the 2026 (6th) edition of the Compendium. Seven sizes were plainly wrong; for example the Soul Nebula was listed at 1.8′ instead of 90′. Three positions had been updated in the new edition.
  • GaryImmFull.yaml: Gary Imm's Deep Sky Compendium (2026, 6th edition), data © Gary Imm. The spreadsheet states no redistribution terms.
  • OpenNGC.yaml and OpenIC.yaml derive from OpenNGC by Mattia Verga, licensed CC BY-SA 4.0.
  • Comet orbital elements: IAU Minor Planet Center.
  • Constellation boundaries and lookup from astrogo (MIT), transcribing the IAU boundaries (Delporte 1930) from CDS/VizieR catalog VI/49 (Davenhall & Leggett 1989).
  • Weather and aerosols: Open-Meteo (CC BY 4.0; aerosol data from the Copernicus Atmosphere Monitoring Service) and 7Timer!.
  • Geocoding: Nominatim, data © OpenStreetMap contributors (ODbL).
  • Time zones: tzf (MIT), a Go counterpart of node-geo-tz. Both use timezone-boundary-builder data (ODbL), which is embedded and looked up offline.

Documentation

Overview

Command astro-recommender lists the best deep sky objects for a location, tonight, between the start and end of astronomical night. Scoring follows uptonight (https://github.com/mawinkler/uptonight).

Directories

Path Synopsis
internal
astro
Package astro computes Sun and Moon positions, sidereal time, altitude and azimuth, precession and the astronomical night window from compact published formulas (validated against SOFA, see the README).
Package astro computes Sun and Moon positions, sidereal time, altitude and azimuth, precession and the astronomical night window from compact published formulas (validated against SOFA, see the README).
atmos
Package atmos models the atmosphere for imaging: airmass, extinction and night sky brightness (Krisciunas & Schaefer 1991), with Bortle/SQM darkness.
Package atmos models the atmosphere for imaging: airmass, extinction and night sky brightness (Krisciunas & Schaefer 1991), with Bortle/SQM darkness.
catalog
Package catalog loads deep sky targets: the embedded uptonight lists or an uptonight-format YAML file.
Package catalog loads deep sky targets: the embedded uptonight lists or an uptonight-format YAML file.
comets
Package comets turns Minor Planet Center comet orbital elements into moving targets.
Package comets turns Minor Planet Center comet orbital elements into moving targets.
config
Package config parses and validates the command-line flags.
Package config parses and validates the command-line flags.
constellation
Package constellation finds the IAU constellation containing a position.
Package constellation finds the IAU constellation containing a position.
fetch
Package fetch provides HTTP helpers and a small download cache.
Package fetch provides HTTP helpers and a small download cache.
geocode
Package geocode reverse geocodes a location to an approximate place name (OpenStreetMap Nominatim).
Package geocode reverse geocodes a location to an approximate place name (OpenStreetMap Nominatim).
geotz
Package geotz finds the IANA time zone of a location from its coordinates, offline, using github.com/ringsaturn/tzf (timezone-boundary-builder data, the same source as node-geo-tz).
Package geotz finds the IANA time zone of a location from its coordinates, offline, using github.com/ringsaturn/tzf (timezone-boundary-builder data, the same source as node-geo-tz).
horizon
Package horizon reads a local horizon profile and interpolates it by azimuth.
Package horizon reads a local horizon profile and interpolates it by azimuth.
num
Package num holds numeric checks shared by the parsers of untrusted input.
Package num holds numeric checks shared by the parsers of untrusted input.
output
Package output prints the report: header, forecast table, night plan and ranked targets, with optional ANSI colors.
Package output prints the report: header, forecast table, night plan and ranked targets, with optional ANSI colors.
plan
Package plan splits the observing window into blocks and assigns one target to each.
Package plan splits the observing window into blocks and assigns one target to each.
sanitize
Package sanitize strips terminal control characters from untrusted text.
Package sanitize strips terminal control characters from untrusted text.
scoring
Package scoring evaluates targets minute by minute over the observing window.
Package scoring evaluates targets minute by minute over the observing window.
sqm
Package sqm looks up a location's zenith sky brightness from the DarkSkySites light pollution map (https://www.darkskysites.com/api-access).
Package sqm looks up a location's zenith sky brightness from the DarkSkySites light pollution map (https://www.darkskysites.com/api-access).
weather
Package weather fetches Open-Meteo weather and aerosol forecasts and 7Timer transparency and seeing.
Package weather fetches Open-Meteo weather and aerosol forecasts and 7Timer transparency and seeing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL