/***********************************************************************//** * @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; }
/***********************************************************************//** * @brief Read instrument scales from XML element * * @param[in] xml XML source element. * * Reads the instrument scale factors from a tag with the following format * * <scaling> * <instrument name="LAT" scale="1.0" min="0.1" max="10.0" value="1.0" free="0"/> * <instrument name="CTA" scale="1.0" min="0.1" max="10.0" value="0.5" free="0"/> * </scaling> * * The instrument name is case sensitive, but any leading and trailing white * space will be removed. * * If no scaling tag is found, all instrument scale factors will be cleared. ***************************************************************************/ void GModel::read_scales(const GXmlElement& xml) { // Clear any existing scales m_scales.clear(); // Continue only if there is a <scaling> tag if (xml.elements("scaling") != 0) { // Get pointer on first instrument scale factors const GXmlElement* scales = xml.element("scaling", 0); // Determine number of scale factors int nscales = scales->elements("instrument"); // Read all scale factors for (int i = 0; i < nscales; ++i) { const GXmlElement* par = scales->element("instrument", i); GModelPar scale; scale.read(*par); scale.name(gammalib::strip_whitespace(par->attribute("name"))); m_scales.push_back(scale); } } // Return return; }
/***********************************************************************//** * @brief Set model scale factor for a given instrument * * @param[in] par Model parameter for scaling. * * Sets the model parameter for a given instrument. The instrument name is * case sensitive, but any leading to trailing white space will be stripped. * * If the instrument is not yet defined it will be appended to the list of * instruments. ***************************************************************************/ void GModel::scale(const GModelPar& par) { // String leading and trailing while space std::string instrument = gammalib::strip_whitespace(par.name()); // Search for instrument and copy the model parameter if the instrument // has been found. Make sure that the instrument name is in upper case. bool found = false; for (int i = 0; i < m_scales.size(); ++i) { if (m_scales[i].name() == instrument) { found = true; m_scales[i] = par; m_scales[i].name(instrument); break; } } // If instrument has not been found then append it now to the list // of instruments. if (!found) { m_scales.push_back(par); m_scales[m_scales.size()-1].name(instrument); } // Return return; }
/***********************************************************************//** * @brief Returns model scale factor for a given instrument * * @param[in] instrument Instrument. * * Returns the model scale factor for a given @p instrument. The search is * case sensitive. * * If the @p instrument is not found, the method returns a scale factor of * unity. ***************************************************************************/ GModelPar GModel::scale(const std::string& instrument) const { // Initialise unit scale factor GModelPar scale; scale.value(1.0); scale.name(instrument); scale.fix(); // Search for instrument and recover scale factor if the instrument // has been found. for (int i = 0; i < m_scales.size(); ++i) { if (m_scales[i].name() == instrument) { scale = m_scales[i]; break; } } // Return scale factor return scale; }
/***********************************************************************//** * @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; }