/***********************************************************************//**
 * @brief Constructor
 *
 * @param[in] coeffs Vector of polynomial coefficients.
 ***************************************************************************/
GCTAModelRadialPolynom::GCTAModelRadialPolynom(const std::vector<double>& coeffs)
                                                          : GCTAModelRadial()
{
    // Initialise members
    init_members();

    // Assign coefficients
    for (int i = 0; i < coeffs.size(); ++i) {

        // Allocate parameter
        GModelPar par;

        // Set value
        par.real_value(coeffs[i]);

        // Set other attributes
        std::string name = "coeff"+str(i);
        par.name(name);
        par.unit("");
        par.free();
        par.scale(1.0);
        par.gradient(0.0);
        par.hasgrad(true);

        // Push coefficient on list
        m_coeffs.push_back(par);

    } // endfor: looped over coefficients

    // Update parameter mapping
    update_pars();

    // Return
    return;
}
Exemple #2
0
/***********************************************************************//**
 * @brief Read model from XML element
 *
 * @param[in] xml XML element.
 *
 * @exception GException::invalid_value
 *            Model definition requires at least one node.
 *
 * Read the COMPTEL DRB fitting model from an XML element.
 *
 * The model is composed of nodes that define the normalization value as
 * function of Phibar value. The following XML file syntax is expected:
 *
 *     <source name="Background" type="DRBFitting" instrument="COM">
 *       <node>
 *         <parameter name="Phibar"        .../>
 *         <parameter name="Normalization" .../>
 *       </node>
 *       ...
 *       <node>
 *         <parameter name="Phibar"        .../>
 *         <parameter name="Normalization" .../>
 *       </node>
 *     </source>
 ***************************************************************************/
void GCOMModelDRBFitting::read(const GXmlElement& xml)
{
    // Free space for nodes
    m_phibars.clear();
    m_values.clear();

    // Get number of nodes from XML file
    int nodes = xml.elements("node");

    // Throw an error if there are no nodes
    if (nodes < 1) {
        std::string msg = "DRB fitting model requires at least one Phibar "
                          "node. Please correct XML format.";
        throw GException::invalid_value(G_READ, msg);
    }

    // Loop over all nodes
    for (int i = 0; i < nodes; ++i) {

        // Allocate node parameters
        GModelPar phibar;
        GModelPar normalization;
            
        // Get node
        const GXmlElement* node = xml.element("node", i);

        // Read Phibar parameter
        const GXmlElement* par = gammalib::xml_get_par(G_READ, *node, "Phibar");
        phibar.read(*par);

        // Read Normalization parameter
        par = gammalib::xml_get_par(G_READ, *node, "Normalization");
        normalization.read(*par);

        // Set parameter names
        std::string phibar_name        = "Phibar layer "+gammalib::str(i);
        std::string normalization_name = "Scale factor "+gammalib::str(i);

        // Set Phibar attributes
        phibar.name(phibar_name);
        phibar.unit("deg");
        phibar.has_grad(false);

        // Set normalization attributes
        normalization.name(normalization_name);
        normalization.unit("");
        normalization.has_grad(true);

        // Push node parameters on list
        m_phibars.push_back(phibar);
        m_values.push_back(normalization);

    } // endfor: looped over nodes

    // Set model name
    name(xml.attribute("name"));

    // Set instruments
    instruments(xml.attribute("instrument"));

    // Set observation identifiers
    ids(xml.attribute("id"));

    // Check flag if TS value should be computed
    bool tscalc = (xml.attribute("tscalc") == "1") ? true : false;

    // Set flag if TS value should be computed
    this->tscalc(tscalc);

    // Set pointers
    set_pointers();

    // Set evluation cache
    set_cache();

    // Return
    return;
}
/***********************************************************************//**
 * @brief Read model from XML element
 *
 * @param[in] xml XML element.
 *
 * @exception GException::model_invalid_parnum
 *            Invalid number of model parameters found in XML element.
 * @exception GException::model_invalid_parnames
 *            Invalid model parameter names found in XML element.
 *
 * Read the radial Polynom model information from an XML element. The XML
 * element is required to have at least one parameter. Parameters are named
 * "CoeffX", where "X" starts from "0".  
 *
 * @todo Implement a test of the coefficient boundaries.
 ***************************************************************************/
