Прогноз для астронома: модели и расчёты «Астросферума».Forecast for astronomers: models and calculations in Astrosferum.
Как численный прогноз погоды превращается в почасовую оценку облаков, состояния атмосферы и пригодности ночи для наблюдений.How numerical weather prediction becomes an hourly view of clouds, atmospheric stability and observing conditions.
В обычном прогнозе погоды часто хватает одной строки: облачность, осадки, ветер у земли. Для телескопа этого мало. Тонкие верхние облака и плотная облачность у горизонта мешают по-разному, а спокойный воздух рядом с наблюдателем ничего не говорит о сильном потоке на высоте десяти километров.
С этого и начался «Астросферум». Одного показателя оказалось мало: на графике должны быть и общая оценка ночи, и конкретная причина, которая мешает наблюдению в выбранный час. Исходный цикл погодной модели при этом сохраняется вместе с результатом.
01МодельICON-EU или ICON Global
02ПоляGRIB2, уровни атмосферы
03Расчётоблака, ветер, турбулентность
04Результатпочасовые графики
Сначала — подходящая модель
Внутри европейской области служба использует ICON-EU с шагом сетки около семи километров. За её пределами берётся всемирная ICON Global с более крупной сеткой. Все величины для одного прогноза приходят из одной модели: приземная погода, облака и высотный профиль не смешиваются между разными источниками.
Новый цикл становится рабочим только после проверки полноты. Если загрузка оборвалась, ссылка current не меняется и запросы продолжают читать предыдущий завершённый цикл.
Один процесс, несколько независимых контуров
Рабочая служба — один исполняемый файл на Go и один основной контейнер. Внутри него живут планировщик обновления моделей, общий обработчик прогноза, расчёты, отрисовка и два независимых опросчика Telegram и VK. Адаптеры платформ не знают друг о друге: временный сбой одного API не останавливает получение моделей и вторую платформу.
Процессы собраны в одном контейнере, но разделены по пакетам. Адаптеры отвечают за доставку; слой приложения — за команды, очередь и кэш; пакеты модели получают GRIB2; расчётные пакеты содержат физику; отрисовка работает с готовыми рядами и не обращается к сети. Для одного экземпляра этого достаточно без отдельного брокера, Redis и службы построения изображений.
Новый цикл публикуется целиком
Планировщик проверяет DWD при старте и затем раз в 15 минут. Файлы нового цикла сначала попадают в отдельный каталог incoming: загрузка идёт во временные имена, после чего проверяются размер, поля, уровни, сроки, чтение ecCodes и SHA-256. Только полностью собранный набор переносится в runs, а ссылка current меняется одной атомарной операцией.
Пока идёт загрузка, запросы продолжают читать предыдущий полный цикл. Неполные данные не могут случайно стать рабочими. Хранятся два опубликованных цикла; временные каталоги, старые точечные кэши и готовые изображения очищаются по ограниченным правилам. Синхронизация не начинается, если на диске не осталось заданного запаса.
Что извлекается из GRIB2
Для заданных координат выбирается ближайший узел сетки. Из приземных полей берутся температура, влажность, осадки, видимость и ветер. Из слоёв атмосферы — давление, температура, составляющие ветра, облачная вода и лёд, высота слоёв и модельная энергия турбулентности.
Облачная преграда, туман, осадки, ветер и оптическая турбулентность рассчитываются отдельно. На графике поэтому видно, что испортило конкретный час: плотные нижние облака, сильный сдвиг ветра на высоте или осадки, при которых наблюдение теряет смысл.
Запрос пользователя ничего не скачивает
Координаты проходят проверку, для них определяется часовой пояс, затем маршрутизатор выбирает ICON-EU или ICON Global. Внутри европейского покрытия используется ближайшая ячейка ICON-EU; для всемирной модели CDO привязывает координаты к нативной треугольной сетке DWD. Приземные поля, облака и вертикальный профиль всегда берутся из одного цикла одной модели.
Сначала проверяется комплект готовых графиков, затем точечный кэш на диске и ограниченный кэш в памяти. Совпавшие одновременные запросы объединяются, а общая очередь расчётов не позволяет Telegram и VK одновременно занять все процессы ecCodes/CDO. Холодный запрос выполняет извлечение и расчёт; повторный обычно ограничивается чтением готового набора и отправкой семи PNG.
Одна оценка — не весь прогноз
Общий индекс пригодности от 1 до 10 удобен для первого взгляда, но рядом всегда остаются исходные причины. Потеря качества распределяется между ними, а не прячется внутри итогового числа. Отдельно строятся облачность по высоте, скорость и сдвиг ветра, оценка качества изображения, события Солнца, Луны, Юпитера и Сатурна.
«Астросферум» не измеряет небо над площадкой. Это расчёт по конкретному циклу модели; на графиках отдельно отмечено, где точность такой оценки ограничена.
Число, связанное с размыванием изображения атмосферой, остаётся модельной оценкой. Локальный рельеф, нагретая крыша, купол телескопа и облако меньше шага сетки могут изменить реальную картину. Для абсолютной калибровки нужны наблюдения и специализированные приборы, а не ещё один коэффициент в программе.
«Горизонт»: восемь направлений и 73 часа
Прогноз над площадкой не показывает, что встретит луч зрения у горизонта: в каждом азимуте он проходит через свой участок атмосферы. Поэтому «Горизонт» рассчитывает условия отдельно по восьми направлениям для объекта на геометрической высоте 10°. Расчёт повторяется для 73 почасовых сроков f000…f072 одного неизменяемого цикла ICON-EU.
Для каждого азимута строится прямой луч на сферической Земле от модельной высоты наблюдателя до 22,3 км. На уровне моря длина такого пути около 122 км. Он разбивается по наземному расстоянию шагом не более 500 м — примерно на 240 сегментов в каждом направлении. Высота точки луча вычисляется из его длины s, радиуса Земли R, высоты площадки h₀ и угла e:
h(s) = √((R + h₀)² + s² + 2(R + h₀)s·sin e) − R
Средняя точка каждого сегмента переводится в широту и долготу по большому кругу и сопоставляется с ячейкой ICON-EU. Поля поверхности и нативных слоёв доступны каждый час. Исходные U/V/T/Z на изобарических уровнях приходят раз в три часа: между сроками интерполируются именно они, а нелинейные величины — профиль Cn², сиинг, время когерентности и итоговый индекс — каждый час рассчитываются заново.
Вдоль луча суммируются два момента турбулентности. Первый задаёт модельное размытие изображения, второй учитывает поперечную к лучу скорость ветра и определяет время когерентности:
JH = Σ Cn² · ΔsJV,H = Σ Cn² · V⊥5/3 · Δs
Поперечный ветер нельзя взять одной разностью азимутов. Направление луча фиксируется в земной системе координат, а в каждой точке заново проецируется в локальный базис «восток — север — вверх». Так учитываются изгиб большого круга и изменение локальной вертикали. Вертикальная скорость в открытых полях отсутствует и принимается нулевой — это явно записанное ограничение.
Облака, рельеф и качество входов
На высоте каждого сегмента выбираются давление, температура, облачная вода и лёд, покрытие облаками и границы слоёв HHL. Путь конденсата переводится в оптическую толщину; повторные точки одной модельной ячейки группируются, чтобы шаг 500 м не учитывал одно покрытие много раз. Отдельно проверяется, не проходит ли луч ниже модельной поверхности HHL. Это грубый рельеф сетки около семи километров, а не локальная линия горизонта.
Туман берётся в ячейке наблюдателя и одинаков для всех направлений: сетка не позволяет честно восстановить локальную стену тумана по азимуту. Состояние дня, сумерек и ночи влияет только на фон графика. Луна, засветка, атмосферная рефракция и оборудование пользователя в этот расчёт не входят.
Итоговая ячейка показывает оценку 1–10, основной ограничитель и полоску качества данных. Эта полоска — не вероятность удачной съёмки: она учитывает полноту пути, срок прогноза и доступность профилей. Её верхняя граница намеренно ограничена, поскольку HHL не заменяет цифровую модель рельефа и съёмку реального горизонта.
Почему расчёт вынесен в отдельную очередь
Один запуск обрабатывает восемь направлений, десятки тысяч сегментов и полный почасовой период. Чтобы такой расчёт не задерживал обычный прогноз, у «Горизонта» есть собственная ограниченная очередь, отдельный предел процессов CDO и атомарный кэш. Одинаковые задачи объединяются, а перед извлечением, после расчёта и непосредственно перед отправкой снова проверяется идентификатор текущего цикла. Если модель успела смениться, старое изображение пользователю не отправляется.
Как сохраняется воспроизводимость
На каждом графике указаны источник, модель, время исходного цикла, сетка, часовой пояс и версии расчёта и отрисовки. Идентификатор цикла входит в ключи кэша, поэтому после публикации нового цикла старые производные данные больше не подходят по ключу. Для повторения результата нужны тот же цикл, конфигурация без секретов и соответствующая ревизия кода.
PostgreSQL хранит сохранённые точки и ограниченную сводную статистику, но не модельные поля и не очередь заданий. Точные несохранённые координаты могут временно оказаться только внутри ограниченного кэша изображений без идентификатора пользователя. В журнал не попадают токены, тексты сообщений и полные координаты.
Как система ведёт себя при сбоях
Недоступность DWD оставляет в работе последний полный цикл с явным предупреждением о возрасте. Ошибка GEOS-CF убирает необязательную оценку в полосе Johnson V, но не ломает основной прогноз ICON. Если не построился один график, отправляются остальные, а сбой сообщается после всех попыток. Telegram и VK перезапускаются независимо; публичного входящего порта у приложения нет.
Перед выпуском проходят тесты расчётных формул, границ сетки, неполных циклов, кэшей и очередей, а также реальные контрольные построения. Для «Горизонта» отдельно проверяются сферические траектории, линия перемены даты, околополярные точки, проекция ветра, облачное замыкание, грубый рельеф и отсутствие функции у ICON Global.
A conventional weather forecast can often be reduced to cloud cover, precipitation and surface wind. A telescope needs more context. Thin high cloud and dense cloud near the horizon cause different problems, while calm air at the observing site says little about a strong flow ten kilometres above it.
That was the starting point for Astrosferum. One value was not enough: the chart had to show both the overall outlook and the specific reason that limits observing at a given hour. The source model run is kept with the result.
01ModelICON-EU or ICON Global
02FieldsGRIB2, atmospheric levels
03Calculationcloud, wind, turbulence
04Resulthourly charts
Choosing one coherent model
Within the European domain, the service uses ICON-EU at roughly seven-kilometre grid spacing. Outside that domain it uses the coarser global ICON model. Every value in one forecast comes from the same model, so surface weather, cloud fields and the vertical profile are not mixed across unrelated sources.
A new model run becomes active only after a completeness check. If a download is interrupted, the current link is left unchanged and requests continue to use the previous complete run.
One process with several independent paths
The production service is one Go executable in one main container. It contains the model scheduler, shared forecast handler, calculations, rendering, and independent Telegram and VK pollers. The platform adapters do not depend on each other: a temporary failure of one API does not stop model updates or the other platform.
The processes share one container but remain separated by package. Adapters handle delivery; the application layer owns commands, queues and caches; model packages acquire GRIB2; forecast packages own the calculations; and rendering receives finished series without network access. One running instance needs no external broker, Redis or separate image service.
A model run is published as a whole
The scheduler checks DWD at startup and every 15 minutes. Files for a new run first enter a dedicated incoming directory under temporary names. Size, fields, levels, valid times, ecCodes readability and SHA-256 are checked before the run moves to runs and the current link changes in one atomic operation.
Requests keep reading the previous complete run while a download is in progress. Partial data cannot become current by accident. Two published runs are retained; staging directories, old point caches and rendered images have explicit limits. Synchronisation does not begin when free disk space falls below the configured reserve.
What is extracted from GRIB2
The nearest model grid point is selected for the requested coordinates. Surface fields provide temperature, humidity, precipitation, visibility and wind. Atmospheric layers provide pressure, temperature, wind components, cloud water and ice, layer heights and model turbulent kinetic energy.
Cloud obstruction, fog, precipitation, wind and optical turbulence are calculated separately. The chart therefore shows what spoiled a given hour: dense low cloud, strong shear aloft or precipitation that makes practical observing pointless.
A user request downloads nothing
Coordinates are validated and resolved to a time zone before the router selects ICON-EU or ICON Global. The nearest regular ICON-EU cell is used inside its domain; for the global model, CDO maps the location onto DWD's native triangular grid. Surface fields, cloud layers and the vertical profile always come from one provider and one run.
The request checks the rendered bundle first, followed by the disk point cache and a bounded in-memory cache. Concurrent misses for the same cell are combined, while a shared forecast queue prevents Telegram and VK from occupying every ecCodes/CDO process at once. A cold request extracts and computes the data; a repeated request normally reads and delivers the existing seven PNG files.
One score is not the whole forecast
The overall 1–10 suitability score is useful for a quick scan, but the underlying reasons remain visible. Losses are attributed to individual factors instead of being hidden inside the final number. Separate charts cover cloud by height, wind speed and shear, image-quality estimates, and events for the Sun, Moon, Jupiter and Saturn.
Astrosferum does not measure the sky above an observing site. It is a calculation based on a specific model run, and the charts mark where that estimate is limited.
The atmospheric image-blur value remains a model-derived estimate. Local terrain, a warm roof, a telescope dome or cloud smaller than the model grid can change real conditions. Absolute calibration requires observations and dedicated instruments, not another tuning constant.
Horizon: eight directions over 73 hours
A forecast above the site does not show what a low line of sight crosses near the horizon: each azimuth passes through a different part of the atmosphere. Horizon therefore calculates eight directions separately for a target at a geometric elevation of 10°. The calculation is repeated across 73 hourly steps f000…f072 from one immutable ICON-EU run.
Each azimuth starts as a straight ray over a spherical Earth, from the model surface elevation to 22.3 km. At sea level that path is about 122 km long. Ground-distance boundaries are no more than 500 metres apart, producing roughly 240 segments per direction. Ray height follows from the path length s, Earth radius R, site elevation h₀ and elevation angle e:
h(s) = √((R + h₀)² + s² + 2(R + h₀)s·sin e) − R
The midpoint of every segment is converted to latitude and longitude along a great-circle path and matched to an ICON-EU cell. Surface and native-level data are hourly. Pressure-level U/V/T/Z arrives every three hours: those input variables are interpolated inside one run, then nonlinear quantities—Cn², seeing, coherence time and the directional score—are recomputed for every hour.
Two turbulence moments are accumulated along the line of sight. The first determines model-derived image blur; the second uses wind transverse to the ray and determines coherence time:
JH = Σ Cn² · ΔsJV,H = Σ Cn² · V⊥5/3 · Δs
Transverse wind cannot be reduced to one azimuth difference. The ray direction is fixed in Earth-centred coordinates and projected into the local east–north–up basis at every midpoint. This accounts for the great-circle turn and changing local vertical. Public inputs contain horizontal wind only, so vertical velocity is set to zero as an explicit limitation.
Cloud, terrain and input quality
Pressure, temperature, cloud water and ice, cloud fraction and HHL layer boundaries are sampled at each ray height. Condensate path becomes optical depth; repeated points in the same model cell are grouped so a 500-metre integration step does not count one cloud fraction repeatedly. A separate test checks whether the ray falls below the HHL model surface. This is terrain averaged over a roughly seven-kilometre cell, not a surveyed local skyline.
Fog is classified in the observer's cell and is therefore common to all directions: the grid cannot honestly resolve a nearby directional fog bank. Day, twilight and night change only the chart background. The Moon, light pollution, atmospheric refraction and the observer's equipment are outside this calculation.
Every output cell carries a 1–10 score, the main limiting factor and a data-quality strip. That strip is not the probability of a successful exposure: it records path completeness, forecast lead time and profile availability. Its upper bound is deliberately capped because HHL cannot replace a local digital terrain model or a measured skyline.
Why Horizon has its own queue
One run covers eight directions, tens of thousands of segments and a full hourly period. To keep that work from delaying a normal forecast, Horizon has a separate bounded queue, its own CDO process limit and an atomic cache. Identical jobs are combined, while the current run ID is checked before extraction, after calculation and immediately before delivery. If the model run changed, the stale image is not sent.
Keeping results reproducible
Every chart records the source, model, base time, grid, time zone, calculation version and renderer version. The run ID is part of each cache key, so derived data from an older run no longer match after a new run is published. Reproducing a result requires the same model run, non-secret configuration and matching source revision.
PostgreSQL stores saved locations and bounded aggregate statistics, not model fields or a job queue. Exact unsaved coordinates may temporarily exist only inside a limited image cache without a user identifier. Tokens, message text and complete coordinates are not written to application logs.
Behaviour under failure
If DWD is unavailable, the last complete run remains active and its age is shown explicitly. A GEOS-CF failure removes the optional Johnson V estimate without breaking the main ICON forecast. If one chart fails, the others are delivered before the error is reported. Telegram and VK supervisors restart independently, and the application exposes no public listening port.
Releases cover calculation formulas, grid boundaries, incomplete runs, caches and queues, followed by live reference renders. Horizon adds tests for spherical paths, the date line, near-polar coordinates, wind projection, cloud closure, coarse terrain and the deliberate absence of the feature for ICON Global.
Демонстрация полного пути данных: публикация проверенного цикла ICON, выбор модели и точки, расчёт, построение графиков и независимая доставка в Telegram и VK.The complete data path: publishing a validated ICON run, selecting the provider and point, calculation, chart rendering and independent delivery to Telegram and VK.
Фактический результатActual output
Что получает наблюдатель.What the observer receives.
Пример построен для Плавска по одному сохранённому циклу ICON-EU. Это датированный результат из репозитория, а не текущий прогноз.This Plavsk example was rendered from one preserved ICON-EU run. It is a dated repository artifact, not a current forecast.
01Почасовая погодаHourly weatherОблака по ярусам, видимость, осадки, ветер и события светил на одной временной шкале.Cloud layers, visibility, precipitation, wind and astronomical events on one timeline.02Общий индекс и причиныOverall score and causesСохранившаяся пригодность и вклад турбулентности, облаков, ветра, тумана и осадков.Remaining suitability and the contributions of turbulence, cloud, wind, fog and precipitation.03Облачная преградаCloud obstructionВидно, в каком слое и в какой час возникает оптически значимая облачность.Shows the layer and hour in which optically significant cloud appears.04«Горизонт»HorizonСравнение восьми азимутов на 10° для каждого часа одного 72-часового периода.Eight azimuths at 10° compared for every hour in one 72-hour period.
ПродолжитьContinue
К профилю и другим проектам.Back to the profile and other work.