Beispiel #1
0
    def _get_crab_flux(self, emin, emax):
        """
        Return Crab photon flux in a given energy interval

        Parameters
        ----------
        emin : `~gammalib.GEnergy`
            Minimum energy
        emax : `~gammalib.GEnergy`
            Maximum energy

        Returns
        -------
        flux : float
            Crab photon flux in specified energy interval (ph/cm2/s)
        """
        # Set Crab TeV spectral model based on a power law
        crab = gammalib.GModelSpectralPlaw(5.7e-16, -2.48,
                                           gammalib.GEnergy(0.3, 'TeV'))

        # Determine photon flux
        flux = crab.flux(emin, emax)

        # Return photon flux
        return flux
Beispiel #2
0
def add_background_model(obs):
    """
    Add standard CTA background model to observations container.

    We use a simple power law here, scaled to Konrad's E configuration
    performance table. The model needs still to be validated.
    """
    # Recover models from observation
    models = obs.models()

    # Define background model
    bgd_radial   = gammalib.GCTAModelRadialGauss(3.0)
    bgd_spectrum = gammalib.GModelSpectralPlaw(61.8e-6, -1.85, gammalib.GEnergy(1.0, "TeV"))
    bgd_model    = gammalib.GCTAModelRadialAcceptance(bgd_radial, bgd_spectrum)
    bgd_model.name("Background")
    bgd_model.instruments("CTA")

    # Add background model to container
    models.append(bgd_model)

    # Put container back in observation container
    obs.models(models)

    # Return observation container
    return obs
def flux_from_gammacat(cat, emin, emax=eup):
    # calculate integral flux in desired energy range from spectral model
    fluxes = np.array([])
    for source in cat:
        try:
            flux = source.spectral_model().integral(emin * u.TeV, emax * u.TeV)
            fluxes = np.append(fluxes, flux.value)
        except:
            # sources without spectral model
            fluxes = np.append(fluxes, np.nan)

    # convert to Crab units
    # conversion consistent with utils for gammalib model containers
    # simple Crab TeV power law model
    crab = gammalib.GModelSpectralPlaw(5.7e-16, -2.48,
                                       gammalib.GEnergy(0.3, 'TeV'))
    # calculate crab flux over the desired energy range
    crab_flux = crab.flux(gammalib.GEnergy(emin, 'TeV'),
                          gammalib.GEnergy(emax, 'TeV'))
    # remormalize crab flux so that it matches the Meyer model > 1 TeV (consistent with gamma-cat)
    crab_flux_1TeV = crab.flux(gammalib.GEnergy(1., 'TeV'),
                               gammalib.GEnergy(eup, 'TeV'))
    # (Meyer model, flux > 1 TeV in ph cm-2 s-1)
    crab_flux *= 2.0744340476909142e-11 / crab_flux_1TeV
    fluxes /= crab_flux

    return fluxes
Beispiel #4
0
def bin2gammalib(filename, flux_thresh, outdir):
    data = open(filename).readlines()

    # convert phasogram to numpy array
    phasogram = np.genfromtxt(data[14:])

    # only include model if peak in lightcurve is > threshold
    if np.max(phasogram[:, 2]) > flux_thresh:

        # final name
        num = int(data[0].split('#')[-1])
        name = 'bin{:03d}'.format(num)

        # spatial model
        # read Galactic longitude
        lon = float(data[1].split('   ')[-1])
        # Galactic latitude is random with Gaussian distribution with 95% containment at bmax
        lat = np.random.normal(0, bmax / 2)
        src_dir = gammalib.GSkyDir()
        src_dir.lb_deg(lon, lat)
        spatial = gammalib.GModelSpatialPointSource(src_dir)

        # spectral model
        # average flux in ph/cm2/s
        f0 = np.average(phasogram[:, 1])
        # convert to differential flux at eref in ph/cm2/s/MeV
        n0 = (gamma - 1) * f0 / eref
        spectral = gammalib.GModelSpectralPlaw(
            n0, -gamma, gammalib.GEnergy(np.double(eref), 'MeV'))

        # orbital phase model
        # create phasogram file
        fname = 'phasecurve_' + name + '.fits'
        phasogram_file(phasogram, outdir + fname, outdir)
        # period in days
        per = float(data[4].split(' ')[-1])
        # convert to frequency in s
        per *= 86400
        f0 = 1 / per
        temporal = gammalib.GModelTemporalPhaseCurve(
            gammalib.GFilename(fname),
            t0,
            np.random.random(),  # phase at t0 randomly drawn
            f0,
            0.,
            0.,  # orbit is stable, no derivatives
            1.,
            True)  # normalized so that spectral model represents average flux

        # assemble final model
        model = gammalib.GModelSky(spatial, spectral, temporal)
        model.name(name)

    else:
        # empty model
        lat = 0.
        model = gammalib.GModelSky()

    return model, lat
def create_model(flux, index=-2.48, fitidx=False):
    """
    Add standard CTA background model to observations container.
    We use a simple power law here, scaled to Konrad's E configuration
    performance table.

    Parameters:
     flux - Flux in Crab units
    """
    # Define background model
    bgd_radial = gammalib.GCTAModelRadialGauss(3.0)
    bgd_spectrum = gammalib.GModelSpectralPlaw(61.8, -1.85)
    bgd_spectrum["Prefactor"].scale(1.0e-6)
    bgd_spectrum["PivotEnergy"].value(1.0)
    bgd_spectrum["PivotEnergy"].scale(1.0e6)
    if fitidx:
        bgd_spectrum["Index"].free()
    else:
        bgd_spectrum["Index"].fix()
    bgd_model = gammalib.GCTAModelRadialAcceptance(bgd_radial, bgd_spectrum)
    bgd_model.name("Background")
    bgd_model.instruments("CTA")

    # Define source spectrum
    location = gammalib.GSkyDir()
    location.radec_deg(83.6331, 22.0145)
    src_spatial = gammalib.GModelSpatialPtsrc(location)
    src_spectrum = gammalib.GModelSpectralPlaw(flux, index)
    src_spectrum["Prefactor"].scale(5.7e-16)
    src_spectrum["PivotEnergy"].value(0.3)
    src_spectrum["PivotEnergy"].scale(1.0e6)
    if fitidx:
        src_spectrum["Index"].free()
    else:
        src_spectrum["Index"].fix()
    src_model = gammalib.GModelPointSource(src_spatial, src_spectrum)
    src_model.name("Test")

    # Add models to container
    models = gammalib.GModels()
    models.append(bgd_model)
    models.append(src_model)

    # Return model container
    return models
Beispiel #6
0
def crab_spec():
    """
    Set Crab spectrum based on MAGIC observations
    (Albert et al. 2008, ApJ, 674, 1037)
    """
    # Set parameters
    spectrum = gammalib.GModelSpectralPlaw(5.7e-16, -2.48, gammalib.GEnergy(0.3, "TeV"))

    # Return spectrum
    return spectrum
Beispiel #7
0
    def _set_bkg(self, modeltype):
        """
        Set background model

        Parameters
        ----------
        modeltype : str
            Model type ('IRF', 'AEFF', 'CUBE' or 'RACC')

        Returns
        -------
        model : `~gammalib.GModelData()`
            Background model
        """
        # Pivot energy
        epivot = gammalib.GEnergy(1.0, 'TeV')

        # Set background model
        if modeltype == 'IRF':
            spectral = gammalib.GModelSpectralPlaw(1.0, 0.0, epivot)
            model = gammalib.GCTAModelIrfBackground(spectral)
        elif modeltype == 'AEFF':
            spectral = gammalib.GModelSpectralPlaw(1.0e-13, -2.5, epivot)
            model = gammalib.GCTAModelAeffBackground(spectral)
        elif modeltype == 'CUBE':
            spectral = gammalib.GModelSpectralPlaw(1.0, 0.0, epivot)
            model = gammalib.GCTAModelCubeBackground(spectral)
        elif modeltype == 'RACC':
            radial = gammalib.GCTAModelRadialGauss(3.0)
            spectral = gammalib.GModelSpectralPlaw(1.0e-4, -2.5, epivot)
            model = gammalib.GCTAModelRadialAcceptance(radial, spectral)
        else:
            model = None

        # Set background name
        if model is not None:
            model.name('Background')

        # Return model
        return model
Beispiel #8
0
def create_models():
    """
    """
    # Create model container
    models = gammalib.GModels()
    
    # Create a power law model for the Crab
    crabdir = gammalib.GSkyDir()
    crabdir.radec_deg(83.6331, 22.0145)
    spatial  = gammalib.GModelSpatialPointSource(crabdir)
    energy   = gammalib.GEnergy(100.0, "MeV")
    spectral = gammalib.GModelSpectralPlaw(5.7e-16, -2.48, energy)
    model    = gammalib.GModelSky(spatial, spectral)
    models.append(model)
    
    # Return models
    return models
Beispiel #9
0
def flux_Crab(model, emin, emax):
    emin = gammalib.GEnergy(emin, 'TeV')
    emax = gammalib.GEnergy(emax, 'TeV')
    flux = model.spectral().flux(emin, emax)
    # convert to Crab units
    # Set Crab TeV spectral model based on a power law
    crab = gammalib.GModelSpectralPlaw(5.7e-16, -2.48,
                                       gammalib.GEnergy(0.3, 'TeV'))
    # calculate crab flux over the same energy range
    crab_flux = crab.flux(emin, emax)
    # remormalize crab flux so that it matches the Meyer model > 1 TeV (consistent with gamma-cat)
    crab_flux_1TeV = crab.flux(gammalib.GEnergy(1., 'TeV'),
                               gammalib.GEnergy(1000., 'TeV'))
    # (Meyer model, flux > 1 TeV in ph cm-2 s-1)
    crab_flux *= 2.0744340476909142e-11 / crab_flux_1TeV
    flux /= crab_flux
    return flux
Beispiel #10
0
    def _get_crab_flux(self, emin, emax):
        """
        Return Crab photon flux in a given energy interval.

        Args:
            emin: Minimum energy
            emax: Maximum energy

        Returns:
            Crab photon flux in specified energy interval.
        """
        # Set Crab TeV spectral model based on a power law
        crab = gammalib.GModelSpectralPlaw(5.7e-16, -2.48,
                                           gammalib.GEnergy(0.3, "TeV"))

        # Determine flux
        flux = crab.flux(emin, emax)

        # Return flux
        return flux
Beispiel #11
0
    def _set_ptsrc(self, pos):
        """
        Set point source model

        Parameters
        ----------
        pos : `~gammalib.GSkyDir()`
            Sky direction of model

        Returns
        -------
        model : `~gammalib.GModelSky()`
            Point source model
        """
        # Set spatial component
        spatial = gammalib.GModelSpatialPointSource(pos)

        # Get fit parameters
        fit_pos = self['fit_pos'].boolean()
        #fit_shape = self['fit_shape'].boolean()

        # Loop over all parameters
        for par in spatial:

            # Handle position parameters
            if par.name() == 'RA' or par.name() == 'DEC':
                if fit_pos:
                    par.free()
                else:
                    par.fix()

        # Set spectral component (powerlaw with 1% of Crab)
        spectral = gammalib.GModelSpectralPlaw(5.7e-18, -2.48,
                                               gammalib.GEnergy(0.3, 'TeV'))

        # Set sky model
        model = gammalib.GModelSky(spatial, spectral)

        # Return model
        return model
def flux_Crab(model, Emin, Emax):
    emin = gammalib.GEnergy(Emin, 'TeV')
    emax = gammalib.GEnergy(Emax, 'TeV')
    # deal with special case of cubes
    if model.spatial().type() == 'DiffuseMapCube':
        # get cube flux
        flux = cube_flux(model, Emin, Emax)
    else:
        flux = model.spectral().flux(emin, emax)
    # convert to Crab units
    # Set Crab TeV spectral model based on a power law
    crab = gammalib.GModelSpectralPlaw(5.7e-16, -2.48,
                                       gammalib.GEnergy(0.3, 'TeV'))
    # calculate crab flux over the same energy range
    crab_flux = crab.flux(emin, emax)
    # remormalize crab flux so that it matches the Meyer model > 1 TeV (consistent with gamma-cat)
    crab_flux_1TeV = crab.flux(gammalib.GEnergy(1., 'TeV'),
                               gammalib.GEnergy(1000., 'TeV'))
    # (Meyer model, flux > 1 TeV in ph cm-2 s-1)
    crab_flux *= 2.0744340476909142e-11 / crab_flux_1TeV
    flux /= crab_flux
    return flux
