Универсальный пакет для синтеза изображений srhimages
srhimages
ПрограммаСибирский радиогелиограф (СРГ) каждый день записывает огромные объёмы данных.
Чтобы получить готовые радиокарты Солнца в радиодиапазоне, сырые данные нужно откалибровать,
собрать воедино из функций видности на UV-плоскости, «нарисовать» — синтезировать изображение
с помощью обратного Фурье-преобразования и вычистить боковые лепестки диаграммы направленности
алгоритмом CLEAN.
Пакет srhimages предоставляетберёт функциина длясебя синтезавсю радиоизображенийэту рутину: организует список расчётных заданий
и доводит их до готовых FITS-файлов и красивых картинок. Нужно только указать требуемый интервал времени,
список частот и параметры синтеза.
Что умеет пакет
Установка
КодПонадобится Сергея Анфиногентова работает на pythonPython 3.13,12, кодconda Мариии Глобы - пока только на 3.10! Поэтому желательно устанавливать именно ту версию, которую нужно. Для расчётов на удалённых машинах версия питона не особо важна, но рекомендуется использовать что-то новое.uv:
conda create -c conda-forge -n srhsynth python=3.1312 uv git
conda activate srhsynth
uv pip uninstall srhimages srh_synth srhdata
uv pip install -U "srhimages[anfinogentov,globa] @ git+https://git.iszf.irk.ru/fedenev/srhimages"
# или [globa], [anfinogentov] вместо [all], чтобы выбрать только конкретный расчётный код
Дополнительные пакеты anfinogentov и globa — это два расчётных ядра
(два подхода к синтезу, разработанные в ИСЗФ). Если производитсянужно свежаятолько установкаодно,
споставьте использованием[anfinogentov] расчётногоили кода[globa]. МарииНа Глобы,данный томомент требуетсярекомендуется обновитьпользоваться
кодом Сергея Анфиногентова
Если вы ставите ядро globa впервые, обновите данные CASA:
python3 -m casaconfig --update-all
Установка
Первый изшаг каталога- ссинтез git-репозиторием1 (для разработки)изображения
# git clone https://git.iszf.irk.ru/fedenev/srhimages
# cd ./srhimages
git pull -a
uv pip uninstallfrom srhimages srhsynth
uv cache clean
uv pip install -U -e "srhimages[anfinogentov] @ ."
Использование уже установленного окружения на сервере ИСЗФ
conda activate /opt/miniconda3/envs/srhsynth/
Интерфейс командной строки
srhimages create_synth_tasks --help
Использование в своих скриптах
import srhimagescreate_synth_tasks, help(srhimages.create_synth_tasks)
help(srhimages.run_computation)
Обратите внимание, что если запуск кода происходит через Python скрипт .py, то требуется запускать расчёты следующим образом:
import srhimagesrun_computation
if __name__ == "__main__":
#tasks = create_synth_tasks(
"2024-03-02 01:00:00",
frequencies=[21000],
average_width=1,
)
for result in srhimages.run_computation(.....tasks, algorithm="anfinogentov"):
passresult.to_json_file("progress.json")
ЭтотЧерез костыльнесколько связан с особым механизмом работы систем параллельных расчётовминут в Python.папке Приimages/out запускепоявятся кодаготовые изображения.
Если запускаете код из обычного
.py-файла, оборачивайте вычисления вJupyter, скорее всего, это не понадобится.
Описание команд и принципы работы
Расчётные задачи
Программа работает в парадигме так называемых расчётных задач ("tasks"). Каждая из задач представляет собой Python-словарь или его JSON-представление и описывает, из каких данных (сырых файлов и сканов внутри них) должно получиться итоговое изображение, куда оно будет сохранено и с какими параметрами синтезировано.
Актуальная спецификация формата расчётной задачи естьв исходном кодев форматеjsonschema. Спецификация API для работы с амплитудно-фазовыми калибровками антенннаходитсяв репозиторииbadary-services.
Интерфейс программы:
create_synth_tasks(time1, time2=None, cadence="15min", frequencies="all", resample_from=None, save_to=None, average_width=20, average_unit="scans", average_position="after", average_mode = "visibilities", output_polarizations="IV", naxis=512, cdelt=4.9, clean_disk=True, compressed=True, smooth_gains=False)
Назначение:Создает список (некалиброванных) задач по синтезу радиоизображений с телескопа.
Аргументы:time1(str): Время начала наблюдения в формате 'ГГГГ-ММ-ДД ЧЧ:ММ:СС'.time2(str или None, опционально): Время окончания в том же формате.cadence(str, опционально): Временной интервал между каждым наблюдением в формате "NNmin" или "NNs". По умолчанию "15min".frequencies(list(int) или str, опционально): Список частот для наблюдения в МГц или "all" в виде строки, или диапазон вида "3000-5000", или список вида [3000, "6000-8000", "SRH1224"].resample_from(list или str): Список задач или путь к файлу, содержащему список задач в формате JSON, откуда брать калибровки. Доступные частоты в списке resample должны совпадать с запрошенными пользователем частотами.save_to(str, опционально): Путь к json файлу для сохранения списка задач.average_width(int или float, опционально): Количество сканов или секунд для усреднения. По умолчанию 20.average_unit(str, опционально): Может быть 'scans' или 'seconds'. По умолчанию 'scans'.average_position(str, опционально): Временное окно для усреднения. Может быть 'after', 'before' или 'center'. По умолчанию 'after'.average_mode(str, опционально): Режим усреднения. Может быть 'visibilities', 'gridding' или 'images'. По умолчанию 'visibilities'.output_polarizations(str, опционально): Может быть 'IV' или 'RL'.naxis(int, опционально): Количество пикселей вдоль каждой оси выходного изображения. По умолчанию 512.cdelt(float, опционально): Размер каждого пикселя в угловых секундах. По умолчанию 4.9 для СРГ.clean_disk(bool, опционально): Флаг для включения/выключения очистки "грязного" изображения. По умолчанию True.compressed(bool, опционально): Флаг для включения/выключения сжатия FITS выходного изображения. По умолчанию True.smooth_gains(bool, опционально): Предпочтение сплайн-интерполяции калибровок вместо ближайших соседей при передискретизации. Используйте True для калибровок за весь день.
Возвращает:Список задач синтеза (каждая задача – Python dict), например, для отправки на кластер или для локального вычисления.
run_computation(task_list, algorithm, cache_dir="./images/raw/", out_dir="./images/out/", ftp_server="https://ftp.rao.istp.ac.ru", n_threads=5, calibrate="prefer_server", skip_postprocessing=False, skip_images=False, input_dir=None, cluster_object="local", run_id=None)task_list(list или str): Список задач для вычисления или путь к файлу, содержащему список задач в формате JSON.algorithm(str): "globa" или "anfinogentov".cache_dir(str): Директория для хранения загруженных сырых файлов СРГ.out_dir(str): Директория для сохранения синтезированных изображений.ftp_server(str): Адрес сервера для загрузки файлов. По умолчанию загрузка осуществляется с использованием HTTPS (адрес начинается со схемы https://).n_threads(int): Количество потоков для вычислений (по умолчанию 5).calibrate(str): "prefer_server" или "from_scratch". По умолчанию "prefer_server". "from_scratch" удаляет все уже имеющиеся калибровки в списке задач и заставляет калиброваться всё заново.skip_postprocessing(bool, опционально): Пропустить выравнивание и сглаживание амплитуды/фазы усилений для антенн СРГ. По умолчанию False, True не рекомендуется.skip_images(bool, опционально): Только откалибровать (и выполнить постобработку) задачи и не выполнять этап CLEAN и синтез изображений. По умолчанию: False.input_dir(str, опционально): Директория, содержащая входные файлы, в случае, если SRH NAS смонтирован там. Для локальных расчётов всегда должно быть None.cluster_object(str или object): Тип кластерного объекта для использования для вычислений, 'local' для локальных вычислений (по умолчанию 'local') и 'badary' для кластера в Бадарах. Другие варианты включают передачу пользовательских объектов Dask.distributed (например, SSHCluster).run_id(str, опционально): Префикс строки для Redis для хранения прогресса задачи (и списка задач) во время вычислений. По умолчанию None, что приведёт к случайной строке.
Возвращает:results: Список задач с результатами вычислений, либо с ошибками.
Примечание:Еслиtask_listявляется строкой или объектом pathlib.Path, он будет загружен как JSON файл.Загружает необработанные файлы с FTP сервера в директорию кэша.Калибрует задачи, используя серверные калибровки или локально.Постобработка калибровок выполняется методом, разработанным Сергеем Анфиногентовым.Все ошибки в вычислениях будут сохранены в возвращаемом объекте или сохранены в результирующем файле в формате JSON.
Пример использования
Простой случай нескольких изображений в течение дня.import srhimages time1, time2 = "2024-06-01 02:00:00", "2024-06-01 02:00:05" frequencies = [2800, 3000] task_list = srhimages.create_synth_tasks(time1, time2, cadence="3s", frequencies=frequencies,\ save_to="single-day.json", average_width=5, average_unit="seconds", average_mode = "visibilities", average_position="after",\ output_polarizations = "IV", naxis=512, cdelt=4.9, clean_disk=True, compressed=True)if __name__ == "__main__":forЭтоi,особенностьresults1параллельныхinрасчётовenumerate(srhimages.run_computation(в Python; в Jupyter это обычно не нужно.
Как это устроено
Расчётные задания
Вся работа в srhimages построена вокруг расчётных заданий. Расчётное
задание — это маленький «рецепт» получения одного изображения. В нём записано:
Задание — обычный Python-овский словарь, который можно сохранить в JSON и посмотреть глазами:
{
".task": [
{
"file_path": "/single-day.json"SRH/SRH0306/2024/03/02/file.fits",
"globa"))scans": results1.to_json_file(f"[0, 1, 2],
"frequency_index": 2
}
],
"params": {
"array": "SRH0306",
"frequency": 3000,
"average_mode": "visibilities",
"output_polarizations": "IV",
"cdelt": 4.9,
"clean_disk": true,
"naxis": 512,
"compressed": true
}
}
Зачем они нужны? Задание полностью описывает, что нужно посчитать, — поэтому вычисления становятся воспроизводимыми.
Вручную их писать не нужно: create_synth_tasks построит задания по вашему
запросу — времени, частоте и шагу по времени (cadence)./single-day-results-{i}.json")
Что происходит с заданием дальше
Каждое задание проходит цепочку этапов:
За пакетной обработкой следит менеджер очередей на основе Redis: задания распределяются между воркерами, а по ходу расчёта видно, какие расчётные задания уже готовы, а какие упали с ошибкой.
Примеры
Готовые примеры лежат в каталоге ./images/outexamples/ репозитория:
basic_srh_image.py
Одно изображение «от начала до конца», плюс работа с радиокартой.
solar_flare.py
Обработка солнечной вспышкиЗдесь требуется уже откалибровать данные на достаточно большом интервале времени, поскольку во время вспышки резко снижается вклад коротких баз радиотелескопа. Поэтому расчёт будет проходить в 2два этапа:
Первыйсначала этап - калибровкакалибровки на длинном интервалеинтервале, временипотом разсерия в 5 минут, чтобы отследить тренд "уплывания" коэффициентов усиления антенн в течение дня. Обязательно используется постобработка калибровок и их сглаживание. Рекомендуются интервалы от нескольких часов, самое идеальное - весь день.
import srhimages
freq_list = [3000, "5500-6200"]
time1, time2 = "2024-02-06 02:10:00", "2024-02-06 04:00:00"
calib_tasks = srhimages.create_synth_tasks(time1, time2, cadence="5min",\
frequencies=freq_list, save_to="calibs.json")
# в файле calibs.json появятся задания для вычисления первоначальных калибровок
if __name__ == "__main__":
for i, calibrations in enumerate(srhimages.run_computation("calibs.json", "globa",\
skip_images=True)):
if len(calibrations) == 0:
continue
freq = calibrations.frequencies[0]
calibrations.to_json_file(f"calibs_ready_{i}_{freq}.json")
# параметр skip_images нужен, потому что
# нам нужны только калибровки, а не сами изображения
# если всё хорошо, то в файлах calibs_ready**.json будут готовые калибровки.
Второй этап. Когда у нас уже имеются постобработанные калибровки, то можно на их основе посчитать картинкиизображений с максимальным временным разрешением.
cadence="0s"artifacts_filesystem.py
artifacts_http.py
resample_from
Полезные для новых заданий берутся уже посчитанные калибровки и переносятся на новую сетку по времени. smooth_gains означает, что интерполяция коэффициентов усиления антенн на нужный кадр будет производиться с помощью сплайна, а не ближайшего соседа. Эта настройка рекомендуется, когда временное разрешение финальных изображений чаще, чем разрешение калибровок.команды:
synth_taskssrhimages =create_synth_tasks srhimages.create_synth_tasks(time1,--help
time2,srhimages cadence="0s",run_computation frequencies=freq_list,\
resample_from="calibs_ready.json", smooth_gains=True, save_to="synth.json")
if __name__ == "__main__":
for i, results in enumerate(srhimages.run_computation("synth.json", "anfinogentov")):
if len(results) > 0:
dt = results.dates[0]
freq = results.frequencies[0]
results.to_json_file(f"result_{freq}_{dt}_{i}.json")--help
В
Ссылки
resultsREADME.md synth**Reference: https://git.iszf.irk.ru/fedenev/srhimages/-/wikis/home
База знаний отдела радиоастрофизики: страница о пакете.Загрузка калибровок на сервер
from srhimages import TaskCollection
calibrated_tasks = TaskCollection("synth_progress.json")
calibrated_tasks.extract_gains().upload()