A case study

Tonight

One real night at 48.14° N, and the instrument that decides what to do with it.

Site
48.1374° N · 11.5755° E
Date
20 April 2026 · CEST · UTC+02:00
Astronomical dark
22:11 – 04:12 · 6h 01m
Target
M51 — Whirlpool Galaxy
Transit
00:47 at 89.1°

I · Darkness

Astronomical darkness is a resource, and it is rationed.

The sun has to fall 18° below the horizon before the sky stops glowing. Tonight that happens at 22:11, and it un-happens at 04:12. Six hours and one minute — that is the whole budget.

Stars arrive in order of brightness, because that is the order in which a darkening sky releases them. The limiting magnitude readout is the real one.

“Twilight time never counts as imaging time.”services/scoring — observable-hours rule
Sun altitude
-17.9°

at the moment astronomical darkness begins

Twilight phase
astronomical
Limiting magnitude
5.43

sky brightness 20.44 mag/arcsec²

II · The site

The sky you can actually use is smaller than the sky.

A horizon is not a circle. It is a roofline, a birch, a neighbour’s conifer, and a balcony rail. AstroBrain lets you draw yours — up to 720 points — and then refuses to plan through it.

It also models something no capture software can express: an overhead ceiling. My roof blocks everything above 55° to the south. The exported horizon file stays byte-identical either way.

Horizon profile
720 pts · versioned
Sky brightness
21.0 mag/arcsec²

lorenz-viirs-sqm-v1

Bortle class
approx. 4

labelled approximate

Light-pollution grid
7200 × 3600 @ 0.05°

III · The rig

Then the question narrows to glass.

A 130 mm apochromat at f/7, pulled to 728 mm by a 0.8× reducer, in front of a 26-megapixel APS-C sensor with 3.76 µm pixels. Those five numbers decide most of what follows.

Assembled from 2,831 source-backed components, then frozen as an immutable rig version — so changing your camera next month does not silently rewrite last month’s plan.

Aperture
130 mm
Effective focal length
728 mm

910 × 0.8

Focal ratio
f/5.6
Pixel scale
1.07 ″/px

206.265 × 3.76 ÷ 728

Field of view
1.85° × 1.24°

2·atan(d / 2f)

Resolution
6250 × 4176 px

IV · The verdict

Thirteen hundred candidates. One night. Show your work.

Every other planner hands you a score. AstroBrain hands you the derivation: seven weighted components, twenty-six reason codes, and a confidence label that drops when an input is missing rather than pretending it is not.

Feasibility precedes ranking. A target that never clears your treeline is not a low score — it is not a candidate.

“Do not render black-box scores.”ADR-011 — explainability boundary
Catalog
1,309 objects

OpenNGC-anchored

Score model
score-model-visible-v1
Components
7 weighted, normalised
Minimum altitude
30°
Moon separation floor
45°
Feasibility, then rankingremaining
Catalog—1,309
Never risestarget_never_rises1,204
Behind the treelineblocked_by_horizon1,174
Below 30°altitude_below_minimum846
Outside the dark windowwindow_outside_darkness530
Under 90 minutesobservable_hours_short453
Too close to the Moonmoon_separation_low419
Does not fit the frameframing_fit_out_of_band270
Too faint for this skysurface_brightness_unreachable83
Rankedranked_first1
M51 · why this scorescore-model-visible-v1
Altitude window98 · w 1.0

transits 89.1° at 00:47 · airmass 1.00

Observable hours96 · w 1.0

6h 01m above 30° inside astronomical dark

Moon separation100 · w 0.8

90° from a 16% crescent that sets at 00:53

Framing fit42 · w 0.7

11.2′ in a 111′ frame · under-filled, single panel

Cloud cover86 · w 0.9

8% mean cover · open-meteo, 41 min old

Light pollution71 · w 0.6

SQM 21.0 · 43° from the town glow

Your history60 · w 0.5

never imaged · no logged integration

100 × Σ(wᵢcᵢ) ÷ Σ(wᵢ)82.4

V · The distance

The light in tonight’s frames is older than the species collecting it.

M51 is 23 million light-years away. The photons that will land on the sensor tonight left before the Alps finished rising.

Two galaxies, mid-collision. The small one, NGC 5195, has already passed through the disc of the large one — twice.

Object
M51 · NGC 5194
Constellation
Canes Venatici
Right ascension
13h 29m 53s
Declination
+47° 11′ 43″
Apparent magnitude
8.4
Angular size
11.2 ′

VI · The frame

A galaxy is a shape. A sensor is a rectangle. They have to agree.

Field of view uses the exact 2·atan(d ÷ 2f), not the small-angle shortcut — the shortcut is fine at 2 000 mm and wrong at 200. Rotate the camera and the numbers move with it.