void GCTAModelRadialPolynom::read(const GXmlElement& xml)
{
    // Free space for coefficients
    m_coeffs.clear();

    // Get maximum number of coefficients from XML file
    int max_coeffs = xml.elements("parameter");

    // Throw an error if no parameters were found
    if (max_coeffs < 1) {
        std::string message = "Radial polynomial model requires at least"
                              " one coefficient.";
        throw GException::model_invalid_parnum(G_READ, xml, message);
    }

    // Verify XML file consistency and determine number of coefficients
    int ncoeffs = 0;
    std::vector<int> npar;
    npar.assign(max_coeffs, 0);
    for (int i = 0; i < max_coeffs; ++i) {

        // Get parameter element
        GXmlElement* par = static_cast<GXmlElement*>(xml.element("parameter", i));

        // Verify that parameter is indeed a coefficient
        if (par->attribute("name").compare(0,5,"Coeff") != 0) {
            throw GException::model_invalid_parnames(G_READ, xml, 
                  par->attribute("name"));
        }
        
        // Verify that parameter coefficient has index in valid range
        int index = -1;
        size_t nchars = par->attribute("name").length() - 5;
        if (nchars > 0) {
            index = toint(par->attribute("name").substr(5, nchars));
        }
        else {
            throw GException::model_invalid_parnames(G_READ, xml,
                  "Radial polynomial \"Coeff\" parameter has no index.");
        }
        if (index < 0) {
            throw GException::model_invalid_parnames(G_READ, xml,
                  "Radial polynomial \"Coeff\" parameter index < 0.");
        }
        if (index >= max_coeffs) {
            std::string message = "There are "+str(max_coeffs)+" parameters,"
                                  " hence polynomial coefficients are expected"
                                  " to run from 0 to "+str(max_coeffs-1)+", yet"
                                  " a coefficient with index "+str(index)+" was"
                                  " encountered.";
            throw GException::model_invalid_parnames(G_READ, xml, message);
        }

        // Increment parameter counter
        npar[index]++;
        
        // Update number of coefficients
        if (index+1 > ncoeffs) {
            ncoeffs = index + 1;
        }

    } // endfor: verified XML file consistency
    
    // Verify that the number of coefficients is between 1 and max_coeffs
    if (ncoeffs < 0 || ncoeffs > max_coeffs) {
        std::string message = "Radial polynomial model requires at between"
                              " 1 and "+str(max_coeffs)+" parameters.";
        throw GException::model_invalid_parnum(G_READ, xml, message);
    }

    // Verify that all parameters were found
    for (int i = 0; i < ncoeffs; ++i) {
        if (npar[i] == 0) {
            std::string message = "Parameter \"Coeff"+str(i)+"\" required,"
                                  " but not found in XML file.";
            throw GException::model_invalid_parnames(G_READ, xml, message);
        }
        else if (npar[i] > 1) {
            std::string message = "Multiple parameters \"Coeff"+str(i)+"\""
                                  " found in XML file.";
            throw GException::model_invalid_parnames(G_READ, xml, message);
        }
    }

    // Finally get all coefficients in order
    for (int i = 0; i < ncoeffs; ++i) {

        // Set parameter name
        std::string name = "Coeff"+str(i);

        // Get corresponding parameter element
        GXmlElement* par = NULL;
        for (int k = 0; k < ncoeffs; ++k) {
            GXmlElement* element = static_cast<GXmlElement*>(xml.element("parameter", k));
            if (element->attribute("name") == name) {
                par = element;
                break;
            }
        }

        // Make sure that we really have one (just a double check, this should
        // never fail)
        if (par == NULL) {
            std::string message = "Required parameter \""+name+"\" not found.";
            throw GException::model_invalid_parnames(G_READ, xml, message);
        }

        // Now read that parameter ...
        GModelPar coeff;
        coeff.read(*par);

        // ... set other attributes ...
        coeff.name(name);
        coeff.unit("");

        //TODO: Check parameter

        // ... and push it on the list
        m_coeffs.push_back(coeff);

    } // endfor: looped over all parameters

    // Update parameter mapping
    update_pars();

    // Return
    return;
}