Commit b81c122e89891ea75d5cf211c05243ed2c8569ad

Authored by Michael Mayer
1 parent bc55f554

Improved cstsmapmerge unit testing and updated the test cases, started to adapt …

…cttsmap and cstsmapmerge to the new logging conventions
cscripts/cstsmapmerge.py
... ... @@ -46,7 +46,7 @@ class cstsmapmerge(ctools.cscript):
46 46 self._files = None
47 47 self._in_filename = ''
48 48 self._tsmap = gammalib.GSkyMap() # Empty sky map
49   - self._statusmap = gammalib.GSkyMap() # Empty sky map
  49 + self._statusmap = gammalib.GSkyMap() # Empty sky map
50 50 self._maps = []
51 51 self._mapnames = []
52 52 self._merged_files = []
... ... @@ -148,7 +148,7 @@ class cstsmapmerge(ctools.cscript):
148 148 for hdu in fits:
149 149  
150 150 # Leave out primary and status extension
151   - if hdu.extname() != "IMAGE" and hdu.extname() != 'STATUS MAP':
  151 + if hdu.extname() != 'IMAGE' and hdu.extname() != 'STATUS MAP':
152 152  
153 153 # Add present maps
154 154 skymap = gammalib.GSkyMap()
... ... @@ -185,7 +185,7 @@ class cstsmapmerge(ctools.cscript):
185 185 for hdu in fits:
186 186  
187 187 # Leave out primary and status extension
188   - if hdu.extname() != "IMAGE" and hdu.extname() != 'STATUS MAP':
  188 + if hdu.extname() != 'IMAGE' and hdu.extname() != 'STATUS MAP':
189 189  
190 190 # Add present maps
191 191 skymap = gammalib.GSkyMap()
... ... @@ -197,9 +197,9 @@ class cstsmapmerge(ctools.cscript):
197 197  
198 198 # Compare size of maps
199 199 if not len(add_maps) == len(self._maps):
200   - msg = "Cannot merge map \""+fitsfile+"\" into map \""+\
201   - self._in_filename+"\" since the number of parameters "\
202   - "between both maps is different."
  200 + msg = 'Cannot merge map "'+fitsfile+'" into map "'+\
  201 + self._in_filename+'" since the number of parameters ' +\
  202 + 'between both maps is different.'
203 203 raise RuntimeError(msg)
204 204  
205 205 # Loop over bins
... ... @@ -210,10 +210,10 @@ class cstsmapmerge(ctools.cscript):
210 210  
211 211 # Raise exception if this bin has already been computed
212 212 if self._statusmap[i] > -0.5 and not self._overwrite:
213   - msg = "Attempt to merge bin which apparently has "+\
214   - "already been merged. File \""+fitsfile+"\" "+\
215   - "contains already merged bins. Set hidden "+\
216   - "parameter \"overwrite=yes\" to avoid this error."
  213 + msg = 'Attempt to merge bin which apparently has '+\
  214 + 'already been merged. File "'+fitsfile+'" '+\
  215 + 'contains already merged bins. Set hidden '+\
  216 + 'parameter "overwrite=yes" to avoid this error.'
