Source code for asgardpy.gammapy.read_models

"""
Functions for reading different Models type objects with Gammapy
objects.
"""

import xmltodict
from gammapy.maps import Map
from gammapy.modeling.models import (
    SPATIAL_MODEL_REGISTRY,
    SPECTRAL_MODEL_REGISTRY,
    SkyModel,
    create_fermi_isotropic_diffuse_model,
)

from asgardpy.data.target import (
    add_ebl_model_from_config,
    read_models_from_asgardpy_config,
)
from asgardpy.gammapy.interoperate_models import (
    get_gammapy_spectral_model,
    xml_spatial_model_to_gammapy,
    xml_spectral_model_to_gammapy,
)

__all__ = [
    "create_gal_diffuse_skymodel",
    "create_iso_diffuse_skymodel",
    "create_source_skymodel",
    "read_fermi_xml_models_list",
    "update_aux_info_from_fermi_xml",
]


[docs] def read_fermi_xml_models_list( list_source_models, dl3_aux_path, xml_file, diffuse_models, asgardpy_target_config=None ): """ Read from the Fermi-XML file to enlist the various objects and get their SkyModels. Parameters ---------- list_source_models: list List of source models to be filled. dl3_aux_path: str Path location of the DL3 auxiliary files for reading Spatial Models from separate files. xml_file: str Path of the Fermi-XML file to be read. diffuse_models: dict Dict containing diffuse models' filenames and instrument key. asgardpy_target_config: `AsgardpyConfig` Config section containing the Target source information. Returns ------- list_source_models: list List of filled source models. diffuse_models: dict Dict containing diffuse models objects replacing the filenames. """ with open(xml_file, encoding="utf-8") as file: xml_data = xmltodict.parse(file.read())["source_library"]["source"] is_target_source = False for source_info in xml_data: match source_info["@name"]: # Nomenclature as per enrico and fermipy case "IsoDiffModel" | "isodiff": diffuse_models["iso_diffuse"] = create_iso_diffuse_skymodel( diffuse_models["iso_diffuse"], diffuse_models["key_name"] ) source_info = diffuse_models["iso_diffuse"] case "GalDiffModel" | "galdiff": diffuse_models["gal_diffuse"], diffuse_models["gal_diffuse_map"] = create_gal_diffuse_skymodel( diffuse_models["gal_diffuse"] ) source_info = diffuse_models["gal_diffuse"] case _: source_info, is_target_source = create_source_skymodel( source_info, dl3_aux_path, base_model_type="Fermi-XML", asgardpy_target_config=asgardpy_target_config, ) if is_target_source: list_source_models.insert(0, source_info) is_target_source = False # To not let it repeat else: list_source_models.append(source_info) return list_source_models, diffuse_models
[docs] def update_aux_info_from_fermi_xml( diffuse_models_file_names_dict, xml_file, fetch_iso_diff=False, fetch_gal_diff=False ): """ When no glob_search patterns on axuillary files are provided, fetch them from the XML file and update the dict containing diffuse models' file names. Parameters ---------- diffuse_models_file_names_dict: `dict` Dict containing the information on the DL3 files input. xml_file: str Path of the Fermi-XML file to be read. fetch_iso_diff: bool Boolean to get the information of the Isotropic diffuse model from the Fermi-XML file fetch_gal_diff: bool Boolean to get the information of the Galactic diffuse model from the Fermi-XML file Returns ------- diffuse_models_file_names_dict: `dict` Dict containing the updated information on the DL3 files input. """ with open(xml_file) as file: data = xmltodict.parse(file.read())["source_library"]["source"] for source in data: match source["@name"]: case "IsoDiffModel" | "isodiff": if fetch_iso_diff: file_path = source["spectrum"]["@file"] file_name = file_path.split("/")[-1] diffuse_models_file_names_dict["iso_diffuse"] = file_name case "GalDiffModel" | "galdiff": if fetch_gal_diff: file_path = source["spatialModel"]["@file"] file_name = file_path.split("/")[-1] diffuse_models_file_names_dict["gal_diffuse"] = file_name return diffuse_models_file_names_dict
def get_target_model_from_config(source_name, asgardpy_target_config): """ Function to get the model of the target source from AsgardpyConfig. """ spectral_model = None is_source_target = False # If Target source model's spectral component is to be taken from Config # and not from 3D dataset. if asgardpy_target_config: source_name_check = source_name.replace("_", "").replace(" ", "") target_check = asgardpy_target_config.source_name.replace("_", "").replace(" ", "") if source_name_check == target_check: source_name = asgardpy_target_config.source_name is_source_target = True # Only taking the spectral model information. if not asgardpy_target_config.from_3d: models_ = read_models_from_asgardpy_config(asgardpy_target_config) spectral_model = models_[0].spectral_model return source_name, spectral_model, is_source_target
[docs] def create_source_skymodel(source_info, dl3_aux_path, base_model_type="Fermi-XML", asgardpy_target_config=None): """ Build SkyModels from given base model information. If AsgardpyConfig section of the target is provided for the target source information, it will be used to check if the target `source_name` is provided in the base_model file. If it exists, then check if the model information is to be read from AsgardpyConfig using `from_3d` boolean value. Also, if EBL model information is provided in the AsgardpyConfig, it will be added to the SkyModel object. Parameters ---------- source_info: dict Dictionary containing the source models information from XML file. dl3_aux_path: str Path location of the DL3 auxiliary files for reading Spatial Models from separate files. base_model_type: str Name indicating the model format used to read the skymodels from. asgardpy_target_config: `AsgardpyConfig` Config section containing the Target source information. Returns ------- source_sky_model: `gammapy.modeling.SkyModel` SkyModels object for the given source information. is_source_target: bool Boolean to check if the Models belong to the target source. """ if base_model_type == "Fermi-XML": source_name = source_info["@name"] spectrum_type = source_info["spectrum"]["@type"] spectrum_params = source_info["spectrum"]["parameter"] # initialized to check for the case if target spectral model information # is to be taken from the Config spectral_model = None # Check if target_source file exists is_source_target = False ebl_atten = False source_name, spectral_model, is_source_target = get_target_model_from_config( source_name, asgardpy_target_config ) if spectral_model is None: # Define the Spectral Model type for Gammapy spectral_model, ebl_atten = get_gammapy_spectral_model( spectrum_type, ebl_atten, base_model_type, ) spectrum_type = spectrum_type.split("EblAtten::")[-1] # Read the parameter values from XML file to create SpectralModel params_list = xml_spectral_model_to_gammapy( spectrum_params, spectrum_type, is_target=is_source_target, keep_sign=ebl_atten, base_model_type=base_model_type, ) for param_ in params_list: setattr(spectral_model, param_.name, param_) if asgardpy_target_config: model_config = asgardpy_target_config.components[0] ebl_absorption_included = model_config.spectral.ebl_abs.reference != "" if is_source_target and ebl_absorption_included: spectral_model = add_ebl_model_from_config(spectral_model, model_config) # Reading Spatial model from the XML file spatial_model = xml_spatial_model_to_gammapy(dl3_aux_path, source_info["spatialModel"], base_model_type) spatial_model.freeze() source_sky_model = SkyModel( spectral_model=spectral_model, spatial_model=spatial_model, name=source_name, ) return source_sky_model, is_source_target
[docs] def create_iso_diffuse_skymodel(iso_file, key_name): """ Create a SkyModel of the Fermi Isotropic Diffuse Model and assigning name as per the observation key. If there are no distinct key types of files, the value is None. Parameters ---------- iso_file: str Path to the isotropic diffuse model file key: str Instrument key-name, if exists Returns ------- diff_iso: `gammapy.modeling.SkyModel` SkyModel object of the isotropic diffuse model. """ diff_iso = create_fermi_isotropic_diffuse_model(filename=iso_file, interp_kwargs={"fill_value": None}) if key_name: diff_iso._name = f"{diff_iso.name}-{key_name}" # Parameters' limits diff_iso.spectral_model.model2.parameters[0].min = 0 diff_iso.spectral_model.model2.parameters[0].max = 10 return diff_iso
[docs] def create_gal_diffuse_skymodel(diff_gal_file): """ Create SkyModel of the Diffuse Galactic sources either by reading a file or by using a provided Map object. Parameters ---------- diff_gal_file: Path, `gammapy.maps.Map` Path to the isotropic diffuse model file, or a Map object already read from a file. Returns ------- model: `gammapy.modeling.SkyModel` SkyModel object read from a given galactic diffuse model file. diff_gal: `gammapy.maps.Map` Map object of the galactic diffuse model """ if not isinstance(diff_gal_file, Map): # assuming it is Path or str type diff_gal_filename = diff_gal_file diff_gal = Map.read(diff_gal_file) diff_gal.meta["filename"] = diff_gal_filename else: diff_gal = diff_gal_file template_diffuse = SPATIAL_MODEL_REGISTRY.get_cls("TemplateSpatialModel")( diff_gal, normalize=False, filename=diff_gal.meta["filename"] ) model = SkyModel( spectral_model=SPECTRAL_MODEL_REGISTRY.get_cls("PowerLawNormSpectralModel")(), spatial_model=template_diffuse, name="diffuse-iem", ) model.parameters["norm"].min = 0 model.parameters["norm"].max = 10 model.parameters["norm"].frozen = False return model, diff_gal