Commit adf6ef3aeab7262b8d6aed911fccbe520ad8e3c9

Authored by Jürgen Knödlseder
1 parent cfa7379f

Increase ctools coverage (#1828)

src/ctobssim/ctobssim.cpp
... ... @@ -1418,8 +1418,9 @@ void ctobssim::simulate_background(GCTAObservation* obs,
1418 1418 ***************************************************************************/
1419 1419 void ctobssim::save_fits(void)
1420 1420 {
1421   - // Save only if event list has not yet been saved and disposed
1422   - if (!m_save_and_dispose) {
  1421 + // Save only if event list has not yet been saved and disposed and if
  1422 + // there are observations
  1423 + if (!m_save_and_dispose && m_obs.size() > 0) {
1423 1424  
1424 1425 // Get output filename
1425 1426 m_outevents = (*this)["outevents"].filename();
... ...
src/ctselect/ctselect.cpp
... ... @@ -314,8 +314,7 @@ void ctselect::run(void)
314 314 // Log saved FITS file.
315 315 if (logExplicit()) {
316 316 GFits tmpfile(filename);
317   - log << std::endl;
318   - log.header1("FITS file content of temporary file");
  317 + log.header3("FITS file content of temporary file");
319 318 log << tmpfile << std::endl;
320 319 tmpfile.close();
321 320 }
... ... @@ -609,6 +608,9 @@ void ctselect::select_events(GCTAObservation* obs,
609 608 const std::string& evtname,
610 609 const std::string& gtiname)
611 610 {
  611 + // Write header into logger
  612 + log_header3(NORMAL, "Events selection");
  613 +
612 614 // Initialise selection string
613 615 std::string selection;
614 616  
... ... @@ -818,9 +820,9 @@ void ctselect::select_events(GCTAObservation* obs,
818 820 log_value(NORMAL, "cfitsio selection", selection);
819 821  
820 822 // Build input filename including selection expression
821   - std::string expression = filename;
  823 + std::string expression = filename + "[" + evtname + "]";
822 824 if (selection.length() > 0) {
823   - expression += "["+evtname+"]["+selection+"]";
  825 + expression += "["+selection+"]";
824 826 }
825 827  
826 828 // Dump FITS filename including selection expression
... ... @@ -830,7 +832,7 @@ void ctselect::select_events(GCTAObservation* obs,
830 832 GFits file(expression);
831 833  
832 834 // Log selected FITS file
833   - log_header1(EXPLICIT, "FITS file content after selection");
  835 + log_header3(EXPLICIT, "FITS file content after selection");
834 836 log_string(EXPLICIT, file.print(m_chatter));
835 837  
836 838 // Check if we have an events HDU
... ... @@ -864,7 +866,11 @@ void ctselect::select_events(GCTAObservation* obs,
864 866 // Get CTA event list pointer
865 867 list = static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events()));
866 868  
867   - // If ROI selection has been applied then set the event list ROI
  869 + // Make sure that events are fetched since the temporary file will be
  870 + // closed later
  871 + list->fetch();
  872 +
  873 + // If RoI selection has been applied then set the event list RoI
868 874 if (m_select_roi) {
869 875 GCTAInstDir instdir;
870 876 instdir.dir().radec_deg(ra, dec);
... ... @@ -872,7 +878,7 @@ void ctselect::select_events(GCTAObservation* obs,
872 878 } // endif: Roi selection was performed
873 879  
874 880 else if (old_roi.is_valid()) {
875   - // Restore old Roi information in case no selection was performed
  881 + // Restore old RoI information in case no selection was performed
876 882 // and RoI was existing before
877 883 list->roi(old_roi);
878 884 }
... ... @@ -1178,43 +1184,48 @@ std::string ctselect::get_gtiname(const std::string&amp; filename,
1178 1184 ***************************************************************************/
1179 1185 void ctselect::save_fits(void)
1180 1186 {
1181   - // Get output filename
1182   - m_outobs = (*this)["outobs"].filename();
  1187 + // Save only if there are observations
  1188 + if (m_obs.size() > 0) {
1183 1189  
1184   - // Get CTA observation from observation container
1185   - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]);
  1190 + // Get output filename
  1191 + m_outobs = (*this)["outobs"].filename();
1186 1192  
1187   - // Save only if it's a CTA observation
1188   - if (obs != NULL) {
  1193 + // Get CTA observation from observation container
  1194 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]);
  1195 +
  1196 + // Save only if it's a CTA observation
  1197 + if (obs != NULL) {
1189 1198  
1190   - // Save only if file name is non-empty
1191   - if (m_infiles[0].length() > 0) {
  1199 + // Save only if file name is non-empty
  1200 + if (m_infiles[0].length() > 0) {
1192 1201  
1193   - // Create file name object
1194   - GFilename fname(m_outobs);
  1202 + // Create file name object
  1203 + GFilename fname(m_outobs);
1195 1204  
1196   - // Extract filename and event extension name
1197   - std::string outfile = fname.url();
  1205 + // Extract filename and event extension name
  1206 + std::string outfile = fname.url();
1198 1207  
1199   - // Append event extension name. We handle here the possibility
1200   - // to write the events into a different extension.
1201   - if (fname.has_extname()) {
1202   - outfile += "["+fname.extname()+"]";
1203   - }
1204   - else {
1205   - outfile += "["+m_evtname[0]+"]";
1206   - }
  1208 + // Append event extension name. We handle here the possibility
  1209 + // to write the events into a different extension.
  1210 + if (fname.has_extname()) {
  1211 + outfile += "["+fname.extname()+"]";
  1212 + }
  1213 + else {
  1214 + outfile += "["+m_evtname[0]+"]";
  1215 + }
  1216 +
  1217 + // Log filename
  1218 + log_value(NORMAL, "Event list file", outfile);
1207 1219  
1208   - // Log filename
1209   - log_value(NORMAL, "Event list file", outfile);
  1220 + // Save event list
  1221 + save_event_list(obs, m_infiles[0], m_evtname[0], m_gtiname[0],
  1222 + outfile);
1210 1223  
1211   - // Save event list
1212   - save_event_list(obs, m_infiles[0], m_evtname[0], m_gtiname[0],
1213   - outfile);
  1224 + } // endif: filename was non empty
1214 1225  
1215   - } // endif: filename was non empty
  1226 + } // endif: observation was CTA observation
1216 1227  
1217   - } // endif: observation was CTA observation
  1228 + } // endif: there were observations
1218 1229  
1219 1230 // Return
1220 1231 return;
... ...
test/test_ctobssim.py
... ... @@ -18,6 +18,7 @@
18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19 #
20 20 # ==========================================================================
  21 +import os
21 22 import gammalib
22 23 import ctools
23 24 from cscripts import obsutils
... ... @@ -71,7 +72,7 @@ class Test(test):
71 72  
72 73 # Setup ctobssim command
73 74 cmd = ctobssim+' inmodel="'+self._model+'" '+ \
74   - ' outevents="events.fits"'+ \
  75 + ' outevents="ctobssim_cmd1.fits"'+ \
75 76 ' caldb="'+self._caldb+'" irf="'+self._irf+'" '+ \
76 77 ' ra=83.63 dec=22.01 rad=10.0'+ \
77 78 ' tmin=0.0 tmax=1800.0 emin=0.1 emax=100.0'+ \
... ... @@ -86,12 +87,12 @@ class Test(test):
86 87 'Check successful execution from command line')
87 88  
88 89 # Load counts cube and check content.
89   - evt = gammalib.GCTAEventList('events.fits')
  90 + evt = gammalib.GCTAEventList('ctobssim_cmd1.fits')
90 91 self._test_list(evt, 6881)
91 92  
92 93 # Setup ctobssim command
93 94 cmd = ctobssim+' inmodel="model_that_does_not_exist.xml"'+ \
94   - ' outevents="events.fits"'+ \
  95 + ' outevents="ctobssim_cmd2.fits"'+ \
95 96 ' caldb="'+self._caldb+'" irf="'+self._irf+'" '+ \
96 97 ' ra=83.63 dec=22.01 rad=10.0'+ \
97 98 ' tmin=0.0 tmax=1800.0 emin=0.1 emax=100.0'+ \
... ... @@ -109,10 +110,26 @@ class Test(test):
109 110 """
110 111 Test ctobssim from Python
111 112 """
112   - # Set-up ctobssim
  113 + # Allocate ctobssim
  114 + sim = ctools.ctobssim()
  115 +
  116 + # Check that empty ctobssim tool holds an empty observation
  117 + self.test_value(sim.obs().size(), 0, 'Check number of observations')
  118 +
  119 + # Check that saving saves an empty model definition file
  120 + sim['outevents'] = 'ctobssim_py0.fits'
  121 + sim['logfile'] = 'ctobssim_py0.log'
  122 + sim.logFileOpen()
  123 + sim.save()
  124 + self.test_assert(not os.path.isfile('ctobssim_py0.fits'),
  125 + 'Check that no event list has been created')
  126 +
  127 + # Check that clearing does not lead to an exception or segfault
  128 + sim.clear()
  129 +
  130 + # Now set ctobssim parameters
113 131 sim = ctools.ctobssim()
114 132 sim['inmodel'] = self._model
115   - sim['outevents'] = 'events.fits'
116 133 sim['caldb'] = self._caldb
117 134 sim['irf'] = self._irf
118 135 sim['ra'] = 83.63
... ... @@ -122,6 +139,7 @@ class Test(test):
122 139 sim['tmax'] = 1800.0
123 140 sim['emin'] = 0.1
124 141 sim['emax'] = 100.0
  142 + sim['outevents'] = 'ctobssim_py1.fits'
125 143 sim['logfile'] = 'ctobssim_py1.log'
126 144 sim['chatter'] = 2
127 145  
... ... @@ -137,7 +155,7 @@ class Test(test):
137 155 sim.save()
138 156  
139 157 # Load counts cube and check content.
140   - evt = gammalib.GCTAEventList('events.fits')
  158 + evt = gammalib.GCTAEventList('ctobssim_py1.fits')
141 159 self._test_list(evt, 6881)
142 160  
143 161 # Set-up observation container
... ... @@ -149,7 +167,7 @@ class Test(test):
149 167  
150 168 # Set-up ctobssim from observation container
151 169 sim = ctools.ctobssim(obs)
152   - sim['outevents'] = 'sim_events.xml'
  170 + sim['outevents'] = 'ctobssim_py2.xml'
153 171 sim['inmodel'] = self._model
154 172 sim['logfile'] = 'ctobssim_py2.log'
155 173 sim['chatter'] = 3
... ... @@ -175,7 +193,7 @@ class Test(test):
175 193 sim.save()
176 194  
177 195 # Load events
178   - obs = gammalib.GObservations('sim_events.xml')
  196 + obs = gammalib.GObservations('ctobssim_py2.xml')
179 197  
180 198 # Retrieve observation and check content
181 199 self._test_list(obs[0].events(), 6003)
... ... @@ -186,7 +204,6 @@ class Test(test):
186 204 # Set-up ctobssim with invalid event file
187 205 sim = ctools.ctobssim()
188 206 sim['inmodel'] = 'model_file_that_does_not_exist.xml'
189   - sim['outevents'] = 'events.fits'
190 207 sim['caldb'] = self._caldb
191 208 sim['irf'] = self._irf
192 209 sim['ra'] = 83.63
... ... @@ -196,6 +213,7 @@ class Test(test):
196 213 sim['tmax'] = 1800.0
197 214 sim['emin'] = 0.1
198 215 sim['emax'] = 100.0
  216 + sim['outevents'] = 'ctobssim_py3.fits'
199 217 sim['logfile'] = 'ctobssim_py3.log'
200 218 sim['chatter'] = 4
201 219  
... ...
test/test_ctselect.py
... ... @@ -18,6 +18,7 @@
18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19 #
20 20 # ==========================================================================
  21 +import os
21 22 import gammalib
22 23 import ctools
23 24 from testing import test
... ... @@ -103,10 +104,26 @@ class Test(test):
103 104 """
104 105 Test ctselect from Python
105 106 """
106   - # Set-up ctselect
  107 + # Allocate ctselect
  108 + select = ctools.ctselect()
  109 +
  110 + # Check that empty ctselect tool holds an empty observation
  111 + self._check_obs(select.obs(), nobs=0)
  112 +
  113 + # Check that saving does nothing
  114 + select['outobs'] = 'ctselect_py0.fits'
  115 + select['logfile'] = 'ctselect_py0.log'
  116 + select.logFileOpen()
  117 + select.save()
  118 + self.test_assert(not os.path.isfile('ctselect_py0.fits'),
  119 + 'Check that no event list has been created')
  120 +
  121 + # Check that clearing does not lead to an exception or segfault
  122 + select.clear()
  123 +
  124 + # Now set ctselect parameters
107 125 select = ctools.ctselect()
108 126 select['inobs'] = self._events
109   - select['outobs'] = 'ctselect_py1.fits'
110 127 select['ra'] = 83.63
111 128 select['dec'] = 22.01
112 129 select['rad'] = 3
... ... @@ -114,6 +131,7 @@ class Test(test):
114 131 select['tmax'] = 1800
115 132 select['emin'] = 0.1
116 133 select['emax'] = 100
  134 + select['outobs'] = 'ctselect_py1.fits'
117 135 select['logfile'] = 'ctselect_py1.log'
118 136 select['chatter'] = 2
119 137  
... ... @@ -125,6 +143,49 @@ class Test(test):
125 143 # Check result file
126 144 self._check_result_file('ctselect_py1.fits')
127 145  
  146 + # Copy ctselect tool
  147 + cpy_select = select.copy()
  148 +
  149 + # Check observation of ctselect copy
  150 + self._check_obs(cpy_select.obs())
  151 +
  152 + # Execute copy of ctselect tool again, now with a higher chatter
  153 + # level than before and without any selection
  154 + cpy_select['ra'] = 'NONE'
  155 + cpy_select['dec'] = 'NONE'
  156 + cpy_select['rad'] = 'NONE'
  157 + cpy_select['tmin'] = 'NONE'
  158 + cpy_select['tmax'] = 'NONE'
  159 + cpy_select['emin'] = 'NONE'
  160 + cpy_select['emax'] = 'NONE'
  161 + cpy_select['outobs'] = 'ctselect_py2.fits'
  162 + cpy_select['logfile'] = 'ctselect_py2.log'
  163 + cpy_select['chatter'] = 3
  164 + cpy_select.logFileOpen() # Needed to get a new log file
  165 + cpy_select.execute()
  166 +
  167 + # Check result file
  168 + self._check_result_file('ctselect_py2.fits')
  169 + print('Step3')
  170 +
  171 + # Execute again the copy of ctselect tool again, now using the pointing
  172 + # information in the input observation
  173 + cpy_select['usepnt'] = True
  174 + cpy_select['outobs'] = 'ctselect_py3.fits'
  175 + cpy_select['logfile'] = 'ctselect_py3.log'
  176 + cpy_select['chatter'] = 4
  177 + cpy_select.logFileOpen() # Needed to get a new log file
  178 + cpy_select.execute()
  179 +
  180 + # Check result file
  181 + self._check_result_file('ctselect_py3.fits')
  182 +
  183 + # Now clear copy of ctselect tool
  184 + cpy_select.clear()
  185 +
  186 + # Check that cleared ctselect tool holds no observations and events
  187 + self._check_obs(cpy_select.obs(), nobs=0)
  188 +
128 189 # Return
129 190 return
130 191  
... ... @@ -134,16 +195,59 @@ class Test(test):
134 195 Check result file
135 196 """
136 197 # Open result file
137   - result = gammalib.GCTAEventList(filename)
138   -
139   - # Check file
140   - self.test_value(result.size(), 6127, 'Check for 6127 events')
141   - self.test_value(result.roi().centre().dir().ra_deg(), 83.63, 1.0e-6,
142   - 'Check for ROI Right Ascension')
143   - self.test_value(result.roi().centre().dir().dec_deg(), 22.01, 1.0e-6,
144   - 'Check for ROI Declination')
145   - self.test_value(result.roi().radius(), 3.0, 1.0e-6,
146   - 'Check for ROI Radius')
  198 + events = gammalib.GCTAEventList(filename)
  199 +
  200 + # Check event list
  201 + self._check_events(events, nevents=6127)
  202 +
  203 + # Return
  204 + return
  205 +
  206 + # Check observation and event list
  207 + def _check_obs(self, obs, nobs=1, nevents=6127):
  208 + """
  209 + Check observation and event list
  210 +
  211 + Parameters
  212 + ----------
  213 + obs : `~gammalib.GObservations`
  214 + Models
  215 + nobs : int, optional
  216 + Expected number of observations
  217 + nevents : int, optional
  218 + Expected number of events
  219 + """
  220 + # Check number of observations
  221 + self.test_value(obs.size(), nobs, 'Check number of observations')
  222 +
  223 + # If there is an observation then check the event list of the first
  224 + # one
  225 + if obs.size() > 0:
  226 + self._check_events(obs[0].events(), nevents=nevents)
  227 +
  228 + # Return
  229 + return
  230 +
  231 + # Check events
  232 + def _check_events(self, events, nevents=6127):
  233 + """
  234 + Check event list
  235 +
  236 + Parameters
  237 + ----------
  238 + events : `~gammalib.GCTAEventList`
  239 + Event list
  240 + nevents : int, optional
  241 + Expected number of events
  242 + """
  243 + # Check event list
  244 + self.test_value(events.size(), nevents, 'Check number of events')
  245 + self.test_value(events.roi().centre().dir().ra_deg(), 83.63, 1.0e-6,
  246 + 'Check for RoI centre Right Ascension')
  247 + self.test_value(events.roi().centre().dir().dec_deg(), 22.01, 1.0e-6,
  248 + 'Check for RoI centre Declination')
  249 + self.test_value(events.roi().radius(), 3.0, 1.0e-6,
  250 + 'Check for RoI radius')
147 251  
148 252 # Return
149 253 return
... ...