217 217 raise RuntimeError(msg)
218 218  
219 219 # Copy TS values
... ... @@ -240,7 +240,7 @@ class cstsmapmerge(ctools.cscript):
240 240 Number of pixels for which TS has been computed.
241 241 """
242 242 # Get status map for this file
243   - status = gammalib.GSkyMap(fitsfile+"[STATUS MAP]")
  243 + status = gammalib.GSkyMap(fitsfile+'[STATUS MAP]')
244 244  
245 245 # Count number of pixels with TS status set
246 246 count = 0
... ... @@ -265,10 +265,10 @@ class cstsmapmerge(ctools.cscript):
265 265 self._get_parameters()
266 266  
267 267 # Write header into logger
268   - self._log_header1(gammalib.TERSE, "Merge TS maps")
  268 + self._log_header1(gammalib.TERSE, 'Merge TS maps')
269 269  
270 270 # Initialise file to start with
271   - file0 = ""
  271 + file0 = ''
272 272 self._merged_files = []
273 273  
274 274 # Test files for the entry status map. Use the first one to appear
... ... @@ -279,7 +279,7 @@ class cstsmapmerge(ctools.cscript):
279 279 if not gammalib.GFilename(fitsfile).is_fits():
280 280  
281 281 # Log message
282   - self._log_value(gammalib.EXPLICIT, "Skip file", fitsfile +" (not a FITS file)")
  282 + self._log_value(gammalib.EXPLICIT, 'Skip file', fitsfile +' (not a FITS file)')
283 283  
284 284 # Continue
285 285 continue
... ... @@ -297,8 +297,8 @@ class cstsmapmerge(ctools.cscript):
297 297 file0 = fitsfile
298 298  
299 299 # Log message
300   - pix_info = " (%d TS pixels computed)" % self._get_number_of_ts_pixels(fitsfile)
301   - self._log_value(gammalib.TERSE, "Initial TS map file", fitsfile + pix_info)
  300 + pix_info = ' (%d TS pixels computed)' % self._get_number_of_ts_pixels(fitsfile)
  301 + self._log_value(gammalib.TERSE, 'Initial TS map file', fitsfile + pix_info)
302 302  
303 303 # Leave loop
304 304 break
... ... @@ -310,16 +310,18 @@ class cstsmapmerge(ctools.cscript):
310 310 fits.close()
311 311  
312 312 # Info message
313   - self._log_value(gammalib.EXPLICIT, "Skip file", fitsfile +" (no \"STATUS MAP\" extension)")
  313 + self._log_value(gammalib.EXPLICIT, 'Skip file', fitsfile +' (no "STATUS MAP" extension)')
314 314  
315 315 # Continue
316 316 continue
317 317  
318 318 # Signal if no suitable file was found
319   - if file0 == "":
320   - self._log_string(gammalib.TERSE, "None of the provided files seems to be a sliced "
321   - "TS map file (none has a \"STATUS MAP\" "
322   - "extension).\n")
  319 + if file0 == '':
  320 + msg = 'None of the provided files seems to be a sliced ' + \
  321 + 'TS map file (none has a "STATUS MAP" ' + \
  322 + 'extension)'
  323 + raise RuntimeError(msg)
  324 +
323 325  
324 326 # ... otherwise merge files
325 327 else:
... ... @@ -341,7 +343,7 @@ class cstsmapmerge(ctools.cscript):
341 343  
342 344 # Skip if file is not FITS
343 345 if not gammalib.GFilename(fitsfile).is_fits():
344   - self._log_value(gammalib.EXPLICIT, "Skip file", fitsfile +" (not a FITS file)")
  346 + self._log_value(gammalib.EXPLICIT, 'Skip file', fitsfile +' (not a FITS file)')
345 347 continue
346 348  
347 349 # Open FITS file
... ... @@ -350,15 +352,15 @@ class cstsmapmerge(ctools.cscript):
350 352 # Skip if file does not contain status map
351 353 if not fits.contains('STATUS MAP'):
352 354 fits.close()
353   - self._log_value(gammalib.EXPLICIT, "Skip file", fitsfile +" (no \"STATUS MAP\" extension)")
  355 + self._log_value(gammalib.EXPLICIT, 'Skip file', fitsfile +' (no "STATUS MAP" extension)')
354 356 continue
355 357  
356 358 # Close FITS file
357 359 fits.close()
358 360  
359 361 # Logging
360   - pix_info = " (%d TS pixels computed)" % self._get_number_of_ts_pixels(fitsfile)
361   - self._log_value(gammalib.TERSE, "Merge TS map file", fitsfile + pix_info)
  362 + pix_info = ' (%d TS pixels computed)' % self._get_number_of_ts_pixels(fitsfile)
  363 + self._log_value(gammalib.TERSE, 'Merge TS map file', fitsfile + pix_info)
362 364  
363 365 # Merge TS map
364 366 self._merge_ts_map(fitsfile)
... ... @@ -375,7 +377,7 @@ class cstsmapmerge(ctools.cscript):
375 377 """
376 378  
377 379 # Get output filename in case it was not read ahead
378   - outmap = self["outmap"].filename()
  380 + outmap = self['outmap'].filename()
379 381  
380 382 # Create FITS file
381 383 fits = gammalib.GFits()
... ... @@ -402,29 +404,29 @@ class cstsmapmerge(ctools.cscript):
402 404 bins_merged += 1
403 405  
404 406 # Set boolean if map is fully done
405   - done = (bins_merged == self._tsmaps.npix())
  407 + done = (bins_merged == self._tsmap.npix())
406 408  
407 409 # Log summary header
408   - self._log_header2(gammalib.TERSE, "Merging Summary")
  410 + self._log_header2(gammalib.TERSE, 'Merging Summary')
409 411  
410   - # Write status map if we are not done yet
  412 + # Write computing status if we are not done yet