def set_source_model(srcmodel,
                     spec='plaw',
                     alpha=1.0,
                     mapname='../map_RXJ1713.fits'):
    """
    Set source model

    Parameters
    ----------
    srcmodel : str
        Source model name
    spec : str, optional
        Spectral model
    alpha : float, optional
        Map scaling factor
    mapname : str, optional
        Sky map name

    Returns
    -------
    source : `~gammalib.GModelSky()`
        Source model
    """
    # Set spectral component
    if spec == 'plaw':
        spectral = gammalib.GModelSpectralPlaw(1.0e-17, -2.0,
                                               gammalib.GEnergy(1.0, 'TeV'))
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'eplaw':
        spectral = gammalib.GModelSpectralExpPlaw(
            1.0e-17, -2.0, gammalib.GEnergy(1.0, 'TeV'),
            gammalib.GEnergy(10.0, 'TeV'))
        spectral['CutoffEnergy'].min(1.0e6)
        spectral['CutoffEnergy'].max(1.0e8)
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'inveplaw':
        spectral = gammalib.GModelSpectralExpInvPlaw(
            1.0e-17, -2.0, gammalib.GEnergy(1.0, 'TeV'),
            gammalib.GEnergy(10.0, 'TeV'))
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'logparabola':
        spectral = gammalib.GModelSpectralLogParabola(
            1.0e-17, -2.0, gammalib.GEnergy(1.0, 'TeV'), -0.3)
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'abdalla2018':
        spectral = gammalib.GModelSpectralExpPlaw(
            2.3e-17, -2.06, gammalib.GEnergy(1.0, 'TeV'),
            gammalib.GEnergy(12.9, 'TeV'))
        spectral['Prefactor'].fix()
        spectral['Index'].fix()
        spectral['CutoffEnergy'].fix()
    elif spec == 'abdalla2018Ec':
        spectral = gammalib.GModelSpectralExpPlaw(
            2.3e-17, -2.06, gammalib.GEnergy(1.0, 'TeV'),
            gammalib.GEnergy(12.9, 'TeV'))
        spectral['CutoffEnergy'].fix()
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'aharonian2007':
        spectral = gammalib.GModelSpectralLogParabola(
            2.06e-17, -2.02, gammalib.GEnergy(1.0, 'TeV'), -0.29)
        spectral['Prefactor'].fix()
        spectral['Index'].fix()
        spectral['Curvature'].fix()

    # Set spatial component
    if 'map' in srcmodel:
        filename = '%s' % mapname
        map = gammalib.GSkyMap(filename)
        map = scale_map(map, alpha)
        filename = 'map_RXJ1713_%.2f.fits' % alpha
        map.save(filename, True)
        spatial = gammalib.GModelSpatialDiffuseMap(filename)
    elif 'disk' in srcmodel:
        dir = gammalib.GSkyDir()
        dir.radec_deg(258.3, -39.7)
        spatial = gammalib.GModelSpatialRadialDisk(dir, 0.5)
        spatial['RA'].free()
        spatial['DEC'].free()
    elif 'gauss' in srcmodel:
        dir = gammalib.GSkyDir()
        dir.radec_deg(258.3, -39.7)
        spatial = gammalib.GModelSpatialRadialGauss(dir, 0.5)
        spatial['RA'].free()
        spatial['DEC'].free()
    elif 'shell' in srcmodel:
        dir = gammalib.GSkyDir()
        dir.radec_deg(258.3, -39.7)
        spatial = gammalib.GModelSpatialRadialShell(dir, 0.4, 0.2)
        spatial['RA'].free()
        spatial['DEC'].free()

    # Set source model
    source = gammalib.GModelSky(spatial, spectral)
    source.name('RX J1713.7-3946')
    source.tscalc(True)

    # Return source model
    return source
def background(model_tot, bkg_dict_in, setID=True):
    """
    Build a ctools model for the background.
    
    Parameters
    ----------
    - model_tot: a gammalib.GModels object
    - bkg_dict (dictionary): the dictionary that 
    contain the background properties (from class 
    Background). In case of multiple background this can be a list.
    - setID (bool): decide to set or not an ID in the bkg model
    
    Outputs
    --------
    - the model is updated to include the background
    """

    #---------- Get the number of background
    if type(bkg_dict_in) == list:
        Nbkg = len(bkg_dict_in)
    else:
        Nbkg = 1

    #---------- Add all bkg models
    for i in range(Nbkg):
        #---------- Select the background from the list or not
        if type(bkg_dict_in) == list:
            bkg_dict = bkg_dict_in[i]
        else:
            bkg_dict = bkg_dict_in

        #----- Spectral model

        # PowerLaw
        if bkg_dict.spectral['type'] == 'PowerLaw':
            prefact = bkg_dict.spectral['param']['Prefactor']['value']
            index = bkg_dict.spectral['param']['Index']['value']
            pivot = gammalib.GEnergy(
                bkg_dict.spectral['param']['PivotEnergy']['value'].to_value(
                    'TeV'), 'TeV')
            spectral = gammalib.GModelSpectralPlaw(prefact, index, pivot)

        # PowerLawExpCutoff
        elif bkg_dict.spectral['type'] == 'PowerLawExpCutoff':
            prefact = bkg_dict.spectral['param']['Prefactor']['value']
            index = bkg_dict.spectral['param']['Index']['value']
            pivot = gammalib.GEnergy(
                bkg_dict.spectral['param']['PivotEnergy']['value'].to_value(
                    'TeV'), 'TeV')
            cutoff = gammalib.GEnergy(
                bkg_dict.spectral['param']['Cutoff']['value'].to_value('TeV'),
                'TeV')
            spectral = gammalib.GModelSpectralExpPlaw(prefact, index, pivot,
                                                      cutoff)

        # Error
        else:
            raise ValueError('Spectral model not available')

        # Parameter management
        spectral = manage_parameters(bkg_dict.spectral['param'], spectral)

        #----- Spatial model
        # CTAIrfBackground
        if bkg_dict.spatial['type'] == 'CTAIrfBackground':

            #----- Overal model for each source
            model = gammalib.GCTAModelIrfBackground(spectral)

        # Error
        else:
            raise ValueError('Spatial model not avaiable')

        #----- Append model
        model.name(bkg_dict.name)
        model.instruments(bkg_dict.instrument)
        if setID:
            if bkg_dict.obsid is not None: model.ids(bkg_dict.obsid)

        model_tot.append(model)
def compact_sources(model_tot, source_dict, tscalc=True):
    """
    Build a ctools model for the compact sources.
    
    Parameters
    ----------
    - model_tot: a gammalib.GModels object
    - source_dict (dictionary): the source dictionary 
    as defined by the CompactSource class
    - tscalc (bool): request TS computation or not

    Outputs
    --------
    - the model is updated to include the sources
    """

    Nsource = len(source_dict.name)

    for ips in range(Nsource):
        #----- Spatial model
        # PointSource
        if source_dict.spatial[ips]['type'] == 'PointSource':
            RA = source_dict.spatial[ips]['param']['RA']['value'].to_value(
                'deg')
            Dec = source_dict.spatial[ips]['param']['DEC']['value'].to_value(
                'deg')
            spatial = gammalib.GModelSpatialPointSource(RA, Dec)

        # Error
        else:
            raise ValueError('Spatial model not avaiable')

        #----- Spectral model
        # PowerLaw
        if source_dict.spectral[ips]['type'] == 'PowerLaw':
            prefact = source_dict.spectral[ips]['param']['Prefactor'][
                'value'].to_value('cm-2 s-1 MeV-1')
            index = source_dict.spectral[ips]['param']['Index']['value']
            pivot = gammalib.GEnergy(
                source_dict.spectral[ips]['param']['PivotEnergy']
                ['value'].to_value('TeV'), 'TeV')
            spectral = gammalib.GModelSpectralPlaw(prefact, index, pivot)

        # PowerLawExpCutoff
        elif source_dict.spectral[ips]['type'] == 'PowerLawExpCutoff':
            prefact = source_dict.spectral[ips]['param']['Prefactor'][
                'value'].to_value('cm-2 s-1 MeV-1')
            index = source_dict.spectral[ips]['param']['Index']['value']
            pivot = gammalib.GEnergy(
                source_dict.spectral[ips]['param']['PivotEnergy']
                ['value'].to_value('TeV'), 'TeV')
            cutoff = gammalib.GEnergy(
                source_dict.spectral[ips]['param']['Cutoff']['value'].to_value(
                    'TeV'), 'TeV')
            spectral = gammalib.GModelSpectralExpPlaw(prefact, index, pivot,
                                                      cutoff)

        # Error
        else:
            raise ValueError('Spectral model not available')

#----- Temporal model
# Constant
        if source_dict.temporal[ips]['type'] == 'Constant':
            temporal = gammalib.GModelTemporalConst(
                source_dict.temporal[ips]['param']['Normalization']['value'])

        # Error
        else:
            raise ValueError('Temporal model not available')

        #----- Parameter management
        spatial = manage_parameters(source_dict.spatial[ips]['param'], spatial)
        spectral = manage_parameters(source_dict.spectral[ips]['param'],
                                     spectral)
        temporal = manage_parameters(source_dict.temporal[ips]['param'],
                                     temporal)

        #----- Overal model for each source
        model = gammalib.GModelSky(spatial, spectral, temporal)
        model.name(source_dict.name[ips])
        model.tscalc(tscalc)

        #----- Append model for each source
        model_tot.append(model)