When a target overflows the frame, AstroBrain lays mosaic panels on a proper gnomonic tangent plane. The flat cos(δ) approximation misplaces a panel by 6% of a frame at declination 80° — and a clamped mosaic points somewhere you did not ask for.

Frame
111.0 ′ × 74.1 ′
Sampling
1.07 ″/px
Seeing tonight
2.4 ″

user-entered, not a provider claim

Regime
optimal

inside seeing ÷ 3 … seeing ÷ 2

Target fill
10.1% of frame width
Panels
1 · no mosaic needed

VII · The photon budget

How long should one frame be? There is an actual answer.

Long enough that the sky itself swamps the camera’s read noise, and short enough that the stars do not saturate. Everything between those two walls is arithmetic.

Read noise is charged once per read, as RN², not scaled with exposure time. Most calculators get that wrong, and it is why they recommend twenty-minute subs to people who do not need them.

“Never thousands of nights.”spec 252 — the depth-verdict rewrite
Sky rate
0.39 e⁻/px/s

SQM 20.9 · 130 mm · QE 80%

Read noise
1.5 e⁻
Swamp factor
10 × RN² ÷ sky rate
Sky-limited above
57 s
Chosen sub
180 s

3× the floor · headroom for guiding

SNR per sub
3.5

VIII · The night runs

Signal adds. Noise adds in quadrature. That difference is the entire craft.

One 180-second frame of M51 is an insult. Stack N of them and the signal-to-noise ratio climbs as √N — which is why four hours looks twice as good as one, and sixteen hours looks twice as good as four.

Something crosses frame 61 — a satellite, most likely. Sigma-clipping deletes the streak without deleting the frame, because those pixels disagree with the other ninety-three and the threshold does not care what made them.

Sub length
180 s
Cycle
203 s

180 exposure + 8 download + dither share

Frames written
102
Rejected — cloud
8
Frames kept
94
Integration
4h 42m
Stacked SNR
34

3.5 × √94

Meridian flip
00:47

at transit, 89.1° altitude

IX · Morning

The sky closes in the same order it opened.

Astronomical dark ends at 04:12 and nautical twilight follows at 04:58. The faint stars go first, then everything under third magnitude, then the target. The mount parks itself long before the sun is anywhere near the horizon.

In the morning you drag the FITS files in. AstroBrain reads seven header keys and nothing else — by design — then tells you the truth: four hours forty-two is a first look, and you are eighteen minutes short of calling it solid. Deep is fifteen hours. That is three more nights like this one.

“…and you find that out in PixInsight three weeks later, when two nights will not co-stack.”services/sequence — why the Night Script exists
Planned integration
5h 06m
Actual integration
4h 42m
Median FWHM
2.6 ″
First look — 1.5 h
reached
Solid — 5 h
18 min short
Deep — 15 h
3 more nights
Header keys read
7

allow-list, privacy by design

X · The machine

None of that was an animation.

The sun altitude, the moon phase, the sidereal rotation, the airmass, the sub-exposure length — all of it was computed from the date and the coordinates while you scrolled. Change either one and the night changes with it.

That is also how the product works. AstroBrain is deterministic at runtime: pure functions, no clock reads inside the domain, no random numbers, no model inference. Same inputs, same numbers, forever.

“AI output must not enter deterministic score vectors or acquisition recipes.”ADR-016 — the AI trust boundary
TypeScript
384,580 lines · 1,669 files
Test files
717
Specifications
241
Architecture decisions
38
Domain services
24
Runtime
Cloudflare Workers · Neon Postgres

Determinism

no Date.now, no Math.random

Domain services are pure functions. The same inputs produce the same numbers, permanently — which is the only way a saved plan can still be true in six months.

Provenance

every number carries its model id

skyflux-calibrated-v1, lorenz-viirs-sqm-v1, score-model-visible-v1, recipe-model-practical-v3. Versions are minted beside old ones, never mutated in place.

Honesty

missing is a value

No provider seeing or transparency figure is shown, because the provider does not measure them. A blank with a reason beats a number with none.

Execution

62 emittable N.I.N.A. entities

The plan compiles to a real Advanced Sequencer file, checked by 18 preflight rules in under 200 ms, and the telescope runs it unattended.

The AI boundary

built with it, does not run on it

AstroBrain was written with heavy model assistance across 1,416 commits. Not one inference happens at runtime. Every figure on screen is physics with a citation.

Enter

AstroBrain

A planning instrument for deep-sky astrophotography. Your site, your horizon, your rig, tonight’s sky — turned into one decision you can audit, and a sequence file your telescope will actually run.

Private beta. The planner runs in the browser against a real ephemeris.