Skip to main content

Универсальный пакет для синтеза изображений srhimages

srhimages

ПрограммаСибирский радиогелиограф (СРГ) каждый день записывает огромные объёмы данных. Чтобы получить готовые радиокарты Солнца в радиодиапазоне, сырые данные нужно откалибровать, собрать воедино из функций видности на UV-плоскости, «нарисовать» — синтезировать изображение с помощью обратного Фурье-преобразования и вычистить боковые лепестки диаграммы направленности алгоритмом CLEAN.

Пакет srhimages предоставляетберёт функциина длясебя синтезавсю радиоизображенийэту рутину: организует список расчётных заданий и доводит их до готовых FITS-файлов и красивых картинок. Нужно только указать требуемый интервал времени, список частот и параметры синтеза.

Что умеет пакет

    Создаёт расчётные задания по вашему запросу. По запросам вроде "мне нужно Солнце 5 марта с 02:00 до 04:00, каждые 15 минут, на 3000 МГц" — и получите список задач в JSON. Самостоятельно скачивает данные. Сырые файлы подтянутся с сервера в Иркутске (или с Бадар, если очень надо), ничего вручную искать не нужно. Калибрует. Коэффициенты усиления антенн берутся с сервера, а если их нет — считаются с нуля. Пакет сам выравнивает и сглаживает их суточный ход, чтобы изображение было качественным. Синтезирует изображения. На выходе — FITS-файлы в поляризациях I, V (или R, L). При необходимости FITS можно пересохранить в HDF5, в том числе со сжатием Считает где угодно. Локально на вашей машине, на кластере в Бадарах или на удалённом сервере. Помогает анализировать результат. Радиокарты можно открыть, обрезать, получить PSF, отобразить, пересчитать яркостные температуры в SFU и собрать видео из данныхсерии Сибирскогокадров. Радиогелиографа (SRH).

    Установка

    КодПонадобится Сергея Анфиногентова работает на 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 построена вокруг расчётных заданий. Расчётное задание — это маленький «рецепт» получения одного изображения. В нём записано:

                    какие сырые файлы телескопа взять и какие сканы внутри них усреднить; на какой частоте и в каких поляризациях строить картинку; с какими параметрами: размер изображения, масштаб пикселя, нужен ли CLEAN.

                    Задание — обычный 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")

                      #

                      Что происходит с заданием дальше

                      Каждое задание проходит цепочку этапов:

                        Калибровка — подбор коэффициентов усиления антенн. Готовые можно взять с сервера (srhimages занимается этим сам, но можно и вытащить их самостоятельно), а можно посчитать с нуля. Постобработка — выравнивание и сглаживание суточного хода коэффициентов усиления, чтобы картинка получилась без артефактов. Синтез — сам расчёт изображения появятся(сборка радиокарты в яркостных температурах + CLEAN).

                        За пакетной обработкой следит менеджер очередей на основе 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 быть темТо же самым,самое, нано которомчерез шлаHTTP-сервер калибровка.артефактов. Параметр 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
                        

                        В

                        Ссылки

                        списке
                        выполненныхИсходный (иликод: невыполненных)https://git.iszf.irk.ru/fedenev/srhimages задач,Техническое которыйописание появитсяAPI — в переменной resultsREADME.md илирепозитория. вWIKI файлеи synth**Reference: https://git.iszf.irk.ru/fedenev/srhimages/-/wikis/home База знаний отдела радиоастрофизики: страница о пакете.json, будут уже прописаны полные пути к полученным изображениям

                        Загрузка калибровок на сервер

                        from srhimages import TaskCollection
                        calibrated_tasks = TaskCollection("synth_progress.json")
                        calibrated_tasks.extract_gains().upload()