def gw_simulation(sim_in, config_in, model_xml, fits_model, counter):
    """

    :param sim_in:
    :param config_in:
    :param model_xml:
    :param fits_model:
    :param counter:
    :return:
    """

    src_name = fits_model.split("/")[-1][:-5]
    run_id, merger_id = src_name.split('_')

    fits_header_0 = fits.open(fits_model)[0].header
    ra_src = fits_header_0['RA']
    dec_src = fits_header_0['DEC']

    coordinate_source = SkyCoord(ra=ra_src * u.deg, dec=dec_src * u.deg, frame="icrs")

    src_yaml = sim_in['source']

    point_path = create_path(src_yaml['pointings_path'])
    opt_point_path = f"{point_path}/optimized_pointings"

    ctools_pipe_path = create_path(config_in['exe']['software_path'])
    ctobss_params = sim_in['ctobssim']

    seed = int(counter)*10

    # # PARAMETERS FROM THE CTOBSSIM
    sim_e_min = u.Quantity(ctobss_params['energy']['e_min']).to_value(u.TeV)
    sim_e_max = u.Quantity(ctobss_params['energy']['e_max']).to_value(u.TeV)

    sim_rad = ctobss_params['radius']
    output_path = create_path(sim_in['output']['path'] + f"/{src_name}/seed-{seed:03}")

    irf_dict = sim_in['IRF']
    site = irf_dict['site']

    detection = sim_in['detection']
    significance_map = detection['skymap_significance']
    srcdetect_ctlike = detection['srcdetect_likelihood']

    save_simulation = ctobss_params['save_simulation']

    try:
        mergers_data = pd.read_csv(
            f"{point_path}/BNS-GW-Time_onAxis5deg.txt",
            sep=" ")
    except FileNotFoundError:
        print("merger data not present. check that the text file with the correct pointings is in the 'pointings' folder!")
        sys.exit()

    filter_mask = (mergers_data["run"] == run_id) & (mergers_data["MergerID"] == f"Merger{merger_id}")
    merger_onset_data = mergers_data[filter_mask]
    time_onset_merger = merger_onset_data['Time'].values[0]

    with open(f"{output_path}/GW-{src_name}_seed-{seed:03}_site-{site}.txt", "w") as f:
        f.write(f"GW_name\tRA_src\tDEC_src\tseed\tpointing_id\tsrc_to_point\tsrc_in_point\tra_point\tdec_point\tradius\ttime_start\ttime_end\tsignificanceskymap\tsigmasrcdetectctlike\n")
        try:
            file_name = f"{opt_point_path}/{run_id}_Merger{merger_id}_GWOptimisation_v3.txt"
            pointing_data = pd.read_csv(
                file_name,
                header=0,
                sep=",")
        except FileNotFoundError:
            print("File not found\n")
            sys.exit()

        RA_data = pointing_data['RA(deg)']
        DEC_data = pointing_data['DEC(deg)']
        times = pointing_data['Observation Time UTC']
        durations = pointing_data['Duration']

        # LOOP OVER POINTINGS
        for index in range(0, len(pointing_data)):
            RA_point = RA_data[index]
            DEC_point = DEC_data[index]
            coordinate_pointing = SkyCoord(
                ra=RA_point * u.degree,
                dec=DEC_point * u.degree,
                frame="icrs"
            )
            src_from_pointing = coordinate_pointing.separation(coordinate_source)

            t_in_point = Time(times[index])

            obs_condition = Observability(site=site)
            obs_condition.set_irf(irf_dict)
            obs_condition.Proposal_obTime = 10
            obs_condition.TimeOffset = 0
            obs_condition.Steps_observability = 10
            condition_check = obs_condition.check(RA=RA_point, DEC=DEC_point, t_start=t_in_point)

            # once the IRF has been chosen, the times are shifted
            # this is a quick and dirty solution to handle the times in ctools...not elegant for sure
            t_in_point = (Time(times[index]) - Time(time_onset_merger)).to(u.s)
            t_end_point = t_in_point + durations[index] * u.s

            if len(condition_check) == 0:
                print(f"Source Not Visible in pointing {index}")
                f.write(
                    f"{src_name}\t{ra_src}\t{dec_src}\t{seed}\t{index}\t{src_from_pointing.value:.2f}\t{src_from_pointing.value < sim_rad}\t{RA_point}\t{DEC_point}\t{sim_rad}\t{t_in_point.value:.2f}\t{t_end_point.value:.2f}\t -1 \t -1\n")
                continue

            name_irf = condition_check['IRF_name'][0]
            irf = condition_check['IRF'][0]
            # model loading

            if irf.prod_number == "3b" and irf.prod_version == 0:
                caldb = "prod3b"
            else:
                caldb = f'prod{irf.prod_number}-v{irf.prod_version}'

            # simulation
            sim = ctools.ctobssim()
            sim['inmodel'] = model_xml
            sim['caldb'] = caldb
            sim['irf'] = name_irf
            sim['ra'] = RA_point
            sim['dec'] = DEC_point
            sim['rad'] = sim_rad
            sim['tmin'] = t_in_point.value
            sim['tmax'] = t_end_point.value
            sim['emin'] = sim_e_min
            sim['emax'] = sim_e_max
            sim['seed'] = seed

            if save_simulation:
                event_list_path = create_path(f"{ctobss_params['output_path']}/{src_name}/seed-{seed:03}/")
                sim['outevents'] = f"{event_list_path}/event_list_source-{src_name}_seed-{seed:03}_pointingID-{index}.fits"
                sim.execute()
                f.write(
                    f"{src_name}\t{ra_src}\t{dec_src}\t{seed}\t{index}\t{src_from_pointing.value:.2f}\t{src_from_pointing.value < sim_rad}\t{RA_point}\t{DEC_point}\t{sim_rad}\t{t_in_point.value:.2f}\t{t_end_point.value:.2f}\t -1 \t -1\n"
                )
                continue
            else:
                sim.run()

            obs = sim.obs()

            obs.models(gammalib.GModels())

            # ctskymap

            sigma_onoff = -1
            sqrt_ts_like = -1

            if significance_map:
                pars_skymap = detection['parameters_skymap']
                scale = float(pars_skymap['scale'])
                npix = 2 * int(sim_rad / scale)

                fits_temp_title = f"{output_path}/GW-skymap_point-{index}_{seed}.fits"

                skymap = ctools.ctskymap(obs.copy())
                skymap['proj'] = 'CAR'
                skymap['coordsys'] = 'CEL'
                skymap['xref'] = RA_point
                skymap['yref'] = DEC_point
                skymap['binsz'] = scale
                skymap['nxpix'] = npix
                skymap['nypix'] = npix
                skymap['emin'] = sim_e_min
                skymap['emax'] = sim_e_max
                skymap['bkgsubtract'] = 'RING'
                skymap['roiradius'] = pars_skymap['roiradius']
                skymap['inradius'] = pars_skymap['inradius']
                skymap['outradius'] = pars_skymap['outradius']
                skymap['iterations'] = pars_skymap['iterations']
                skymap['threshold'] = pars_skymap['threshold']
                skymap['outmap'] = fits_temp_title
                skymap.execute()

                input_fits = fits.open(fits_temp_title)
                datain = input_fits['SIGNIFICANCE'].data
                datain[np.isnan(datain)] = 0.0
                datain[np.isinf(datain)] = 0.0

                sigma_onoff = np.max(datain)

                if pars_skymap['remove_fits']:
                    os.remove(fits_temp_title)

            if srcdetect_ctlike:
                pars_detect = detection['parameters_detect']
                scale = float(pars_detect['scale'])
                npix = 2 * int(sim_rad / scale)

                skymap = ctools.ctskymap(obs.copy())
                skymap['proj'] = 'TAN'
                skymap['coordsys'] = 'CEL'
                skymap['xref'] = RA_point
                skymap['yref'] = DEC_point
                skymap['binsz'] = scale
                skymap['nxpix'] = npix
                skymap['nypix'] = npix
                skymap['emin'] = sim_e_min
                skymap['emax'] = sim_e_max
                skymap['bkgsubtract'] = 'NONE'
                skymap.run()

                # cssrcdetect
                srcdetect = cscripts.cssrcdetect(skymap.skymap().copy())
                srcdetect['srcmodel'] = 'POINT'
                srcdetect['bkgmodel'] = 'NONE'
                srcdetect['corr_kern'] = 'GAUSSIAN'
                srcdetect['threshold'] = pars_detect['threshold']
                srcdetect['corr_rad'] = pars_detect['correlation']
                srcdetect.run()

                models = srcdetect.models()

                # if there's some detection we can do the likelihood.
                # Spectral model is a PL and the spatial model is the one from cssrcdetect
                if len(models) > 0:
                    hotspot = models['Src001']
                    ra_hotspot = hotspot['RA'].value()
                    dec_hotspot = hotspot['DEC'].value()

                    models_ctlike = gammalib.GModels()

                    src_dir = gammalib.GSkyDir()
                    src_dir.radec_deg(ra_hotspot, dec_hotspot)
                    spatial = gammalib.GModelSpatialPointSource(src_dir)

                    spectral = gammalib.GModelSpectralPlaw()
                    spectral['Prefactor'].value(5.5e-16)
                    spectral['Prefactor'].scale(1e-16)
                    spectral['Index'].value(-2.6)
                    spectral['Index'].scale(-1.0)
                    spectral['PivotEnergy'].value(50000)
                    spectral['PivotEnergy'].scale(1e3)

                    model_src = gammalib.GModelSky(spatial, spectral)
                    model_src.name('PL_fit_GW')
                    model_src.tscalc(True)

                    models_ctlike.append(model_src)

                    spectral_back = gammalib.GModelSpectralPlaw()
                    spectral_back['Prefactor'].value(1.0)
                    spectral_back['Prefactor'].scale(1.0)
                    spectral_back['Index'].value(0)
                    spectral_back['PivotEnergy'].value(300000)
                    spectral_back['PivotEnergy'].scale(1e6)

                    back_model = gammalib.GCTAModelIrfBackground()
                    back_model.instruments('CTA')
                    back_model.name('Background')
                    back_model.spectral(spectral_back.copy())
                    models_ctlike.append(back_model)

                    xmlmodel_PL_ctlike_std = f"{output_path}/model_PL_ctlike_std_seed-{seed}_pointing-{index}.xml"
                    models_ctlike.save(xmlmodel_PL_ctlike_std)

                    like_pl = ctools.ctlike(obs.copy())
                    like_pl['inmodel'] = xmlmodel_PL_ctlike_std
                    like_pl['caldb'] = caldb
                    like_pl['irf'] = name_irf
                    like_pl.run()

                    ts = -like_pl.obs().models()[0].ts()
                    if ts > 0:
                        sqrt_ts_like = np.sqrt(ts)
                    else:
                        sqrt_ts_like = 0

                    if pars_detect['remove_xml']:
                        os.remove(xmlmodel_PL_ctlike_std)

            f.write(
                f"{src_name}\t{ra_src}\t{dec_src}\t{seed}\t{index}\t{src_from_pointing.value:.2f}\t{src_from_pointing.value < sim_rad}\t{RA_point:.2f}\t{DEC_point:.2f}\t{sim_rad}\t{t_in_point:.2f}\t{t_end_point:.2f}\t{sigma_onoff:.2f}\t{sqrt_ts_like}\n")
 # convert norm from ph cm-2 s-1 TeV-1 (gamma-cat) to ph cm-2 s-1 MeV-1 (gammalib)
 norm *= 1.e-6
 index = np.double(index)
 norm = np.double(norm)
 # Set artifical cutoffs for sources measured with hard PL spectra without measured cutoff
 # Binaries and pulsars are skipped because they are addressed later
 # We also leave Westerlund 1 and HESS J1641-463 as PeVatron candidates
 if index < 2.4 and not source['classes'] == 'bin'\
         and not source['classes'] == 'psr'\
         and not source['common_name'] == 'Westerlund 1'\
         and not source['common_name'] == 'HESS J1641-463':
     # if source may be PWN treat as such
     if 'pwn' in source['classes']:
         # dummy model to obtain search radius
         mod = gammalib.GModelSky(spatial,
                                  gammalib.GModelSpectralPlaw())
         # search radius
         rad = get_model_radius(mod) + 0.2
         # set cutoff
         ecut = get_cutoff(ra, dec, 'PSR', rad_search=rad)
         ecut_pwn.append(ecut)
         n_ecut_pwn += 1
     # otherwise consider SNR
     elif 'snr' in source['classes']:
         # try to get Green name
         onames = source['other_names'].split(',')
         gname = [
             name for name in onames
             if name[:5] == 'SNR G' or name[0] == 'G'
         ]
         if len(gname) > 0:
Beispiel #18
0
def compact_sources(model_tot,
                    source_dict,
                    work_dir,
                    tscalc=True,
                    EBL_model='dominguez',
                    energy=np.logspace(-1, 5, 1000) * u.GeV):
    """
    Build a ctools model for the compact sources.
    
    Parameters
    ----------
    - model_tot: a gammalib.GModels object
    - source_dict (dictionary): the source dictionary 
    as defined by the CompactSource class
    - tscalc (bool): request TS computation or not
    - EBL_model (string): the EBL model to use

    Outputs
    --------
    - The model is updated to include the sources
    """

    Nsource = len(source_dict.name)

    for ips in range(Nsource):
        #----- Spatial model
        # PointSource
        if source_dict.spatial[ips]['type'] == 'PointSource':
            RA = source_dict.spatial[ips]['param']['RA']['value'].to_value(
                'deg')
            Dec = source_dict.spatial[ips]['param']['DEC']['value'].to_value(
                'deg')
            spatial = gammalib.GModelSpatialPointSource(RA, Dec)

        # Error
        else:
            raise ValueError('Spatial model not avaiable')

        #----- Spectral model
        # PowerLaw
        if source_dict.spectral[ips]['type'] == 'PowerLaw':
            prefact = source_dict.spectral[ips]['param']['Prefactor'][
                'value'].to_value('cm-2 s-1 MeV-1')
            index = source_dict.spectral[ips]['param']['Index']['value']
            pivot = gammalib.GEnergy(
                source_dict.spectral[ips]['param']['PivotEnergy']
                ['value'].to_value('TeV'), 'TeV')
            spectral0 = gammalib.GModelSpectralPlaw(prefact, index, pivot)

        # PowerLawExpCutoff
        elif source_dict.spectral[ips]['type'] == 'PowerLawExpCutoff':
            prefact = source_dict.spectral[ips]['param']['Prefactor'][
                'value'].to_value('cm-2 s-1 MeV-1')
            index = source_dict.spectral[ips]['param']['Index']['value']
            pivot = gammalib.GEnergy(
                source_dict.spectral[ips]['param']['PivotEnergy']
                ['value'].to_value('TeV'), 'TeV')
            cutoff = gammalib.GEnergy(
                source_dict.spectral[ips]['param']['Cutoff']['value'].to_value(
                    'TeV'), 'TeV')
            spectral0 = gammalib.GModelSpectralExpPlaw(prefact, index, pivot,
                                                       cutoff)

        # Error
        else:
            raise ValueError('Spectral model not available')

        # EBL absorb
        if EBL_model is not None and source_dict.redshift[ips] is not None:
            absorb = cluster_spectra.get_ebl_absorb(energy.to_value('GeV'),
                                                    source_dict.redshift[ips],
                                                    EBL_model)
            absmin = np.amin(absorb[absorb > 0])
            absorb[absorb == 0] = np.amin(np.array([absmin, 1e-16
                                                    ]))  # does not accept 0

            ebl_abs_file = work_dir + '/EBLmodel_' + source_dict.name[
                ips] + '.txt'
            save_txt_file(ebl_abs_file, energy.to_value('MeV'), absorb,
                          'energy (MeV)', 'Absorb')
            ebl_spec = gammalib.GModelSpectralFunc(ebl_abs_file, 1.0)
            ebl_spec['Normalization'].fix()
            doEBL = True
        else:
            doEBL = False

        #----- Temporal model
        # Constant
        if source_dict.temporal[ips]['type'] == 'Constant':
            temporal = gammalib.GModelTemporalConst(
                source_dict.temporal[ips]['param']['Normalization']['value'])

        # Error
        else:
            raise ValueError('Temporal model not available')

        #----- Parameter management
        spatial = manage_parameters(source_dict.spatial[ips]['param'], spatial)
        spectral0 = manage_parameters(source_dict.spectral[ips]['param'],
                                      spectral0)
        temporal = manage_parameters(source_dict.temporal[ips]['param'],
                                     temporal)

        #----- EBL x initial spectrum
        if doEBL:
            spectral = gammalib.GModelSpectralMultiplicative()
            spectral.append(spectral0)
            spectral.append(ebl_spec)
        else:
            spectral = spectral0

        #----- Overal model for each source
        model = gammalib.GModelSky(spatial, spectral, temporal)
        model.name(source_dict.name[ips])
        model.tscalc(tscalc)

        #----- Append model for each source
        model_tot.append(model)