411 413 if not done:
412 414  
413 415 # Log bins that were computed and those that were missing
414   - self._log_value(gammalib.TERSE, "TS map bins", self._tsmap.npix())
415   - self._log_value(gammalib.TERSE, "Bins computed and merged", bins_merged )
416   - self._log_value(gammalib.TERSE, "Bins missing", self._tsmap.npix() - bins_merged)
  416 + self._log_value(gammalib.TERSE, 'TS map bins', self._tsmap.npix())
  417 + self._log_value(gammalib.TERSE, 'Bins computed and merged', bins_merged )
  418 + self._log_value(gammalib.TERSE, 'Bins missing', self._tsmap.npix() - bins_merged)
417 419  
418 420 else:
419 421  
420 422 # Write success message
421   - self._log_string(gammalib.TERSE, "TS map was fully computed and successfully merged")
  423 + self._log_string(gammalib.TERSE, 'TS map was fully computed and successfully merged')
422 424  
423 425 # Write header
424   - self._log_header1(gammalib.TERSE, "Save TS map")
  426 + self._log_header1(gammalib.TERSE, 'Save TS map')
425 427  
426 428 # Log filename
427   - self._log_value(gammalib.TERSE, "TS map file", outmap.url())
  429 + self._log_value(gammalib.TERSE, 'TS map file', outmap.url())
428 430  
429 431 # Save FITS file
430 432 fits.saveto(outmap, self._clobber())
... ... @@ -433,7 +435,7 @@ class cstsmapmerge(ctools.cscript):
433 435 if self._delete and done:
434 436  
435 437 # Log header
436   - self._log_header2(gammalib.TERSE, "Delete slices TS map files")
  438 + self._log_header2(gammalib.TERSE, 'Delete slices TS map files')
437 439  
438 440 # Loop over sliced files
439 441 for filename in self._merged_files:
... ... @@ -442,7 +444,7 @@ class cstsmapmerge(ctools.cscript):
442 444 os.remove(filename)
443 445  
444 446 # Log message about file
445   - self._log_value(gammalib.TERSE,"Deleted input file", filename)
  447 + self._log_value(gammalib.TERSE,'Deleted input file', filename)
446 448  
447 449 # Return
448 450 return
... ...
doc/source/users/reference_manual/cttsmap.rst
... ... @@ -21,7 +21,10 @@ Gaussian sigma).
21 21  
22 22 cttsmap generates a FITS file comprising a sky map of TS values followed by
23 23 one extension per free parameter that contains sky maps of the fitted
24   -parameter values.
  24 +parameter values. To save computation time, the errors are not computed by
  25 +default. Specifying the hidden parameter ``errors=yes`` will switch on the
  26 +error computation. Accordingly, for each free parameter, the errors are also
  27 +stored in a separate sky map.
25 28  
26 29  
27 30 General parameters
... ... @@ -56,6 +59,9 @@ General parameters
56 59  
57 60 ``outmap [file]``
58 61 Output Test Statistic map file.
  62 +
  63 +``(errors = no) [boolean]``
  64 + Compute and store parameter errors?
