Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов

от автора

Как мы сделали сервис, который подбирает спутниковые снимки под уровень воды на гидропосту

Всем привет. Меня зовут Александр Иннокентьев, и уже больше года мы с моим коллегой Павлом Головлевым делаем веб-инструмент для гидрологов под названием «Уровень-Спутник».

Идея проекта родилась из вполне обычной рабочей проблемы. Когда занимаешься русловыми процессами, берегами, поймой, затоплением или просто пытаешься понять, что происходило на реке в конкретный момент, очень быстро упираешься в одну и ту же вещь: снимков много, гидрологических данных тоже много, но связать одно с другим удобно и быстро не так-то просто.

Казалось бы, что сложного: открыл архив спутниковых снимков, нашёл нужную дату и работаешь. На практике всё не так. Один снимок закрыт облаками, другой снят не в тот день, третий вроде хороший, но уровень воды на гидропосту в этот момент совсем не тот, который тебе нужен. А ведь для гидролога это критично: один и тот же участок реки при разных уровнях воды может выглядеть настолько по-разному, что сравнивать такие снимки напрямую иногда просто бессмысленно.

В какой-то момент нам надоело каждый раз собирать это вручную. Так и появился «Уровень-Спутник» — сервис, который помогает подбирать снимки Landsat и Sentinel не просто по дате, а под конкретный уровень воды на гидропосту.

И тут обычно возникает закономерный вопрос: а зачем вообще кому-то подбирать космоснимки именно под уровень воды? Если коротко — затем, что иначе очень легко начать сравнивать несравнимое.

Общий вид сайта

Общий вид сайта

Как зарождался прототип

Когда идея «Уровня-Спутника» только появилась, первым делом я сел делать прототип в Google Earth Engine. Логика была простой: платформа бесплатная, там уже есть спутниковые данные, значит можно быстро собрать рабочую схему и проверить саму идею.

Первый прототип мы делали на одном бассейновом округе. Для тестов брали данные с АИС ГМВО. На этом этапе стало понятно, что сама идея рабочая, но технически всё выглядело довольно тяжело: интерфейс лагал, фильтрации работали медленно, а большое количество обращений к коллекциям просто съедало лимиты GEE. Сейчас, когда квоты Earth Engine стали ещё строже, я особенно ясно понимаю, что решение со временем уйти на другую платформу было правильным.

Дальше нужно было как-то это оптимизировать. И в какой-то момент пришла довольно простая мысль: если вся логика в итоге сводится к поиску снимков по дате, а дата — это связка между спутниковым снимком и уровнем воды на гидропосту, то, возможно, не стоит каждый раз заново фильтровать огромные коллекции изображений.

Так появился отдельный идея предобработки данных с использованием GEE API. Он проходил по постам, обращался к спутниковым коллекциям, отбирал снимки по геометрии конкретного поста и формировал большую таблицу: пост, идентификатор снимка, облачность и несколько вспомогательных параметров.

Таблица получалась огромная, но суть была в другом: дальше в интерфейсе GEE мы уже фильтровали не бесконечные коллекции снимков, а эту заранее подготовленную таблицу, а затем просто вызывали нужный снимок по ID. Нагрузка заметно снижалась, и схема действительно заработала.

В тот момент это казалось почти прорывом. Но довольно быстро стало понятно, что такое решение всё равно остаётся промежуточным.

  • Один бассейновый округ обсчитывался примерно 8-10 часов, и это был ещё не самый крупный случай. А всего таких округов больше двадцати.

  • При такой схеме почти не было нормального масштабирования: каждый новый день, каждый новый пост и любое расширение набора данных означали пересчёт или дозаполнение огромной заготовки.

  • Система получалась слишком хрупкой: если где-то на одном из этапов закрадывалась ошибка, значительную часть работы приходилось переделывать заново.

То есть сама идея уже доказала свою жизнеспособность, но было очевидно, что в таком виде далеко не уедешь.