def grb_simulation(sim_in, config_in, model_xml, fits_header_0, counter):
    """
    Function to handle the GRB simulation.
    :param sim_in: the yaml file for the simulation (unpacked as a dict of dicts)
    :param config_in: the yaml file for the job handling (unpacked as a dict of dicts)
    :param model_xml: the XML model name for the source under analysis
    :param fits_header_0: header for the fits file of the GRB model to use. Used in the visibility calculation
    :param counter: integer number. counts the id of the source realization
    :return: significance obtained with the activated detection methods
    """

    src_name = model_xml.split('/')[-1].split('model_')[1][:-4]
    print(src_name, counter)

    ctools_pipe_path = create_path(config_in['exe']['software_path'])
    ctobss_params = sim_in['ctobssim']

    seed = int(counter)*10

    # PARAMETERS FROM THE CTOBSSIM
    sim_t_min = u.Quantity(ctobss_params['time']['t_min']).to_value(u.s)
    sim_t_max = u.Quantity(ctobss_params['time']['t_max']).to_value(u.s)
    sim_e_min = u.Quantity(ctobss_params['energy']['e_min']).to_value(u.TeV)
    sim_e_max = u.Quantity(ctobss_params['energy']['e_max']).to_value(u.TeV)
    sim_rad = ctobss_params['radius']

    models = sim_in['source']
    source_type = models['type']

    if source_type == "GRB":
        phase_path = "/" + models['phase']
    elif source_type == "GW":
        phase_path = ""

    output_path = create_path(sim_in['output']['path'] + phase_path + '/' + src_name)

    save_simulation = ctobss_params['save_simulation']

    with open(f"{output_path}/GRB-{src_name}_seed-{seed}.txt", "w") as f:
        f.write(f"GRB,seed,time_start,time_end,sigma_lima,sqrt_TS_onoff,sqrt_TS_std\n")
        # VISIBILITY PART
        # choose between AUTO mode (use visibility) and MANUAL mode (manually insert IRF)
        simulation_mode = sim_in['IRF']['mode']

        if simulation_mode == "auto":
            print("using visibility to get IRFs")

            # GRB information from the fits header
            ra = fits_header_0['RA']
            dec = fits_header_0['DEC']
            t0 = Time(fits_header_0['GRBJD'])

            irf_dict = sim_in['IRF']
            site = irf_dict['site']
            obs_condition = Observability(site=site)
            obs_condition.set_irf(irf_dict)

            t_zero_mode = ctobss_params['time']['t_zero'].lower()

            if t_zero_mode == "VIS":
                # check if the source is visible one day after the onset of the source
                print("time starts when source becomes visible")
                obs_condition.Proposal_obTime = 86400
                condition_check = obs_condition.check(RA=ra, DEC=dec, t_start=t0)

            elif t_zero_mode == "ONSET":
                print("time starts from the onset of the GRB")
                condition_check = obs_condition.check(RA=ra, DEC=dec, t_start=t0, t_min=sim_t_min, t_max=sim_t_max)

            else:
                print(f"Choose some proper mode between 'VIS' and 'ONSET'. {t_zero_mode} is not a valid one.")
                sys.exit()

            # NO IRF in AUTO mode ==> No simulation! == EXIT!
            if len(condition_check) == 0:
                f.write(f"{src_name},{seed}, -1, -1, -1, -1, -1\n")
                sys.exit()

        elif simulation_mode == "manual":
            print("manual picking IRF")

            # find proper IRF name
            irf = IRFPicker(sim_in, ctools_pipe_path)
            name_irf = irf.irf_pick()

            backgrounds_path = create_path(ctobss_params['bckgrnd_path'])
            fits_background_list = glob.glob(
                f"{backgrounds_path}/{irf.prod_number}_{irf.prod_version}_{name_irf}/background*.fits")

            if len(fits_background_list) == 0:
                print(f"No background for IRF {name_irf}")
                sys.exit()

            fits_background_list = sorted(fits_background_list, key=sort_background)
            background_fits = fits_background_list[int(counter) - 1]
            obs_back = gammalib.GCTAObservation(background_fits)

        else:
            print(f"wrong input for IRF - mode. Input is {simulation_mode}. Use 'auto' or 'manual' instead")
            sys.exit()

        if irf.prod_number == "3b" and irf.prod_version == 0:
            caldb = "prod3b"
        else:
            caldb = f'prod{irf.prod_number}-v{irf.prod_version}'

        # source simulation
        sim = ctools.ctobssim()
        sim['inmodel'] = model_xml
        sim['caldb'] = caldb
        sim['irf'] = name_irf
        sim['ra'] = 0.0
        sim['dec'] = 0.0
        sim['rad'] = sim_rad
        sim['tmin'] = sim_t_min
        sim['tmax'] = sim_t_max
        sim['emin'] = sim_e_min
        sim['emax'] = sim_e_max
        sim['seed'] = seed
        sim.run()

        obs = sim.obs()

        # # move the source photons from closer to (RA,DEC)=(0,0), where the background is located
        # for event in obs[0].events():
        #     # ra_evt = event.dir().dir().ra()
        #     dec_evt = event.dir().dir().dec()
        #     ra_evt_deg = event.dir().dir().ra_deg()
        #     dec_evt_deg = event.dir().dir().dec_deg()
        #
        #     ra_corrected = (ra_evt_deg - ra_pointing)*np.cos(dec_evt)
        #     dec_corrected = dec_evt_deg - dec_pointing
        #     event.dir().dir().radec_deg(ra_corrected, dec_corrected)

        # append all background events to GRB ones ==> there's just one observation and not two
        for event in obs_back.events():
            obs[0].events().append(event)

        # ctselect to save data on disk
        if save_simulation:
            event_list_path = create_path(f"{ctobss_params['output_path']}/{src_name}/")
            #obs.save(f"{event_list_path}/event_list_source-{src_name}_seed-{seed:03}.fits")

            select_time = ctools.ctselect(obs)
            select_time['rad'] = sim_rad
            select_time['tmin'] = sim_t_min
            select_time['tmax'] = sim_t_max
            select_time['emin'] = sim_e_min
            select_time['emax'] = sim_e_max
            select_time['outobs'] = f"{event_list_path}/event_list_source-{src_name}_{seed:03}.fits"
            select_time.run()
            sys.exit()

        # delete all 70+ models from the obs def file...not needed any more
        obs.models(gammalib.GModels())

        # CTSELECT
        select_time = sim_in['ctselect']['time_cut']
        slices = int(select_time['t_slices'])

        if slices == 0:
            times = [sim_t_min, sim_t_max]
            times_start = times[:-1]
            times_end = times[1:]
        elif slices > 0:
            time_mode = select_time['mode']
            if time_mode == "log":
                times = np.logspace(np.log10(sim_t_min), np.log10(sim_t_max), slices + 1, endpoint=True)
            elif time_mode == "lin":
                times = np.linspace(sim_t_min, sim_t_max, slices + 1, endpoint=True)
            else:
                print(f"{time_mode} not valid. Use 'log' or 'lin' ")
                sys.exit()

            if select_time['obs_mode'] == "iter":
                times_start = times[:-1]
                times_end = times[1:]
            elif select_time['obs_mode'] == "cumul":
                times_start = np.repeat(times[0], slices)         # this is to use the same array structure for the loop
                times_end = times[1:]
            elif select_time['obs_mode'] == "all":
                begins, ends = np.meshgrid(times[:-1], times[1:])
                mask_times = begins < ends
                times_start = begins[mask_times].ravel()
                times_end = ends[mask_times].ravel()
            else:
                print(f"obs_mode: {select_time['obs_mode']} not supported")
                sys.exit()

        else:
            print(f"value {slices} not supported...check yaml file")
            sys.exit()

        # ------------------------------------
        # ----- TIME LOOP STARTS HERE --------
        # ------------------------------------

        ctlike_mode = sim_in['detection']
        mode_1 = ctlike_mode['counts']
        mode_2 = ctlike_mode['ctlike-onoff']
        mode_3 = ctlike_mode['ctlike-std']

        for t_in, t_end in zip(times_start, times_end):
            sigma_onoff = 0
            sqrt_ts_like_onoff = 0
            sqrt_ts_like_std = 0
            print("-----------------------------")
            print(f"t_in: {t_in:.2f}, t_end: {t_end:.2f}")

            # different ctlikes (onoff or std) need different files.
            # will be appended here and used later on for the final likelihood
            dict_obs_select_time = {}

            # perform time selection for this specific time bin
            select_time = ctools.ctselect(obs)
            select_time['rad'] = sim_rad
            select_time['tmin'] = t_in
            select_time['tmax'] = t_end
            select_time['emin'] = sim_e_min
            select_time['emax'] = sim_e_max
            select_time.run()

            if mode_1:
                fits_temp_title = f"skymap_{seed}_{t_in:.2f}_{t_end:.2f}.fits"
                pars_counts = ctlike_mode['pars_counts']
                scale = float(pars_counts['scale'])
                npix = 2*int(sim_rad/scale)
                skymap = ctools.ctskymap(select_time.obs().copy())
                skymap['emin'] = sim_e_min
                skymap['emax'] = sim_e_max
                skymap['nxpix'] = npix
                skymap['nypix'] = npix
                skymap['binsz'] = scale
                skymap['proj'] = 'TAN'
                skymap['coordsys'] = 'CEL'
                skymap['xref'] = 0
                skymap['yref'] = 0
                skymap['bkgsubtract'] = 'RING'
                skymap['roiradius'] = pars_counts['roiradius']
                skymap['inradius'] = pars_counts['inradius']
                skymap['outradius'] = pars_counts['outradius']
                skymap['iterations'] = pars_counts['iterations']
                skymap['threshold'] = pars_counts['threshold']
                skymap['outmap'] = fits_temp_title
                skymap.execute()

                input_fits = fits.open(fits_temp_title)
                datain = input_fits[2].data
                datain[np.isnan(datain)] = 0.0
                datain[np.isinf(datain)] = 0.0

                sigma_onoff = np.max(datain)
                os.remove(fits_temp_title)

            if mode_3:
                dict_obs_select_time['std'] = select_time.obs().copy()

            if mode_2:
                onoff_time_sel = cscripts.csphagen(select_time.obs().copy())
                onoff_time_sel['inmodel'] = 'NONE'
                onoff_time_sel['ebinalg'] = 'LOG'
                onoff_time_sel['emin'] = sim_e_min
                onoff_time_sel['emax'] = sim_e_max
                onoff_time_sel['enumbins'] = 30
                onoff_time_sel['coordsys'] = 'CEL'
                onoff_time_sel['ra'] = 0.0
                onoff_time_sel['dec'] = 0.5
                onoff_time_sel['rad'] = 0.2
                onoff_time_sel['bkgmethod'] = 'REFLECTED'
                onoff_time_sel['use_model_bkg'] = False
                onoff_time_sel['stack'] = False
                onoff_time_sel.run()

                dict_obs_select_time['onoff'] = onoff_time_sel.obs().copy()

                del onoff_time_sel

                # print(f"sigma ON/OFF: {sigma_onoff:.2f}")

            if mode_2 or mode_3:

                # Low Energy PL fitting
                # to be saved in this dict
                dict_pl_ctlike_out = {}

                e_min_pl_ctlike = 0.030
                e_max_pl_ctlike = 0.080

                # simple ctobssim copy and select for ctlike-std
                select_pl_ctlike = ctools.ctselect(select_time.obs().copy())
                select_pl_ctlike['rad'] = 3
                select_pl_ctlike['tmin'] = t_in
                select_pl_ctlike['tmax'] = t_end
                select_pl_ctlike['emin'] = e_min_pl_ctlike
                select_pl_ctlike['emax'] = e_max_pl_ctlike
                select_pl_ctlike.run()

                # create test source
                src_dir = gammalib.GSkyDir()
                src_dir.radec_deg(0, 0.5)
                spatial = gammalib.GModelSpatialPointSource(src_dir)

                # create and append source spectral model
                spectral = gammalib.GModelSpectralPlaw()
                spectral['Prefactor'].value(5.5e-16)
                spectral['Prefactor'].scale(1e-16)
                spectral['Index'].value(-2.6)
                spectral['Index'].scale(-1.0)
                spectral['PivotEnergy'].value(50000)
                spectral['PivotEnergy'].scale(1e3)
                model_src = gammalib.GModelSky(spatial, spectral)
                model_src.name('PL_fit_temp')
                model_src.tscalc(True)

                spectral_back = gammalib.GModelSpectralPlaw()
                spectral_back['Prefactor'].value(1.0)
                spectral_back['Prefactor'].scale(1.0)
                spectral_back['Index'].value(0)
                spectral_back['PivotEnergy'].value(300000)
                spectral_back['PivotEnergy'].scale(1e6)

                if mode_2:
                    back_model = gammalib.GCTAModelIrfBackground()
                    back_model.instruments('CTAOnOff')
                    back_model.name('Background')
                    back_model.spectral(spectral_back.copy())

                    onoff_pl_ctlike_lima = cscripts.csphagen(select_pl_ctlike.obs().copy())
                    onoff_pl_ctlike_lima['inmodel'] = 'NONE'
                    onoff_pl_ctlike_lima['ebinalg'] = 'LOG'
                    onoff_pl_ctlike_lima['emin'] = e_min_pl_ctlike
                    onoff_pl_ctlike_lima['emax'] = e_max_pl_ctlike
                    onoff_pl_ctlike_lima['enumbins'] = 30
                    onoff_pl_ctlike_lima['coordsys'] = 'CEL'
                    onoff_pl_ctlike_lima['ra'] = 0.0
                    onoff_pl_ctlike_lima['dec'] = 0.5
                    onoff_pl_ctlike_lima['rad'] = 0.2
                    onoff_pl_ctlike_lima['bkgmethod'] = 'REFLECTED'
                    onoff_pl_ctlike_lima['use_model_bkg'] = False
                    onoff_pl_ctlike_lima['stack'] = False
                    onoff_pl_ctlike_lima.run()

                    onoff_pl_ctlike_lima.obs().models(gammalib.GModels())
                    onoff_pl_ctlike_lima.obs().models().append(model_src.copy())
                    onoff_pl_ctlike_lima.obs().models().append(back_model.copy())

                    like_pl = ctools.ctlike(onoff_pl_ctlike_lima.obs())
                    like_pl['refit'] = True
                    like_pl.run()
                    dict_pl_ctlike_out['onoff'] = like_pl.obs().copy()
                    del onoff_pl_ctlike_lima
                    del like_pl

                if mode_3:
                    models_ctlike_std = gammalib.GModels()
                    models_ctlike_std.append(model_src.copy())
                    back_model = gammalib.GCTAModelIrfBackground()
                    back_model.instruments('CTA')
                    back_model.name('Background')
                    back_model.spectral(spectral_back.copy())
                    models_ctlike_std.append(back_model)

                    # save models
                    xmlmodel_PL_ctlike_std = 'test_model_PL_ctlike_std.xml'
                    models_ctlike_std.save(xmlmodel_PL_ctlike_std)
                    del models_ctlike_std

                    like_pl = ctools.ctlike(select_pl_ctlike.obs().copy())
                    like_pl['inmodel'] = xmlmodel_PL_ctlike_std
                    like_pl['refit'] = True
                    like_pl.run()
                    dict_pl_ctlike_out['std'] = like_pl.obs().copy()
                    del like_pl

                del spatial
                del spectral
                del model_src
                del select_pl_ctlike

                # EXTENDED CTLIKE
                for key in dict_obs_select_time.keys():
                    likelihood_pl_out = dict_pl_ctlike_out[key]
                    selected_data = dict_obs_select_time[key]

                    pref_out_pl = likelihood_pl_out.models()[0]['Prefactor'].value()
                    index_out_pl = likelihood_pl_out.models()[0]['Index'].value()
                    pivot_out_pl = likelihood_pl_out.models()[0]['PivotEnergy'].value()

                    expplaw = gammalib.GModelSpectralExpPlaw()
                    expplaw['Prefactor'].value(pref_out_pl)
                    expplaw['Index'].value(index_out_pl)
                    expplaw['PivotEnergy'].value(pivot_out_pl)
                    expplaw['CutoffEnergy'].value(80e3)

                    if key == "onoff":
                        selected_data.models()[0].name(src_name)
                        selected_data.models()[0].tscalc(True)
                        selected_data.models()[0].spectral(expplaw.copy())

                        like = ctools.ctlike(selected_data)
                        like['refit'] = True
                        like.run()
                        ts = like.obs().models()[0].ts()
                        if ts > 0:
                            sqrt_ts_like_onoff = np.sqrt(like.obs().models()[0].ts())
                        else:
                            sqrt_ts_like_onoff = 0

                        del like

                    if key == "std":
                        models_fit_ctlike = gammalib.GModels()

                        # create test source
                        src_dir = gammalib.GSkyDir()
                        src_dir.radec_deg(0, 0.5)
                        spatial = gammalib.GModelSpatialPointSource(src_dir)

                        # append spatial and spectral models
                        model_src = gammalib.GModelSky(spatial, expplaw.copy())
                        model_src.name('Source_fit')
                        model_src.tscalc(True)
                        models_fit_ctlike.append(model_src)

                        # create and append background
                        back_model = gammalib.GCTAModelIrfBackground()
                        back_model.instruments('CTA')
                        back_model.name('Background')
                        spectral_back = gammalib.GModelSpectralPlaw()
                        spectral_back['Prefactor'].value(1.0)
                        spectral_back['Prefactor'].scale(1.0)
                        spectral_back['Index'].value(0)
                        spectral_back['PivotEnergy'].value(300000)
                        spectral_back['PivotEnergy'].scale(1e6)
                        back_model.spectral(spectral_back)
                        models_fit_ctlike.append(back_model)

                        # save models
                        input_ctlike_xml = "model_GRB_fit_ctlike_in.xml"
                        models_fit_ctlike.save(input_ctlike_xml)
                        del models_fit_ctlike

                        like = ctools.ctlike(selected_data)
                        like['inmodel'] = input_ctlike_xml
                        like['refit'] = True
                        like.run()
                        ts = like.obs().models()[0].ts()
                        if ts > 0:
                            sqrt_ts_like_std = np.sqrt(like.obs().models()[0].ts())
                        else:
                            sqrt_ts_like_std = 0

                        del like

                    # E_cut_off = like.obs().models()[0]['CutoffEnergy'].value()
                    # E_cut_off_error = like.obs().models()[0]['CutoffEnergy'].error()

                    # print(f"sqrt(TS) {key}: {np.sqrt(ts_like):.2f}")
                    # print(f"E_cut_off {key}: {E_cut_off:.2f} +- {E_cut_off_error:.2f}")
                del dict_pl_ctlike_out

            f.write(f"{src_name},{seed},{t_in:.2f},{t_end:.2f},{sigma_onoff:.2f},{sqrt_ts_like_onoff:.2f},{sqrt_ts_like_std:.2f}\n")
            del dict_obs_select_time
            del select_time