59 65  
60 66 ``(usepnt = no) [boolean]``
61 67 Use CTA pointing direction for map centre instead of xref/yref parameters?
... ...
src/cttsmap/cttsmap.cpp
... ... @@ -173,26 +173,20 @@ cttsmap& cttsmap::operator=(const cttsmap& app)
173 173 ==========================================================================*/
174 174  
175 175 /***********************************************************************//**
176   - * @brief Clear cttsmap tool
177   - *
178   - * Clears cttsmap tool.
  176 + * @brief Clear instance
179 177 ***************************************************************************/
180 178 void cttsmap::clear(void)
181 179 {
182 180 // Free members
183 181 free_members();
184 182 this->ctool::free_members();
185   -
186   - // Clear base class (needed to conserve tool name and version)
187   - this->GApplication::clear();
  183 + this->GApplication::free_members();
188 184  
189 185 // Initialise members
  186 + this->GApplication::init_members();
190 187 this->ctool::init_members();
191 188 init_members();
192 189  
193   - // Write header into logger
194   - log_header();
195   -
196 190 // Return
197 191 return;
198 192 }
... ... @@ -215,12 +209,9 @@ void cttsmap::run(void)
215 209 // Get task parameters
216 210 get_parameters();
217 211  
218   -<<<<<<< HEAD
219   -=======
220 212 // Write parameters into logger
221 213 log_parameters(TERSE);
222 214  
223   ->>>>>>> b7dd76b35e6d2fd74ff010258ffa7606e072dbf5
224 215 // Set energy dispersion flag for all CTA observations and save old
225 216 // values in save_edisp vector
226 217 std::vector<bool> save_edisp;
... ... @@ -234,22 +225,16 @@ void cttsmap::run(void)
234 225 }
235 226  
236 227 // Write observation(s) into logger
237   - if (logTerse()) {
238   - log << std::endl;
239   - if (m_obs.size() > 1) {
240   - log.header1("Observations");
241   - }
242   - else {
243   - log.header1("Observation");
244   - }
245   - log << m_obs << std::endl;
  228 + if (m_obs.size() > 1) {
  229 + log_header1(TERSE, "Observations");
  230 + }
  231 + else {
  232 + log_header1(TERSE, "Observation");
246 233 }
  234 + log_string(TERSE, m_obs.print());
247 235  
248 236 // Write header
249   - if (logTerse()) {
250   - log << std::endl;
251   - log.header1("Initialise TS map");
252   - }
  237 + log_header1(TERSE, "Initialise TS map");
253 238  
254 239  
255 240 // Get bins to be computed
... ... @@ -276,10 +261,7 @@ void cttsmap::run(void)
276 261 if (m_logL0 == 0.0) {
277 262  
278 263 // Write header
279   - if (logTerse()) {
280   - log << std::endl;
281   - log.header1("Compute NULL Hypothesis for TS computation");
282   - }
  264 + log_header1(TERSE, "Compute NULL Hypothesis for TS computation");
283 265  
284 266 // Compute likelihood without the test source
285 267 m_obs.models(models);
... ... @@ -289,10 +271,7 @@ void cttsmap::run(void)
289 271 }
290 272  
291 273 // Write header
292   - if (logTerse()) {
293   - log << std::endl;
294   - log.header1("Generate TS map");
295   - }
  274 + log_header1(TERSE, "Generate TS map");
296 275  
297 276 // Loop over grid positions
298 277 for (int i = binmin; i < binmax; ++i) {
... ... @@ -301,12 +280,9 @@ void cttsmap::run(void)
301 280 GSkyDir bincentre = m_tsmap.inx2dir(i);
302 281  
303 282 // Header for verbose logging
304   - if (logExplicit()) {
305   - std::string msg = "Computing TS for bin number "+gammalib::str(i)+
306   - " at "+bincentre.print();
307   - log << std::endl;
308   - log.header2(msg);
309   - }
  283 + std::string msg = "Computing TS for bin number "+gammalib::str(i)+
  284 + " at "+bincentre.print();
  285 + log_header2(EXPLICIT, msg);
310 286  
311 287 // Add test source at current bin position
312 288 if (m_testsource != NULL) {
... ... @@ -340,7 +316,6 @@ void cttsmap::run(void)
340 316 log << " TS value ....: ";
341 317 log << ts << std::endl;
342 318 }
343   -
344 319 else if (logTerse()) {
345 320 log << "TS for bin number ";
346 321 log << i;
... ... @@ -445,7 +420,7 @@ void cttsmap::save(void)
445 420  
446 421 // Write Fit status map
447 422 m_statusmap.write(fits);
448   - fits[fits.size()-1]->extname("FITSTATUS");
  423 + fits[fits.size()-1]->extname("STATUS MAP");
449 424  
450 425 // Save FITS file
451 426 fits.saveto(m_outmap, clobber());
... ... @@ -465,10 +440,7 @@ void cttsmap::save(void)
465 440 void cttsmap::publish(const std::string& name)
466 441 {
467 442 // Write header
468   - if (logTerse()) {
469   - log << std::endl;
470   - log.header1("Publish TS map");
471   - }
  443 + log_header1(TERSE, "Publish TS map");
472 444  
473 445 // Set default name is user name is empty
474 446 std::string user_name(name);
... ... @@ -477,10 +449,7 @@ void cttsmap::publish(const std::string&amp; name)
477 449 }
478 450  
479 451 // Log filename
480   - if (logTerse()) {
481   - log << gammalib::parformat("Publish TS map");
482   - log << user_name << std::endl;
483   - }
  452 + log_value(TERSE, "Publish TS map", user_name);
484 453  
485 454 // Publish TS map
486 455 m_tsmap.publish(user_name);
... ... @@ -659,9 +628,6 @@ void cttsmap::get_parameters(void)
659 628 m_outmap = (*this)["outmap"].filename();
660 629 }
661 630  
662   - // Write parameters into logger
663   - log_parameters(TERSE);
664   -
665 631 // Return
666 632 return;
667 633 }
... ... @@ -716,7 +682,8 @@ void cttsmap::init_maps(const GSkyMap&amp; map)
716 682  
717 683 // Store name of parameter error
718 684 m_mapnames.push_back("e_" + (*m_testsource)[i].name());
719   - }
  685 +
  686 + } // endif: error calculation was requested