Страх потерять доступ к данным

Примерно в это же время начали приходить новости, что доступ к данным уровней и расходов воды скоро могут закрыть. И вот тут проект на секунду действительно оказался на грани тупика.

История с получением этих данных вообще получилась почти приключенческой. Я как раз был в командировке — у гидрологов это называется «в полях», хотя значительную часть времени мы проводим не в поле, а на воде. За несколько дней до выезда я начал делать парсер для АИС ГМВО, чтобы в перспективе массово наполнять базу данных для всего проекта.

И вот в один из дней мы под вечер возвращаемся на лодке к точке выгрузки, время что-то около пяти вечера, и во всех чатах одновременно начинает сыпаться одно и то же: портал вот-вот закроют, в 18:00 по Москве точно все, часть данных уже недоступна, срочно сохраняйте всё, что можете.

И я буквально сижу в лодке и с помощью ИИ допиливаю парсер, чтобы он мог массово выкачать всё нужное. Потом забегаю в гостиницу, в спешке пытаюсь всё это развернуть и запустить. С первого раза, конечно, ничего нормально не заводится, но в какой-то момент процесс всё-таки пошёл. И в 17:55 я вижу заветное download successful и наконец выдыхаю.

Сейчас, оглядываясь назад, я понимаю, что это, наверное, был один из самых нервных и одновременно самых важных эпизодов за всю историю проекта.

Это наши "поля"

Это наши «поля»

Поворотный момент: STAC и Microsoft Planetary Computer

Следующим большим поворотом для проекта стали STAC и Microsoft Planetary Computer. На конференции в ИКИ РАН, посвящённой дистанционным методам, нам посоветовали посмотреть именно в эту сторону. И это оказалось очень удачным советом.

Если объяснять совсем по-простому, то STAC — это современный стандарт описания спутниковых данных. Он нужен для того, чтобы сцены из разных архивов и коллекций были не хаотичным набором файлов, а нормальным каталогом, с которым можно работать программно.

А Microsoft Planetary Computer — это платформа, которая даёт доступ к таким каталогам и к самим данным через API. То есть не нужно жить внутри одной замкнутой системы, как в раннем прототипе на Earth Engine. Можно строить свою собственную архитектуру: отдельно хранить гидрологические данные, отдельно быстро искать нужные сцены по метаданным, отдельно подгружать снимки уже по запросу.

Для «Уровня-Спутника» это было очень важное изменение. Мы ушли от модели, где всё держалось на тяжёлом фильтровании коллекций внутри одной платформы, к более гибкой схеме: быстрый запрос к своей базе, поиск подходящих сцен по метаданным и обращение к спутниковым данным уже тогда, когда действительно нужно.

Именно здесь проект начал превращаться из прототипа в систему.

Когда CSV и Excel заканчиваются

Параллельно стало очевидно, что надо переходить к нормальной архитектуре хранения данных. CSV и Excel, конечно, хороши, пока ты что-то быстро проверяешь или собираешь прототип. Но когда у тебя уже десятки миллионов строк наблюдений, это перестаёт быть «табличкой» и превращается в полноценную задачу по организации данных.

Тут стоит честно сказать: я не человек с классическим бэкграундом разработчика. Я скорее самоучка. То есть это уже давно не уровень hello world, но и до образа «сеньор-разработчика» мне очень далеко. С нормальными базами данных до этого проекта я почти не работал, и во всё это тоже приходилось влезать по ходу дела.

Разобраться в базовых принципах проектирования БД, запросах, связях между таблицами и общей логике хранения данных оказалось вполне реально, конечно не без помощи ИИ.

И именно на этом этапе проект получил, наверное, самый заметный прирост в скорости. Если раньше связь «уровень воды — спутниковый снимок» собиралась через тяжёлые обходные схемы, то после перехода к нормальной базе данных запросы начали проходить практически мгновенно — по ощущениям уже за миллисекунды или за считанные секунды.

Что представляет собой проект сейчас