Beispiel #20
0
def dealWithModelFile(cfg):
    """
    Import infos from configuration file and create a model file
    for the analysis
    """
    # Create model container
    models = gammalib.GModels()

    # coordinates
    src_dir = gammalib.GSkyDir()
    src_dir.radec_deg(cfg.getValue('model', 'coords', 'ra'),
                      cfg.getValue('model', 'coords', 'dec'))

    # spatial model
    spatial = None
    spectral = None
    opt_spatial = cfg.getValue('model', 'spatial')
    if opt_spatial == 'plike':
        spatial = gammalib.GModelSpatialPointSource(src_dir)
        spatial['RA'].min(-360.)
        spatial['RA'].max(360.)
        spatial['DEC'].min(-90.)
        spatial['DEC'].max(90.)
        if cfg.getValue('model', 'coords', 'fitposition') is True:
            spatial['RA'].free()
            spatial['DEC'].free()

    else:  # TODO
        pass

    # spectral model
    opt_spectral = cfg.getValue('model', 'spectral')
    if opt_spectral == 'pwl':
        spectral = gammalib.GModelSpectralPlaw()
        # handle prefactor
        prefactor = cfg.getValue('model', 'pwl', 'prefactor')
        spectral['Prefactor'].value(prefactor * 1.e-17)
        spectral['Prefactor'].min(1.e-24)
        spectral['Prefactor'].max(1.e-14)
        spectral['Prefactor'].scale(1.e-17)
        # handle scale
        scale = cfg.getValue('model', 'pwl', 'scale')
        spectral['PivotEnergy'].value(scale * 1.e6)
        spectral['PivotEnergy'].scale(1.e6)
        spectral['PivotEnergy'].min(1.e4)
        spectral['PivotEnergy'].max(1.e9)
        # handle index
        index = cfg.getValue('model', 'pwl', 'index')
        spectral['Index'].value(index)
        spectral['Index'].scale(-1.)
        spectral['Index'].min(-0)
        spectral['Index'].max(-5)
    elif opt_spectral == 'logpwl':
        spectral = gammalib.GModelSpectralLogParabola()
        # handle prefactor
        prefactor = cfg.getValue('model', 'logpwl', 'prefactor')
        spectral['Prefactor'].value(prefactor * 1.e-17)
        spectral['Prefactor'].min(1.e-24)
        spectral['Prefactor'].max(1.e-14)
        spectral['Prefactor'].scale(1.e-17)
        # handle scale
        scale = cfg.getValue('model', 'logpwl', 'scale')
        spectral['PivotEnergy'].value(scale * 1.e6)
        spectral['PivotEnergy'].scale(1.e6)
        spectral['PivotEnergy'].min(1.e4)
        spectral['PivotEnergy'].max(1.e9)
        # handle index
        index = cfg.getValue('model', 'logpwl', 'index')
        spectral['Index'].value(index)
        spectral['Index'].scale(-1.)
        spectral['Index'].min(-0)
        spectral['Index'].max(-5)
        # handle curvature
        curvature = cfg.getValue('model', 'logpwl', 'curvature')
        spectral['Curvature'].value(curvature)
        spectral['Curvature'].scale(-1.)
        spectral['Curvature'].min(5)
        spectral['Curvature'].max(-5)
    elif opt_spectral == 'exppwl':
        spectral = gammalib.GModelSpectralExpPlaw()
        # handle prefactor
        prefactor = cfg.getValue('model', 'exppwl', 'prefactor')
        spectral['Prefactor'].value(prefactor * 1.e-17)
        spectral['Prefactor'].min(1.e-24)
        spectral['Prefactor'].max(1.e-14)
        spectral['Prefactor'].scale(1.e-17)
        # handle scale
        scale = cfg.getValue('model', 'exppwl', 'scale')
        spectral['PivotEnergy'].value(scale * 1.e6)
        spectral['PivotEnergy'].scale(1.e6)
        spectral['PivotEnergy'].min(1.e4)
        spectral['PivotEnergy'].max(1.e9)
        # handle index
        index = cfg.getValue('model', 'exppwl', 'index')
        spectral['Index'].value(index)
        spectral['Index'].scale(-1.)
        spectral['Index'].min(-0)
        spectral['Index'].max(-5)
        # handle index
        cutoff = cfg.getValue('model', 'exppwl', 'cutoff')
        spectral['CutoffEnergy'].value(cutoff * 1.e6)
        spectral['CutoffEnergy'].scale(1.e6)
        spectral['CutoffEnergy'].min(1.e4)
        spectral['CutoffEnergy'].max(1.e9)
    else:
        pass

    model = gammalib.GModelSky(spatial, spectral)
    models.append(model)

    outputdir = cfg.getValue('general', 'outputdir')
    models.save(outputdir + '/' + cfg.getValue('model', 'output'))
    # print(models)
    del models