720 687  
721 688 } // endfor: looped over all model parameters
722 689  
... ...
src/cttsmap/cttsmap.par
... ... @@ -27,7 +27,7 @@ bkgcube, f, a, &quot;NONE&quot;,,, &quot;Input background cube file (only needed for stacked
27 27 caldb, s, a, "prod2",,, "Calibration database"
28 28 irf, s, a, "South_0.5h",,, "Instrument response function"
29 29 edisp, b, h, no,,, "Apply energy dispersion?"
30   -errors, b, h, no,,, "Compute/store parameter errors?"
  30 +errors, b, h, no,,, "Compute and store parameter errors?"
31 31 outmap, f, a, "tsmap.fits",,, "Output Test Statistic map file"
32 32  
33 33 #
... ...
test/data/tsmap_0.fits
No preview for this file type
test/data/tsmap_1.fits
No preview for this file type
test/test_cstsmapmerge.py
... ... @@ -21,6 +21,8 @@
21 21 import gammalib
22 22 import cscripts
23 23 from testing import test
  24 +from __builtin__ import False
  25 +from Carbon.Aliases import false
24 26  
25 27  
26 28 # ================================== #
... ... @@ -98,7 +100,16 @@ class Test(test):
98 100 # Check if execution failed
99 101 self.test_assert(self._execute(cmd) != 0,
100 102 'Check invalid input file when executed from command line')
101   -
  103 +
  104 + # Setup cstsmapmerge command
  105 + cmd = cstsmapmerge+' inmaps="'+self._events+' '+self._model+'"'+ \
  106 + ' outmap="cstsmapmerge_cmd3.fits"'+ \
  107 + ' logfile="cstsmapmerge_cmd3.log" chatter=4'
  108 +
  109 + # Check if execution failed
  110 + self.test_assert(self._execute(cmd) != 0,
  111 + 'Check input file that are no TS maps when executed from command line')
  112 +
102 113 # Return
103 114 return
104 115  
... ... @@ -160,10 +171,10 @@ class Test(test):
160 171  
161 172 # Check merged TS map
162 173 self._check_result_file('cstsmapmerge_py4.fits')
163   -
164   - # Set-up space-separated cstsmapmerge with invalid files
  174 +
  175 + # Set-up cstsmapmerge with incomplete file list
165 176 merge = cscripts.cstsmapmerge()
166   - merge['inmaps'] = self._events+' '+self._model
  177 + merge['inmaps'] = self._map0 + ' ' + self._events
167 178 merge['outmap'] = 'cstsmapmerge_py5.fits'
168 179 merge['logfile'] = 'cstsmapmerge_py5.log'
169 180 merge['chatter'] = 4
... ... @@ -172,13 +183,13 @@ class Test(test):
172 183 merge.execute()
173 184  
174 185 # Check merged TS map
175   - #self._check_result_file('cstsmapmerge_py5.fits')
  186 + self._check_result_file('cstsmapmerge_py5.fits', False)
176 187  
177 188 # Return
178 189 return
179 190  
180 191 # Check result file
181   - def _check_result_file(self, filename):
  192 + def _check_result_file(self, filename, test_complete = True):
182 193 """
183 194 Check result file
184 195 """
... ... @@ -189,6 +200,7 @@ class Test(test):
189 200 ts = fits['Primary']
190 201 prefactor = fits['Prefactor']
191 202 index = fits['Index']
  203 + status = fits['STATUS MAP']
192 204  
193 205 # Check dimensions
194 206 self.test_value(ts.naxis(), 2, 'Check for 2 dimensions')
... ... @@ -200,6 +212,23 @@ class Test(test):
200 212 self.test_value(index.naxis(), 2, 'Check for 2 dimensions')
201 213 self.test_value(index.naxes(0), 2, 'Check for 2 pixels in X')
202 214 self.test_value(index.naxes(1), 1, 'Check for 1 pixel in Y')
  215 + self.test_value(status.naxis(), 2, 'Check for 2 dimensions')
  216 + self.test_value(status.naxes(0), 2, 'Check for 2 pixels in X')
  217 + self.test_value(status.naxes(1), 1, 'Check for 1 pixel in Y')
  218 +
  219 + # Initialise flag if map is complete
  220 + done = True
  221 +
  222 + # Loop over status sky map
  223 + for pix in status:
  224 +
  225 + # Check if pix is larger than threshold
  226 + if pix < -0.5:
  227 + done = False
  228 + break
  229 +
  230 + # Test for completeness of merged map
  231 + self.test_assert(done == test_complete, 'Test if map was merged completely')
203 232  
204 233 # Return
205 234 return
... ...