Skip to main content
HARP

HARP

image the sky your balcony can actually see

Horizon-Aware Recommender and Planner

A CLI planner for deep-sky astrophotography sessions. Given a date, a site, your telescope + camera, the real horizon of your spot and the Moon, HARP ranks the targets you can actually image tonight — usable windows, Moon impact, and mosaic framing tailored to your rig.

Version CI Python GitHub issues

License: GPL v3 License: BSD-2 License: BSD-3 License: MIT

🧱 Horizon-aware visibility
Measure your site's obstructions once as an azimuth-dependent mask (.hrz, N.I.N.A.-compatible). A target counts as observable only when its altitude clears the ridge/wall in its own direction — not against an idealized flat horizon. Horizon guide
⏱️ Continuous imaging windows
Per target: total usable hours during astronomical darkness plus the longest continuous run before it enters a blocked sector — the number you actually size exposures and mosaic panels on. Reading the output
🏆 Desirability ranking
Every target gets a 0-100 score: a weighted geometric mean of continuous window, total hours, peak altitude (inverse-airmass), Moon verdict, field-of-view fill, intrinsic prominence, and sky contrast — so one hopeless factor sinks a target instead of averaging away. --sort hours restores the classic order.
🌙 Moon impact model
Phase and separation folded into a per-target verdict — none, ok(NB), low/med/high — with narrowband auto-derived from the object type: planetaries, supernova remnants and HII regions shrug at a Moon that ruins broadband RGB.
🖼️ Mosaic framing & panel coordinates
Your focal length + sensor decide 1 frame or mosaic NxM; harp mosaic then emits the actual per-panel RA/Dec centers (overlap-aware, position-angle rotated, correct at any declination) — plus single-frame crop suggestions for the monsters. Mosaic guide
🎯 N.I.N.A. integration
The same .hrz horizon drives both tools, and --nina exports ranked targets or mosaic panels as CSVs N.I.N.A.'s sequencer imports directly — verified against N.I.N.A.'s actual parser source. Plan in HARP, shoot in N.I.N.A., retype nothing. N.I.N.A. guide
🔭 Offline catalogues + your own
Full Messier/NGC/IC via pyongc (--catalogs M,NGC,IC) with magnitude-less emission nebulae kept (ranked by size, not magnitude), the 313 Sharpless H II regions with their measured sizes correcting OpenNGC's under-sized nebulae (the Heart is 150' not 60'), and a user targets file that overrides everything (--targets). Cross-identification dedup: M42 and NGC1976 are one object, M43 stays its own. No network at run time.
📈 Table, CSV, charts, links
A ranked terminal table, a CSV for your session log — each target with an informative web link (SIMBAD, Wikipedia, AstroBin, or Aladin, built offline) — altitude charts with the horizon band overlaid, and harp info TARGET for details on demand.
🪐 Solar System targets
The Moon and the eight planets are ranked alongside deep-sky objects (on by default, fully offline) — position and apparent disk recomputed for every step of the night, since they move. Moon-impact and mosaic columns show n/a/planetary; N.I.N.A. exports get a dusk snapshot. Major satellites are an online opt-in (--ss-moons). Solar System guide
🏷️ Target classification
Every target carries its nature — nebula, galaxy, cluster, planetary, star, planet, moon, sun — surfaced in the table, CSV and JSON, and filterable: --filter planet, --filter galaxy,cluster. Note planetary (planetary nebula) stays distinct from planet. Filtering guide
🌆 Light-pollution aware
Declare your sky (--bortle 6, or a measured --sqm) and ranking switches from magnitude to contrast: surface brightness against the sky background. That is why M57 (mag 8.8, but 17.8/arcsec²) is a city classic while M101 (mag 7.9 — brighter! — but 23.8/arcsec²) drowns. Narrowband targets barely degrade, because a dual-band filter rejects broadband glow; aperture nudges gently. Declare nothing and the term is exactly neutral. Sky quality guide
🧭 Polar alignment in twilight
The Android app rough-aligns the mount before Polaris is visible: strap the phone to the tube and it gives live azimuth/altitude bolt corrections onto the refracted pole, with a bullseye whose inner ring is a polar-scope field. Honest about its ±1-2° magnetometer limit — which is exactly what a 5-8° polar scope needs. Refine afterwards with N.I.N.A. TPPA. Polar alignment guide
🗓️ When, not just what
harp when M51 --days 30 inverts the question: instead of ranking targets for tonight, it ranks the coming nights for one target. Same desirability score, so "best" means the same thing in both. For a galaxy the top nights cluster around new Moon; for a narrowband target a flat month is the honest answer, and the ranking falls back to the longest continuous window. ~2 s for a month. Scheduling guide
📓 Observation log
harp log add M42 records what you actually shot — subs, exposure, filter, notes — and harp log list totals it per target ("M42: 8h 20m over 2 sessions"). Integration time, not prose, because that is the question imagers ask. Plain hand-editable YAML beside your sites config; M42 and M 42 are matched as one object. The Android app writes the same file from a log action on each plan row, and shows the integration already banked on a target. Log guide
🐍 Stable Python API
harp plan/info/mosaic --json emit machine-readable output, and harp.api is the supported import surface for scripts and frontends — planning, targets, optics, horizons, saved sites, sky quality, the observation log and polar geometry. Breaking changes bump API_VERSION; the Android app rides the same surface, which is what stops it drifting from the CLI. Scripting guide

