Ejemplo n.º 1
0
/***********************************************************************//**
 * @brief Set energies for map cube
 *
 * @param[in] energies Sky map energies.
 *
 * @exception GException::invalid_argument
 *            Specified sky map energies incompatible with map cube.
 *
 * Sets the energies for the map cube.
 ***************************************************************************/
void GModelSpatialDiffuseCube::energies(const GEnergies& energies)
{
    // Initialise energies
    m_logE.clear();

    // Fetch cube
    fetch_cube();

    // Extract number of energies in vector
    int num = energies.size();

    // Check if energy binning is consistent with number of maps in the cube
    if (num != m_cube.nmaps() ) {
        std::string msg = "Number of specified energies ("+gammalib::str(num)+")"
                          " does not match the number of maps ("
                          ""+gammalib::str(m_cube.nmaps())+" in the map cube.\n"
                          "The energies argument shall provide a vector of length"
                          " "+gammalib::str(m_cube.nmaps())+".";
        throw GException::invalid_argument(G_ENERGIES, msg);
    }

    // Set log10(energy) nodes, where energy is in units of MeV
    for (int i = 0; i < num; ++i) {
        m_logE.append(energies[i].log10MeV());
    }

    // Set energy boundaries
    set_energy_boundaries();

    // Update MC cache
    update_mc_cache();

    // Return
    return;
}
Ejemplo n.º 2
0
/***********************************************************************//**
 * @brief Load cube into the model class
 *
 * @param[in] filename cube file.
 *
 * @exception GException::invalid_value
 *            Number of maps in cube mismatches number of energy bins.
 *
 * Loads cube into the model class.
 ***************************************************************************/
void GModelSpatialDiffuseCube::load(const std::string& filename)
{
    // Initialise skymap
    m_cube.clear();
    m_logE.clear();

    // Store filename of cube (for XML writing). Note that we do not
    // expand any environment variable at this level, so that if we write
    // back the XML element we write the filepath with the environment
    // variables
    m_filename = filename;

    // Get expanded filename
    std::string fname = gammalib::expand_env(filename);

    // Load cube
    m_cube.load(fname);

    // Load energies
    GEnergies energies(fname);

    // Extract number of energy bins
    int num = energies.size();

    // Check if energy binning is consistent with primary image hdu
    if (num != m_cube.nmaps() ) {
        std::string msg = "Number of energies in \"ENERGIES\" extension"
                          " ("+gammalib::str(num)+") does not match the"
                          " number of maps ("+gammalib::str(m_cube.nmaps())+""
                          " in the map cube.\n"
                          "The \"ENERGIES\" extension table shall provide"
                          " one enegy value for each map in the cube.";
        throw GException::invalid_value(G_LOAD, msg);
    }

    // Set log10(energy) nodes, where energy is in units of MeV
    for (int i = 0; i < num; ++i) {
        m_logE.append(energies[i].log10MeV());
    }

    // Signal that cube has been loaded
    m_loaded = true;

    // Set energy boundaries
    set_energy_boundaries();

    // Update Monte Carlo cache
    update_mc_cache();

    // Return
    return;
}
Ejemplo n.º 3
0
/***********************************************************************//**
 * @brief Returns Monte Carlo energy between [emin, emax]
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @param[in] time True photon arrival time.
 * @param[in,out] ran Random number generator.
 * @return Energy.
 *
 * @exception GException::erange_invalid
 *            Energy range is invalid (emin < emax required).
 *
 * Returns Monte Carlo energy by randomly drawing from a power law.
 ***************************************************************************/
GEnergy GModelSpectralPlaw::mc(const GEnergy& emin,
                               const GEnergy& emax,
                               const GTime&   time,
                               GRan&          ran) const
{
    // Throw an exception if energy range is invalid
    if (emin >= emax) {
        throw GException::erange_invalid(G_MC, emin.MeV(), emax.MeV(),
              "Minimum energy < maximum energy required.");
    }

    // Update cache
    update_mc_cache(emin, emax);

    // Get uniform random number
    double u = ran.uniform();

    // Initialise energy
    double eng;

    // Case A: Index is not -1
    if (index() != -1.0) {
        if (u > 0.0) {
            eng = std::exp(std::log(u * m_mc_pow_ewidth + m_mc_pow_emin) /
                           m_mc_exponent);
        }
        else {
            eng = 0.0;
        }
    }

    // Case B: Index is -1
    else {
        eng = std::exp(u * m_mc_pow_ewidth + m_mc_pow_emin);
    }

    // Set energy
    GEnergy energy;
    energy.MeV(eng);

    // Return energy
    return energy;
}
Ejemplo n.º 4
0
/***********************************************************************//**
 * @brief Returns Monte Carlo energy between [emin, emax]
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @param[in] time True photon arrival time.
 * @param[in,out] ran Random number generator.
 * @return Energy.
 *
 * @exception GException::erange_invalid
 *            Energy range is invalid (emin < emax required).
 *
 * Returns Monte Carlo energy by randomly drawing from a smoothly broken
 * power law.
 ***************************************************************************/
