diff --git a/src/ctobssim/ctobssim.cpp b/src/ctobssim/ctobssim.cpp index e9869dd..66136bd 100644 --- a/src/ctobssim/ctobssim.cpp +++ b/src/ctobssim/ctobssim.cpp @@ -1418,8 +1418,9 @@ void ctobssim::simulate_background(GCTAObservation* obs, ***************************************************************************/ void ctobssim::save_fits(void) { - // Save only if event list has not yet been saved and disposed - if (!m_save_and_dispose) { + // Save only if event list has not yet been saved and disposed and if + // there are observations + if (!m_save_and_dispose && m_obs.size() > 0) { // Get output filename m_outevents = (*this)["outevents"].filename(); diff --git a/src/ctselect/ctselect.cpp b/src/ctselect/ctselect.cpp index 7206015..86a2503 100644 --- a/src/ctselect/ctselect.cpp +++ b/src/ctselect/ctselect.cpp @@ -314,8 +314,7 @@ void ctselect::run(void) // Log saved FITS file. if (logExplicit()) { GFits tmpfile(filename); - log << std::endl; - log.header1("FITS file content of temporary file"); + log.header3("FITS file content of temporary file"); log << tmpfile << std::endl; tmpfile.close(); } @@ -609,6 +608,9 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& evtname, const std::string& gtiname) { + // Write header into logger + log_header3(NORMAL, "Events selection"); + // Initialise selection string std::string selection; @@ -818,9 +820,9 @@ void ctselect::select_events(GCTAObservation* obs, log_value(NORMAL, "cfitsio selection", selection); // Build input filename including selection expression - std::string expression = filename; + std::string expression = filename + "[" + evtname + "]"; if (selection.length() > 0) { - expression += "["+evtname+"]["+selection+"]"; + expression += "["+selection+"]"; } // Dump FITS filename including selection expression @@ -830,7 +832,7 @@ void ctselect::select_events(GCTAObservation* obs, GFits file(expression); // Log selected FITS file - log_header1(EXPLICIT, "FITS file content after selection"); + log_header3(EXPLICIT, "FITS file content after selection"); log_string(EXPLICIT, file.print(m_chatter)); // Check if we have an events HDU @@ -864,7 +866,11 @@ void ctselect::select_events(GCTAObservation* obs, // Get CTA event list pointer list = static_cast(const_cast(obs->events())); - // If ROI selection has been applied then set the event list ROI + // Make sure that events are fetched since the temporary file will be + // closed later + list->fetch(); + + // If RoI selection has been applied then set the event list RoI if (m_select_roi) { GCTAInstDir instdir; instdir.dir().radec_deg(ra, dec); @@ -872,7 +878,7 @@ void ctselect::select_events(GCTAObservation* obs, } // endif: Roi selection was performed else if (old_roi.is_valid()) { - // Restore old Roi information in case no selection was performed + // Restore old RoI information in case no selection was performed // and RoI was existing before list->roi(old_roi); } @@ -1178,43 +1184,48 @@ std::string ctselect::get_gtiname(const std::string& filename, ***************************************************************************/ void ctselect::save_fits(void) { - // Get output filename - m_outobs = (*this)["outobs"].filename(); + // Save only if there are observations + if (m_obs.size() > 0) { - // Get CTA observation from observation container - GCTAObservation* obs = dynamic_cast(m_obs[0]); + // Get output filename + m_outobs = (*this)["outobs"].filename(); - // Save only if it's a CTA observation - if (obs != NULL) { + // Get CTA observation from observation container + GCTAObservation* obs = dynamic_cast(m_obs[0]); + + // Save only if it's a CTA observation + if (obs != NULL) { - // Save only if file name is non-empty - if (m_infiles[0].length() > 0) { + // Save only if file name is non-empty + if (m_infiles[0].length() > 0) { - // Create file name object - GFilename fname(m_outobs); + // Create file name object + GFilename fname(m_outobs); - // Extract filename and event extension name - std::string outfile = fname.url(); + // Extract filename and event extension name + std::string outfile = fname.url(); - // Append event extension name. We handle here the possibility - // to write the events into a different extension. - if (fname.has_extname()) { - outfile += "["+fname.extname()+"]"; - } - else { - outfile += "["+m_evtname[0]+"]"; - } + // Append event extension name. We handle here the possibility + // to write the events into a different extension. + if (fname.has_extname()) { + outfile += "["+fname.extname()+"]"; + } + else { + outfile += "["+m_evtname[0]+"]"; + } + + // Log filename + log_value(NORMAL, "Event list file", outfile); - // Log filename - log_value(NORMAL, "Event list file", outfile); + // Save event list + save_event_list(obs, m_infiles[0], m_evtname[0], m_gtiname[0], + outfile); - // Save event list - save_event_list(obs, m_infiles[0], m_evtname[0], m_gtiname[0], - outfile); + } // endif: filename was non empty - } // endif: filename was non empty + } // endif: observation was CTA observation - } // endif: observation was CTA observation + } // endif: there were observations // Return return; diff --git a/test/test_ctobssim.py b/test/test_ctobssim.py index 4117ded..debb565 100755 --- a/test/test_ctobssim.py +++ b/test/test_ctobssim.py @@ -18,6 +18,7 @@ # along with this program. If not, see . # # ========================================================================== +import os import gammalib import ctools from cscripts import obsutils @@ -71,7 +72,7 @@ class Test(test): # Setup ctobssim command cmd = ctobssim+' inmodel="'+self._model+'" '+ \ - ' outevents="events.fits"'+ \ + ' outevents="ctobssim_cmd1.fits"'+ \ ' caldb="'+self._caldb+'" irf="'+self._irf+'" '+ \ ' ra=83.63 dec=22.01 rad=10.0'+ \ ' tmin=0.0 tmax=1800.0 emin=0.1 emax=100.0'+ \ @@ -86,12 +87,12 @@ class Test(test): 'Check successful execution from command line') # Load counts cube and check content. - evt = gammalib.GCTAEventList('events.fits') + evt = gammalib.GCTAEventList('ctobssim_cmd1.fits') self._test_list(evt, 6881) # Setup ctobssim command cmd = ctobssim+' inmodel="model_that_does_not_exist.xml"'+ \ - ' outevents="events.fits"'+ \ + ' outevents="ctobssim_cmd2.fits"'+ \ ' caldb="'+self._caldb+'" irf="'+self._irf+'" '+ \ ' ra=83.63 dec=22.01 rad=10.0'+ \ ' tmin=0.0 tmax=1800.0 emin=0.1 emax=100.0'+ \ @@ -109,10 +110,26 @@ class Test(test): """ Test ctobssim from Python """ - # Set-up ctobssim + # Allocate ctobssim + sim = ctools.ctobssim() + + # Check that empty ctobssim tool holds an empty observation + self.test_value(sim.obs().size(), 0, 'Check number of observations') + + # Check that saving saves an empty model definition file + sim['outevents'] = 'ctobssim_py0.fits' + sim['logfile'] = 'ctobssim_py0.log' + sim.logFileOpen() + sim.save() + self.test_assert(not os.path.isfile('ctobssim_py0.fits'), + 'Check that no event list has been created') + + # Check that clearing does not lead to an exception or segfault + sim.clear() + + # Now set ctobssim parameters sim = ctools.ctobssim() sim['inmodel'] = self._model - sim['outevents'] = 'events.fits' sim['caldb'] = self._caldb sim['irf'] = self._irf sim['ra'] = 83.63 @@ -122,6 +139,7 @@ class Test(test): sim['tmax'] = 1800.0 sim['emin'] = 0.1 sim['emax'] = 100.0 + sim['outevents'] = 'ctobssim_py1.fits' sim['logfile'] = 'ctobssim_py1.log' sim['chatter'] = 2 @@ -137,7 +155,7 @@ class Test(test): sim.save() # Load counts cube and check content. - evt = gammalib.GCTAEventList('events.fits') + evt = gammalib.GCTAEventList('ctobssim_py1.fits') self._test_list(evt, 6881) # Set-up observation container @@ -149,7 +167,7 @@ class Test(test): # Set-up ctobssim from observation container sim = ctools.ctobssim(obs) - sim['outevents'] = 'sim_events.xml' + sim['outevents'] = 'ctobssim_py2.xml' sim['inmodel'] = self._model sim['logfile'] = 'ctobssim_py2.log' sim['chatter'] = 3 @@ -175,7 +193,7 @@ class Test(test): sim.save() # Load events - obs = gammalib.GObservations('sim_events.xml') + obs = gammalib.GObservations('ctobssim_py2.xml') # Retrieve observation and check content self._test_list(obs[0].events(), 6003) @@ -186,7 +204,6 @@ class Test(test): # Set-up ctobssim with invalid event file sim = ctools.ctobssim() sim['inmodel'] = 'model_file_that_does_not_exist.xml' - sim['outevents'] = 'events.fits' sim['caldb'] = self._caldb sim['irf'] = self._irf sim['ra'] = 83.63 @@ -196,6 +213,7 @@ class Test(test): sim['tmax'] = 1800.0 sim['emin'] = 0.1 sim['emax'] = 100.0 + sim['outevents'] = 'ctobssim_py3.fits' sim['logfile'] = 'ctobssim_py3.log' sim['chatter'] = 4 diff --git a/test/test_ctselect.py b/test/test_ctselect.py index 8522cd4..b793e1d 100755 --- a/test/test_ctselect.py +++ b/test/test_ctselect.py @@ -18,6 +18,7 @@ # along with this program. If not, see . # # ========================================================================== +import os import gammalib import ctools from testing import test @@ -103,10 +104,26 @@ class Test(test): """ Test ctselect from Python """ - # Set-up ctselect + # Allocate ctselect + select = ctools.ctselect() + + # Check that empty ctselect tool holds an empty observation + self._check_obs(select.obs(), nobs=0) + + # Check that saving does nothing + select['outobs'] = 'ctselect_py0.fits' + select['logfile'] = 'ctselect_py0.log' + select.logFileOpen() + select.save() + self.test_assert(not os.path.isfile('ctselect_py0.fits'), + 'Check that no event list has been created') + + # Check that clearing does not lead to an exception or segfault + select.clear() + + # Now set ctselect parameters select = ctools.ctselect() select['inobs'] = self._events - select['outobs'] = 'ctselect_py1.fits' select['ra'] = 83.63 select['dec'] = 22.01 select['rad'] = 3 @@ -114,6 +131,7 @@ class Test(test): select['tmax'] = 1800 select['emin'] = 0.1 select['emax'] = 100 + select['outobs'] = 'ctselect_py1.fits' select['logfile'] = 'ctselect_py1.log' select['chatter'] = 2 @@ -125,6 +143,49 @@ class Test(test): # Check result file self._check_result_file('ctselect_py1.fits') + # Copy ctselect tool + cpy_select = select.copy() + + # Check observation of ctselect copy + self._check_obs(cpy_select.obs()) + + # Execute copy of ctselect tool again, now with a higher chatter + # level than before and without any selection + cpy_select['ra'] = 'NONE' + cpy_select['dec'] = 'NONE' + cpy_select['rad'] = 'NONE' + cpy_select['tmin'] = 'NONE' + cpy_select['tmax'] = 'NONE' + cpy_select['emin'] = 'NONE' + cpy_select['emax'] = 'NONE' + cpy_select['outobs'] = 'ctselect_py2.fits' + cpy_select['logfile'] = 'ctselect_py2.log' + cpy_select['chatter'] = 3 + cpy_select.logFileOpen() # Needed to get a new log file + cpy_select.execute() + + # Check result file + self._check_result_file('ctselect_py2.fits') + print('Step3') + + # Execute again the copy of ctselect tool again, now using the pointing + # information in the input observation + cpy_select['usepnt'] = True + cpy_select['outobs'] = 'ctselect_py3.fits' + cpy_select['logfile'] = 'ctselect_py3.log' + cpy_select['chatter'] = 4 + cpy_select.logFileOpen() # Needed to get a new log file + cpy_select.execute() + + # Check result file + self._check_result_file('ctselect_py3.fits') + + # Now clear copy of ctselect tool + cpy_select.clear() + + # Check that cleared ctselect tool holds no observations and events + self._check_obs(cpy_select.obs(), nobs=0) + # Return return @@ -134,16 +195,59 @@ class Test(test): Check result file """ # Open result file - result = gammalib.GCTAEventList(filename) - - # Check file - self.test_value(result.size(), 6127, 'Check for 6127 events') - self.test_value(result.roi().centre().dir().ra_deg(), 83.63, 1.0e-6, - 'Check for ROI Right Ascension') - self.test_value(result.roi().centre().dir().dec_deg(), 22.01, 1.0e-6, - 'Check for ROI Declination') - self.test_value(result.roi().radius(), 3.0, 1.0e-6, - 'Check for ROI Radius') + events = gammalib.GCTAEventList(filename) + + # Check event list + self._check_events(events, nevents=6127) + + # Return + return + + # Check observation and event list + def _check_obs(self, obs, nobs=1, nevents=6127): + """ + Check observation and event list + + Parameters + ---------- + obs : `~gammalib.GObservations` + Models + nobs : int, optional + Expected number of observations + nevents : int, optional + Expected number of events + """ + # Check number of observations + self.test_value(obs.size(), nobs, 'Check number of observations') + + # If there is an observation then check the event list of the first + # one + if obs.size() > 0: + self._check_events(obs[0].events(), nevents=nevents) + + # Return + return + + # Check events + def _check_events(self, events, nevents=6127): + """ + Check event list + + Parameters + ---------- + events : `~gammalib.GCTAEventList` + Event list + nevents : int, optional + Expected number of events + """ + # Check event list + self.test_value(events.size(), nevents, 'Check number of events') + self.test_value(events.roi().centre().dir().ra_deg(), 83.63, 1.0e-6, + 'Check for RoI centre Right Ascension') + self.test_value(events.roi().centre().dir().dec_deg(), 22.01, 1.0e-6, + 'Check for RoI centre Declination') + self.test_value(events.roi().radius(), 3.0, 1.0e-6, + 'Check for RoI radius') # Return return