Full documentation — installation, usage, horizon measuring, configuration


What HARP does

harp plan                                    # tonight, default site/optics from config
harp plan 2026-08-15 --site balcony --optics newton800
harp plan --catalogs M,NGC,IC --targets my_targets.yaml   # full catalog + your objects
harp plan --filter planet                    # planets only (Moon + planets are on by default)
harp plan --no-solar-system                  # deep-sky only, no Moon/planets
harp plan --nina tonight.csv                 # export ranked targets for N.I.N.A.
harp mosaic IC1396 --pa 30 --nina panels.csv # per-panel coords -> N.I.N.A. sequencer
harp list                                    # sites and optics defined in the config
harp horizon points.yaml -o balcony.hrz      # measured vertices -> .hrz horizon file
=== Night 2026-08-15 | Castelli Balcony 41.7380,12.8899 ===
Astronomical darkness: 21:53 -> 04:32 local
Moon: ~12% illuminated  |  above horizon: below horizon all night
Setup: 800 mm + custom 23.5x15.7
Field of view: 101' x 67'  |  horizon: balcony.hrz

 # object                 score kind      const   hrs cont       window altMx   az moonSep   Moon  frame
--------------------------------------------------------------------------------------------------------
 1 NGC281 Pacman             99 Nebula    Cas     6.7  6.7  21:53-04:28    75    0     127   none  1 frame
 2 NGC7380 Wizard            99 Nebula    Cep     5.2  5.2  21:53-03:03    73    0     124   none  1 frame
 3 NGC1039                   99 Open Clus Per     6.7  6.7  21:53-04:28    71   78     128   none  1 frame
 4 IC59/63 Ghost of Cas      99 Nebula    Cas     6.7  6.7  21:53-04:28    71  360     122   none  1 frame
 5 Sh2-155 Cave              98 Nebula    Cep     5.8  5.8  21:53-03:38    69    0     121   none  1 frame

The Moon and planets are ranked in the same table (kind Planet/Moon, Moon verdict n/a, frame planetary) — on this night Uranus, Saturn, Mars and Neptune land further down the list; --filter planet isolates them, --no-solar-system drops them.

Altitude charts

The typical flow: measure the horizon once → generate the .hrz → load it in N.I.N.A. and in HARP → plan the night → export the ranked targets (or the mosaic panels) straight into N.I.N.A.'s sequencer. See examples/ for a working config, horizon file, and sample outputs.

The name

A harp is the celestial Lyre — the constellation Lyra, home of Vega and the Ring Nebula. And the acronym leads with the input most planners ignore: your horizon.

Installation

pip install harp-astro

The distribution is harp-astro (the bare PyPI name is squatted by an empty project; a PEP 541 request is pending) — the installed package and the CLI command are plain harp.

From source:

git clone https://github.com/szaghi/harp
cd harp
make dev

Configuration