def set_source_model(srcmodel, spec='plaw'):
    """
    Set source model

    Parameters
    ----------
    srcmodel : str
        Source model name
    spec : str, optional
        Spectral model

    Returns
    -------
    source : `~gammalib.GModelSky()`
        Source model
    """
    # Set spectral component
    if spec == 'plaw':
        spectral = gammalib.GModelSpectralPlaw(1.0e-17, -2.0,
                                               gammalib.GEnergy(1.0, 'TeV'))
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'plaw145':
        spectral = gammalib.GModelSpectralPlaw(1.0e-17, -2.0,
                                               gammalib.GEnergy(1.45, 'TeV'))
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'eplaw':
        spectral = gammalib.GModelSpectralExpPlaw(
            1.0e-17, -2.0, gammalib.GEnergy(1.0, 'TeV'),
            gammalib.GEnergy(10.0, 'TeV'))
        spectral['Prefactor'].min(1.0e-25)
        spectral['CutoffEnergy'].min(3.0e6)
        spectral['CutoffEnergy'].max(1.0e12)
    elif spec == 'inveplaw':
        spectral = gammalib.GModelSpectralExpInvPlaw(
            1.0e-17, -2.0, gammalib.GEnergy(1.0, 'TeV'),
            gammalib.GEnergy(10.0, 'TeV'))
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'logparabola':
        spectral = gammalib.GModelSpectralLogParabola(
            1.0e-17, -2.0, gammalib.GEnergy(1.0, 'TeV'), -0.3)
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'fplaw':
        spectral = gammalib.GModelSpectralPlawPhotonFlux(
            1.0e-11, -2.0, gammalib.GEnergy(1.0, 'TeV'),
            gammalib.GEnergy(100.0, 'TeV'))
        spectral['PhotonFlux'].min(1.0e-25)
    elif spec == 'aharonian2006':
        spectral = gammalib.GModelSpectralExpPlaw(
            3.84e-17, -2.41, gammalib.GEnergy(1.0, 'TeV'),
            gammalib.GEnergy(15.1, 'TeV'))
        spectral['Prefactor'].fix()
        spectral['Index'].fix()
        spectral['CutoffEnergy'].fix()
    elif spec == 'nigro2019':
        spectral = gammalib.GModelSpectralLogParabola(
            4.47e-17, -2.39, gammalib.GEnergy(1.0, 'TeV'), -0.16)
        spectral['Prefactor'].fix()
        spectral['Index'].fix()
        spectral['Curvature'].fix()

    # Set spatial component
    dir = gammalib.GSkyDir()
    dir.radec_deg(83.6331, 22.0145)
    if srcmodel == 'ptsrc':
        spatial = gammalib.GModelSpatialPointSource(dir)
    elif srcmodel == 'gauss':
        spatial = gammalib.GModelSpatialRadialGauss(dir, 0.1)
        spatial['Sigma'].min(0.0001)
        spatial['Sigma'].free()
    elif srcmodel == 'egauss':
        spatial = gammalib.GModelSpatialEllipticalGauss(dir, 0.02, 0.01, 0.0)
        spatial['MinorRadius'].min(0.0001)
        spatial['MinorRadius'].free()
        spatial['MajorRadius'].min(0.0001)
        spatial['MajorRadius'].free()
        spatial['PA'].free()
    spatial['RA'].free()
    spatial['DEC'].free()

    # Set source model
    source = gammalib.GModelSky(spatial, spectral)
    source.name('Crab')
    source.tscalc(True)

    # Return source model
    return source
Beispiel #22
0
def append_hawc(models,
                bmax,
                pwn_models,
                pwn_dict,
                pwn_distx,
                pwn_disty,
                pwn_radr,
                pwn_frlog,
                dist_sigma=3.,
                radmin=0.05):
    """
    Append missing models from HAWC catalog to gammalib model container
    :param models: input gammalib model container
    :param models: ~gammalib.GModels, gammalib model container
    :param bmax: float, maximum latitude of models to include
    :param dist_sigma: float, minimum distance in sigma's from pre-existing source to add as new
    """

    # pre-filter known sources based on information in the hawc catalog
    sources = hawc_sources[hawc_sources['dist_tevcat'] > dist_sigma *
                           hawc_sources['pos_err']]

    # prepare new gammalib model container
    newpt = 0
    newext = 0
    newmodels = gammalib.GModels()
    warning = ''
    n_pwn_del = 0

    # loop over sources and compare with input models
    for hsource in sources:
        # assume source is new
        new = 1
        # hawc source position as gammalib.GSkyDir
        hdir = gammalib.GSkyDir()
        ra = np.double(hsource['ra'])
        dec = np.double(hsource['dec'])
        hdir.radec_deg(ra, dec)
        # hawc source radius
        hradius = hsource['radius']
        ######################################### treat pointlike sources for HAWC ###########
        if hradius == 0.:
            # case of sources pointlike for HAWC
            # loop over gammalib container and determine closest neighbor
            # initialize at 1000
            dist_min = 1000.
            for source in models:
                dir = get_model_dir(source)
                dist = hdir.dist_deg(dir)
                dist_min = np.minimum(dist, dist_min)
            if dist_min < dist_sigma * hsource['pos_err']:
                # closeby source foud in container, source will not be added
                new = 0
            else:
                # source will be added to container, set spatial model
                spatial = gammalib.GModelSpatialPointSource(hdir)
                newpt += 1
        ######################################### treat extended sources for HAWC ############
        else:
            # "corrected" distance, i.e, centre distance - radius of source - error on position
            # initialize at 1000
            dist_corr = 1000.
            for source in models:
                dir = get_model_dir(source)
                dist = dir.dist_deg(dir)
                # get source radius according to model used
                radius = get_model_radius(source)
                # use as radius the max between HAWC and model
                radius = np.maximum(hradius, radius)
                # subtract from distance the max radius
                dist -= radius + hsource['pos_err']
                dist_corr = np.minimum(dist, dist_corr)
            if dist_corr < 0.:
                # overlapping source foud in container, source will not be added
                new = 0
            else:
                # source will be added to container, set spatial model
                spatial = gammalib.GModelSpatialRadialDisk(hdir, hradius)
        ######################################### spectra #####################################
        if new == 1 and np.abs(hdir.b_deg()) < bmax:
            # spectral model
            # identify spectral model in table 3
            spectrum = hawc_spectra[
                (hawc_spectra['name'] == hsource['name'])
                & (hawc_spectra['radius'] == hsource['radius'])][0]
            # flux scaling factor
            # 1e-15 ph TeV-1 -> ph MeV-1
            spectral = gammalib.GModelSpectralPlaw(1.e-21 * spectrum['F7'],
                                                   spectrum['index'], eref)
            if spectrum['index'] > -2.4:
                warning += '2HWC source {} has hard index {}'.format(
                    hawc_spectra['name'], spectrum['index'])
            # assemble model and append to container
            model = gammalib.GModelSky(spatial, spectral)
            model.name(hsource['name'])
            newmodels.append(model)
            # delete synthetic PWN
            rname, pwn_dict, distx, disty, radr, frlog = find_source_to_delete(
                pwn_dict,
                hdir.l_deg(),
                hdir.b_deg(),
                get_model_radius(model),
                flux_Crab(model, 1., 1000.),
                radmin=radmin)
            pwn_models.remove(rname)
            n_pwn_del += 1
            pwn_distx.append(distx)
            pwn_disty.append(disty)
            pwn_radr.append(radr)
            pwn_frlog.append(frlog)
        else:
            # source already present, skip
            pass

    # add new models to original container
    for model in newmodels:
        models.append(model)

    return models, newpt, newext, warning, pwn_models, n_pwn_del, pwn_distx, pwn_disty, pwn_radr, pwn_frlog
Beispiel #23
0
    def _background_spectrum(self, prefactor, index, emin=0.01, emax=100.0):
        """
        Create a background spectrum model dependent on user parameters
        
        Parameters
        ----------
        prefactor : float
            Power law prefactor of spectral model
        index : float
            Power law index of spectral model
        emin : float
            Minimum energy (in case a spectral node function is required)
        emax : float
            Maximum energy (in case a spectral node function is required)
        
        Returns
        -------
        spec : `~gammalib.GModelSpectral()`
            Spectral model for the background shape     
        """
        # Handle constant spectral model
        if index == 0.0 and self._bkgpars <= 1:
            spec = gammalib.GModelSpectralConst()

            # Set parameter range
            spec['Normalization'].min(prefactor / self._bkg_range_factor)
            spec['Normalization'].max(prefactor * self._bkg_range_factor)
            spec['Normalization'].value(prefactor)

            # Freeze or release normalisation parameter
            if self._bkgpars == 0:
                spec['Normalization'].fix()
            else:
                spec['Normalization'].free()

        else:

            # Create power law model
            if self._bkgpars <= 2:

                # Set Power Law model with arbitrary pivot energy
                pivot = gammalib.GEnergy(1.0, 'TeV')
                spec = gammalib.GModelSpectralPlaw(prefactor, index, pivot)

                # Set parameter ranges
                spec[0].min(prefactor / self._bkg_range_factor)
                spec[0].max(prefactor * self._bkg_range_factor)
                spec[1].scale(1)
                spec[1].min(-5.0)
                spec[1].max(5.0)

                # Set number of free parameters
                if self._bkgpars == 0:
                    spec[0].fix()
                    spec[1].fix()
                elif self._bkgpars == 1:
                    spec[0].free()
                    spec[1].fix()
                else:
                    spec[0].free()
                    spec[1].free()

            else:

                # Create reference powerlaw
                pivot = gammalib.GEnergy(1.0, 'TeV')
                plaw = gammalib.GModelSpectralPlaw(prefactor, index, pivot)

                # Create spectral model and energy values
                spec = gammalib.GModelSpectralNodes()

                # Create logarithmic energy nodes
                bounds = gammalib.GEbounds(self._bkgpars,
                                           gammalib.GEnergy(emin, 'TeV'),
                                           gammalib.GEnergy(emax, 'TeV'), True)

                # Loop over bounds and set intensity value
                for i in range(bounds.size()):
                    energy = bounds.elogmean(i)
                    value = plaw.eval(energy)

                    # Append energy, value - tuple to node function
                    spec.append(energy, value)

                # Loop over parameters
                for par in spec:

                    # Fix energy nodes
                    if 'Energy' in par.name():
                        par.fix()

                    # Release intensity nodes
                    elif 'Intensity' in par.name():
                        value = par.value()
                        par.scale(value)
                        par.min(value / self._bkg_range_factor)
                        par.max(value * self._bkg_range_factor)

        # Return spectrum
        return spec
Beispiel #24
0
def set_source_model(srcmodel, spec='plaw'):
    """
    Set source model

    Parameters
    ----------
    srcmodel : str
        Source model name
    spec : str, optional
        Spectral model

    Returns
    -------
    source : `~gammalib.GModelSky()`
        Source model
    """
    # Set spectral component
    if spec == 'plaw':
        spectral = gammalib.GModelSpectralPlaw(7.0e-17, -3.0,
                                               gammalib.GEnergy(1.0,'TeV'))
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'eplaw':
        spectral = gammalib.GModelSpectralExpPlaw(7.0e-17, -3.0,
                                                  gammalib.GEnergy(1.0,'TeV'),
                                                  gammalib.GEnergy(3.0,'TeV'))
        spectral['Prefactor'].min(1.0e-25)
        spectral['CutoffEnergy'].min(1.0e5)
        spectral['CutoffEnergy'].max(1.0e8)
    elif spec == 'logparabola':
        spectral = gammalib.GModelSpectralLogParabola(7.0e-17, -3.0,
                                                      gammalib.GEnergy(1.0,'TeV'),
                                                      -0.8)
        spectral['Prefactor'].min(1.0e-25)
    elif spec == 'fplaw200':
        spectral = gammalib.GModelSpectralPlawPhotonFlux(1.0e-10, -2.0,
                                                         gammalib.GEnergy(0.2,'TeV'),
                                                         gammalib.GEnergy(100.0,'TeV'))
        spectral['PhotonFlux'].min(1.0e-25)
    elif spec == 'fplaw300':
        spectral = gammalib.GModelSpectralPlawPhotonFlux(1.0e-10, -2.0,
                                                         gammalib.GEnergy(0.3,'TeV'),
                                                         gammalib.GEnergy(100.0,'TeV'))
        spectral['PhotonFlux'].min(1.0e-25)
    elif spec == 'fplaw700':
        spectral = gammalib.GModelSpectralPlawPhotonFlux(1.0e-10, -3.3,
                                                         gammalib.GEnergy(0.7,'TeV'),
                                                         gammalib.GEnergy(100.0,'TeV'))
        spectral['PhotonFlux'].min(1.0e-25)
        spectral['Index'].min(-5.0)
        spectral['Index'].max(-1.5)

    # Set spatial component
    dir = gammalib.GSkyDir()
    dir.radec_deg(329.71694, -30.22559)
    if srcmodel == 'ptsrc':
        spatial = gammalib.GModelSpatialPointSource(dir)
    elif srcmodel == 'gauss':
        spatial = gammalib.GModelSpatialRadialGauss(dir, 0.1)
        spatial['Sigma'].min(0.0001)
        spatial['Sigma'].free()
    spatial['RA'].free()
    spatial['DEC'].free()

    # Set source model
    source = gammalib.GModelSky(spatial, spectral)
    source.name('PKS 2155-304')
    source.tscalc(True)

    # Return source model
    return source
