/*************************************************************************** * test_COM.cpp - test COM classes * * ----------------------------------------------------------------------- * * copyright (C) 2012-2014 by Juergen Knoedlseder * * ----------------------------------------------------------------------- * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ***************************************************************************/ /** * @file test_COM.cpp * @brief Testing of COM classes * @author Juergen Knoedlseder */ /* __ Includes ___________________________________________________________ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "GTools.hpp" #include "test_COM.hpp" /* __ Namespaces _________________________________________________________ */ /* __ Globals ____________________________________________________________ */ /* __ Constants __________________________________________________________ */ const std::string datadir = PACKAGE_SOURCE"/inst/com/test/data"; const std::string com_caldb = PACKAGE_SOURCE"/inst/com/caldb"; const std::string com_iaq = "u47569_iaq.fits"; // 1-3 MeV const std::string com_dre = datadir+"/m50439_dre.fits"; // 1-3 MeV const std::string com_drb = datadir+"/m34997_drg.fits"; const std::string com_drg = datadir+"/m34997_drg.fits"; const std::string com_drx = datadir+"/m32171_drx.fits"; const std::string com_obs = datadir+"/obs.xml"; const std::string com_model = datadir+"/crab.xml"; /***********************************************************************//** * @brief Set COMPTEL response test methods ***************************************************************************/ void TestGCOMResponse::set(void) { // Set test name name("GCOMResponse"); // Append tests to test suite append(static_cast(&TestGCOMResponse::test_inst_dir), "Test instrument direction"); append(static_cast(&TestGCOMResponse::test_response), "Test response"); // Return return; } /***********************************************************************//** * @brief Clone test suite * * @return Pointer to deep copy of test suite. ***************************************************************************/ TestGCOMResponse* TestGCOMResponse::clone(void) const { // Clone test suite return new TestGCOMResponse(*this); } /***********************************************************************//** * @brief Set COMPTEL observation test methods ***************************************************************************/ void TestGCOMObservation::set(void) { // Set test name name("GCOMObservation"); // Append tests to test suite append(static_cast(&TestGCOMObservation::test_binned_obs), "Test binned observation"); append(static_cast(&TestGCOMObservation::test_event_bin), "Test event bin"); append(static_cast(&TestGCOMObservation::test_event_cube), "Test event cube"); // Return return; } /***********************************************************************//** * @brief Clone test suite * * @return Pointer to deep copy of test suite. ***************************************************************************/ TestGCOMObservation* TestGCOMObservation::clone(void) const { // Clone test suite return new TestGCOMObservation(*this); } /***********************************************************************//** * @brief Set COMPTEL optimizer test methods ***************************************************************************/ void TestGCOMOptimize::set(void) { // Set test name name("COMPTEL optimizers"); // Append tests to test suite append(static_cast(&TestGCOMOptimize::test_binned_optimizer), "Test binned optimizer"); // Return return; } /***********************************************************************//** * @brief Clone test suite * * @return Pointer to deep copy of test suite. ***************************************************************************/ TestGCOMOptimize* TestGCOMOptimize::clone(void) const { // Clone test suite return new TestGCOMOptimize(*this); } /***********************************************************************//** * @brief Test GCOMInstDir class ***************************************************************************/ void TestGCOMResponse::test_inst_dir(void) { // Test constructors test_try("Test constructors"); try { // Void constructor GCOMInstDir dir1; // Copy constructor GCOMInstDir dir2(dir1); // If we arrived here, signal success test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Create void object GCOMInstDir dir; // skydir method GSkyDir sky; sky.radec_deg(37.0, 45.3); dir.dir(sky); test_assert(dir.dir() == sky, "Test skydir() method.", "Expected "+sky.print()+", found "+dir.dir().print()); // phibar method dir.phibar(27.2); test_value(dir.phibar(), 27.2, 1.0e-10, "Test phibar() method."); // copy constructor GCOMInstDir dir_copy(dir); test_assert(dir_copy.dir() == sky, "Test copy constructor method.", "Expected "+sky.print()+", found "+dir_copy.dir().print()); test_value(dir_copy.phibar(), 27.2, 1.0e-10, "Test copy constructor method."); // assignment operator GCOMInstDir dir_assign = dir; test_assert(dir_assign.dir() == sky, "Test assignment operator method.", "Expected "+sky.print()+", found "+dir_assign.dir().print()); test_value(dir_assign.phibar(), 27.2, 1.0e-10, "Test assignment operator method."); // clone GCOMInstDir* dir_clone = dir.clone(); test_assert(dir_clone->dir() == sky, "Test clone() method.", "Expected "+sky.print()+", found "+dir_clone->dir().print()); test_value(dir_clone->phibar(), 27.2, 1.0e-10, "Test clone() method."); delete dir_clone; // clear dir.clear(); sky.clear(); test_assert(dir.dir() == sky, "Test clear() method.", "Expected "+sky.print()+", found "+dir.dir().print()); test_value(dir.phibar(), 0.0, 1.0e-10, "Test clean() method."); // Return return; } /***********************************************************************//** * @brief Checks handling of IAQ response files * * This function checks the handling of IAQ response files. IAQ response * files are 2D images that show the instrument response as function of * geometrical (Phi_geo) and measured (Phi_bar) Compton scatter angle. ***************************************************************************/ void TestGCOMResponse::test_response(void) { // Test constructors test_try("Test constructors"); try { // Void constructor GCOMResponse rsp1; // Copy constructor GCOMResponse rsp2(rsp1); // If we arrived here, signal success test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test response loading test_try("Test response loading"); try { // Construct response from datasets GCOMResponse rsp(com_iaq, com_caldb); // If we arrived here, signal success test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Return return; } /***********************************************************************//** * @brief Checks handling of binned observations * * This function checks the handling of binned observations. Binned * observations are defined by * a DRE file containing the events, * a DRB file containing the background model, * a DRG file containing the geometrical probability of having an interaction * in the second detector plane, and * a DRX file containing the sky exposure. * * Note that in first approximation we can use the DRG file as background * model. ***************************************************************************/ void TestGCOMObservation::test_binned_obs(void) { // Test constructors test_try("Test constructors"); try { // Void constructor GCOMObservation obs1; // Copy constructor GCOMObservation obs2(obs1); // If we arrived here, signal success test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test observation loading test_try("Test observation loading"); try { // Construct observation from datasets GCOMObservation obs(com_dre, com_drb, com_drg, com_drx); //std::cout << obs << std::endl; // If we arrived here, signal success test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test XML constructor test_try("Test XML constructor"); try { // Construct observation from datasets GObservations obs(com_obs); //std::cout << obs << std::endl; // If we arrived here, signal success test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Exit test return; } /***********************************************************************//** * @brief Checks handling of COMPTEL event bin ***************************************************************************/ void TestGCOMObservation::test_event_bin(void) { // Test COMPTEL event bin methods (one by one) test_try("Test event bin methods"); try { // Event bin void constructor GCOMEventBin bin; // Copy constructor GCOMEventBin bin2(bin); // Assignment operator GCOMEventBin bin3 = bin; // clear method bin.clear(); // clone method GCOMEventBin* bin4 = bin.clone(); // size method test_value(bin.size(), 0.0, 1.0e-10, "Test size() method."); test_value(bin4->size(), 0.0, 1.0e-10, "Test size() method."); delete bin4; // dir method GCOMInstDir dir = bin.dir(); // energy method GEnergy energy = bin.energy(); // time method GTime time = bin.time(); // counts method test_value(bin.counts(), 0.0, 1.0e-10, "Test counts() method for zero counts."); // error method test_value(bin.error(), 0.0, 1.0e-10, "Test error() method for zero counts."); // counts setting bin.counts(1.0); test_value(bin.counts(), 1.0, 1.0e-10, "Test counts() method for one count."); test_value(bin.error(), 1.0, 1.0e-10, "Test error() method for one count."); // print method std::string text = bin.print(); test_assert(text == "1", "Test print() method."); // solidangle method test_value(bin.solidangle(), 0.0, 1.0e-10, "Test solidangle() method."); // ewidth method GEnergy ewidth = bin.ewidth(); // ontime method test_value(bin.ontime(), 0.0, 1.0e-10, "Test ontime() method."); // If we arrived here, signal success test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test COMPTEL event bin operations GCOMEventBin bin; bin.counts(3.3); test_value(bin.counts(), 3.3, 1.0e-10, "Test counts() method for 3.3 counts."); // Return return; } /***********************************************************************//** * @brief Checks handling of COMPTEL event cube ***************************************************************************/ void TestGCOMObservation::test_event_cube(void) { // Event cube void constructor GCOMEventCube cube; // Event cube load constructor GCOMEventCube cube2(com_dre); // Event cube copy constructor GCOMEventCube cube3(cube2); test_value(cube2.size(), cube3.size(), "Test copy constructor.", "Different cube size after using the" " copy constructor (before="+gammalib::str(cube2.size())+ " after="+gammalib::str(cube3.size())+")"); test_value(cube2.number(), cube3.number(), "Test copy constructor.", "Different number of events after using the" " copy constructor (before="+gammalib::str(cube2.number())+ " after="+gammalib::str(cube3.number())+")."); // Event cube assignment operator GCOMEventCube cube4 = cube2; test_value(cube2.size(), cube4.size(), "Test assignment operator.", "Different cube size after using the" " assignment operator (before="+gammalib::str(cube2.size())+ " after="+gammalib::str(cube4.size())+")"); test_value(cube2.number(), cube4.number(), "Test assignment operator.", "Different number of events after using the" " assignment operator (before="+gammalib::str(cube2.number())+ " after="+gammalib::str(cube4.number())+")."); // clear method cube4.clear(); test_value(cube4.size(), 0, "Test clear method.", "Expected event cube with size 0 after" " clear but found size "+gammalib::str(cube4.size())+"."); test_value(cube4.number(), 0, "Test clear method.", "Expected 0 events in cube after" " clear but found "+gammalib::str(cube4.size())+" events."); // clone method GCOMEventCube* cube5 = cube2.clone(); test_value(cube2.size(), cube5->size(), "Test clone() method.", "Different cube size after cloning" " (before="+gammalib::str(cube2.size())+ " after="+gammalib::str(cube5->size())+")"); test_value(cube2.number(), cube5->number(), "Test clone() method.", "Different number of events after cloning" " (before="+gammalib::str(cube2.number())+ " after="+gammalib::str(cube5->number())+")."); delete cube5; // size method test_value(cube2.size(), 140600, "Test size() method.", "Expected cube dimension 140600, found "+ gammalib::str(cube2.size())+"."); // dim method test_value(cube2.dim(), 3, "Test dim() method.", "Expected 3 cube dimensions, found "+ gammalib::str(cube2.dim())+"."); // naxis method test_value(cube2.naxis(0), 76, "Test naxis(0) method.", "Expected Chi axis dimension 76, found "+ gammalib::str(cube2.naxis(0))+"."); test_value(cube2.naxis(1), 74, "Test naxis(1) method.", "Expected Chi axis dimension 74, found "+ gammalib::str(cube2.naxis(1))+"."); test_value(cube2.naxis(2), 25, "Test naxis(2) method.", "Expected Chi axis dimension 25, found "+ gammalib::str(cube2.naxis(2))+"."); // nchi, npsi, nphi methods test_value(cube2.nchi(), 76, "Test nchi() method.", "Expected Chi axis dimension 76, found "+ gammalib::str(cube2.nchi())+"."); test_value(cube2.npsi(), 74, "Test npsi() method.", "Expected Chi axis dimension 74, found "+ gammalib::str(cube2.npsi())+"."); test_value(cube2.nphi(), 25, "Test nphi() method.", "Expected Chi axis dimension 25, found "+ gammalib::str(cube2.nphi())+"."); // npix method int npix = cube2.nchi() * cube2.npsi(); test_value(cube2.npix(), npix, "Test npix() method.", "Expected "+gammalib::str(npix)+" pixels in (Chi,Psi) plane, found "+ gammalib::str(cube2.npix())+"."); // number method test_value(cube2.number(), 316141, "Test number() method.", "Expected 316141 events in cube, found "+ gammalib::str(cube2.number())+"."); // event access double sum = 0.0; for (int i = 0; i < cube2.size(); ++i) { sum += cube2[i]->counts(); } test_value(cube2.number(), int(sum+0.5), "Test event access.", "Expected "+gammalib::str(cube2.number())+ " events in cube, found "+ gammalib::str(int(sum+0.5))+" by summing over all elements."); // Return return; } /***********************************************************************//** * @brief Test binned optimizer ***************************************************************************/ void TestGCOMOptimize::test_binned_optimizer(void) { // Declare observations GObservations obs; GCOMObservation run; // Load binned COMPTEL observation test_try("Load binned COMPTEL observation"); try { run.load(com_dre, com_drb, com_drg, com_drx); run.response(com_iaq, com_caldb); obs.append(run); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Load models from XML file obs.models(com_model); // Perform LM optimization double fit_results[] = {83.4258, 0.157307, 21.5952, 0.143873, 0.001907, 8.31055e-05, -2.05, 0, 1, 0, 1, 0, 1, 0, 0, 0, 3, 0, 0, 0, 5, 0, 3.15461, 0.0904736, 7, 0, 27.8763, 0.272976, 9, 0, 43.6555, 0.348297, 11, 0, 54.1233, 0.396509, 13, 0, 60.9322, 0.431667, 15, 0, 65.1235, 0.457003, 17, 0, 64.8946, 0.466807, 19, 0, 60.7385, 0.458565, 21, 0, 57.5857, 0.451466, 23, 0, 54.447, 0.441844, 25, 0, 51.9042, 0.433244, 27, 0, 49.0977, 0.422531, 29, 0, 47.1811, 0.416003, 31, 0, 44.2415, 0.406013, 33, 0, 43.1503, 0.40499, 35, 0, 41.7076, 0.403297, 37, 0, 39.92, 0.39994, 39, 0, 37.602, 0.39392, 41, 0, 36.7116, 0.395238, 43, 0, 35.8177, 0.397315, 45, 0, 33.7205, 0.392628, 47, 0, 29.9617, 0.377506, 49, 0, 27.9992, 0.372603}; test_try("Perform LM optimization"); try { GOptimizerLM opt; opt.max_iter(100); obs.optimize(opt); test_try_success(); for (int i = 0, j = 0; i < obs.models().size(); ++i) { const GModel* model = obs.models()[i]; for (int k = 0; k < model->size(); ++k) { GModelPar par = (*model)[k]; std::string msg = "Verify optimization result for " + par.print(); test_value(par.value(), fit_results[j++], 5.0e-5, msg); test_value(par.error(), fit_results[j++], 5.0e-5, msg); } } } catch (std::exception &e) { test_try_failure(e); } // Exit test return; } /*************************************************************************** * @brief Main entry point for test executable ***************************************************************************/ int main(void) { // Allocate test suit container GTestSuites testsuites("COMPTEL instrument specific class testing"); // Set GAMMALIB_CALDB environment variable std::string caldb = "GAMMALIB_CALDB="+com_caldb; putenv((char*)caldb.c_str()); // Initially assume that we pass all tests bool success = true; // Create test suites and append them to the container TestGCOMResponse rsp; TestGCOMObservation obs; TestGCOMOptimize opt; testsuites.append(rsp); testsuites.append(obs); testsuites.append(opt); // Run the testsuites success = testsuites.run(); // Save test report testsuites.save("reports/GCOM.xml"); // Return success status return (success ? 0 : 1); }