Sites (position + .hrz + timezone) and optical setups (focal + sensor) live in sites.yaml, searched in the current directory and ~/.config/harp/. Precedence: CLI option > config value > built-in default. Details in the usage guide.

Android app (experimental)

An Android frontend lives in android/: the same Python core, embedded on-device via Chaquopy, so the app and the CLI cannot drift apart. Five tabs, all working offline:

  • Home — a dashboard laid out as a mini solar system: tonight's darkness window and Moon on the Sun, the other tabs as planets carrying their status.
  • Horizon — the wizard that measures your skyline with the phone's sensors: true-north azimuths computed on-device (built-in World Magnetic Model, no manual declination), tap-to-record vertices, .hrz export.
  • Plan — the full ranking on-device, with filter chips by target class. Each row logs a session, shows the integration already banked on that target, and can rank the coming nights for it.
  • Align — a compass rose plus a polar-alignment assistant that gives live bolt corrections while the phone is fixed to the mount.
  • Settings — rig, planning thresholds, catalogues, seven indoor themes, a red night-vision mode, and the observation-log export.

Saved sites and the observation log use the CLI's exact layout (sites.yaml

  • one .hrz per site, plus observations.yaml), so the directory can be copied to a desktop ~/.config/harp/ and used unchanged.

Two ways to get an APK: CI (every push builds the harp-debug-apk artifact in the Android workflow — zero local setup) or a local build for the fast bugfix loop (gradle -p android :app:assembleDebug, headless toolchain, no Android Studio). Setup commands, phone transfer (HTTP or wireless adb), and the device test checklist: android/README.md.

Scripting/frontend note: harp plan --json, harp info --json, and harp mosaic --json emit machine-readable output over the stable harp.api surface.

Development

make dev     # editable install with dev extras into .venv
make test    # pytest with coverage
make lint    # ruff check + format check (read-only)
make fmt     # ruff auto-fix + format

Releases: ./release.sh --major|--minor|--patch|X.Y.Z (trunk model on main; tag push triggers CI → PyPI).

Authors

Stefano Zaghi (@szaghi)

HPC/CFD researcher by day, balcony astrophotographer by night. Owns a Newton 200/800 f/4 and a balcony whose entire southern hemisphere is a wall. Measured the horizon with a phone compass while fending off a magnetized railing, then wrote a planner rather than accept that M8 belongs to the neighbours.

Claude (Anthropic)

Large language model, second author, zero telescopes. Has never seen the night sky — or anything else — yet computed where the Moon would be at 03:46 and was right. Refactored the whole toolkit between dusk and dawn, no coffee involved; accepts payment in tokens and byte-identical CSVs.

License

Multi-licensed under GPL-3.0-or-later, BSD-2-Clause, BSD-3-Clause, and MIT — choose the one that fits your use. See licensing/.

Metadata

Release files for harp-astro 0.3.3

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

Source distribution (sdist)

Source distribution for harp-astro 0.3.3
File Size Uploaded
harp_astro-0.3.3.tar.gz 116.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for harp-astro 0.3.3
File Interpreter ABI Platform
harp_astro-0.3.3-py3-none-any.whl Python 3 none any Details

Total release size: 208.5 kB

Release files / harp_astro-0.3.3.tar.gz

Download URL harp_astro-0.3.3.tar.gz
Size 116.4 kB
Tags Source
SHA-256 checksum
How to use checksums
6dc6f97b764d6dd70686ac3474585199b9b7622a92ac3a93626839848bc6e84f
BLAKE2b-256 checksum
How to use checksums
0a9fdd559a8abb5d886b8feb78f823d459710b018d1476d644b51b894949f249
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.

Transparency log

Release files / harp_astro-0.3.3-py3-none-any.whl

Download URL harp_astro-0.3.3-py3-none-any.whl
Size 92.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7a89cfe89f35444b0f4102488df1f73ccd8211630f4633cf86ee20b8657d997b
BLAKE2b-256 checksum
How to use checksums
f17177eb69b9fc3a07872b8712c5d6d00f6b55a5cc3473781ddb5e40efbd96c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.5

2 release files

0.3.4

2 release files

This release

0.3.3 This release

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.5

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