Beispiel #25
0
def show_one_sensitivity(rsp,
                         name,
                         color='r',
                         duration=180000.0,
                         alpha=0.2,
                         sigma=5.0):
    """
    Show one sensitivity

    Parameters
    ----------
    rsp : `~gammalib.GCTAResponse`
        Response function
    name : str
        Name of the response function
    color : str, optional
        Color for plot
    duration : float, optional
        Duration of observation (s)
    alpha : float, optional
        Ratio of on-to-off exposure
    sigma : float, optional
        Required detection significance in Gaussian sigma
    """
    # Set constants
    r68_to_sigma = 0.6624305
    TeV2erg = 1.0e6 * gammalib.MeV2erg

    # Set to figure 3
    plt.figure(3)

    # Generate logE(TeV) vector
    nbins = 20
    logE = [-1.7 + 0.2 * i for i in range(nbins)]
    E = [math.pow(10.0, e) for e in logE]

    # Generate sensitivity vector
    flux = [0.0 for i in range(nbins)]
    for i in range(nbins):
        ewidth     = (math.pow(10.0, logE[i]+0.1) - \
                      math.pow(10.0, logE[i]-0.1))*1.0e6
        aeff = rsp.aeff()(logE[i])
        r68 = rsp.psf().delta_max(logE[i]) / 5.0 / r68_to_sigma
        solidangle = gammalib.twopi * (1.0 - math.cos(r68))
        bgd_counts = rsp.background()(logE[i], 0.0,
                                      0.0) * duration * ewidth * solidangle
        Noff = bgd_counts / alpha
        if Noff > 0:
            Non = Non_lima(sigma, Noff)
            src_counts = Non - bgd_counts
            if src_counts < 0.05 * bgd_counts:
                src_counts = 0.05 * bgd_counts
            if src_counts < 10:
                src_counts = 10.0
            emin = gammalib.GEnergy(math.pow(10.0, logE[i] - 0.1), 'TeV')
            emax = gammalib.GEnergy(math.pow(10.0, logE[i] + 0.1), 'TeV')
            epivot = gammalib.GEnergy(math.pow(10.0, logE[i]), 'TeV')
            plaw = gammalib.GModelSpectralPlaw(1.0e-6, -2.6, epivot)
            conv = TeV2erg * E[i] * E[i] / plaw.flux(emin, emax)
            flux[i] = conv * src_counts / (duration * aeff * 0.68)

    # Plot data
    plt.loglog(E, flux, color + '-', label=name)
    plt.loglog(E, flux, color + 'o')

    # Set axes
    plt.xlabel('Energy (TeV)')
    plt.ylabel(r'Sensitivity (erg cm$^{-2}$ s$^{-1}$)')

    # Set legend
    plt.legend(loc='upper right')

    # Return
    return
Beispiel #26
0
    def _background_spectrum(self,
                             run,
                             prefactor,
                             index,
                             emin=0.01,
                             emax=100.0):

        # Handle constant spectral model
        if index == 0.0 and self._bkgpars <= 1:
            spec = gammalib.GModelSpectralConst()
            spec['Normalization'].min(prefactor / self._bkg_range_factor)
            spec['Normalization'].max(prefactor * self._bkg_range_factor)
            spec['Normalization'].value(prefactor)
            if self._bkgpars == 0:
                spec['Normalization'].fix()
            else:
                spec['Normalization'].free()

        else:

            # Create power law model
            if self._bkgpars <= 2:
                e = gammalib.GEnergy(1.0, 'TeV')
                spec = gammalib.GModelSpectralPlaw(prefactor, index, e)

                # Set parameter ranges
                spec[0].min(prefactor / self._bkg_range_factor)
                spec[0].max(prefactor * self._bkg_range_factor)
                spec[1].scale(1)
                spec[1].min(-5.0)
                spec[1].max(5.0)

                # Set number of free parameters
                if self._bkgpars == 0:
                    spec[0].fix()
                    spec[1].fix()
                elif self._bkgpars == 1:
                    spec[0].free()
                    spec[1].fix()
                else:
                    spec[0].free()
                    spec[1].free()

            else:

                # Create reference powerlaw
                plaw = gammalib.GModelSpectralPlaw(
                    prefactor, index, gammalib.GEnergy(1.0, 'TeV'))

                # Create spectral model and energy values
                spec = gammalib.GModelSpectralNodes()
                bounds = gammalib.GEbounds(self._bkgpars,
                                           gammalib.GEnergy(emin, 'TeV'),
                                           gammalib.GEnergy(emax, 'TeV'), True)
                for i in range(bounds.size()):
                    energy = bounds.elogmean(i)
                    value = plaw.eval(energy, gammalib.GTime())
                    spec.append(energy, value)
                for par in spec:

                    if 'Energy' in par.name():
                        par.fix()
                    elif 'Intensity' in par.name():
                        value = par.value()
                        par.scale(value)
                        par.min(value / self._bkg_range_factor)
                        par.max(value * self._bkg_range_factor)

        # Return spectrum
        return spec
Beispiel #27
0
    def _generate_initial_model(self, sigma_min=2.0, sigma_max=1000.0):
        """
        Generate initial background model

        Parameters
        ----------
        sigma_min : float, optional
            Minimum sigma
        sigma_max : float, optional
            Maximum sigma

        Returns
        -------
        model : `~gammalib.GModelData()`
            Background model
        """
        # Handle IRF model
        if self['spatial'].string() == 'IRF':
            epivot = gammalib.GEnergy(1.0, 'TeV')
            spectral = gammalib.GModelSpectralPlaw(1.0, 0.0, epivot)
            model = gammalib.GCTAModelIrfBackground(spectral)

        # Handle AEFF model
        elif self['spatial'].string() == 'AEFF':
            epivot = gammalib.GEnergy(1.0, 'TeV')
            spectral = gammalib.GModelSpectralPlaw(1.0e-13, -2.5, epivot)
            model = gammalib.GCTAModelAeffBackground(spectral)

        # Handle other models
        else:

            # Handle LOOKUP model
            if self['spatial'].string() == 'LOOKUP':

                # Set spatial model
                factor1 = gammalib.GCTAModelSpatialLookup(
                    self['slufile'].filename())

            # Handle GAUSS model
            elif self['spatial'].string() == 'GAUSS':

                # Set spatial model
                factor1 = gammalib.GCTAModelRadialGauss(3.0)
                factor1['Sigma'].min(sigma_min)
                factor1['Sigma'].max(sigma_max)

            # Handle GAUSS(E) model
            elif self['spatial'].string() == 'GAUSS(E)':

                # Set spatial model. If a single energy bin is specified then
                # use the GAUSS model. Otherwise allocate a node spectrum for
                # the energy nodes of GAUSS(E).
                if self['snumbins'].integer() == 1:
                    factor1 = gammalib.GCTAModelRadialGauss(3.0)
                    factor1['Sigma'].min(sigma_min)
                    factor1['Sigma'].max(sigma_max)
                else:
                    emin = gammalib.GEnergy(self['smin'].real(), 'TeV')
                    emax = gammalib.GEnergy(self['smax'].real(), 'TeV')
                    energies = gammalib.GEnergies(self['snumbins'].integer(),
                                                  emin, emax)
                    spectrum = gammalib.GModelSpectralConst(3.0)
                    nodes = gammalib.GModelSpectralNodes(spectrum, energies)
                    for i in range(nodes.nodes()):
                        nodes[i * 2 + 1].min(sigma_min)
                        nodes[i * 2 + 1].max(sigma_max)
                    nodes.autoscale()
                    factor1 = gammalib.GCTAModelSpatialGaussSpectrum(nodes)

            # Handle PROFILE model
            elif self['spatial'].string() == 'PROFILE':

                # Set spatial model
                factor1 = gammalib.GCTAModelRadialProfile(2.0, 4.0, 5.0)
                factor1['Width'].min(1.0)
                factor1['Width'].max(10.0)
                factor1['Core'].min(1.0)
                factor1['Core'].max(10.0)
                factor1['Tail'].min(1.0)
                factor1['Tail'].max(10.0)
                factor1['Tail'].free()

            # Handle POLYNOM model
            elif self['spatial'].string() == 'POLYNOM':

                # Set spatial model
                factor1 = gammalib.GCTAModelRadialPolynom([1.0, -0.1, +0.1])
                factor1['Coeff0'].min(0.1)
                factor1['Coeff0'].max(10.0)
                factor1['Coeff0'].fix()
                factor1['Coeff1'].min(-10.0)
                factor1['Coeff1'].max(10.0)
                factor1['Coeff2'].min(-10.0)
                factor1['Coeff2'].max(10.0)

            # Any other strings (should never occur)
            else:
                model = None

            # Optionally add gradient
            if self['gradient'].boolean():
                spatial = gammalib.GCTAModelSpatialMultiplicative()
                factor2 = gammalib.GCTAModelSpatialGradient()
                spatial.append(factor1)
                spatial.append(factor2)
            else:
                spatial = factor1

            # Set spectral model
            epivot = gammalib.GEnergy(1.0, 'TeV')
            spectral = gammalib.GModelSpectralPlaw(3.0e-4, -1.5, epivot)
            spectral['Prefactor'].min(1.0e-8)

            # Set background model
            model = gammalib.GCTAModelBackground(spatial, spectral)

        # Set background name and instrument
        if model is not None:
            model.name('Background')
            model.instruments(self._instrument)

        # Return model
        return model
glats = [0.80, -0.40]

# resolution of output maps in deg
out_res = 0.05

# set output in the templates directory
outdir = '../known-sources/templates/'

# spectral models
# the spectrum for the Cygnus cocoon comes from the joint ARGO+Fermi fit in Bartoli et al.  2014ApJ...790..152B
# with the cutoff at 40 TeV suggested by Milagro (Fig. 3)
spectrum_cyg = gammalib.GModelSpectralExpPlaw(3.5e-15, -2.16,
                                              gammalib.GEnergy(0.1, 'TeV'),
                                              gammalib.GEnergy(40, 'TeV'))
# the spectrum of Westerlund 1 comes from HESS collaboration 2011 A&A...537A.114A
spectrum_wd1 = gammalib.GModelSpectralPlaw(9.e-18, -2.19,
                                           gammalib.GEnergy(1, 'TeV'))
spectral_models = [spectrum_cyg, spectrum_wd1]

for s, name in enumerate(names):
    # first, create map

    # create wcs for output map
    npix = 1 + int(2 * rad_max[s] / out_res)
    out_wcs = wcs.WCS(naxis=2)
    out_wcs.wcs.crpix = [(npix - 1.) / 2 + 1., (npix - 1) / 2 + 1.]
    out_wcs.wcs.cdelt = [-out_res, out_res]
    out_wcs.wcs.crval = [glons[s], glats[s]]  # centered on cluster
    out_wcs.wcs.ctype = ["GLON-TAN", "GLAT-TAN"]

    # open gas map
    gasmap = fits.open(gasmaps[s])[0]
