/***********************************************************************//** * @brief Read energy boundaries from XML element * * @param[in] xml XML element. * * @exception GException::invalid_value * Invalid XML format encountered. * * Read energy boundaries from an XML element. The format of the energy * boundaries is * * <parameter name="EnergyBoundaries" emin="0.1" emax="10.0"/> * * The units of the @a emin and @a emax parameters are MeV. ***************************************************************************/ void GEbounds::read(const GXmlElement& xml) { // Clear energy boundaries clear(); // Get energy boundaries parameter const GXmlElement* par = gammalib::xml_get_par(G_READ_XML, xml, "EnergyBoundaries"); // Extract position attributes if (par->has_attribute("emin") && par->has_attribute("emax")) { double emin = gammalib::todouble(par->attribute("emin")); double emax = gammalib::todouble(par->attribute("emax")); append(GEnergy(emin, "MeV"), GEnergy(emax, "MeV")); } else { std::string msg = "Attributes \"emin\" and/or \"emax\" not found" " in XML parameter \"EnergyBoundaries\"." " Please verify the XML format."; throw GException::invalid_value(G_READ_XML, msg); } // Set attribues set_attributes(); // Return return; }
/***********************************************************************//** * @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). * * Returns Monte Carlo energy by randomly drawing from a constant between * the minimum and maximum photon energy. * * Method Used: Box-Muller transform, outlined here: * http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform * * Code from: http://www.design.caltech.edu/erik/Misc/Gaussian.html ***************************************************************************/ GEnergy GModelSpectralGauss::mc(const GEnergy& emin, const GEnergy& emax, const GTime& time, GRan& ran) const { // Get energy boundaries in MeV double xmax = emax.MeV(); double xmin = emin.MeV(); // Initialize return energy double energy = 0.0; // Throw an exception if energy range is invalid if (xmin >= xmax) { throw GException::erange_invalid(G_MC, xmin, xmax, "Minimum energy < maximum energy required."); } // Sample until we find a value within the requested energy range do { // Compute random value double val = ran.normal(); // Scale to specified width and shift by mean value energy = m_sigma.value() * val + m_mean.value(); } while (energy < xmin || energy > xmax); // Return energy return GEnergy(energy, "MeV"); }
/***********************************************************************//** * @brief Test GEbounds ***************************************************************************/ void TestGObservation::test_ebounds(void) { // Test void constructor test_try("Void constructor"); try { GEbounds ebds; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Manipulate energy boudaries starting from an empty object GEbounds ebds; test_value(ebds.size(), 0, "GEbounds should have zero size."); test_assert(ebds.is_empty(), "GEbounds should be empty."); test_value(ebds.emin().MeV(), 0.0, 1.0e-10, "Minimum energy should be 0."); test_value(ebds.emax().MeV(), 0.0, 1.0e-10, "Maximum energy should be 0."); // Add empty interval ebds.append(GEnergy(1.0, "MeV"), GEnergy(1.0, "MeV")); test_value(ebds.size(), 0, "GEbounds should have zero size."); test_assert(ebds.is_empty(), "GEbounds should be empty."); test_value(ebds.emin().MeV(), 0.0, 1.0e-10, "Minimum energy should be 0."); test_value(ebds.emax().MeV(), 0.0, 1.0e-10, "Maximum energy should be 0."); // Add one interval ebds.append(GEnergy(1.0, "MeV"), GEnergy(10.0, "MeV")); test_value(ebds.size(), 1, "GEbounds should have 1 element."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 10.0, 1.0e-10, "Maximum energy should be 10."); // Remove interval ebds.remove(0); test_value(ebds.size(), 0, "GEbounds should have zero size."); test_assert(ebds.is_empty(), "GEbounds should be empty."); test_value(ebds.emin().MeV(), 0.0, 1.0e-10, "Minimum energy should be 0."); test_value(ebds.emax().MeV(), 0.0, 1.0e-10, "Maximum energy should be 0."); // Append two overlapping intervals ebds.append(GEnergy(1.0, "MeV"), GEnergy(100.0, "MeV")); ebds.append(GEnergy(10.0, "MeV"), GEnergy(1000.0, "MeV")); test_value(ebds.size(), 2, "GEbounds should have 2 elements."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 1000.0, 1.0e-10, "Maximum energy should be 1000."); // Clear object ebds.clear(); test_value(ebds.size(), 0, "GEbounds should have zero size."); test_assert(ebds.is_empty(), "GEbounds should be empty."); test_value(ebds.emin().MeV(), 0.0, 1.0e-10, "Minimum energy should be 0."); test_value(ebds.emax().MeV(), 0.0, 1.0e-10, "Maximum energy should be 0."); // Append two overlapping intervals in inverse order ebds.clear(); ebds.append(GEnergy(10.0, "MeV"), GEnergy(1000.0, "MeV")); ebds.append(GEnergy(1.0, "MeV"), GEnergy(100.0, "MeV")); test_value(ebds.size(), 2, "GEbounds should have 2 elements."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 1000.0, 1.0e-10, "Maximum energy should be 1000."); // Insert two overlapping intervals ebds.clear(); ebds.insert(GEnergy(1.0, "MeV"), GEnergy(100.0, "MeV")); ebds.insert(GEnergy(10.0, "MeV"), GEnergy(1000.0, "MeV")); test_value(ebds.size(), 2, "GEbounds should have 2 elements."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 1000.0, 1.0e-10, "Maximum energy should be 1000."); // Insert two overlapping intervals in inverse order ebds.clear(); ebds.insert(GEnergy(10.0, "MeV"), GEnergy(1000.0, "MeV")); ebds.insert(GEnergy(1.0, "MeV"), GEnergy(100.0, "MeV")); test_value(ebds.size(), 2, "GEbounds should have 2 elements."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 1000.0, 1.0e-10, "Maximum energy should be 1000."); // Merge two overlapping intervals ebds.clear(); ebds.merge(GEnergy(1.0, "MeV"), GEnergy(100.0, "MeV")); ebds.merge(GEnergy(10.0, "MeV"), GEnergy(1000.0, "MeV")); test_value(ebds.size(), 1, "GEbounds should have 1 element."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 1000.0, 1.0e-10, "Maximum energy should be 1000."); // Merge two overlapping intervals in inverse order ebds.clear(); ebds.merge(GEnergy(10.0, "MeV"), GEnergy(1000.0, "MeV")); ebds.merge(GEnergy(1.0, "MeV"), GEnergy(100.0, "MeV")); test_value(ebds.size(), 1, "GEbounds should have 1 element."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 1000.0, 1.0e-10, "Maximum energy should be 1000."); // Check linear boundaries ebds.clear(); ebds.set_lin(2, GEnergy(1.0, "MeV"), GEnergy(3.0, "MeV")); test_value(ebds.size(), 2, "GEbounds should have 2 elements."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin(0).MeV(), 1.0, 1.0e-10, "Bin 0 minimum energy should be 1."); test_value(ebds.emin(1).MeV(), 2.0, 1.0e-10, "Bin 1 minimum energy should be 2."); test_value(ebds.emax(0).MeV(), 2.0, 1.0e-10, "Bin 0 maximum energy should be 2."); test_value(ebds.emax(1).MeV(), 3.0, 1.0e-10, "Bin 1 maximum energy should be 3."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 3.0, 1.0e-10, "Maximum energy should be 3."); // Check logarithmic boundaries ebds.clear(); ebds.set_log(2, GEnergy(1.0, "MeV"), GEnergy(100.0, "MeV")); test_value(ebds.size(), 2, "GEbounds should have 2 elements."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin(0).MeV(), 1.0, 1.0e-10, "Bin 0 minimum energy should be 1."); test_value(ebds.emin(1).MeV(), 10.0, 1.0e-10, "Bin 1 minimum energy should be 10."); test_value(ebds.emax(0).MeV(), 10.0, 1.0e-10, "Bin 0 maximum energy should be 10."); test_value(ebds.emax(1).MeV(), 100.0, 1.0e-10, "Bin 1 maximum energy should be 100."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 100.0, 1.0e-10, "Maximum energy should be 100."); // Check boundary extension GEbounds ext(1, GEnergy(100.0, "MeV"), GEnergy(1000.0, "MeV")); ebds.extend(ext); test_value(ebds.size(), 3, "GEbounds should have 3 elements."); test_assert(!ebds.is_empty(), "GEbounds should not be empty."); test_value(ebds.emin(0).MeV(), 1.0, 1.0e-10, "Bin 0 minimum energy should be 1."); test_value(ebds.emin(1).MeV(), 10.0, 1.0e-10, "Bin 1 minimum energy should be 10."); test_value(ebds.emin(2).MeV(), 100.0, 1.0e-10, "Bin 2 minimum energy should be 100."); test_value(ebds.emax(0).MeV(), 10.0, 1.0e-10, "Bin 0 maximum energy should be 10."); test_value(ebds.emax(1).MeV(), 100.0, 1.0e-10, "Bin 1 maximum energy should be 100."); test_value(ebds.emax(2).MeV(), 1000.0, 1.0e-10, "Bin 1 maximum energy should be 1000."); test_value(ebds.emin().MeV(), 1.0, 1.0e-10, "Minimum energy should be 1."); test_value(ebds.emax().MeV(), 1000.0, 1.0e-10, "Maximum energy should be 1000."); // Return return; }
/***********************************************************************//** * @brief Test GEnergies ***************************************************************************/ void TestGObservation::test_energies(void) { // Test void constructor test_try("Void constructor"); try { GEnergies energies; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Manipulate GEnergies starting from an empty object GEnergies energies; test_value(energies.size(), 0, "GEnergies should have zero size."); test_assert(energies.is_empty(), "GEnergies should be empty."); // Add an energy energies.append(GEnergy()); test_value(energies.size(), 1, "GEnergies should have 1 energy."); test_assert(!energies.is_empty(), "GEnergies should not be empty."); // Remove energy energies.remove(0); test_value(energies.size(), 0, "GEnergies should have zero size."); test_assert(energies.is_empty(), "GEnergies should be empty."); // Append two energies energies.append(GEnergy()); energies.append(GEnergy()); test_value(energies.size(), 2, "GEnergies should have 2 energies."); test_assert(!energies.is_empty(), "GEnergies should not be empty."); // Clear object energies.clear(); test_value(energies.size(), 0, "GEnergies should have zero size."); test_assert(energies.is_empty(), "GEnergies should be empty."); // Insert two energies energies.insert(0, GEnergy()); energies.insert(0, GEnergy()); test_value(energies.size(), 2, "GEnergies should have 2 energies."); test_assert(!energies.is_empty(), "GEnergies should not be empty."); // Extend energies energies.extend(energies); test_value(energies.size(), 4, "GEnergies should have 4 energies."); test_assert(!energies.is_empty(), "GEnergies should not be empty."); // Create 4 energies energies.clear(); for (int i = 0; i < 4; ++i) { energies.append(GEnergy(double(i), "MeV")); } for (int i = 0; i < 4; ++i) { test_value(energies[i].MeV(), double(i)); } // Save and reload energies test_try("Saving and loading"); try { energies.save("test_energies.fits", true); energies.clear(); energies.load("test_energies.fits"); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } for (int i = 0; i < 4; ++i) { test_value(energies[i].MeV(), double(i)); } // Test load constructor test_try("Load constructor"); try { GEnergies energies2("test_energies.fits"); for (int i = 0; i < 4; ++i) { test_value(energies[i].MeV(), double(i)); } test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Return return; }
/***********************************************************************//** * @brief Test GPha class **************************************************************************/ void TestGXspec::test_GPha(void) { // Test void constructor test_try("GPha void constructor"); try { GPha pha; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test energy boundary constructor test_try("GPha energy boundary constructor"); try { GEbounds ebds(10, GEnergy(0.1, "TeV"), GEnergy(10.0, "TeV")); GPha pha(ebds); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test filling and accessing GEbounds ebds(9, GEnergy(1.0, "TeV"), GEnergy(10.0, "TeV"), false); GPha pha(ebds); for (int i = 0; i < 12; i += 2) { pha.fill(GEnergy(double(i), "TeV"), 1.0); } test_value(pha.counts(), 4.0); test_value(pha.underflow(), 1.0); test_value(pha.overflow(), 1.0); test_value(pha.outflow(), 0.0); for (int i = 0; i < 9; i += 2) { test_value(pha.at(i), 0.0); test_value(pha[i], 0.0); } for (int i = 1; i < 9; i += 2) { test_value(pha.at(i), 1.0); test_value(pha[i], 1.0); } pha[0] = 5.0; pha[1] = 3.7; test_value(pha[0], 5.0); test_value(pha[1], 3.7); // Test saving and loading pha.save("pha.fits", true); test_assert(pha.filename() == "pha.fits", "Unexpected filename \""+pha.filename()+"\"."); pha.load("pha.fits"); test_assert(pha.filename() == "pha.fits", "Unexpected filename \""+pha.filename()+"\"."); test_value(pha[0], 5.0, 1.0e-6); test_value(pha[1], 3.7, 1.0e-6); test_value(pha.counts(), 11.7, 1.0e-6); test_value(pha.underflow(), 0.0, 1.0e-6); test_value(pha.overflow(), 0.0, 1.0e-6); test_value(pha.outflow(), 0.0, 1.0e-6); for (int i = 2; i < 9; i += 2) { test_value(pha.at(i), 0.0); test_value(pha[i], 0.0); } for (int i = 3; i < 9; i += 2) { test_value(pha.at(i), 1.0); test_value(pha[i], 1.0); } // Test constructing GPha pha2("pha.fits"); test_assert(pha2.filename() == "pha.fits", "Unexpected filename \""+pha2.filename()+"\"."); test_value(pha2[0], 5.0, 1.0e-6); test_value(pha2[1], 3.7, 1.0e-6); test_value(pha2.counts(), 11.7, 1.0e-6); test_value(pha2.underflow(), 0.0, 1.0e-6); test_value(pha2.overflow(), 0.0, 1.0e-6); test_value(pha2.outflow(), 0.0, 1.0e-6); for (int i = 2; i < 9; i += 2) { test_value(pha2.at(i), 0.0); test_value(pha2[i], 0.0); } for (int i = 3; i < 9; i += 2) { test_value(pha2.at(i), 1.0); test_value(pha2[i], 1.0); } //std::cout << pha << std::endl; //std::cout << pha2 << std::endl; // Return return; }
/***********************************************************************//** * @brief Test GRmf class **************************************************************************/ void TestGXspec::test_GRmf(void) { // Test void constructor test_try("GRmf void constructor"); try { GRmf rmf; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test energy boundary constructor test_try("GRmf energy boundary constructor"); try { GEbounds ebds(10, GEnergy(0.1, "TeV"), GEnergy(10.0, "TeV")); GRmf rmf(ebds, ebds); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test filling and accessing GEbounds ebds(9, GEnergy(1.0, "TeV"), GEnergy(10.0, "TeV")); GRmf rmf(ebds, ebds); for (int i = 0; i < 9; ++i) { for (int k = i; k < i+3 && k < 9; ++k) { rmf(i, k) = 1.0; } } for (int i = 0; i < 9; ++i) { int k = 0; for (; k < i; ++k) { test_value(rmf.at(i,k), 0.0); test_value(rmf(i,k), 0.0); } for (; k < i+3 && k < 9; ++k) { test_value(rmf.at(i,k), 1.0); test_value(rmf(i,k), 1.0); } for (; k < 9; ++k) { test_value(rmf.at(i,k), 0.0); test_value(rmf(i,k), 0.0); } } // Test saving and loading rmf.save("rmf.fits", true); test_assert(rmf.filename() == "rmf.fits", "Unexpected filename \""+rmf.filename()+"\"."); rmf.load("rmf.fits"); test_assert(rmf.filename() == "rmf.fits", "Unexpected filename \""+rmf.filename()+"\"."); /* for (int i = 0; i < 9; ++i) { for (int k = 0; k < 9; ++k) { std::cout << rmf(i,k) << " "; } std::cout << std::endl; } */ for (int i = 0; i < 9; ++i) { int k = 0; for (; k < i; ++k) { test_value(rmf.at(i,k), 0.0); test_value(rmf(i,k), 0.0); } for (; k < i+3 && k < 9; ++k) { test_value(rmf.at(i,k), 1.0); test_value(rmf(i,k), 1.0); } for (; k < 9; ++k) { test_value(rmf.at(i,k), 0.0); test_value(rmf(i,k), 0.0); } } // Test constructing GRmf rmf2("rmf.fits"); test_assert(rmf2.filename() == "rmf.fits", "Unexpected filename \""+rmf2.filename()+"\"."); for (int i = 0; i < 9; ++i) { int k = 0; for (; k < i; ++k) { test_value(rmf.at(i,k), 0.0); test_value(rmf(i,k), 0.0); } for (; k < i+3 && k < 9; ++k) { test_value(rmf.at(i,k), 1.0); test_value(rmf(i,k), 1.0); } for (; k < 9; ++k) { test_value(rmf.at(i,k), 0.0); test_value(rmf(i,k), 0.0); } } //std::cout << rmf << std::endl; //std::cout << rmf2 << std::endl; // Return return; }
/***********************************************************************//** * @brief Test GArf class **************************************************************************/ void TestGXspec::test_GArf(void) { // Test void constructor test_try("GArf void constructor"); try { GArf arf; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test energy boundary constructor test_try("GArf energy boundary constructor"); try { GEbounds ebds(10, GEnergy(0.1, "TeV"), GEnergy(10.0, "TeV")); GArf arf(ebds); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test filling and accessing GEbounds ebds(9, GEnergy(1.0, "TeV"), GEnergy(10.0, "TeV")); GArf arf(ebds); for (int i = 0; i < 9; i += 2) { arf[i] = 1.0; } for (int i = 0; i < 9; i += 2) { test_value(arf.at(i), 1.0); test_value(arf[i], 1.0); } for (int i = 1; i < 9; i += 2) { test_value(arf.at(i), 0.0); test_value(arf[i], 0.0); } arf[0] = 5.0; arf[1] = 3.7; test_value(arf[0], 5.0); test_value(arf[1], 3.7); // Test saving and loading arf.save("arf.fits", true); test_assert(arf.filename() == "arf.fits", "Unexpected filename \""+arf.filename()+"\"."); arf.load("arf.fits"); test_assert(arf.filename() == "arf.fits", "Unexpected filename \""+arf.filename()+"\"."); test_value(arf[0], 5.0, 1.0e-6); test_value(arf[1], 3.7, 1.0e-6); for (int i = 2; i < 9; i += 2) { test_value(arf.at(i), 1.0); test_value(arf[i], 1.0); } for (int i = 3; i < 9; i += 2) { test_value(arf.at(i), 0.0); test_value(arf[i], 0.0); } // Test constructing GArf arf2("arf.fits"); test_assert(arf2.filename() == "arf.fits", "Unexpected filename \""+arf2.filename()+"\"."); test_value(arf2[0], 5.0, 1.0e-6); test_value(arf2[1], 3.7, 1.0e-6); for (int i = 2; i < 9; i += 2) { test_value(arf2.at(i), 1.0); test_value(arf2[i], 1.0); } for (int i = 3; i < 9; i += 2) { test_value(arf2.at(i), 0.0); test_value(arf2[i], 0.0); } //std::cout << arf << std::endl; //std::cout << arf2 << std::endl; // Return return; }