GEnergy GModelSpectralSmoothBrokenPlaw::mc(const GEnergy& emin,
                                           const GEnergy& emax,
                                           const GTime&   time,
                                           GRan&          ran) const
{
    // Throw exception if energy range is not valid
    if (emin >= emax) {
        throw GException::erange_invalid(G_MC, emin.MeV(), emax.MeV(),
                            "Minimum energy < maximum energy required.");
    }
    
    // Allocate energy
    GEnergy energy;
    
    // Update Monte Carlo cache
    update_mc_cache();
    
    // Initialse acceptance fraction
    double acceptance_fraction(0.0);
    
    // Use rejection method to draw a random energy. We first draw
    // analytically from a broken power law, and then compare the power law
    // at the drawn energy to the curved function. This gives an acceptance
    // fraction, and we accept the energy only if a uniform random number
    // is <= the acceptance fraction.
    do {
        // Generate an energy from the broken power law distribution
        energy = m_mc_brokenplaw.mc(emin, emax, time, ran);
        
        // Compute acceptance fraction
        acceptance_fraction = eval(energy) / m_mc_brokenplaw.eval(energy);
        
    } while (ran.uniform() > acceptance_fraction);
    
    // Return energy
    return energy;
}
Ejemplo n.º 5
0
/***********************************************************************//**
 * @brief Returns MC energy between [emin, emax]
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @param[in] time True photon arrival time.
 * @param[in,out] ran Random number generator.
 * @return Energy.
 *
 * @exception GException::erange_invalid
 *            Energy range is invalid (emin < emax required).
 *
 * Simulates a random energy in the interval [emin, emax] for an
 * exponentially cut off power law. The simulation is done using a rejection
 * method. First, a random energy within [emin, emax] is drawn from an
 * power law distribution. Then the energy is accepted or rejected based
 * on an acceptance fraction that is computed from the exponential cut off.
 ***************************************************************************/
GEnergy GModelSpectralExpPlaw::mc(const GEnergy& emin,
                                  const GEnergy& emax,
                                  const GTime&   time,
                                  GRan&          ran) const
{
    // Throw an exception if energy range is invalid
    if (emin >= emax) {
        throw GException::erange_invalid(G_MC, emin.MeV(), emax.MeV(),
              "Minimum energy < maximum energy required.");
    }

    // Allocate energy
    GEnergy energy;

    // Update cache
    update_mc_cache(emin, emax);

    // Initialise energy
    double eng;
    
    // Initialse acceptance fraction
    double acceptance_fraction;
    double inv_ecut = 1.0 / m_ecut.value();

    // Use rejection method to draw a random energy. We first draw
    // analytically from a power law, and then compare the power law
    // at the drawn energy to the exponentially cut off function. This
    // gives an acceptance fraction, and we accept the energy only if
    // a uniform random number is <= the acceptance fraction.
    do {

        // Get uniform random number
        double u = ran.uniform();

        // Case A: Index is not -1
        if (index() != -1.0) {
            if (u > 0.0) {
                eng = std::exp(std::log(u * m_mc_pow_ewidth + m_mc_pow_emin) /
                               m_mc_exponent);
            }
            else {
                eng = 0.0;
            }
        }

        // Case B: Index is -1
        else {
            eng = std::exp(u * m_mc_pow_ewidth + m_mc_pow_emin);
        }
        
        // Compute acceptance fraction
        acceptance_fraction = std::exp(-eng * inv_ecut);

    } while (ran.uniform() > acceptance_fraction);
    
    // Set energy
    energy.MeV(eng);

    // Return energy
    return energy;
}