/***********************************************************************//** * @brief Write response information into XML element * * @param[in] xml XML element. * * Writes response information into an XML element. The Exposure, Psf * and background cubes are specified using * * <observation name="..." id="..." instrument="..."> * ... * <parameter name="ExposureCube" file="..."/> * <parameter name="PsfCube" file="..."/> * <parameter name="BkgCube" file="..."/> * </observation> * ***************************************************************************/ void GCTAResponseCube::write(GXmlElement& xml) const { // Add exposure cube filename std::string filename = gammalib::strip_whitespace(m_exposure.filename()); if (!(filename.empty())) { GXmlElement* par = gammalib::xml_need_par(G_WRITE, xml, "ExposureCube"); par->attribute("file", filename); } // Add PSF cube filename filename = gammalib::strip_whitespace(m_psf.filename()); if (!(filename.empty())) { GXmlElement* par = gammalib::xml_need_par(G_WRITE, xml, "PsfCube"); par->attribute("file", filename); } // Add background cube filename filename = gammalib::strip_whitespace(m_background.filename()); if (!(filename.empty())) { GXmlElement* par = gammalib::xml_need_par(G_WRITE, xml, "BkgCube"); par->attribute("file", filename); } // Return return; }
/***********************************************************************//** * @brief Read model from XML element * * @param[in] xml XML element containing power law model information. * * @exception GException::model_invalid_parnum * Invalid number of model parameters found in XML element. * @exception GException::model_invalid_parnames * Invalid model parameter name found in XML element. * * Read the function information from an XML element and load the nodes * from the associated file. The XML element is required to have an * attribute "file" that specifies the function nodes and a parameter * named "Normalization". ***************************************************************************/ void GModelSpectralFunc::read(const GXmlElement& xml) { // Verify that XML element has exactly 1 parameter if (xml.elements() != 1 || xml.elements("parameter") != 1) { throw GException::model_invalid_parnum(G_READ, xml, "Spectral function requires exactly 1 parameter."); } // Get parameter element GXmlElement* par = static_cast<GXmlElement*>(xml.element("parameter", 0)); // Get value if (par->attribute("name") == "Normalization") { m_norm.read(*par); } else { throw GException::model_invalid_parnames(G_READ, xml, "Require \"Normalization\" parameter."); } // Load nodes from file load_nodes(xml.attribute("file")); // 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 skymap information from an XML element. The XML element is * required to have 1 parameter named either "Normalization" or "Prefactor". ***************************************************************************/ void GModelSpatialMap::read(const GXmlElement& xml) { // Verify that XML element has exactly 1 parameters if (xml.elements() != 1 || xml.elements("parameter") != 1) { throw GException::model_invalid_parnum(G_READ, xml, "Spatial map model requires exactly 1 parameter."); } // Get pointer on model parameter GXmlElement* par = static_cast<GXmlElement*>(xml.element("parameter", 0)); // Get value if (par->attribute("name") == "Normalization" || par->attribute("name") == "Prefactor") { m_value.read(*par); } else { throw GException::model_invalid_parnames(G_READ, xml, "Spatial map model requires either \"Prefactor\" or" " \"Normalization\" parameter."); } // Load skymap load_map(xml.attribute("file")); // Return return; }
/***********************************************************************//** * @brief XML constructor * * @param[in] xml XML element. ***************************************************************************/ GModelSky::GModelSky(const GXmlElement& xml) : GModel(xml) { // Initialise private members for clean destruction init_members(); // Get pointers on spectrum and spatial model GXmlElement* spec = static_cast<GXmlElement*>(xml.element("spectrum", 0)); GXmlElement* spat = static_cast<GXmlElement*>(xml.element("spatialModel", 0)); // Allocate constant GModelTemporalConst temporal; // Clone spatial and spectral models m_spatial = xml_spatial(*spat); m_spectral = xml_spectral(*spec); m_temporal = temporal.clone(); // Set parameter pointers set_pointers(); // Return return; }
/***********************************************************************//** * @brief Read model from XML element * * @param[in] xml XML element. * * Reads the temporal information from an XML element. The XML element should * have the format * * <temporalModel type="LightCurve" file=".."> * <parameter name="Normalization" scale="1" value="1" min="0.1" max="10" free="1"/> * </temporalModel> ***************************************************************************/ void GModelTemporalLightCurve::read(const GXmlElement& xml) { // Get parameter pointers const GXmlElement* norm = gammalib::xml_get_par(G_READ, xml, m_norm.name()); // Read parameters m_norm.read(*norm); // Load nodes from file load_nodes(gammalib::xml_file_expand(xml, xml.attribute("file"))); // Return return; }
/***********************************************************************//** * @brief Read observations from XML document * * @param[in] xml XML document. * * @exception GException::invalid_instrument * Invalid instrument encountered. * * Reads observations from the first observation list that is found in the * XML document. The decoding of the instrument specific observation * definition is done within the observation's read() method. * * @todo Observation names and IDs are not verified so far for uniqueness. * This would be required to achieve an unambiguous update of parameters * in an already existing XML file when using the write method. ***************************************************************************/ void GObservations::read(const GXml& xml) { // Get pointer on observation library GXmlElement* lib = xml.element("observation_list", 0); // Loop over all observations int n = lib->elements("observation"); for (int i = 0; i < n; ++i) { // Get pointer on observation GXmlElement* obs = static_cast<GXmlElement*>(lib->element("observation", i)); // Get attributes std::string name = obs->attribute("name"); std::string id = obs->attribute("id"); std::string instrument = obs->attribute("instrument"); // Get model GObservationRegistry registry; GObservation* ptr = registry.alloc(instrument); // If observation is valid then read its definition from XML file if (ptr != NULL) { // Read definition ptr->read(*obs); // Set attributes ptr->name(name); ptr->id(id); } // endif: observation was valid // ... otherwise throw an exception else { throw GException::invalid_instrument(G_READ, instrument); } // Append observation to container append(*ptr); // Free model (appending clones the observation) delete ptr; } // endfor: looped over all observations // Return return; }
/***********************************************************************//** * @brief Test XML element access **************************************************************************/ void TestGXml::test_GXml_access(void) { // Test root document access GXml xml; xml.load(m_xml_file); test_value(xml.size(), 3, "Check number of child elements"); // Test node access for (int i = 0; i < xml.size(); ++i) { GXmlNode* ptr = xml[i]; test_assert(ptr != 0, "Check XML node access"); } test_value(xml.elements(), 1, "Check number of child elements"); // Test node access for (int i = 0; i < xml.elements(); ++i) { GXmlNode* ptr = xml.element(i); test_assert(ptr != 0, "Check XML element access"); } test_value(xml.elements("source_library"), 1, "Check number of child elements"); // Test element access for (int i = 0; i < xml.elements("source_library"); ++i) { GXmlElement* ptr = xml.element("source_library", i); test_value(ptr->name(), "source_library", "Check element name"); } // Test hierarchy access GXmlElement* ptr = NULL; ptr = xml.element("source_library"); test_value(ptr->name(), "source_library", "Check hierarchy level 1"); ptr = xml.element("source_library > source"); test_value(ptr->name(), "source", "Check hierarchy level 2"); ptr = xml.element("source_library > source > spectrum"); test_value(ptr->name(), "spectrum", "Check hierarchy level 3"); ptr = xml.element("source_library > source > spectrum > parameter[2]"); test_value(ptr->name(), "parameter", "Check hierarchy level 4"); test_value(ptr->attribute("name"), "PivotEnergy", "Check for attribute"); // Return return; }
/***********************************************************************//** * @brief Read CTA instrument background model from XML element * * @param[in] xml XML element. * * Set up CTA instrument background model from the information provided by * an XML element. The XML element is expected to have the following * structure * * <source name="..." type="..." instrument="..."> * <spectrum type="..."> * ... * </spectrum> * </source> * * Optionally, a temporal model may be provided using the following * syntax * * <source name="..." type="..." instrument="..."> * <spectrum type="..."> * ... * </spectrum> * <temporalModel type="..."> * ... * </temporalModel> * </source> * * If no temporal component is found a constant model is assumed. ***************************************************************************/ void GCTAModelIrfBackground::read(const GXmlElement& xml) { // Clear model clear(); // Initialise XML elements const GXmlElement* spectral = NULL; const GXmlElement* temporal = NULL; // Get pointer on spectrum spectral = xml.element("spectrum", 0); // Extract spectral model m_spectral = xml_spectral(*spectral); // Optionally get temporal model if (xml.elements("temporalModel")) { temporal = xml.element("temporalModel", 0); m_temporal = xml_temporal(*temporal); } else { GModelTemporalConst constant; m_temporal = constant.clone(); } // 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 parameter pointers set_pointers(); // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element into which model information is written. * * @exception GException::model_invalid_spatial * Existing XML element is not of type 'GaussFunction' * @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. * * Writes the radial disk model information into an XML element. The XML * element will have the format * * <spatialModel type="RadialGaussian"> * <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> * <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> * <parameter name="Sigma" scale="1.0" value="0.45" min="0.01" max="10" free="1"/> * </spatialModel> * ***************************************************************************/ void GModelSpatialRadialGauss::write(GXmlElement& xml) const { // Write Gaussian location GModelSpatialRadial::write(xml); // If XML element has 2 nodes (which should be the location nodes) // then append 1 parameter node if (xml.elements() == 2) { xml.append(GXmlElement("parameter name=\"Sigma\"")); } // Determine number of parameter nodes in XML element int npars = xml.elements("parameter"); // Verify that XML element has exactly 3 parameters if (xml.elements() != 3 || npars != 3) { throw GException::model_invalid_parnum(G_WRITE, xml, "Point source model requires exactly 3 parameters."); } // Set or update model parameter attributes int npar[1] = {0}; for (int i = 0; i < npars; ++i) { // Get parameter element GXmlElement* par = xml.element("parameter", i); // Handle Sigma if (par->attribute("name") == "Sigma") { m_sigma.write(*par); npar[0]++; } } // endfor: looped over all parameters // Check of all required parameters are present if (npar[0] != 1) { throw GException::model_invalid_parnames(G_WRITE, xml, "Require \"Sigma\" parameter."); } // Return return; }
/***********************************************************************//** * @brief Read model from XML element * * @param[in] xml XML element. * * The model is composed of a spectrum component ('spectral'), a spatial * component ('spatialModel'), and, optionally, of a temporal component * ('lightcurve'). If no temporal component is found a constant model is * assumed. ***************************************************************************/ void GCTAModelBackground::read(const GXmlElement& xml) { // Clear model clear(); // Initialise XML elements const GXmlElement* spat = NULL; const GXmlElement* spec = NULL; const GXmlElement* temp = NULL; // Get pointers on spectrum and radial model spat = xml.element("spatialModel", 0); spec = xml.element("spectrum", 0); // Clone radial and spectral models m_spatial = xml_spatial(*spat); m_spectral = xml_spectral(*spec); // Optionally get temporal model if (xml.elements("temporalModel")) { temp = xml.element("temporalModel", 0); m_temporal = xml_temporal(*temp); } else { GModelTemporalConst temporal; m_temporal = temporal.clone(); } // Set model name name(xml.attribute("name")); // Set instruments instruments(xml.attribute("instrument")); // Set observation identifiers ids(xml.attribute("id")); // Set parameter pointers set_pointers(); // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element into which model information is written. * * @exception GException::model_invalid_spectral * Existing XML element is not of type "FileFunction" * @exception GException::model_invalid_parnum * Invalid number of model parameters or nodes found in XML element. * @exception GException::model_invalid_parnames * Invalid model parameter names found in XML element. * * Write the spectral function information into an XML element. The XML * element has to be of type "FileFunction" and will have 1 parameter leaf * named "Normalization". Note that the function nodes will not be written * since they will not be altered by any method. ***************************************************************************/ void GModelSpectralFunc::write(GXmlElement& xml) const { // Set model type if (xml.attribute("type") == "") { xml.attribute("type", "FileFunction"); } // Verify model type if (xml.attribute("type") != "FileFunction") { throw GException::model_invalid_spectral(G_WRITE, xml.attribute("type"), "Spectral model is not of type \"FileFunction\"."); } // If XML element has 0 nodes then append 1 parameter node if (xml.elements() == 0) { xml.append(new GXmlElement("parameter name=\"Normalization\"")); } // Verify that XML element has exactly 1 parameter if (xml.elements() != 1 || xml.elements("parameter") != 1) { throw GException::model_invalid_parnum(G_WRITE, xml, "Spectral function requires exactly 1 parameter."); } // Get parameter element GXmlElement* par = static_cast<GXmlElement*>(xml.element("parameter", 0)); // Set parameyter if (par->attribute("name") == "Normalization") { m_norm.write(*par); } else { throw GException::model_invalid_parnames(G_WRITE, xml, "Require \"Normalization\" parameter."); } // 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; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element into which model information is written. * * @exception GException::model_invalid_spatial * Existing XML element is not of type 'GaussFunction' * @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. * * Writes the radial source location and position angle information into an * XML element in the following format * * <spatialModel type="..."> * <parameter name="RA" scale="1" value="83.63" min="-360" max="360" free="1"/> * <parameter name="DEC" scale="1" value="22.01" min="-90" max="90" free="1"/> * ... * </spatialModel> * * @todo The case that an existing spatial XML element with "GLON" and "GLAT" * as coordinates is not supported. ***************************************************************************/ void GModelSpatialRadial::write(GXmlElement& xml) const { // Set model type if (xml.attribute("type") == "") { xml.attribute("type", type()); } // Verify model type if (xml.attribute("type") != type()) { throw GException::model_invalid_spatial(G_WRITE, xml.attribute("type"), "Radial model is not of type \""+type()+"\"."); } // If XML element has 0 nodes then append 2 parameter nodes if (xml.elements() == 0) { xml.append(GXmlElement("parameter name=\"RA\"")); xml.append(GXmlElement("parameter name=\"DEC\"")); } // Determine number of parameter nodes in XML element int npars = xml.elements("parameter"); // Verify that XML element has at least 2 parameters if (xml.elements() < 2 || npars < 2) { throw GException::model_invalid_parnum(G_WRITE, xml, "Radial source model requires at least 2 parameters."); } // Set or update model parameter attributes int npar[2] = {0, 0}; for (int i = 0; i < npars; ++i) { // Get parameter element GXmlElement* par = xml.element("parameter", i); // Handle RA if (par->attribute("name") == "RA") { npar[0]++; m_ra.write(*par); } // Handle DEC else if (par->attribute("name") == "DEC") { npar[1]++; m_dec.write(*par); } } // endfor: looped over all parameters // Check of all required parameters are present if (npar[0] != 1 || npar[1] != 1) { throw GException::model_invalid_parnames(G_WRITE, xml, "Require \"RA\" and \"DEC\" parameters."); } // 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. * * Reads the radial source location and position angle information from an * XML element in the following format * * <spatialModel type="..."> * <parameter name="RA" scale="1" value="83.63" min="-360" max="360" free="1"/> * <parameter name="DEC" scale="1" value="22.01" min="-90" max="90" free="1"/> * ... * </spatialModel> * * or * * <spatialModel type="..."> * <parameter name="GLON" scale="1" value="83.63" min="-360" max="360" free="1"/> * <parameter name="GLAT" scale="1" value="22.01" min="-90" max="90" free="1"/> * ... * </spatialModel> * ***************************************************************************/ void GModelSpatialRadial::read(const GXmlElement& xml) { // Determine number of parameter nodes in XML element int npars = xml.elements("parameter"); // Verify that XML element has at least 2 parameters if (xml.elements() < 2 || npars < 2) { throw GException::model_invalid_parnum(G_READ, xml, "Radial model requires at least 2 parameters."); } // Extract model parameters bool has_glon = false; bool has_glat = false; int npar[2] = {0, 0}; for (int i = 0; i < npars; ++i) { // Get parameter element const GXmlElement* par = xml.element("parameter", i); // Handle RA/GLON if (par->attribute("name") == "RA") { m_ra.read(*par); npar[0]++; } else if (par->attribute("name") == "GLON") { m_ra.read(*par); npar[0]++; has_glon = true; } // Handle DEC/GLAT else if (par->attribute("name") == "DEC") { m_dec.read(*par); npar[1]++; } else if (par->attribute("name") == "GLAT") { m_dec.read(*par); npar[1]++; has_glat = true; } } // endfor: looped over all parameters // Check if we have to convert GLON/GLAT into RA/DEC if (has_glon && has_glat) { GSkyDir dir; dir.lb_deg(ra(), dec()), m_ra.value(dir.ra_deg()); m_dec.value(dir.dec_deg()); } else if (has_glon || has_glat) { throw GException::model_invalid_parnames(G_READ, xml, "Require either \"RA\"/\"DEC\" or \"GLON\"/\"GLAT\"."); } // Verify that all parameters were found if (npar[0] != 1 || npar[1] != 1) { throw GException::model_invalid_parnames(G_READ, xml, "Require \"RA\"/\"DEC\" and \"GLON\"/\"GLAT\" parameters."); } // Return return; }
/***********************************************************************//** * @brief Process markup segment * * @param[in] current Handle to current node. * @param[in] segment Segment string. * * Process markup segment. ***************************************************************************/ void GXml::process_markup(GXmlNode** current, const std::string& segment) { // Determine segment tag type MarkupType type = get_markuptype(segment); // Do tag specific processing switch (type) { // Handle element start tag case MT_ELEMENT_START: { // Create new element node, set it's parent, append it to the // current node and make it the current node GXmlElement element(segment); element.parent(*current); (*current)->append(element); int last = (*current)->size() - 1; (*current) = (*(*current))[last]; } break; // Handle element end tag case MT_ELEMENT_END: { // Check if we expect an element end tag if ((*current)->type() != GXmlNode::NT_ELEMENT) { throw GException::xml_syntax_error(G_PROCESS, segment, "unexpected element end tag encountered"); } // Check if we have the correct end tag GXmlElement* element = (GXmlElement*)(*current); element->parse_stop(segment); // Set current node pointer back to parent of the current node (*current) = element->parent(); } break; // Append empty-element tag case MT_ELEMENT_EMPTY: { GXmlElement element(segment.substr(1,segment.length()-3)); element.parent(*current); (*current)->append(element); } break; // Append comment markup case MT_COMMENT: { GXmlComment comment(segment); (*current)->append(comment); } break; // Declaration markup case MT_DECLARATION: { // Verify if declaration tag is allowed if (*current != &m_root) { throw GException::xml_syntax_error(G_PROCESS, segment, "unexpected declaration markup encountered"); } if (!m_root.is_empty()) { throw GException::xml_syntax_error(G_PROCESS, segment, "declaration markup only allowed in first line"); } // Create temporary element to read in declaration attributes GXmlElement* element = new GXmlElement(segment); size_t pos = 5; while (pos != std::string::npos) { element->parse_attribute(&pos, segment); } // Set attribute values std::string version = element->attribute("version"); std::string encoding = element->attribute("encoding"); std::string standalone = element->attribute("standalone"); if (version.length() > 0) { m_root.version(version); } if (encoding.length() > 0) { m_root.encoding(encoding); } if (standalone.length() > 0) { m_root.standalone(standalone); } // Delete temporary element delete element; } break; // Processing tag case MT_PROCESSING: { GXmlPI pi(segment); (*current)->append(pi); } break; // Invalid tag, throw an error case MT_INVALID: throw GException::xml_syntax_error(G_PROCESS, segment, "invalid tag"); break; } // Return return; }
/***********************************************************************//** * @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 Write Test Suites into XML document * * @param[in] xml XML document. * * Write test suites into the XML document. ***************************************************************************/ void GTestSuites::write(GXml& xml) const { // Append XML element for Test Suites GXmlElement* testsuites = xml.append("testsuites"); // Set attributes testsuites->attribute("name", "GammaLib"); /* testsuites->attribute("test",str(tests())); testsuites->attribute("errors",str(errors())); testsuites->attribute("failures",str(failures())); testsuites->attribute("time","0"); // not used testsuites->attribute("timestamp",str(timestamp())); */ // Loop over all test suites in the container for (int i = 0; i < m_testsuites.size(); ++i) { // Get a pointer on the current test suite GTestSuite* testsuite = m_testsuites[i]; // Append XML element for this test suite GXmlElement* element_testsuite = testsuites->append("testsuite"); // Set attributes element_testsuite->attribute("disabled",""); // not used element_testsuite->attribute("errors",gammalib::str(testsuite->errors())); element_testsuite->attribute("failures",gammalib::str(testsuite->failures())); element_testsuite->attribute("hostname",""); // not used element_testsuite->attribute("id",gammalib::str(i)); element_testsuite->attribute("name",testsuite->name()); element_testsuite->attribute("package",""); // not used element_testsuite->attribute("skipped",""); // not used element_testsuite->attribute("tests",gammalib::str(testsuite->size())); element_testsuite->attribute("time",gammalib::str(testsuite->duration())); element_testsuite->attribute("timestamp",gammalib::str(testsuite->timestamp())); // Loop over all test cases in the test suite for (int j = 0; j < testsuite->size(); ++j) { // Reference to the current test case GTestCase& testcase = (*testsuite)[j]; // Append XML element for this test case GXmlElement* element_testcase = element_testsuite->append("testcase"); // Set attributes element_testcase->attribute("assertions",""); // not used element_testcase->attribute("classname",name()); element_testcase->attribute("name",testcase.name()); element_testcase->attribute("status",""); // not used element_testcase->attribute("time",gammalib::str(testcase.duration())); // If a failure or error occured then append the message to the // XML element. if (!testcase.has_passed()) { // Append XML element for the test case problem GXmlElement* element_testcase_problem = element_testcase->append("error"); // Set attributes element_testcase_problem->attribute("message",testcase.message()); element_testcase_problem->attribute("type",testcase.type()); // Set tag name dependent on the type of problem if (testcase.kind() == GTestCase::ERROR_TEST) { element_testcase_problem->name("error"); } else { element_testcase_problem->name("failure"); } } // endif: failure or error occured } // endfor: looped over all test cases } // endfor: looped over all test suites // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element. * * @todo Document method. ***************************************************************************/ void GCTAModelBackground::write(GXmlElement& xml) const { // Initialise pointer on source GXmlElement* src = NULL; // Search corresponding source int n = xml.elements("source"); for (int k = 0; k < n; ++k) { GXmlElement* element = xml.element("source", k); if (element->attribute("name") == name()) { src = element; break; } } // If no source with corresponding name was found then append one if (src == NULL) { src = xml.append("source"); if (spectral() != NULL) src->append(GXmlElement("spectrum")); if (spatial() != NULL) src->append(GXmlElement("spatialModel")); //if (temporal() != NULL) src->append(GXmlElement("temporalModel")); } // Set model type, name and optionally instruments src->attribute("name", name()); src->attribute("type", type()); if (instruments().length() > 0) { src->attribute("instrument", instruments()); } std::string identifiers = ids(); if (identifiers.length() > 0) { src->attribute("id", identifiers); } // Write spectral model if (spectral() != NULL) { GXmlElement* spec = src->element("spectrum", 0); spectral()->write(*spec); } // Write spatial model if (spatial() != NULL) { GXmlElement* spat = src->element("spatialModel", 0); spatial()->write(*spat); } // Write temporal model /* if (temporal() != NULL) { if (dynamic_cast<GModelTemporalConst*>(temporal()) == NULL) { GXmlElement* temp = src->element("temporalModel", 0); temporal()->write(*temp); } } */ // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element. * * @exception GException::model_invalid_spatial * Existing XML element is not of type 'Polynom' * @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. * * Write the polynomial radial model information into an XML element. The XML * element will have 1-10 parameter leafs named "CoeffX", where X runs from * 0 to 9. ***************************************************************************/ void GCTAModelRadialPolynom::write(GXmlElement& xml) const { // Determine number of coefficients int ncoeffs = m_coeffs.size(); // Set model type if (xml.attribute("type") == "") { xml.attribute("type", type()); } // Verify model type if (xml.attribute("type") != type()) { throw GException::model_invalid_spatial(G_WRITE, xml.attribute("type"), "Radial polynomial model is not of type \""+type()+"\"."); } // If XML element has 0 nodes then append nodes for coefficients if (xml.elements() == 0) { for (int i = 0; i < ncoeffs; ++i) { std::string name = "parameter name=\"Coeff"+str(i)+"\""; xml.append(new GXmlElement(name)); } } // Verify that XML element has one parameter per coefficient if (xml.elements() != ncoeffs || xml.elements("parameter") != ncoeffs) { std::string message = "Radial polynomial model requires exactly " + str(ncoeffs) + " parameters."; throw GException::model_invalid_parnum(G_WRITE, xml, message); } // Set or update model parameter attributes std::vector<int> npar; npar.assign(ncoeffs, 0); 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_WRITE, xml, message); } // Write parameter m_coeffs[i].write(*par); // Increment parameter counter npar[i]++; } // endfor: looped over all parameters // Verify that all parameters were present for (int i = 0; i < ncoeffs; ++i) { if (npar[i] != 1) { std::string message = "Parameter \"Coeff"+str(i)+"\" required," " but not found in XML file."; throw GException::model_invalid_parnames(G_WRITE, xml, message); } } // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml Source library. ***************************************************************************/ void GModelSky::write(GXmlElement& xml) const { // Initialise pointer on source GXmlElement* src = NULL; // Search corresponding source int n = xml.elements("source"); for (int k = 0; k < n; ++k) { GXmlElement* element = static_cast<GXmlElement*>(xml.element("source", k)); if (element->attribute("name") == name()) { src = element; break; } } // If no source with corresponding name was found then append one if (src == NULL) { src = new GXmlElement("source"); src->attribute("name") = name(); if (spectral() != NULL) src->append(new GXmlElement("spectrum")); if (spatial() != NULL) src->append(new GXmlElement("spatialModel")); xml.append(src); } // Set model attributes src->attribute("name", name()); src->attribute("type", type()); std::string instruments = this->instruments(); if (instruments.length() > 0) { src->attribute("instrument", instruments); } // Write spectral model if (spectral() != NULL) { GXmlElement* spec = static_cast<GXmlElement*>(src->element("spectrum", 0)); spectral()->write(*spec); } // Write spatial model if (spatial() != NULL) { GXmlElement* spat = static_cast<GXmlElement*>(src->element("spatialModel", 0)); spatial()->write(*spat); } // Return return; }
/***********************************************************************//** * @brief Write observation into XML element * * @param[in] xml XML element. * * @exception GException::xml_invalid_parnum * Invalid number of parameters found in XML element. * @exception GException::xml_invalid_parnames * Invalid parameter names found in XML element. * * Writes information for a multi-wavelength observation into an XML element. * The format of the XML element is * * <observation name="..." id="..." instrument="MWL"> * <parameter name="Instrument" value="..."/> * <parameter name="Data" file="..." [extno="..."] [extname="..."]/> * </observation> ***************************************************************************/ void GMWLObservation::write(GXmlElement& xml) const { // If XML element has 0 nodes then append 2 parameter nodes if (xml.elements() == 0) { xml.append(GXmlElement("parameter name=\"Instrument\"")); xml.append(GXmlElement("parameter name=\"Data\"")); } // Verify that XML element has exactly 2 parameters if (xml.elements() != 2 || xml.elements("parameter") != 2) { throw GException::xml_invalid_parnum(G_WRITE, xml, "MWL observation requires exactly 2 parameters."); } // Set or update parameter attributes int npar[] = {0, 0}; for (int i = 0; i < 2; ++i) { // Get parameter element GXmlElement* par = xml.element("parameter", i); // Handle Instrument if (par->attribute("name") == "Instrument") { npar[0]++; par->attribute("value", m_instrument); } // Handle Data else if (par->attribute("name") == "Data") { npar[1]++; par->attribute("file", m_filename); if (gammalib::strip_whitespace(m_extno).length() > 0) { par->attribute("extno", m_extno); } if (gammalib::strip_whitespace(m_extname).length() > 0) { par->attribute("extname", m_extname); } } } // endfor: looped over all parameters // Check of all required parameters are present if (npar[0] != 1 || npar[1] != 1) throw GException::xml_invalid_parnames(G_WRITE, xml, "Require \"Instrument\" and \"Data\" parameters."); // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element into which model information is written. * * @exception GException::model_invalid_spectral * Existing XML element is not of type "ExpCutoff" * @exception GException::model_invalid_parnum * Invalid number of model parameters or nodes found in XML element. * @exception GException::model_invalid_parnames * Invalid model parameter names found in XML element. * * Writes the spectral information into an XML element. The format of the XML * element is * * <spectrum type="ExpCutoff"> * <parameter name="Prefactor" scale=".." value=".." min=".." max=".." free=".."/> * <parameter name="Index" scale=".." value=".." min=".." max=".." free=".."/> * <parameter name="Cutoff" scale=".." value=".." min=".." max=".." free=".."/> * <parameter name="Scale" scale=".." value=".." min=".." max=".." free=".."/> * </spectrum> ***************************************************************************/ void GModelSpectralExpPlaw::write(GXmlElement& xml) const { // Set model type if (xml.attribute("type") == "") { xml.attribute("type", "ExpCutoff"); } // Verify model type if (xml.attribute("type") != "ExpCutoff") { throw GException::model_invalid_spectral(G_WRITE, xml.attribute("type"), "Spectral model is not of type \"ExpCutoff\"."); } // If XML element has 0 nodes then append 4 parameter nodes if (xml.elements() == 0) { xml.append(GXmlElement("parameter name=\"Prefactor\"")); xml.append(GXmlElement("parameter name=\"Index\"")); xml.append(GXmlElement("parameter name=\"Cutoff\"")); xml.append(GXmlElement("parameter name=\"Scale\"")); } // Verify that XML element has exactly 4 parameters if (xml.elements() != 4 || xml.elements("parameter") != 4) { throw GException::model_invalid_parnum(G_WRITE, xml, "Power law model requires exactly 4 parameters."); } // Set or update model parameter attributes int npar[] = {0, 0, 0, 0}; for (int i = 0; i < 4; ++i) { // Get parameter element GXmlElement* par = xml.element("parameter", i); // Handle prefactor if (par->attribute("name") == "Prefactor") { npar[0]++; m_norm.write(*par); } // Handle index else if (par->attribute("name") == "Index") { npar[1]++; m_index.write(*par); } // Handle index else if (par->attribute("name") == "Cutoff") { npar[2]++; m_ecut.write(*par); } // Handle pivot energy else if (par->attribute("name") == "Scale") { m_pivot.write(*par); npar[3]++; } } // endfor: looped over all parameters // Check of all required parameters are present if (npar[0] != 1 || npar[1] != 1 || npar[2] != 1 || npar[3] != 1) { throw GException::model_invalid_parnames(G_WRITE, xml, "Require \"Prefactor\", \"Index\", \"Cutoff\" and \"Scale\"" " parameters."); } // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element. * * @exception GException::model_invalid_spectral * Existing XML element is not of required type * @exception GException::model_invalid_parnum * Invalid number of model parameters or nodes found in XML element. * @exception GException::model_invalid_parnames * Invalid model parameter names found in XML element. * * Write the COMPTEL DRB fitting model into 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::write(GXmlElement& xml) const { // Initialise pointer on source GXmlElement* src = NULL; // Search corresponding source int n = xml.elements("source"); for (int k = 0; k < n; ++k) { GXmlElement* element = xml.element("source", k); if (element->attribute("name") == name()) { src = element; break; } } // If no source with corresponding name was found then append one. // Set also the type and the instrument. if (src == NULL) { src = xml.append("source"); src->attribute("name", name()); src->attribute("type", type()); if (instruments().length() > 0) { src->attribute("instrument", instruments()); } } // Verify model type if (src->attribute("type") != type()) { std::string msg = "Invalid model type \""+src->attribute("type")+"\" " "found in XML file. Model type \""+type()+"\" " "expected."; throw GException::invalid_value(G_WRITE, msg); } // Determine number of nodes int nodes = m_phibars.size(); // If XML element has 0 nodes then append nodes if (src->elements() == 0) { for (int i = 0; i < nodes; ++i) { src->append(GXmlElement("node")); } } // Verify that XML element has the required number of nodes if (src->elements() != nodes || src->elements("node") != nodes) { std::string msg = "Invalid number of nodes "+ gammalib::str(src->elements("node"))+ " found in XML file, but model requires exactly "+ gammalib::str(nodes)+" nodes."; throw GException::invalid_value(G_WRITE, msg); } // Loop over all nodes for (int i = 0; i < nodes; ++i) { // Get node GXmlElement* node = src->element("node", i); // Write Phibar parameter GXmlElement* par = gammalib::xml_need_par(G_WRITE, *node, "Phibar"); m_phibars[i].write(*par); // Write Normalization parameter par = gammalib::xml_need_par(G_WRITE, *node, "Normalization"); m_values[i].write(*par); } // endfor: looped over nodes // 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_parvalue * Non-positive parameter value found. * @exception GException::model_invalid_parlimit * Missing or non-positive minimum parameter boundary. * @exception GException::model_invalid_parnames * Invalid model parameter names found in XML element. * * Read the Profile radial model information from an XML element. The XML * element is required to have 3 parameter named "Width", "Core", and "Tail". ***************************************************************************/ void GCTAModelRadialProfile::read(const GXmlElement& xml) { // Verify that XML element has exactly 3 parameter if (xml.elements() != 3 || xml.elements("parameter") != 3) { throw GException::model_invalid_parnum(G_READ, xml, "Radial Profile model requires exactly 3 parameters."); } // Extract model parameters int npar[] = {0, 0, 0}; for (int i = 0; i < 3; ++i) { // Get parameter element GXmlElement* par = static_cast<GXmlElement*>(xml.element("parameter", i)); // Handle Width if (par->attribute("name") == "Width") { m_width.read(*par); if (m_width.real_value() <= 0.0) { throw GException::model_invalid_parvalue(G_READ, xml, "\"Width\" parameter is required to be positive."); } if (!m_width.hasmin() || m_width.real_min() <= 0.0) { throw GException::model_invalid_parlimit(G_READ, xml, "\"Width\" parameter requires positive minimum boundary."); } npar[0]++; } // Handle Core if (par->attribute("name") == "Core") { m_core.read(*par); if (m_core.real_value() <= 0.0) { throw GException::model_invalid_parvalue(G_READ, xml, "\"Core\" parameter is required to be positive."); } if (!m_core.hasmin() || m_core.real_min() <= 0.0) { throw GException::model_invalid_parlimit(G_READ, xml, "\"Core\" parameter requires positive minimum boundary."); } npar[1]++; } // Handle Tail if (par->attribute("name") == "Tail") { m_tail.read(*par); if (m_tail.real_value() <= 0.0) { throw GException::model_invalid_parvalue(G_READ, xml, "\"Core\" parameter is required to be positive."); } if (!m_tail.hasmin() || m_tail.real_min() <= 0.0) { throw GException::model_invalid_parlimit(G_READ, xml, "\"Core\" parameter requires positive minimum boundary."); } npar[2]++; } } // endfor: looped over all parameters // Verify that all parameters were found if (npar[0] != 1 || npar[1] != 1 || npar[2] != 1) { throw GException::model_invalid_parnames(G_READ, xml, "Require \"Width\", \"Core\" and \"Tail\" parameters."); } // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element. * * @exception GException::model_invalid_spatial * Existing XML element is not of type 'ProfileFunction' * @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. * * Write the radial Profile model information into an XML element. The XML * element will have 3 parameter leafs named "Width", "Core" and "Tail". ***************************************************************************/ void GCTAModelRadialProfile::write(GXmlElement& xml) const { // Set model type if (xml.attribute("type") == "") { xml.attribute("type", type()); } // Verify model type if (xml.attribute("type") != type()) { throw GException::model_invalid_spatial(G_WRITE, xml.attribute("type"), "Radial Profile model is not of type \""+type()+"\"."); } // If XML element has 0 nodes then append 3 parameter nodes if (xml.elements() == 0) { xml.append(new GXmlElement("parameter name=\"Width\"")); xml.append(new GXmlElement("parameter name=\"Core\"")); xml.append(new GXmlElement("parameter name=\"Tail\"")); } // Verify that XML element has exactly 3 parameters if (xml.elements() != 3 || xml.elements("parameter") != 3) { throw GException::model_invalid_parnum(G_WRITE, xml, "Radial Profile model requires exactly 3 parameters."); } // Set or update model parameter attributes int npar[] = {0, 0, 0}; for (int i = 0; i < 3; ++i) { // Get parameter element GXmlElement* par = static_cast<GXmlElement*>(xml.element("parameter", i)); // Handle prefactor if (par->attribute("name") == "Width") { m_width.write(*par); npar[0]++; } // Handle index else if (par->attribute("name") == "Core") { m_core.write(*par); npar[1]++; } // Handle pivot energy else if (par->attribute("name") == "Tail") { m_tail.write(*par); npar[2]++; } } // endfor: looped over all parameters // Check of all required parameters are present if (npar[0] != 1 || npar[1] != 1 || npar[2] != 1) { throw GException::model_invalid_parnames(G_WRITE, xml, "Require \"Width\", \"Core\" and \"Tail\" parameters."); } // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element. * * @exception GException::model_invalid_spectral * Existing XML element is not of type "PowerLaw2" * @exception GException::model_invalid_parnum * Invalid number of model parameters or nodes found in XML element. * @exception GException::model_invalid_parnames * Invalid model parameter names found in XML element. * * Writes the spectral information into an XML element. The format of the XML * element is * * <spectrum type="PowerLaw2"> * <parameter name="Integral" scale=".." value=".." min=".." max=".." free=".."/> * <parameter name="Index" scale=".." value=".." min=".." max=".." free=".."/> * <parameter name="LowerLimit" scale=".." value=".." min=".." max=".." free=".."/> * <parameter name="UpperLimit" scale=".." value=".." min=".." max=".." free=".."/> * </spectrum> ***************************************************************************/ void GModelSpectralPlaw2::write(GXmlElement& xml) const { // Set model type if (xml.attribute("type") == "") { xml.attribute("type", "PowerLaw2"); } // Verify model type if (xml.attribute("type") != "PowerLaw2") { throw GException::model_invalid_spectral(G_WRITE, xml.attribute("type"), "Spectral model is not of type \"PowerLaw2\"."); } // If XML element has 0 nodes then append 4 parameter nodes if (xml.elements() == 0) { xml.append(GXmlElement("parameter name=\"Integral\"")); xml.append(GXmlElement("parameter name=\"Index\"")); xml.append(GXmlElement("parameter name=\"LowerLimit\"")); xml.append(GXmlElement("parameter name=\"UpperLimit\"")); } // Verify that XML element has exactly 4 parameters if (xml.elements() != 4 || xml.elements("parameter") != 4) { throw GException::model_invalid_parnum(G_WRITE, xml, "Power law 2 spectral model requires exactly 4 parameters."); } // Set or update model parameter attributes int npar[] = {0, 0, 0, 0}; for (int i = 0; i < 4; ++i) { // Get parameter element GXmlElement* par = xml.element("parameter", i); // Handle prefactor if (par->attribute("name") == "Integral") { npar[0]++; m_integral.write(*par); } // Handle index else if (par->attribute("name") == "Index") { npar[1]++; m_index.write(*par); } // Handle lower limit else if (par->attribute("name") == "LowerLimit") { m_emin.write(*par); npar[2]++; } // Handle lower limit else if (par->attribute("name") == "UpperLimit") { m_emax.write(*par); npar[3]++; } } // endfor: looped over all parameters // Check of all required parameters are present if (npar[0] != 1 || npar[1] != 1 || npar[2] != 1 || npar[3] != 1) { throw GException::model_invalid_parnames(G_WRITE, xml, "Power law 2 spectral model requires \"Integral\", \"Index\"," " \"LowerLimit\" and \"UpperLimit\" parameters."); } // Return return; }
/***********************************************************************//** * @brief Parse XML URL * * @param[in] url Unified Resource Locator. * * @exception GException::xml_syntax_error * XML syntax error. * * Parses either a XML file or a XML text string and creates all associated * nodes. The XML file is split into segments, made either of text or of * tags. ***************************************************************************/ void GXml::parse(const GUrl& url) { // Initialise parser int c; bool in_markup = false; bool in_comment = false; std::string segment; GXmlNode* current = &m_root; // Main parsing loop while ((c = url.get_char()) != EOF) { // Convert special characters into line feeds if (c == '\x85' || c == L'\x2028') { if (in_markup) { throw GException::xml_syntax_error(G_PARSE, segment, "invalid character encountered"); } else { c = '\x0a'; } } // Skip all linefeeds (to avoid extra linefeeds in text segments) if (c == '\x0a') { continue; } // If we are not within a markup and if a markup is reached then // add the text segment to the nodes and switch to in_markup mode if (in_markup == false) { // Markup start reached? if (c == '<') { // Add text segment to nodes (ignores empty segments) process_text(¤t, segment); // Prepare new segment and signal that we are within tag segment.clear(); segment.append(1, (char)c); in_markup = true; } // Markup stop encountered? else if (c == '>') { segment.append(1, (char)c); throw GException::xml_syntax_error(G_PARSE, segment, "unexpected closing bracket \">\" encountered"); } // ... otherwise add character to segment else { segment.append(1, (char)c); } } // If we are within a markup and if a markup end is reached then // process the markup and switch to not in_tag mode else { // Markup stop reached? if (c == '>') { // Append character to segment segment.append(1, (char)c); // If we are in comment then check if this is the end of // the comment if (in_comment) { int n = segment.length(); if (n > 2) { if (segment.compare(n-3,3,"-->") == 0) { in_comment = false; } } } // If we are not in the comment, then process markup if (!in_comment) { // Process markup process_markup(¤t, segment); // Prepare new segment and signal that we are not // within markup segment.clear(); in_markup = false; } } // Markup start encountered? else if (!in_comment && c == '<') { // Append character to segment segment.append(1, (char)c); // If we encounter an opening bracket then throw an exception throw GException::xml_syntax_error(G_PARSE, segment, "unexpected opening bracket \"<\" encountered"); } // ... otherwise add character to segment else { segment.append(1, (char)c); if (!in_comment && segment == "<!--") { in_comment = true; } } } } // endwhile: main parsing loop // Process any pending segment if (segment.size() > 0) { if (in_markup) { process_markup(¤t, segment); } else { process_text(¤t, segment); } } // Verify that we are back to the root node if (current != &m_root) { std::string message = "closing tag "; GXmlElement* element = dynamic_cast<GXmlElement*>(current); if (element != NULL) { message += "for GXmlElement \""+element->name()+"\""; } message += " is missing"; throw GException::xml_syntax_error(G_PARSE, "", message); } // Return return; }
/***********************************************************************//** * @brief Write CTA instrument background model into XML element * * @param[in] xml XML element. * * Write CTA instrument background model information into an XML element. * The XML element will have the following structure * * <source name="..." type="..." instrument="..."> * <spectrum type="..."> * ... * </spectrum> * </source> * * If the model contains a non-constant temporal model, the temporal * component will also be written following the syntax * * <source name="..." type="..." instrument="..."> * <spectrum type="..."> * ... * </spectrum> * <temporalModel type="..."> * ... * </temporalModel> * </source> * * If no temporal component is found a constant model is assumed. ***************************************************************************/ void GCTAModelIrfBackground::write(GXmlElement& xml) const { // Initialise pointer on source GXmlElement* src = NULL; // Search corresponding source int n = xml.elements("source"); for (int k = 0; k < n; ++k) { GXmlElement* element = xml.element("source", k); if (element->attribute("name") == name()) { src = element; break; } } // If we have a temporal model that is either not a constant, or a // constant with a normalization value that differs from 1.0 then // write the temporal component into the XML element. This logic // assures compatibility with the Fermi/LAT format as this format // does not handle temporal components. bool write_temporal = ((m_temporal != NULL) && (m_temporal->type() != "Constant" || (*m_temporal)[0].value() != 1.0)); // If no source with corresponding name was found then append one if (src == NULL) { src = xml.append("source"); if (spectral() != NULL) src->append(GXmlElement("spectrum")); if (write_temporal) src->append(GXmlElement("temporalModel")); } // Set model type, name and optionally instruments src->attribute("name", name()); src->attribute("type", type()); if (instruments().length() > 0) { src->attribute("instrument", instruments()); } std::string identifiers = ids(); if (identifiers.length() > 0) { src->attribute("id", identifiers); } // Write spectral model if (spectral() != NULL) { GXmlElement* spec = src->element("spectrum", 0); spectral()->write(*spec); } // Optionally write temporal model if (write_temporal) { if (dynamic_cast<GModelTemporalConst*>(temporal()) == NULL) { GXmlElement* temp = src->element("temporalModel", 0); temporal()->write(*temp); } } // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element. * * @exception GException::model_invalid_spatial * Existing XML element is not of type "MapCubeFunction" * @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. * * Write the map cube information into an XML element. The XML element has to * be of type "MapCubeFunction" and will have 1 parameter leaf named either * "Value" or "Normalization" (default). ***************************************************************************/ void GModelSpatialCube::write(GXmlElement& xml) const { // Set model type if (xml.attribute("type") == "") { xml.attribute("type", "MapCubeFunction"); } // Verify model type if (xml.attribute("type") != "MapCubeFunction") { throw GException::model_invalid_spatial(G_WRITE, xml.attribute("type"), "Spatial model is not of type \"MapCubeFunction\"."); } // If XML element has 0 nodes then append parameter node. The name // of the node is "Normalization" as this is the Fermi-LAT standard. // We thus assure that the XML files will be compatible with // Fermi-LAT. if (xml.elements() == 0) { xml.append(new GXmlElement("parameter name=\"Normalization\"")); } // Verify that XML element has exactly 1 parameter if (xml.elements() != 1 || xml.elements("parameter") != 1) { throw GException::model_invalid_parnum(G_WRITE, xml, "Map cube spatial model requires exactly 1 parameter."); } // Get pointers on model parameter GXmlElement* par = static_cast<GXmlElement*>(xml.element("parameter", 0)); // Set or update parameter if (par->attribute("name") == "Normalization" || par->attribute("name") == "Value") { m_value.write(*par); } else { throw GException::model_invalid_parnames(G_WRITE, xml, "Map cube spatial model requires either \"Value\" or" " \"Normalization\" parameter."); } // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element into which model information is written. * * @exception GException::model_invalid_spectral * Existing XML element is not of type "Gaussian" * @exception GException::model_invalid_parnum * Invalid number of model parameters or nodes found in XML element. * @exception GException::model_invalid_parnames * Invalid model parameter names found in XML element. * * Writes the spectral information into an XML element. The format of the XML * element is * * <spectrum type="Gaussian"> * <parameter name="Normalization" scale=".." value=".." min=".." max=".." free=".."/> * <parameter name="Mean" scale=".." value=".." min=".." max=".." free=".."/> * <parameter name="Sigma" scale=".." value=".." min=".." max=".." free=".."/> * </spectrum> ***************************************************************************/ void GModelSpectralGauss::write(GXmlElement& xml) const { // Set model type if (xml.attribute("type") == "") { xml.attribute("type", "Gaussian"); } // Verify model type if (xml.attribute("type") != "Gaussian") { throw GException::model_invalid_spectral(G_WRITE, xml.attribute("type"), "Spectral model is not of type \"Gaussian\"."); } // If XML element has 0 nodes then append 3 parameter nodes if (xml.elements() == 0) { xml.append(GXmlElement("parameter name=\"Normalization\"")); xml.append(GXmlElement("parameter name=\"Mean\"")); xml.append(GXmlElement("parameter name=\"Sigma\"")); } // Verify that XML element has exactly 3 parameters if (xml.elements() != 3 || xml.elements("parameter") != 3) { throw GException::model_invalid_parnum(G_WRITE, xml, "Power law model requires exactly 3 parameters."); } // Set or update model parameter attributes int npar[] = {0, 0, 0}; for (int i = 0; i < 3; ++i) { // Get parameter element GXmlElement* par = xml.element("parameter", i); // Handle normalization if (par->attribute("name") == "Normalization") { npar[0]++; m_norm.write(*par); } // Handle mean else if (par->attribute("name") == "Mean") { npar[1]++; m_mean.write(*par); } // Handle sigma else if (par->attribute("name") == "Sigma") { npar[2]++; m_sigma.write(*par); } } // endfor: looped over all parameters // Check of all required parameters are present if (npar[0] != 1 || npar[1] != 1 || npar[2] != 1 ) { throw GException::model_invalid_parnames(G_WRITE, xml, "Require \"Normalization\", \"Mean\" and \"Sigma\"" " parameters."); } // Return return; }