Сейчас «Уровень-Спутник» — это уже не просто набор экспериментов, а живой рабочий сервис.

По своей логике он устроен довольно просто: пользователь выбирает гидропост, задаёт интересующий диапазон уровней воды, период, месяцы, облачность — и получает список подходящих сцен Sentinel-2 и Landsat. Дальше эти сцены можно посмотреть на карте, а нужные данные — выгрузить и проанализировать.

Общая схема теперь такая:

  • В базе лежат гидропосты и многолетние ряды наблюдений.

  • Пользователь задаёт условия отбора.

  • Сервис быстро находит подходящие даты и уровни.

  • Потом уже по этим условиям обращается к каталогу спутниковых сцен через MPC.

  • Пользователь получает не список снимков «где-то рядом», а набор сцен, реально привязанных к гидрологической обстановке.

Небольшой технически блок

Раз уж Хабр всё-таки техническая площадка, совсем без инженерной части не обойтись. Но здесь хочется не уходить в документацию, а коротко объяснить, в чём вообще была ключевая техническая идея.

По сути, проект держится на одной важной связке: гидрологическое наблюдение → дата → спутниковая сцена. То есть центральной сущностью для нас является не просто снимок и не просто гидропост, а их связь через дату и состояние водного объекта в этот момент.

Технически это означает несколько вещей. Во-первых, нужно быстро работать с большим объёмом рядов наблюдений по постам. Во-вторых, нужно уметь искать спутниковые сцены не «вообще по территории», а именно в привязке к конкретному месту и нужному временному окну. В-третьих, нужно отдавать это пользователю быстро, а не в формате «подождите, сейчас мы пять минут фильтруем коллекции».

Ранний прототип решал эту задачу тяжёлым предрасчётом и большими таблицами соответствия. Текущая версия опирается уже на полноценную БД и более нормальную архитектуру запроса: сначала быстро выбирается нужное гидрологическое условие, потом по нему ищутся подходящие сцены, и только затем подгружаются сами спутниковые данные.

Что лежит в основе проекта:

Слой

Что используется

Backend

Python, Flask, Gunicorn

База данных

PostgreSQL, PostGIS, около 28 млн наблюдений

Спутниковые данные

Microsoft Planetary Computer

Клиентская часть

Leaflet.js, Chart.js

Инфраструктура

Docker, nginx, HTTPS

Про домен и ощущение, что вся работа была не зря

Сейчас проект уже работает на арендованном сервере. Он, честно говоря, совсем небольшой, и вычислительных ресурсов у него немного, но даже это для меня уже важный шаг: сервис живёт не только на локальной машине и не только в виде набора скриптов, а как реальный инструмент, который можно открыть в браузере.

И, наверное, отдельно я до сих пор немного радуюсь тому, что у проекта есть свой домен — level-satellite.ru. Для людей из IT, которые постоянно что-то запускают и выкатывают свои продукты, это, возможно, обычная вещь. Но для меня это был почти отдельный эмоциональный рубеж: больше года работы, десятки переделок, сомнений, костылей, новых решений — и вот у этого всего наконец появилось своё настоящее имя и адрес.

Он еще далек от идеала, но живой

Я прекрасно понимаю, что проект ещё далеко не идеален. Я сам вижу, где что-то работает неровно, где интерфейс можно сделать лучше, где какая-то логика пока ещё требует доработки, а где что-то просто не отрезает, не фильтрует или не обрабатывает так, как хотелось бы.

Но для меня здесь важно другое: проект живой. Он не остался папкой с черновиками, не растворился в прототипах и разговорах о том, «как было бы здорово когда-нибудь сделать». Он уже существует и продолжает развиваться.

Если вам откликается такая тема, можно заглянуть на сайт проекта: level-satellite.ru. А если интересно следить за развитием — вот публичный репозиторий: github.com/ruorv/level-satellite-public.

ссылка на оригинал статьи https://habr.com/ru/articles/1022968/