def append_fhl(models, bmax,
                bin_models, bin_dict, bin_distx, bin_disty, bin_radr, bin_frlog,
                snr_models, snr_dict, snr_distx, snr_disty, snr_radr, snr_frlog,
                isnr_models, isnr_dict, isnr_distx, isnr_disty, isnr_radr, isnr_frlog,
                dist_sigma=3., sig50_thresh=3., eph_thresh=100.):
    """
    Append missing models from Fermi high-energy catalog to gammalib model container
    :param models: ~gammalib.GModels, gammalib model container
    :param bmax: float, maximum latitude of models to include
    :param dist_sigma: float, minimum distance in sigma's from pre-existing source to add as new
    :param sig50_thresh: float, threshold sigma on significance above 50 GeV to apply
    :param eph_thresh: float, minimum energy of detected photons required
    :return: result: dictionary
    """
    # filter FHL table based on latitude and hardness
    # hard sources are seleted based on significance above 50 GeV and highest photon energy
    # calculate significance above 50 GeV
    sig50 = np.sqrt(np.sum(np.power(fhl['Sqrt_TS_Band'][:,2:], 2),axis=1))
    # filter
    fsources = fhl[(np.abs(fhl['GLAT']) <= bmax) & (sig50 >= sig50_thresh) & (
                fhl['HEP_Energy'] >= eph_thresh)]

    # prepare new gammalib model container
    newpt = 0
    newext = 0
    n_bin_del = 0
    n_snr_del = 0
    n_isnr_del = 0
    newmodels = gammalib.GModels()
    # keep track also of artificial cutoffs
    ecut_pwn = []
    ecut_snr = []
    ecut_unid = []
    ecut_agn = []
    n_ecut_pwn = 0
    n_ecut_snr = 0
    n_ecut_agn = 0
    n_ecut_unid = 0

    msg = ''

    # loop over fermi sources
    for fsource in fsources:
        # assume source is new
        new = 1
        # fermi source position as gammalib.GSkyDir
        fdir = gammalib.GSkyDir()
        ra = np.double(fsource['RAJ2000'])
        dec = np.double(fsource['DEJ2000'])
        fdir.radec_deg(ra, dec)
        ######################################### treat pointlike sources for Fermi ###########
        if fsource['Extended_Source_Name'] == '':
            # case of sources pointlike for Fermi
            # loop over gammalib container and determine closest neighbor
            # initialize at 1000
            dist_min = 1000.
            for source in models:
                dir = get_model_dir(source)
                dist = fdir.dist_deg(dir)
                dist_min = np.minimum(dist, dist_min)
            if dist_min < dist_sigma * fsource['Conf_95_SemiMajor'] / 2:
                # closeby source foud in container, source will not be added
                new = 0
            else:
                # source will be added to container, set spatial model
                spatial = gammalib.GModelSpatialPointSource(fdir)
                newpt += 1
        ######################################### treat extended sources for Fermi ############
        else:
            # retrieve Fermi extended source radius
            ext_fsource = ext_fhl[ext_fhl['Source_Name'] == fsource['Extended_Source_Name']][0]
            fradius = np.double(ext_fsource['Model_SemiMajor'])
            # "corrected" distance, i.e, centre distance - radius of source
            # initialize at 1000
            dist_corr = 1000.
            for source in models:
                dir = get_model_dir(source)
                dist = fdir.dist_deg(dir)
                # get source radius according to model used
                radius = get_model_radius(source)
                # use as radius the max between Fermi and model
                radius = np.maximum(fradius,radius)
                # subtract from distance the max radius
                dist -= radius
                dist_corr = np.minimum(dist,dist_corr)
            if dist_corr < 0.:
                # overlapping source foud in container, source will not be added
                new = 0
            else:
                # source will be added to container, set spatial model
                fradius2 = np.double(ext_fsource['Model_SemiMinor'])
                fpangle = np.double(ext_fsource['Model_PosAng'])
                # retrieve Fermi spatial model to set it in container
                if ext_fsource['Model_Form'] == 'Disk':
                    if fradius2 == fradius:
                        spatial = gammalib.GModelSpatialRadialDisk(fdir,fradius)
                    else:
                        spatial = gammalib.GModelSpatialEllipticalDisk(fdir, fradius, fradius2, fpangle)
                elif ext_fsource['Model_Form'] == '2D Gaussian':
                    if fradius2 == fradius:
                        spatial = gammalib.GModelSpatialRadialGauss(fdir,fradius)
                    else:
                        spatial = gammalib.GModelSpatialEllipticalGauss(fdir, fradius, fradius2, fpangle)
                elif ext_fsource['Model_Form'] == 'Ring':
                    spatial = gammalib.GModelSpatialRadialShell(fdir,fradius, fradius2)
                elif ext_fsource['Model_Form'] == 'Map':
                    print('{} modeled by spatial template, which is not implemented, skip'.format(fsource['Source_Name']))
                    new = 0
                else:
                    print('{} modeled by model type {}, which is not implemented, skip'.format(fsource['Source_Name'],ext_fsource['Model_Form']))
                    new = 0
                if new == 1:
                    newext +=1
        ######################################### spectra #####################################
        if new == 1:
            # spectral model
            eref = gammalib.GEnergy(np.double(fsource['Pivot_Energy']), 'GeV')
            norm = np.double(fsource['Flux_Density'])
            norm *= 1.e-3  # ph GeV-1 -> ph MeV-1
            # use power law model only if signifcance of curvature < 1
            # this avoids extrapolating hard power laws not justified by the data
            if fsource['Signif_Curve'] < 1:
                index = np.double(fsource['PowerLaw_Index'])
                if index < 2.4:
                    # correction for fake pevatrons
                    if fsource['CLASS'] == 'PWN' or fsource['CLASS'] == 'pwn':
                        # dummy model to obtain search radius
                        mod = gammalib.GModelSky(spatial, gammalib.GModelSpectralPlaw())
                        # search radius
                        rad = get_model_radius(mod) + 0.2
                        # set cutoff
                        ecut = get_cutoff(ra, dec, 'PSR', rad_search=rad)
                        ecut_pwn.append(ecut)
                        n_ecut_pwn += 1
                    elif fsource['CLASS'] == 'SNR' or fsource['CLASS'] == 'snr':
                        gname = fsource['ASSOC1']
                        if 'SNR' in gname:
                            pass
                        else:
                            gname = None
                        # compute cutoff
                        # we use default value for particle spectral index because measurements are highly uncertain
                        ecut = get_cutoff(ra, dec, 'SNR', name=gname)
                        ecut_snr.append(ecut)
                        n_ecut_snr += 1
                    elif fsource['CLASS'] == 'bll' or fsource['CLASS'] == 'bcu' or fsource['CLASS'] == 'fsrq':
                        ecut = get_cutoff(ra, dec, 'AGN', z = fsource['Redshift'])
                        ecut_agn.append(ecut)
                        n_ecut_agn += 1
                    else:
                        if fsource['CLASS'] == '' or fsource['CLASS'] == 'unknown':
                            pass
                        else:
                            # set warning if we have hard source of unexpected type
                            msg += 'FHL source {} of type {} has an unxepctedly hard spectrum ' \
                                  'with index {}. We are setting a random artificial cutoff\n'.format(
                                fsource['Source_Name'], fsource['CLASS'], index)
                            print(msg)
                        ecut = get_cutoff(ra, dec, 'UNID')
                        ecut_unid.append(ecut)
                        n_ecut_unid += 1
                    ecut = gammalib.GEnergy(np.double(ecut), 'TeV')
                    spectral = gammalib.GModelSpectralExpPlaw(norm, -index, eref, ecut)
                else:
                    spectral = gammalib.GModelSpectralPlaw(norm, -index, eref)
            else:
                index = np.double(fsource['Spectral_Index'])
                curvature = np.double(fsource['beta'])
                spectral = gammalib.GModelSpectralLogParabola(norm, -index, eref, curvature)
            # assemble model and append to container
            model = gammalib.GModelSky(spatial, spectral)
            model.name(fsource['Source_Name'])
            newmodels.append(model)
            # delete synthetic sources as needed
            if fsource['CLASS'] == 'HMB' or fsource['CLASS'] == 'hmb' or fsource['CLASS'] == 'BIN' or fsource['CLASS'] == 'bin':
                rname, bin_dict, distx, disty, radr, frlog = find_source_to_delete(bin_dict, fdir.l_deg(),
                                                        fdir.b_deg(), get_model_radius(model),
                                                        flux_Crab(model,1.,1000.))
                bin_models.remove(rname)
                n_bin_del += 1
                bin_distx.append(distx)
                bin_disty.append(disty)
                bin_radr.append(radr)
                bin_frlog.append(frlog)
            elif fsource['CLASS'] == 'PWN' or fsource['CLASS'] == 'pwn' or fsource['CLASS'] == 'spp':
                # implement synthetic PWNe here
                pass
            elif fsource['CLASS'] == 'SNR' or fsource['CLASS'] == 'snr':
                # determine if snr is interacting
                assoc = snr_class[snr_class['ASSOC1'] == fsource['ASSOC1']]
                if assoc[0]['is int'] == 'yes':
                    # interacting
                    rname, isnr_dict, distx, disty, radr, frlog = find_source_to_delete(isnr_dict,
                                                                                 fdir.l_deg(),
                                                                                 fdir.b_deg(), get_model_radius(model),
                                                                                 flux_Crab(model, 1.,1000.))
                    isnr_models.remove(rname)
                    n_isnr_del += 1
                    isnr_distx.append(distx)
                    isnr_disty.append(disty)
                    isnr_radr.append(radr)
                    isnr_frlog.append(frlog)
                else:
                    # young
                    rname, snr_dict, distx, disty, radr, frlog = find_source_to_delete(snr_dict,
                                                                                  fdir.l_deg(),
                                                                                  fdir.b_deg(), get_model_radius(model),
                                                                                  flux_Crab(model,1.,1000.))
                    snr_models.remove(rname)
                    n_snr_del += 1
                    snr_distx.append(distx)
                    snr_disty.append(disty)
                    snr_radr.append(radr)
                    snr_frlog.append(frlog)
            else:
                pass
        else:
            # source already present, skip
            pass

    # add new models to original container
    for model in newmodels:
        models.append(model)

    # assemble output in dictionary
    result = { 'models' : models, 'newpt' : newpt, 'newext' : newext,
               'ecut_pwn' : ecut_pwn, 'ecut_snr' : ecut_snr, 'ecut_agn' : ecut_agn,
               'ecut_unid' : ecut_unid, 'n_ecut_pwn' : n_ecut_pwn, 'n_ecut_snr' : n_ecut_snr,
               'n_ecut_agn' : n_ecut_agn, 'n_ecut_unid' : n_ecut_unid, 'msg' : msg,
               'bin_models' : bin_models, 'bin_dict' : bin_dict, 'n_bin_del' : n_bin_del,
               'bin_distx' : bin_distx, 'bin_disty' : bin_disty, 'bin_radr' : bin_radr, 'bin_frlog' : bin_frlog,
               'snr_models': snr_models, 'snr_dict': snr_dict, 'n_snr_del': n_snr_del,
               'snr_distx': snr_distx, 'snr_disty': snr_disty, 'snr_radr': snr_radr, 'snr_frlog': snr_frlog,
               'isnr_models': isnr_models, 'isnr_dict': isnr_dict, 'n_isnr_del': n_isnr_del,
               'isnr_distx': isnr_distx, 'isnr_disty': isnr_disty, 'isnr_radr': isnr_radr, 'isnr_frlog': isnr_frlog
    }

    return result
Beispiel #30
0
    def _get_parameters(self):
        """
        Get parameters from parfile and setup observations
        """
        # Clear source models
        self._models.clear()

        # Setup observations (require response and allow event list, don't
        # allow counts cube)
        self._setup_observations(self.obs(), True, True, False)

        # Get source model and source name. First try to extract models from
        # observation container. If this does not work then try creating
        # model from the inmodel parameter
        if self.obs().models().size() > 0:
            self._models = self.obs().models().clone()
            self._srcname = self['srcname'].string()
        elif self['inmodel'].is_valid():
            inmodel = self['inmodel'].filename()
            self._models = gammalib.GModels(inmodel)
            self._srcname = self['srcname'].string()

        # Set energy bounds
        self._ebounds = self._create_ebounds()

        # Initialize empty src regions container
        self._src_reg = gammalib.GSkyRegions()

        # Exclusion map
        if self['inexclusion'].is_valid():
            inexclusion = self['inexclusion'].filename()
            self._excl_reg = gammalib.GSkyRegionMap(inexclusion)
            self._has_exclusion = True
        else:
            self._has_exclusion = False

        # Query remaining parameters
        self['use_model_bkg'].boolean()
        self['stack'].boolean()

        # Query ahead output parameters
        if (self._read_ahead()):
            self['outobs'].filename()
            self['outmodel'].filename()
            self['prefix'].string()

        # If there are no observations in container then get them from the
        # parameter file
        if self.obs().is_empty():
            self.obs(self._get_observations(False))

        # Get background method parameters (have to come after setting up of
        # observations)
        self._get_parameters_bkgmethod()

        # Write input parameters into logger
        self._log_parameters(gammalib.TERSE)

        # Set number of processes for multiprocessing
        self._nthreads = mputils.nthreads(self)

        # If we have no model then create now a dummy model
        if self._models.is_empty():
            spatial = gammalib.GModelSpatialPointSource(self._src_dir)
            spectral = gammalib.GModelSpectralPlaw(
                1.0e-18, -2.0, gammalib.GEnergy(1.0, 'TeV'))
            model = gammalib.GModelSky(spatial, spectral)
            model.name('Dummy')
            self._models.append(model)
            self._srcname = 'Dummy'
            self['use_model_bkg'].boolean(False)

        # Return
        return