Commit b554fc2efa1c85d671fd8fc1844fc497b86b6732

Authored by Jürgen Knödlseder
1 parent 9617e53e

Allow energy boundaries and energy value FITS file as input to ebinfile parameters (#1978)

ChangeLog
1   -2017-03-22
  1 +2017-03-24
2 2  
3 3 * Version 1.3.0 released
4 4 ========================
5 5  
  6 + Support energy boundary FITS file in ctmapcube (#1978)
6 7 Add csebins script (#1976)
7   - Take into account RoI in ctskymap and use numerical integration for IRF (#1975)
  8 + Consider RoI in ctskymap and use numerical integration for IRF (#1975)
8 9 Set local language to english (#1370)
9 10 Enhance logfile output of csroot2caldb script
10 11 Set default deadc value to 0.98 (CTA has <2% deadtime)
... ...
1 1 New Features and Important Changes in ctools 1.3.0.dev1
2 2  
3   -22 March 2017
  3 +24 March 2017
4 4  
5 5  
6 6 Introduction
... ... @@ -87,7 +87,8 @@ None
87 87  
88 88 ctmapcube - CTA map cube generation
89 89 -----------------------------------
90   -None
  90 +The tool now supports loading the energy binning definition from an energy
  91 +boundary FITS file, behaving now similar to the other cube tools (#1978).
91 92  
92 93  
93 94 ctcubemask - CTA cube filtering
... ...
src/ctmapcube/ctmapcube.cpp
... ... @@ -349,7 +349,7 @@ void ctmapcube::get_parameters(void)
349 349 } // endif: there were no models
350 350  
351 351 // Get energy binning parameters
352   - GEnergies energies = create_energies();
  352 + GEnergies energies(create_ebounds());
353 353  
354 354 // Get spatial binning parameters
355 355 double xref = (*this)["xref"].real();
... ... @@ -386,68 +386,6 @@ void ctmapcube::get_parameters(void)
386 386  
387 387  
388 388 /***********************************************************************//**
389   - * @brief Create map cube energies from user parameters
390   - *
391   - * Creates the map cube energies according to the user parameters. If the
392   - * @p ebinfile parameter is "FILE" the method loads the energy information
393   - * from a FITS file. The name of the FITS file is given by the @p ebinfile
394   - * parameter. If no extension name is specified the method will use assume
395   - * the name to be `ENERGIES`.
396   - *
397   - * If the @p ebinfile parameter is "LIN" the method will create a linearly
398   - * spaced series of @p enumbins energies in the interval @p emin to @p emax.
399   - * Otherwise, the @p ebinfile parameter is assumed to be "LOG" and the method
400   - * will create a logarithmically spaced series of @p enumbins energies in the
401   - * interval @p emin to @p emax.
402   - ***************************************************************************/
403   -GEnergies ctmapcube::create_energies(void)
404   -{
405   - // Allocate energies
406   - GEnergies energies;
407   -
408   - // Get energy binning algorithm
409   - std::string ebinalg = (*this)["ebinalg"].string();
410   -
411   - // If energy binning algorithm is of type "FILE" (case sensitive), then
412   - // read energies from FITS file ...
413   - if (ebinalg == "FILE") {
414   -
415   - // Get filename
416   - GFilename ebinfile = (*this)["ebinfile"].filename();
417   -
418   - // Load energies
419   - energies.load(ebinfile);
420   -
421   - } // endif: ebinalg was "FILE"
422   -
423   - // ... otherwise use a linear or a logarithmically-spaced energy binning
424   - else {
425   -
426   - // Get task parameters
427   - double emin = (*this)["emin"].real();
428   - double emax = (*this)["emax"].real();
429   - int enumbins = (*this)["enumbins"].integer();
430   -
431   - // Initialise log mode for ebinning
432   - bool log = true;
433   -
434   - // Check if algorithm is linear
435   - if (ebinalg == "LIN") {
436   - log = false;
437   - }
438   -
439   - // Setup energies
440   - energies = GEnergies(enumbins, GEnergy(emin, "TeV"),
441   - GEnergy(emax, "TeV"), log);
442   -
443   - } // endelse: ebinalg was not "FILE"
444   -
445   - // Return energies
446   - return energies;
447   -}
448   -
449   -
450   -/***********************************************************************//**
451 389 * @brief Generate map cube
452 390 *
453 391 * Generate map cube by looping over all sky models in the container.
... ...
src/ctmapcube/ctmapcube.hpp
1 1 /***************************************************************************
2 2 * ctmapcube - Map cube generation tool *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2016 by Juergen Knoedlseder *
  4 + * copyright (C) 2016-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -34,7 +34,7 @@
34 34  
35 35 /* __Definitions _________________________________________________________ */
36 36 #define CTMAPCUBE_NAME "ctmapcube"
37   -#define CTMAPCUBE_VERSION "1.2.0"
  37 +#define CTMAPCUBE_VERSION "1.3.0"
38 38  
39 39  
40 40 /***********************************************************************//**
... ... @@ -64,17 +64,16 @@ public:
64 64  
65 65 protected:
66 66 // Protected methods
67   - void init_members(void);
68   - void copy_members(const ctmapcube& app);
69   - void free_members(void);
70   - void get_parameters(void);
71   - GEnergies create_energies(void);
72   - void create_cube(void);
73   - void add_model(GModelSky* model);
74   - void add_ptsrc_model(GModelSky* model);
75   - void get_bounding_circle(GModelSky* model,
76   - GSkyDir* dir,
77   - double* radius) const;
  67 + void init_members(void);
  68 + void copy_members(const ctmapcube& app);
  69 + void free_members(void);
  70 + void get_parameters(void);
  71 + void create_cube(void);
  72 + void add_model(GModelSky* model);
  73 + void add_ptsrc_model(GModelSky* model);
  74 + void get_bounding_circle(GModelSky* model,
  75 + GSkyDir* dir,
  76 + double* radius) const;
78 77  
79 78 // User parameters
80 79 GFilename m_outcube; //!< Output map cube filename
... ...
src/support/ctool.cpp
... ... @@ -503,15 +503,19 @@ void ctool::setup_models(GObservations&amp; obs,
503 503 * @brief Create energy boundaries from user parameters
504 504 *
505 505 * @exception GException::invalid_value
506   - * No valid energy boundary extension found.
  506 + * No valid energy boundary extension found or invalid extension
  507 + * name.
507 508 *
508 509 * Get the energy boundaries according to the user parameters. The method
509 510 * supports loading of energy boundary information from the `EBOUNDS` or
510   - * `ENERGYBINS` extension, or setting energy boundaries using a linear
511   - * or logarithmical spacing.
  511 + * `ENERGYBINS` extension, loading of energy value information from the
  512 + * `ENERGIES` extension, or setting energy boundaries using a linear or
  513 + * logarithmical spacing.
512 514 *
513 515 * The following parameters are read:
  516 + *
514 517 * ebinalg - Energy binning algorithm
  518 + * ebinfile - Name of file with energy binning
515 519 * emin - Minimum energy (if ebinalg != FILE)
516 520 * emax - Maximum energy (if ebinalg != FILE)
517 521 * enumbins - Number of energy bins (if ebinalg != FILE)
... ... @@ -529,43 +533,72 @@ GEbounds ctool::create_ebounds(void)
529 533 if (ebinalg == "FILE") {
530 534  
531 535 // Get filename
532   - std::string ebinfile = (*this)["ebinfile"].filename();
533   -
534   - // Create filename instance
535   - GFilename fname(ebinfile);
  536 + GFilename ebinfile = (*this)["ebinfile"].filename();
536 537  
537   - // Check if extension name was provided
538   - if (!fname.has_extname()) {
  538 + // If no extension name was provided then use default extension names
  539 + if (!ebinfile.has_extname()) {
539 540  
540 541 // Open energy boundary file using the EBOUNDS or ENERGYBINS
541   - // extension. Throw an exception if opening fails.
542   - GFits file(ebinfile);
  542 + // extension or energy values using the ENERGIES extension.
  543 + // Throw an exception if opening fails.
  544 + GFits file(ebinfile.url());
543 545 if (file.contains(gammalib::extname_ebounds)) {
544 546 file.close();
545 547 ebounds.load(ebinfile);
546 548 }
547 549 else if (file.contains("ENERGYBINS")) {
548 550 file.close();
549   - ebinfile += "[ENERGYBINS]";
  551 + ebinfile = ebinfile.url() + "[ENERGYBINS]";
550 552 ebounds.load(ebinfile);
551 553 }
  554 + else if (file.contains(gammalib::extname_energies)) {
  555 + file.close();
  556 + ebounds.set(GEnergies(ebinfile));
  557 + }
552 558 else {
553 559 file.close();
554 560 std::string msg = "No extension with name \""+
555   - gammalib::extname_ebounds+"\" or"
556   - " \"ENERGYBINS\" found in FITS file"
557   - " \""+ebinfile+"\". An \""+
558   - gammalib::extname_ebounds+"\" or "
559   - "\"ENERGYBINS\" extension is required if "
560   - "the parameter \"ebinalg\" is set to "
561   - "\"FILE\".";
  561 + gammalib::extname_ebounds+"\", "
  562 + "\"ENERGYBINS\" or \""+
  563 + gammalib::extname_energies+"\" found in FITS "
  564 + "file \""+ebinfile+"\". Please specify a "
  565 + "valid energy binning file.";
562 566 throw GException::invalid_value(G_CREATE_EBOUNDS, msg);
563 567 }
564 568 }
  569 +
  570 + // ... otherwise load energy boundaries from filename including
  571 + // extension
565 572 else {
566   - // Load ebounds from filename including extension
567   - ebounds.load(ebinfile);
568   - }
  573 +
  574 + // Open energy boundary file
  575 + GFits file(ebinfile.url());
  576 +
  577 + // If FITS file does not contain requested extension then throw
  578 + // an exception
  579 + if (!file.contains(ebinfile.extname())) {
  580 + std::string msg = "No extension \""+ebinfile.extname()+"\" "
  581 + "found in energy binning file \""+
  582 + ebinfile.url()+"\". Please provide a valid "
  583 + "extension name.";
  584 + throw GException::invalid_value(G_CREATE_EBOUNDS, msg);
  585 + }
  586 +
  587 + // Get table extension
  588 + GFitsTable& table = *file.table(ebinfile.extname());
  589 +
  590 + // If table contains one column then load energies, otherwise load
  591 + // energy boundaries.
  592 + if (table.ncols() == 1) {
  593 + file.close();
  594 + ebounds.set(GEnergies(ebinfile));
  595 + }
  596 + else {
  597 + file.close();
  598 + ebounds.load(ebinfile);
  599 + }
  600 +
  601 + } // endelse: loaded energy boundaries from table extension
569 602  
570 603 } // endif: ebinalg was "FILE"
571 604  
... ...
test/test_cscript.py
... ... @@ -238,7 +238,13 @@ class Test(test):
238 238 gammalib.GEnergy(10.0,'TeV'))
239 239 ebounds.save('test_ebinfile_ebounds.fits[EBOUNDS]', True)
240 240 ebounds.save('test_ebinfile_energybins.fits[ENERGYBINS]', True)
241   - ebounds.save('test_ebinfile_energies.fits[ENERGIES]', True)
  241 + ebounds.save('test_ebinfile_bins.fits[BINS]', True)
  242 +
  243 + # Create energy bin file
  244 + energies = gammalib.GEnergies(2, gammalib.GEnergy(1.0,'TeV'),
  245 + gammalib.GEnergy(10.0,'TeV'))
  246 + energies.save('test_ebinfile_energies.fits[ENERGIES]', True)
  247 + energies.save('test_ebinfile_engs.fits[ENGS]', True)
242 248  
243 249 # Return
244 250 return
... ... @@ -335,16 +341,28 @@ class Test(test):
335 341 self.test_value(ebounds.emin().TeV(), 1.0, 'Check minimum energy')
336 342 self.test_value(ebounds.emax().TeV(), 10.0, 'Check maximum energy')
337 343  
  344 + # Test create_ebounds() method for "ENERGIES" extension
  345 + ebounds = empty.check_create_ebounds('test_ebinfile_energies.fits')
  346 + self.test_value(ebounds.size(), 1, 'Check number of energy boundaries')
  347 + self.test_value(ebounds.emin().TeV(), 1.0, 'Check minimum energy')
  348 + self.test_value(ebounds.emax().TeV(), 10.0, 'Check maximum energy')
  349 +
338 350 # Test create_ebounds() method for invalid extension
339 351 self.test_try('Check create_ebounds() method for invalid extension')
340 352 try:
341   - empty.check_create_ebounds('test_ebinfile_energies.fits')
  353 + empty.check_create_ebounds('test_ebinfile_energies.fits[INVALID]')
342 354 self.test_try_failure('Exception not thrown')
343 355 except ValueError:
344 356 self.test_try_success()
345 357  
346   - # Test create_ebounds() method for "ENERGIES" extension
347   - ebounds = empty.check_create_ebounds('test_ebinfile_energies.fits[ENERGIES]')
  358 + # Test create_ebounds() method for "BINS" extension
  359 + ebounds = empty.check_create_ebounds('test_ebinfile_bins.fits[BINS]')
  360 + self.test_value(ebounds.size(), 1, 'Check number of energy boundaries')
  361 + self.test_value(ebounds.emin().TeV(), 1.0, 'Check minimum energy')
  362 + self.test_value(ebounds.emax().TeV(), 10.0, 'Check maximum energy')
  363 +
  364 + # Test create_ebounds() method for "ENGS" extension
  365 + ebounds = empty.check_create_ebounds('test_ebinfile_engs.fits[ENGS]')
348 366 self.test_value(ebounds.size(), 1, 'Check number of energy boundaries')
349 367 self.test_value(ebounds.emin().TeV(), 1.0, 'Check minimum energy')
350 368 self.test_value(ebounds.emax().TeV(), 10.0, 'Check maximum energy')
... ...
test/test_ctmapcube.py
... ... @@ -2,7 +2,7 @@
2 2 # ==========================================================================
3 3 # This scripts performs unit tests for the ctmapcube tool.
4 4 #
5   -# Copyright (C) 2016 Juergen Knoedlseder
  5 +# Copyright (C) 2016-2017 Juergen Knoedlseder
6 6 #
7 7 # This program is free software: you can redistribute it and/or modify
8 8 # it under the terms of the GNU General Public License as published by
... ... @@ -242,7 +242,7 @@ class Test(test):
242 242 return
243 243  
244 244 # Check map cube
245   - def _check_cube(self, cube, nmaps=10, npixels=10000):
  245 + def _check_cube(self, cube, nmaps=11, npixels=10000):
246 246 """
247 247 Check map cube
248 248  
... ...