Commit 0c70d44e9ef42b58a3ed881ec2b18a58da57607b
1 parent
e8719183
Add "addbounds" parameter to response cube tools
Showing
19 changed files
with
607 additions
and
101 deletions
cscripts/cspull.py
| ... | ... | @@ -20,6 +20,7 @@ |
| 20 | 20 | # ========================================================================== |
| 21 | 21 | import sys |
| 22 | 22 | import csv |
| 23 | +import math | |
| 23 | 24 | import gammalib |
| 24 | 25 | import ctools |
| 25 | 26 | from cscripts import obsutils |
| ... | ... | @@ -163,6 +164,12 @@ class cspull(ctools.cscript): |
| 163 | 164 | self._log('\n') |
| 164 | 165 | self._log.header1('Compute stacked response') |
| 165 | 166 | |
| 167 | + # Set number of energy bins to at least 30 per energy decade | |
| 168 | + enumbins = int((math.log10(self['emax'].real()) - | |
| 169 | + math.log10(self['emin'].real())) * 30.0) | |
| 170 | + if self._enumbins > enumbins: | |
| 171 | + enumbins = self._enumbins | |
| 172 | + | |
| 166 | 173 | # Get stacked exposure |
| 167 | 174 | expcube = ctools.ctexpcube(self._obs) |
| 168 | 175 | expcube['incube'] = 'NONE' |
| ... | ... | @@ -171,7 +178,7 @@ class cspull(ctools.cscript): |
| 171 | 178 | expcube['binsz'] = self._binsz |
| 172 | 179 | expcube['nxpix'] = self._npix |
| 173 | 180 | expcube['nypix'] = self._npix |
| 174 | - expcube['enumbins'] = self._enumbins | |
| 181 | + expcube['enumbins'] = enumbins | |
| 175 | 182 | expcube['emin'] = self['emin'].real() |
| 176 | 183 | expcube['emax'] = self['emax'].real() |
| 177 | 184 | expcube['coordsys'] = self._coordsys |
| ... | ... | @@ -195,7 +202,7 @@ class cspull(ctools.cscript): |
| 195 | 202 | psfcube['binsz'] = self._binsz*10.0 |
| 196 | 203 | psfcube['nxpix'] = self._npix/10 |
| 197 | 204 | psfcube['nypix'] = self._npix/10 |
| 198 | - psfcube['enumbins'] = self._enumbins | |
| 205 | + psfcube['enumbins'] = enumbins | |
| 199 | 206 | psfcube['emin'] = self['emin'].real() |
| 200 | 207 | psfcube['emax'] = self['emax'].real() |
| 201 | 208 | psfcube['coordsys'] = self._coordsys |
| ... | ... | @@ -220,7 +227,7 @@ class cspull(ctools.cscript): |
| 220 | 227 | edispcube['binsz'] = self._binsz*10.0 |
| 221 | 228 | edispcube['nxpix'] = self._npix/10 |
| 222 | 229 | edispcube['nypix'] = self._npix/10 |
| 223 | - edispcube['enumbins'] = self._enumbins | |
| 230 | + edispcube['enumbins'] = enumbins | |
| 224 | 231 | edispcube['emin'] = self['emin'].real() |
| 225 | 232 | edispcube['emax'] = self['emax'].real() |
| 226 | 233 | edispcube['coordsys'] = self._coordsys |
| ... | ... | @@ -244,7 +251,7 @@ class cspull(ctools.cscript): |
| 244 | 251 | bkgcube['binsz'] = self._binsz |
| 245 | 252 | bkgcube['nxpix'] = self._npix |
| 246 | 253 | bkgcube['nypix'] = self._npix |
| 247 | - bkgcube['enumbins'] = self._enumbins | |
| 254 | + bkgcube['enumbins'] = enumbins | |
| 248 | 255 | bkgcube['emin'] = self['emin'].real() |
| 249 | 256 | bkgcube['emax'] = self['emax'].real() |
| 250 | 257 | bkgcube['coordsys'] = self._coordsys | ... | ... |
doc/source/users/reference_manual/ctbkgcube.rst
| ... | ... | @@ -25,10 +25,14 @@ cube as ``incube`` parameter. This will instruct ctbkgcube to extract the |
| 25 | 25 | background cube definition (such as sky coordinates and projection, number |
| 26 | 26 | of pixels, pixel scale, energy binning) from the counts cube. |
| 27 | 27 | |
| 28 | +Note that there should at least be 25 bins per energy decade in the background | |
| 29 | +cube to assure that the energy dependence of the background rate is sufficiently | |
| 30 | +well sampled (in particular at low energies). | |
| 31 | + | |
| 28 | 32 | ctbkgcube generates a background cube FITS file comprising two extensions. |
| 29 | 33 | The primary extension contains a 3-dimensional image that contains the |
| 30 | -background cube values. The next extension named ``EBOUNDS`` contains a | |
| 31 | -binary table that defines the energy boundaries of the background cube. | |
| 34 | +background cube values. The next extension named ``ENERGIES`` contains a | |
| 35 | +binary table that defines the energies of the background cube. | |
| 32 | 36 | |
| 33 | 37 | ctbkgcube generates also an output model XML file that can serve as input |
| 34 | 38 | for a maximum likelihood analysis. The output model XML file is a copy of |
| ... | ... | @@ -82,7 +86,10 @@ General parameters |
| 82 | 86 | |
| 83 | 87 | ``ebinfile [file]`` |
| 84 | 88 | Name of the file containing the energy bin definition. |
| 85 | - | |
| 89 | + | |
| 90 | +``(addbounds = yes) [boolean]`` | |
| 91 | + Add energies to the background cube at the observation energy boundaries? | |
| 92 | + | |
| 86 | 93 | ``(usepnt = no) [boolean]`` |
| 87 | 94 | Use CTA pointing direction for cube centre instead of xref/yref parameters? |
| 88 | 95 | ... | ... |
doc/source/users/reference_manual/ctedispcube.rst
| ... | ... | @@ -29,13 +29,12 @@ rather coarse spatial binning to keep the file size manageable (with a typical |
| 29 | 29 | value of ``binsz=1.0``). |
| 30 | 30 | |
| 31 | 31 | ctedispcube generates an energy dispersion cube FITS file comprising three |
| 32 | -extensions. The primary extension contains a 3-dimensional image that contains | |
| 33 | -the energy disperison values. The energy and fraction dimensions of the enrgy | |
| 34 | -dispersion cube are folded into the 3rd dimension of the FITS image. The next | |
| 35 | -extension named ``ENERGIES`` contains a binary table that defines the energy | |
| 36 | -values of the energy dispersion cube. The last extension named ``MIGRAS`` | |
| 37 | -contains a binary table that defines the migration values of the cube which | |
| 38 | -is the ratio between reconstructed and true photon energy. | |
| 32 | +extensions. The primary extension contains a 4-dimensional image that contains | |
| 33 | +the energy disperison values. The next extension named ``ENERGIES`` contains | |
| 34 | +a binary table that defines the energies of the energy dispersion cube. The | |
| 35 | +last extension named ``MIGRAS`` contains a binary table that defines the | |
| 36 | +migration values of the cube which is the ratio between reconstructed and true | |
| 37 | +photon energy. | |
| 39 | 38 | |
| 40 | 39 | |
| 41 | 40 | General parameters |
| ... | ... | @@ -71,6 +70,9 @@ General parameters |
| 71 | 70 | ``ebinfile [file]`` |
| 72 | 71 | Name of the file containing the energy bin definition. |
| 73 | 72 | |
| 73 | +``(addbounds = yes) [boolean]`` | |
| 74 | + Add energies to the energy dispersion cube at the observation energy boundaries? | |
| 75 | + | |
| 74 | 76 | ``(usepnt = no) [boolean]`` |
| 75 | 77 | Use CTA pointing direction for cube centre instead of xref/yref parameters? |
| 76 | 78 | ... | ... |
doc/source/users/reference_manual/ctexpcube.rst
| ... | ... | @@ -20,7 +20,7 @@ that has been used in the generation of the counts cube using :doc:`ctbin`. |
| 20 | 20 | |
| 21 | 21 | The binning of an exposure cube does not need to correspond to the binning |
| 22 | 22 | of a counts cube, as exposure values will in any case be determined by linear |
| 23 | -interpolation. For the user's convenience, howver, the counts cube can be | |
| 23 | +interpolation. For the user's convenience, however, the counts cube can be | |
| 24 | 24 | specified as ``incube`` parameter which will instruct ctexpcube to extract |
| 25 | 25 | the exposure cube definition (such as sky coordinates and projection, number |
| 26 | 26 | of pixels, pixel scale, energy binning) from the counts cube. Note, however, |
| ... | ... | @@ -32,13 +32,16 @@ due to the point spread function and energy dispersion. By computing the |
| 32 | 32 | exposure cube on the same grid as the counts cube, the spill over of events |
| 33 | 33 | from sources at the edge of cube will not be handled correctly. |
| 34 | 34 | |
| 35 | +Note that there should at least be 25 bins per energy decade in the exposure | |
| 36 | +cube to assure that the energy dependence of the exposure is sufficiently | |
| 37 | +well sampled (in particular at low energies). | |
| 38 | + | |
| 35 | 39 | ctexpcube generates an exposure cube FITS file comprising three extensions. |
| 36 | 40 | The primary extension contains a 3-dimensional image that contains the |
| 37 | -exposure values. The next extension named ``EBOUNDS`` contains a binary table | |
| 38 | -that defines the energy boundaries of the exposure cube. The last extension | |
| 39 | -named ``GTI`` contains a binary table that provides the Good Time Intervals | |
| 40 | -of all observations that have been used for the computation of the exposure | |
| 41 | -cube. | |
| 41 | +exposure values. The next extension named ``ENERGIES`` contains a binary table | |
| 42 | +that defines the energies of the exposure cube. The last extension named ``GTI`` | |
| 43 | +contains a binary table that provides the Good Time Intervals of all | |
| 44 | +observations that have been used for the computation of the exposure cube. | |
| 42 | 45 | |
| 43 | 46 | |
| 44 | 47 | General parameters |
| ... | ... | @@ -73,7 +76,10 @@ General parameters |
| 73 | 76 | |
| 74 | 77 | ``ebinfile [file]`` |
| 75 | 78 | Name of the file containing the energy bin definition. |
| 76 | - | |
| 79 | + | |
| 80 | +``(addbounds = yes) [boolean]`` | |
| 81 | + Add energies to the exposure cube at the observation energy boundaries? | |
| 82 | + | |
| 77 | 83 | ``(usepnt = no) [boolean]`` |
| 78 | 84 | Use CTA pointing direction for cube centre instead of xref/yref parameters? |
| 79 | 85 | ... | ... |
doc/source/users/reference_manual/ctpsfcube.rst
| ... | ... | @@ -29,13 +29,11 @@ recommended to use a rather coarse spatial binning to keep the file size |
| 29 | 29 | manageable (with a typical value of ``binsz=1.0``). |
| 30 | 30 | |
| 31 | 31 | ctpsfcube generates a point spread function cube FITS file comprising three |
| 32 | -extensions. The primary extension contains a 3-dimensional image that contains | |
| 33 | -the point spread function values. The energy and offset angle dimensions | |
| 34 | -of the point spread function cube are folded into the 3rd dimension of the | |
| 35 | -FITS image. The next extension named ``EBOUNDS`` contains a binary table | |
| 36 | -that defines the energy boundaries of the exposure cube. The last extension | |
| 37 | -named ``DELTAS`` contains a binary table that defines the offset angles | |
| 38 | -between true and measured arrival direction of the photon. | |
| 32 | +extensions. The primary extension contains a 4-dimensional image that contains | |
| 33 | +the point spread function values. The next extension named ``ENERGIES`` contains | |
| 34 | +a binary table that defines the energies of the point spread function cube. | |
| 35 | +The last extension named ``DELTAS`` contains a binary table that defines the | |
| 36 | +offset angles between true and measured arrival direction of the photon. | |
| 39 | 37 | |
| 40 | 38 | |
| 41 | 39 | General parameters |
| ... | ... | @@ -71,6 +69,9 @@ General parameters |
| 71 | 69 | ``ebinfile [file]`` |
| 72 | 70 | Name of the file containing the energy bin definition. |
| 73 | 71 | |
| 72 | +``(addbounds = yes) [boolean]`` | |
| 73 | + Add energies to the point spread function cube at the observation energy boundaries? | |
| 74 | + | |
| 74 | 75 | ``(usepnt = no) [boolean]`` |
| 75 | 76 | Use CTA pointing direction for cube centre instead of xref/yref parameters? |
| 76 | 77 | ... | ... |
src/ctbkgcube/ctbkgcube.cpp
| ... | ... | @@ -217,23 +217,46 @@ void ctbkgcube::run(void) |
| 217 | 217 | log << std::endl; |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | + // Warn if there are not enough energy bins | |
| 221 | + int n = m_background.energies().size(); | |
| 222 | + double logEmin = std::log10(m_background.energies()[0].TeV()); | |
| 223 | + double logEmax = std::log10(m_background.energies()[n-1].TeV()); | |
| 224 | + int nrequired = int((logEmax - logEmin) * 25.0); | |
| 225 | + if ((n < nrequired) && logTerse()) { | |
| 226 | + log << std::endl; | |
| 227 | + log << "WARNING: "; | |
| 228 | + log << "Only " << n-1 << " energy bins have been requested. This may be " | |
| 229 | + "too few energy bins."; | |
| 230 | + log << std::endl << " "; | |
| 231 | + log << "At least 25 bins per decade in energy are recommended, which " | |
| 232 | + "in your case"; | |
| 233 | + log << std::endl << " "; | |
| 234 | + log << "would be " << nrequired-1 << " bins. Consider increasing the " | |
| 235 | + "number of energy bins."; | |
| 236 | + log << std::endl; | |
| 237 | + } | |
| 238 | + | |
| 239 | + // Write header | |
| 240 | + if (logTerse()) { | |
| 241 | + log << std::endl; | |
| 242 | + log.header1("Initialise background cube"); | |
| 243 | + } | |
| 244 | + | |
| 245 | + // Initialise exposure cube | |
| 246 | + init_cube(); | |
| 247 | + | |
| 220 | 248 | // Write observation(s) into logger |
| 221 | 249 | if (logTerse()) { |
| 222 | 250 | log << std::endl; |
| 223 | - if (m_obs.size() > 1) { | |
| 224 | - log.header1("Observations"); | |
| 225 | - } | |
| 226 | - else { | |
| 227 | - log.header1("Observation"); | |
| 228 | - } | |
| 229 | - log << m_obs << std::endl; | |
| 251 | + log.header1(gammalib::number("Observation",m_obs.size())); | |
| 252 | + log << m_obs.print(m_chatter) << std::endl; | |
| 230 | 253 | } |
| 231 | 254 | |
| 232 | 255 | // Log input model |
| 233 | 256 | if (logTerse()) { |
| 234 | 257 | log << std::endl; |
| 235 | 258 | log.header1("Input model"); |
| 236 | - log << m_obs.models() << std::endl; | |
| 259 | + log << m_obs.models().print(m_chatter) << std::endl; | |
| 237 | 260 | } |
| 238 | 261 | |
| 239 | 262 | // Write header |
| ... | ... | @@ -330,6 +353,11 @@ void ctbkgcube::run(void) |
| 330 | 353 | // Append model to output container |
| 331 | 354 | m_outmdl.append(model); |
| 332 | 355 | |
| 356 | + // Log background cube | |
| 357 | + if (logTerse()) { | |
| 358 | + log << m_background.print(m_chatter) << std::endl; | |
| 359 | + } | |
| 360 | + | |
| 333 | 361 | // Log output model |
| 334 | 362 | if (logTerse()) { |
| 335 | 363 | log << std::endl; |
| ... | ... | @@ -445,10 +473,14 @@ void ctbkgcube::publish(const std::string& name) |
| 445 | 473 | ***************************************************************************/ |
| 446 | 474 | void ctbkgcube::init_members(void) |
| 447 | 475 | { |
| 448 | - // Initialise members | |
| 476 | + // Initialise user parameters | |
| 449 | 477 | m_outcube.clear(); |
| 450 | 478 | m_outmodel.clear(); |
| 451 | - m_publish = false; | |
| 479 | + m_addbounds = true; | |
| 480 | + m_publish = false; | |
| 481 | + m_chatter = static_cast<GChatter>(2); | |
| 482 | + | |
| 483 | + // Initialise protected members | |
| 452 | 484 | m_obs.clear(); |
| 453 | 485 | m_background.clear(); |
| 454 | 486 | m_bkgmdl.clear(); |
| ... | ... | @@ -466,10 +498,14 @@ void ctbkgcube::init_members(void) |
| 466 | 498 | ***************************************************************************/ |
| 467 | 499 | void ctbkgcube::copy_members(const ctbkgcube& app) |
| 468 | 500 | { |
| 469 | - // Copy members | |
| 470 | - m_outmodel = app.m_outmodel; | |
| 471 | - m_outcube = app.m_outcube; | |
| 472 | - m_publish = app.m_publish; | |
| 501 | + // Copy user parameters | |
| 502 | + m_outmodel = app.m_outmodel; | |
| 503 | + m_outcube = app.m_outcube; | |
| 504 | + m_addbounds = app.m_addbounds; | |
| 505 | + m_publish = app.m_publish; | |
| 506 | + m_chatter = app.m_chatter; | |
| 507 | + | |
| 508 | + // Copy protected members | |
| 473 | 509 | m_obs = app.m_obs; |
| 474 | 510 | m_background = app.m_background; |
| 475 | 511 | m_bkgmdl = app.m_bkgmdl; |
| ... | ... | @@ -558,7 +594,9 @@ void ctbkgcube::get_parameters(void) |
| 558 | 594 | } |
| 559 | 595 | |
| 560 | 596 | // Get remaining parameters |
| 561 | - m_publish = (*this)["publish"].boolean(); | |
| 597 | + m_addbounds = (*this)["addbounds"].boolean(); | |
| 598 | + m_publish = (*this)["publish"].boolean(); | |
| 599 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 562 | 600 | |
| 563 | 601 | // Read output filenames (if needed) |
| 564 | 602 | if (read_ahead()) { |
| ... | ... | @@ -569,3 +607,70 @@ void ctbkgcube::get_parameters(void) |
| 569 | 607 | // Return |
| 570 | 608 | return; |
| 571 | 609 | } |
| 610 | + | |
| 611 | + | |
| 612 | +/***********************************************************************//** | |
| 613 | + * @brief Initialise background cube | |
| 614 | + * | |
| 615 | + * Initialise the background cube. | |
| 616 | + ***************************************************************************/ | |
| 617 | +void ctbkgcube::init_cube(void) | |
| 618 | +{ | |
| 619 | + // Extract exposure cube definition | |
| 620 | + const GWcs* proj = static_cast<const GWcs*>(m_background.cube().projection()); | |
| 621 | + std::string wcs = m_background.cube().projection()->code(); | |
| 622 | + std::string coords = m_background.cube().projection()->coordsys(); | |
| 623 | + double x = proj->crval(0); | |
| 624 | + double y = proj->crval(1); | |
| 625 | + double dx = proj->cdelt(0); | |
| 626 | + double dy = proj->cdelt(1); | |
| 627 | + int nx = m_background.cube().nx(); | |
| 628 | + int ny = m_background.cube().ny(); | |
| 629 | + | |
| 630 | + // Extract energies | |
| 631 | + GEnergies energies = m_background.energies(); | |
| 632 | + | |
| 633 | + // If requested, insert energies at all event list energy boundaries | |
| 634 | + if (m_addbounds) { | |
| 635 | + | |
| 636 | + // Set logger | |
| 637 | + GLog* logger = NULL; | |
| 638 | + if (logTerse()) { | |
| 639 | + logger = &log; | |
| 640 | + } | |
| 641 | + | |
| 642 | + // Loop over all observations | |
| 643 | + for (int i = 0; i < m_obs.size(); ++i) { | |
| 644 | + | |
| 645 | + // Get observation and continue only if it is a CTA observation | |
| 646 | + const GCTAObservation* cta = dynamic_cast<const GCTAObservation*> | |
| 647 | + (m_obs[i]); | |
| 648 | + | |
| 649 | + // Skip observation if it's not a CTA observation | |
| 650 | + if (cta == NULL) { | |
| 651 | + continue; | |
| 652 | + } | |
| 653 | + | |
| 654 | + // Skip observation if it does not contain an event list | |
| 655 | + if (cta->eventtype() != "EventList") { | |
| 656 | + continue; | |
| 657 | + } | |
| 658 | + | |
| 659 | + // Insert energy boundaries | |
| 660 | + energies = insert_energy_boundaries(energies, *cta, logger); | |
| 661 | + | |
| 662 | + } // endfor: looped over all observations | |
| 663 | + | |
| 664 | + } // endif: energy bin insertion requested | |
| 665 | + | |
| 666 | + // Setup background cube | |
| 667 | + m_background = GCTACubeBackground(wcs, coords, x, y, dx, dy, nx, ny, energies); | |
| 668 | + | |
| 669 | + // Log background cube | |
| 670 | + if (logTerse()) { | |
| 671 | + log << m_background.print(m_chatter) << std::endl; | |
| 672 | + } | |
| 673 | + | |
| 674 | + // Return | |
| 675 | + return; | |
| 676 | +}; | ... | ... |
src/ctbkgcube/ctbkgcube.hpp
| ... | ... | @@ -69,12 +69,15 @@ protected: |
| 69 | 69 | void copy_members(const ctbkgcube& app); |
| 70 | 70 | void free_members(void); |
| 71 | 71 | void get_parameters(void); |
| 72 | - void fill_cube(GCTAObservation* obs); | |
| 72 | + void init_cube(void); | |
| 73 | + //void fill_cube(GCTAObservation* obs); | |
| 73 | 74 | |
| 74 | 75 | // User parameters |
| 75 | 76 | GFilename m_outcube; //!< Filename of output cube |
| 76 | 77 | GFilename m_outmodel; //!< Filename of output XML model |
| 78 | + bool m_addbounds; //!< Add energies at boundaries? | |
| 77 | 79 | bool m_publish; //!< Publish background cube? |
| 80 | + GChatter m_chatter; //!< Chattiness | |
| 78 | 81 | |
| 79 | 82 | // Protected members |
| 80 | 83 | GObservations m_obs; //!< Observation container | ... | ... |
src/ctbkgcube/ctbkgcube.par
| ... | ... | @@ -28,11 +28,12 @@ outmodel, f, a, "NONE",,, "Output model XML file" |
| 28 | 28 | # |
| 29 | 29 | # Energy binning parameters |
| 30 | 30 | #========================== |
| 31 | -ebinalg, s, h, "LOG",FILE|LIN|LOG,, "Algorithm for defining energy bins" | |
| 32 | -emin, r, a, 0.1,,, "Lower energy limit (TeV)" | |
| 33 | -emax, r, a, 100.0,,, "Upper energy limit (TeV)" | |
| 34 | -enumbins, i, a, 20,,, "Number of energy bins" | |
| 35 | -ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | |
| 31 | +ebinalg, s, h, "LOG",FILE|LIN|LOG,, "Algorithm for defining energy bins" | |
| 32 | +emin, r, a, 0.1,,, "Lower energy limit (TeV)" | |
| 33 | +emax, r, a, 100.0,,, "Upper energy limit (TeV)" | |
| 34 | +enumbins, i, a, 20,,, "Number of energy bins" | |
| 35 | +ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | |
| 36 | +addbounds, b, h, yes,,, "Add energies at observation energy boundaries?" | |
| 36 | 37 | |
| 37 | 38 | # |
| 38 | 39 | # Spatial binning parameters | ... | ... |
src/ctedispcube/ctedispcube.cpp
| ... | ... | @@ -229,16 +229,20 @@ void ctedispcube::run(void) |
| 229 | 229 | log << std::endl; |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | + // Write header | |
| 233 | + if (logTerse()) { | |
| 234 | + log << std::endl; | |
| 235 | + log.header1("Initialise energy dispersion cube"); | |
| 236 | + } | |
| 237 | + | |
| 238 | + // Initialise energy dispersion cube | |
| 239 | + init_cube(); | |
| 240 | + | |
| 232 | 241 | // Write observation(s) into logger |
| 233 | 242 | if (logTerse()) { |
| 234 | 243 | log << std::endl; |
| 235 | - if (m_obs.size() > 1) { | |
| 236 | - log.header1("Observations"); | |
| 237 | - } | |
| 238 | - else { | |
| 239 | - log.header1("Observation"); | |
| 240 | - } | |
| 241 | - log << m_obs << std::endl; | |
| 244 | + log.header1(gammalib::number("Observation",m_obs.size())); | |
| 245 | + log << m_obs.print(m_chatter) << std::endl; | |
| 242 | 246 | } |
| 243 | 247 | |
| 244 | 248 | // Write header |
| ... | ... | @@ -247,9 +251,14 @@ void ctedispcube::run(void) |
| 247 | 251 | log.header1("Generate energy dispersion cube"); |
| 248 | 252 | } |
| 249 | 253 | |
| 250 | - // Fill Edisp | |
| 254 | + // Fill energy dispersion cube | |
| 251 | 255 | m_edispcube.fill(m_obs, &log); |
| 252 | 256 | |
| 257 | + // Log energy dispersion cube | |
| 258 | + if (logTerse()) { | |
| 259 | + log << m_edispcube.print(m_chatter) << std::endl; | |
| 260 | + } | |
| 261 | + | |
| 253 | 262 | // Return |
| 254 | 263 | return; |
| 255 | 264 | } |
| ... | ... | @@ -302,8 +311,12 @@ void ctedispcube::save(void) |
| 302 | 311 | ***************************************************************************/ |
| 303 | 312 | void ctedispcube::init_members(void) |
| 304 | 313 | { |
| 305 | - // Initialise members | |
| 314 | + // Initialise user parameters | |
| 306 | 315 | m_outcube.clear(); |
| 316 | + m_addbounds = true; | |
| 317 | + m_chatter = static_cast<GChatter>(2); | |
| 318 | + | |
| 319 | + // Initialise protected members | |
| 307 | 320 | m_obs.clear(); |
| 308 | 321 | m_edispcube.clear(); |
| 309 | 322 | |
| ... | ... | @@ -319,8 +332,12 @@ void ctedispcube::init_members(void) |
| 319 | 332 | ***************************************************************************/ |
| 320 | 333 | void ctedispcube::copy_members(const ctedispcube& app) |
| 321 | 334 | { |
| 322 | - // Copy members | |
| 335 | + // Copy user parameters | |
| 323 | 336 | m_outcube = app.m_outcube; |
| 337 | + m_addbounds = app.m_addbounds; | |
| 338 | + m_chatter = app.m_chatter; | |
| 339 | + | |
| 340 | + // Copy protected members | |
| 324 | 341 | m_obs = app.m_obs; |
| 325 | 342 | m_edispcube = app.m_edispcube; |
| 326 | 343 | |
| ... | ... | @@ -380,7 +397,7 @@ void ctedispcube::get_parameters(void) |
| 380 | 397 | |
| 381 | 398 | } |
| 382 | 399 | |
| 383 | - // ... otherwise setup the exposure cube from the counts map | |
| 400 | + // ... otherwise setup the energy disperison cube from the counts map | |
| 384 | 401 | else { |
| 385 | 402 | |
| 386 | 403 | // Load event cube from filename |
| ... | ... | @@ -391,6 +408,10 @@ void ctedispcube::get_parameters(void) |
| 391 | 408 | |
| 392 | 409 | } // endelse: cube loaded from file |
| 393 | 410 | |
| 411 | + // Get remaining parameters | |
| 412 | + m_addbounds = (*this)["addbounds"].boolean(); | |
| 413 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 414 | + | |
| 394 | 415 | // Read output filename (if needed) |
| 395 | 416 | if (read_ahead()) { |
| 396 | 417 | m_outcube = (*this)["outcube"].filename(); |
| ... | ... | @@ -399,3 +420,73 @@ void ctedispcube::get_parameters(void) |
| 399 | 420 | // Return |
| 400 | 421 | return; |
| 401 | 422 | } |
| 423 | + | |
| 424 | + | |
| 425 | +/***********************************************************************//** | |
| 426 | + * @brief Initialise energy dispersion cube | |
| 427 | + * | |
| 428 | + * Initialise the energy dispersion cube. | |
| 429 | + ***************************************************************************/ | |
| 430 | +void ctedispcube::init_cube(void) | |
| 431 | +{ | |
| 432 | + // Extract energy dispersion definition | |
| 433 | + const GWcs* proj = static_cast<const GWcs*>(m_edispcube.cube().projection()); | |
| 434 | + std::string wcs = m_edispcube.cube().projection()->code(); | |
| 435 | + std::string coords = m_edispcube.cube().projection()->coordsys(); | |
| 436 | + double x = proj->crval(0); | |
| 437 | + double y = proj->crval(1); | |
| 438 | + double dx = proj->cdelt(0); | |
| 439 | + double dy = proj->cdelt(1); | |
| 440 | + int nx = m_edispcube.cube().nx(); | |
| 441 | + int ny = m_edispcube.cube().ny(); | |
| 442 | + double mmax = (*this)["migramax"].real(); | |
| 443 | + int nmbins = (*this)["migrabins"].integer(); | |
| 444 | + | |
| 445 | + // Extract energies | |
| 446 | + GEnergies energies = m_edispcube.energies(); | |
| 447 | + | |
| 448 | + // If requested, insert energies at all event list energy boundaries | |
| 449 | + if (m_addbounds) { | |
| 450 | + | |
| 451 | + // Set logger | |
| 452 | + GLog* logger = NULL; | |
| 453 | + if (logTerse()) { | |
| 454 | + logger = &log; | |
| 455 | + } | |
| 456 | + | |
| 457 | + // Loop over all observations | |
| 458 | + for (int i = 0; i < m_obs.size(); ++i) { | |
| 459 | + | |
| 460 | + // Get observation and continue only if it is a CTA observation | |
| 461 | + const GCTAObservation* cta = dynamic_cast<const GCTAObservation*> | |
| 462 | + (m_obs[i]); | |
| 463 | + | |
| 464 | + // Skip observation if it's not a CTA observation | |
| 465 | + if (cta == NULL) { | |
| 466 | + continue; | |
| 467 | + } | |
| 468 | + | |
| 469 | + // Skip observation if it does not contain an event list | |
| 470 | + if (cta->eventtype() != "EventList") { | |
| 471 | + continue; | |
| 472 | + } | |
| 473 | + | |
| 474 | + // Insert energy boundaries | |
| 475 | + energies = insert_energy_boundaries(energies, *cta, logger); | |
| 476 | + | |
| 477 | + } // endfor: looped over all observations | |
| 478 | + | |
| 479 | + } // endif: energy bin insertion requested | |
| 480 | + | |
| 481 | + // Setup energy dispersion cube | |
| 482 | + m_edispcube = GCTACubeEdisp(wcs, coords, x, y, dx, dy, nx, ny, energies, | |
| 483 | + mmax, nmbins); | |
| 484 | + | |
| 485 | + // Log energy dispersion cube | |
| 486 | + if (logTerse()) { | |
| 487 | + log << m_edispcube.print(m_chatter) << std::endl; | |
| 488 | + } | |
| 489 | + | |
| 490 | + // Return | |
| 491 | + return; | |
| 492 | +}; | ... | ... |
src/ctedispcube/ctedispcube.hpp
| ... | ... | @@ -67,9 +67,12 @@ protected: |
| 67 | 67 | void copy_members(const ctedispcube& app); |
| 68 | 68 | void free_members(void); |
| 69 | 69 | void get_parameters(void); |
| 70 | + void init_cube(void); | |
| 70 | 71 | |
| 71 | 72 | // User parameters |
| 72 | - GFilename m_outcube; //!< Output energy dispersion cube file name | |
| 73 | + GFilename m_outcube; //!< Output exposure cube file | |
| 74 | + bool m_addbounds; //!< Add energies at boundaries? | |
| 75 | + GChatter m_chatter; //!< Chattiness | |
| 73 | 76 | |
| 74 | 77 | // Protected members |
| 75 | 78 | GObservations m_obs; //!< Observation container | ... | ... |
src/ctedispcube/ctedispcube.par
| ... | ... | @@ -26,11 +26,12 @@ outcube, f, a, "edispcube.fits",,, "Output energy dispersion cube file" |
| 26 | 26 | # |
| 27 | 27 | # Energy binning parameters |
| 28 | 28 | #========================== |
| 29 | -ebinalg, s, h, "LOG", FILE|LIN|LOG,, "Algorithm for defining energy bins" | |
| 30 | -emin, r, a, 0.1,,, "Lower energy limit (TeV)" | |
| 31 | -emax, r, a, 100.0,,, "Upper energy limit (TeV)" | |
| 32 | -enumbins, i, a, 20,,, "Number of energy bins" | |
| 33 | -ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | |
| 29 | +ebinalg, s, h, "LOG", FILE|LIN|LOG,, "Algorithm for defining energy bins" | |
| 30 | +emin, r, a, 0.1,,, "Lower energy limit (TeV)" | |
| 31 | +emax, r, a, 100.0,,, "Upper energy limit (TeV)" | |
| 32 | +enumbins, i, a, 20,,, "Number of energy bins" | |
| 33 | +ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | |
| 34 | +addbounds, b, h, yes,,, "Add energies at observation energy boundaries?" | |
| 34 | 35 | |
| 35 | 36 | # |
| 36 | 37 | # Spatial binning parameters | ... | ... |
src/ctexpcube/ctexpcube.cpp
| ... | ... | @@ -217,11 +217,39 @@ void ctexpcube::run(void) |
| 217 | 217 | log << std::endl; |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | + // Warn if there are not enough energy bins | |
| 221 | + int n = m_expcube.energies().size(); | |
| 222 | + double logEmin = std::log10(m_expcube.energies()[0].TeV()); | |
| 223 | + double logEmax = std::log10(m_expcube.energies()[n-1].TeV()); | |
| 224 | + int nrequired = int((logEmax - logEmin) * 25.0); | |
| 225 | + if ((n < nrequired) && logTerse()) { | |
| 226 | + log << std::endl; | |
| 227 | + log << "WARNING: "; | |
| 228 | + log << "Only " << n-1 << " energy bins have been requested. This may be " | |
| 229 | + "too few energy bins."; | |
| 230 | + log << std::endl << " "; | |
| 231 | + log << "At least 25 bins per decade in energy are recommended, which " | |
| 232 | + "in your case"; | |
| 233 | + log << std::endl << " "; | |
| 234 | + log << "would be " << nrequired-1 << " bins. Consider increasing the " | |
| 235 | + "number of energy bins."; | |
| 236 | + log << std::endl; | |
| 237 | + } | |
| 238 | + | |
| 239 | + // Write header | |
| 240 | + if (logTerse()) { | |
| 241 | + log << std::endl; | |
| 242 | + log.header1("Initialise exposure cube"); | |
| 243 | + } | |
| 244 | + | |
| 245 | + // Initialise exposure cube | |
| 246 | + init_cube(); | |
| 247 | + | |
| 220 | 248 | // Write observation(s) into logger |
| 221 | 249 | if (logTerse()) { |
| 222 | 250 | log << std::endl; |
| 223 | 251 | log.header1(gammalib::number("Observation",m_obs.size())); |
| 224 | - log << m_obs << std::endl; | |
| 252 | + log << m_obs.print(m_chatter) << std::endl; | |
| 225 | 253 | } |
| 226 | 254 | |
| 227 | 255 | // Write header |
| ... | ... | @@ -230,9 +258,14 @@ void ctexpcube::run(void) |
| 230 | 258 | log.header1("Generate exposure cube"); |
| 231 | 259 | } |
| 232 | 260 | |
| 233 | - // Fill exposure | |
| 261 | + // Fill exposure cube | |
| 234 | 262 | m_expcube.fill(m_obs, &log); |
| 235 | 263 | |
| 264 | + // Log exposure cube | |
| 265 | + if (logTerse()) { | |
| 266 | + log << m_expcube.print(m_chatter) << std::endl; | |
| 267 | + } | |
| 268 | + | |
| 236 | 269 | // Optionally publish exposure cube |
| 237 | 270 | if (m_publish) { |
| 238 | 271 | publish(); |
| ... | ... | @@ -321,9 +354,11 @@ void ctexpcube::publish(const std::string& name) |
| 321 | 354 | ***************************************************************************/ |
| 322 | 355 | void ctexpcube::init_members(void) |
| 323 | 356 | { |
| 324 | - // Initialise members | |
| 357 | + // Initialise user parameters | |
| 325 | 358 | m_outcube.clear(); |
| 326 | - m_publish = false; | |
| 359 | + m_addbounds = true; | |
| 360 | + m_publish = false; | |
| 361 | + m_chatter = static_cast<GChatter>(2); | |
| 327 | 362 | |
| 328 | 363 | // Initialise protected members |
| 329 | 364 | m_obs.clear(); |
| ... | ... | @@ -341,9 +376,11 @@ void ctexpcube::init_members(void) |
| 341 | 376 | ***************************************************************************/ |
| 342 | 377 | void ctexpcube::copy_members(const ctexpcube& app) |
| 343 | 378 | { |
| 344 | - // Copy attributes | |
| 345 | - m_outcube = app.m_outcube; | |
| 346 | - m_publish = app.m_publish; | |
| 379 | + // Copy user parameters | |
| 380 | + m_outcube = app.m_outcube; | |
| 381 | + m_addbounds = app.m_addbounds; | |
| 382 | + m_publish = app.m_publish; | |
| 383 | + m_chatter = app.m_chatter; | |
| 347 | 384 | |
| 348 | 385 | // Copy protected members |
| 349 | 386 | m_obs = app.m_obs; |
| ... | ... | @@ -413,7 +450,9 @@ void ctexpcube::get_parameters(void) |
| 413 | 450 | } // endelse: cube loaded from file |
| 414 | 451 | |
| 415 | 452 | // Get remaining parameters |
| 416 | - m_publish = (*this)["publish"].boolean(); | |
| 453 | + m_addbounds = (*this)["addbounds"].boolean(); | |
| 454 | + m_publish = (*this)["publish"].boolean(); | |
| 455 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 417 | 456 | |
| 418 | 457 | // Read output filename (if needed) |
| 419 | 458 | if (read_ahead()) { |
| ... | ... | @@ -423,3 +462,70 @@ void ctexpcube::get_parameters(void) |
| 423 | 462 | // Return |
| 424 | 463 | return; |
| 425 | 464 | } |
| 465 | + | |
| 466 | + | |
| 467 | +/***********************************************************************//** | |
| 468 | + * @brief Initialise exposure cube | |
| 469 | + * | |
| 470 | + * Initialise the exposure cube. | |
| 471 | + ***************************************************************************/ | |
| 472 | +void ctexpcube::init_cube(void) | |
| 473 | +{ | |
| 474 | + // Extract exposure cube definition | |
| 475 | + const GWcs* proj = static_cast<const GWcs*>(m_expcube.cube().projection()); | |
| 476 | + std::string wcs = m_expcube.cube().projection()->code(); | |
| 477 | + std::string coords = m_expcube.cube().projection()->coordsys(); | |
| 478 | + double x = proj->crval(0); | |
| 479 | + double y = proj->crval(1); | |
| 480 | + double dx = proj->cdelt(0); | |
| 481 | + double dy = proj->cdelt(1); | |
| 482 | + int nx = m_expcube.cube().nx(); | |
| 483 | + int ny = m_expcube.cube().ny(); | |
| 484 | + | |
| 485 | + // Extract energies | |
| 486 | + GEnergies energies = m_expcube.energies(); | |
| 487 | + | |
| 488 | + // If requested, insert energies at all event list energy boundaries | |
| 489 | + if (m_addbounds) { | |
| 490 | + | |
| 491 | + // Set logger | |
| 492 | + GLog* logger = NULL; | |
| 493 | + if (logTerse()) { | |
| 494 | + logger = &log; | |
| 495 | + } | |
| 496 | + | |
| 497 | + // Loop over all observations | |
| 498 | + for (int i = 0; i < m_obs.size(); ++i) { | |
| 499 | + | |
| 500 | + // Get observation and continue only if it is a CTA observation | |
| 501 | + const GCTAObservation* cta = dynamic_cast<const GCTAObservation*> | |
| 502 | + (m_obs[i]); | |
| 503 | + | |
| 504 | + // Skip observation if it's not a CTA observation | |
| 505 | + if (cta == NULL) { | |
| 506 | + continue; | |
| 507 | + } | |
| 508 | + | |
| 509 | + // Skip observation if it does not contain an event list | |
| 510 | + if (cta->eventtype() != "EventList") { | |
| 511 | + continue; | |
| 512 | + } | |
| 513 | + | |
| 514 | + // Insert energy boundaries | |
| 515 | + energies = insert_energy_boundaries(energies, *cta, logger); | |
| 516 | + | |
| 517 | + } // endfor: looped over all observations | |
| 518 | + | |
| 519 | + } // endif: energy bin insertion requested | |
| 520 | + | |
| 521 | + // Setup exposure cube | |
| 522 | + m_expcube = GCTACubeExposure(wcs, coords, x, y, dx, dy, nx, ny, energies); | |
| 523 | + | |
| 524 | + // Log exposure cube | |
| 525 | + if (logTerse()) { | |
| 526 | + log << m_expcube.print(m_chatter) << std::endl; | |
| 527 | + } | |
| 528 | + | |
| 529 | + // Return | |
| 530 | + return; | |
| 531 | +}; | ... | ... |
src/ctexpcube/ctexpcube.hpp
| ... | ... | @@ -68,10 +68,13 @@ protected: |
| 68 | 68 | void copy_members(const ctexpcube& app); |
| 69 | 69 | void free_members(void); |
| 70 | 70 | void get_parameters(void); |
| 71 | + void init_cube(void); | |
| 71 | 72 | |
| 72 | 73 | // User parameters |
| 73 | - GFilename m_outcube; //!< Output exposure cube file | |
| 74 | - bool m_publish; //!< Publish exposure cube? | |
| 74 | + GFilename m_outcube; //!< Output exposure cube file | |
| 75 | + bool m_addbounds; //!< Add energies at boundaries? | |
| 76 | + bool m_publish; //!< Publish exposure cube? | |
| 77 | + GChatter m_chatter; //!< Chattiness | |
| 75 | 78 | |
| 76 | 79 | // Protected members |
| 77 | 80 | GObservations m_obs; //!< Observation container | ... | ... |
src/ctexpcube/ctexpcube.par
| ... | ... | @@ -26,11 +26,12 @@ outcube, f, a, "expcube.fits",,, "Output exposure cube file" |
| 26 | 26 | # |
| 27 | 27 | # Energy binning parameters |
| 28 | 28 | #========================== |
| 29 | -ebinalg, s, h, "LOG", FILE|LIN|LOG,,"Algorithm for defining energy bins" | |
| 30 | -emin, r, a, 0.1,,,"Lower energy limit (TeV)" | |
| 31 | -emax, r, a, 100.0,,, "Upper energy limit (TeV)" | |
| 32 | -enumbins, i, a, 20,,, "Number of energy bins" | |
| 33 | -ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | |
| 29 | +ebinalg, s, h, "LOG", FILE|LIN|LOG,,"Algorithm for defining energy bins" | |
| 30 | +emin, r, a, 0.1,,,"Lower energy limit (TeV)" | |
| 31 | +emax, r, a, 100.0,,, "Upper energy limit (TeV)" | |
| 32 | +enumbins, i, a, 20,,, "Number of energy bins" | |
| 33 | +ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | |
| 34 | +addbounds, b, h, yes,,, "Add energies at observation energy boundaries?" | |
| 34 | 35 | |
| 35 | 36 | # |
| 36 | 37 | # Spatial binning parameters | ... | ... |
src/ctpsfcube/ctpsfcube.cpp
| ... | ... | @@ -216,16 +216,20 @@ void ctpsfcube::run(void) |
| 216 | 216 | log << std::endl; |
| 217 | 217 | } |
| 218 | 218 | |
| 219 | + // Write header | |
| 220 | + if (logTerse()) { | |
| 221 | + log << std::endl; | |
| 222 | + log.header1("Initialise PSF cube"); | |
| 223 | + } | |
| 224 | + | |
| 225 | + // Initialise exposure cube | |
| 226 | + init_cube(); | |
| 227 | + | |
| 219 | 228 | // Write observation(s) into logger |
| 220 | 229 | if (logTerse()) { |
| 221 | 230 | log << std::endl; |
| 222 | - if (m_obs.size() > 1) { | |
| 223 | - log.header1("Observations"); | |
| 224 | - } | |
| 225 | - else { | |
| 226 | - log.header1("Observation"); | |
| 227 | - } | |
| 228 | - log << m_obs << std::endl; | |
| 231 | + log.header1(gammalib::number("Observation",m_obs.size())); | |
| 232 | + log << m_obs.print(m_chatter) << std::endl; | |
| 229 | 233 | } |
| 230 | 234 | |
| 231 | 235 | // Write header |
| ... | ... | @@ -234,9 +238,14 @@ void ctpsfcube::run(void) |
| 234 | 238 | log.header1("Generate PSF cube"); |
| 235 | 239 | } |
| 236 | 240 | |
| 237 | - // Fill PSF | |
| 241 | + // Fill PSF cube | |
| 238 | 242 | m_psfcube.fill(m_obs, &log); |
| 239 | 243 | |
| 244 | + // Log PSF cube | |
| 245 | + if (logTerse()) { | |
| 246 | + log << m_psfcube.print(m_chatter) << std::endl; | |
| 247 | + } | |
| 248 | + | |
| 240 | 249 | // Return |
| 241 | 250 | return; |
| 242 | 251 | } |
| ... | ... | @@ -286,8 +295,10 @@ void ctpsfcube::save(void) |
| 286 | 295 | ***************************************************************************/ |
| 287 | 296 | void ctpsfcube::init_members(void) |
| 288 | 297 | { |
| 289 | - // Initialise members | |
| 298 | + // Initialise user parameters | |
| 290 | 299 | m_outcube.clear(); |
| 300 | + m_addbounds = true; | |
| 301 | + m_chatter = static_cast<GChatter>(2); | |
| 291 | 302 | |
| 292 | 303 | // Initialise protected members |
| 293 | 304 | m_obs.clear(); |
| ... | ... | @@ -305,12 +316,14 @@ void ctpsfcube::init_members(void) |
| 305 | 316 | ***************************************************************************/ |
| 306 | 317 | void ctpsfcube::copy_members(const ctpsfcube& app) |
| 307 | 318 | { |
| 308 | - // Copy attributes | |
| 309 | - m_outcube = app.m_outcube; | |
| 319 | + // Copy user parameters | |
| 320 | + m_outcube = app.m_outcube; | |
| 321 | + m_addbounds = app.m_addbounds; | |
| 322 | + m_chatter = app.m_chatter; | |
| 310 | 323 | |
| 311 | 324 | // Copy protected members |
| 312 | - m_obs = app.m_obs; | |
| 313 | - m_psfcube = app.m_psfcube; | |
| 325 | + m_obs = app.m_obs; | |
| 326 | + m_psfcube = app.m_psfcube; | |
| 314 | 327 | |
| 315 | 328 | // Return |
| 316 | 329 | return; |
| ... | ... | @@ -379,6 +392,10 @@ void ctpsfcube::get_parameters(void) |
| 379 | 392 | |
| 380 | 393 | } // endelse: cube loaded from file |
| 381 | 394 | |
| 395 | + // Get remaining parameters | |
| 396 | + m_addbounds = (*this)["addbounds"].boolean(); | |
| 397 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 398 | + | |
| 382 | 399 | // Read output filename (if needed) |
| 383 | 400 | if (read_ahead()) { |
| 384 | 401 | m_outcube = (*this)["outcube"].filename(); |
| ... | ... | @@ -387,3 +404,73 @@ void ctpsfcube::get_parameters(void) |
| 387 | 404 | // Return |
| 388 | 405 | return; |
| 389 | 406 | } |
| 407 | + | |
| 408 | + | |
| 409 | +/***********************************************************************//** | |
| 410 | + * @brief Initialise PSF cube | |
| 411 | + * | |
| 412 | + * Initialise the PSF cube. | |
| 413 | + ***************************************************************************/ | |
| 414 | +void ctpsfcube::init_cube(void) | |
| 415 | +{ | |
| 416 | + // Extract exposure cube definition | |
| 417 | + const GWcs* proj = static_cast<const GWcs*>(m_psfcube.cube().projection()); | |
| 418 | + std::string wcs = m_psfcube.cube().projection()->code(); | |
| 419 | + std::string coords = m_psfcube.cube().projection()->coordsys(); | |
| 420 | + double x = proj->crval(0); | |
| 421 | + double y = proj->crval(1); | |
| 422 | + double dx = proj->cdelt(0); | |
| 423 | + double dy = proj->cdelt(1); | |
| 424 | + int nx = m_psfcube.cube().nx(); | |
| 425 | + int ny = m_psfcube.cube().ny(); | |
| 426 | + double dmax = (*this)["amax"].real(); | |
| 427 | + int ndbins = (*this)["anumbins"].integer(); | |
| 428 | + | |
| 429 | + // Extract energies | |
| 430 | + GEnergies energies = m_psfcube.energies(); | |
| 431 | + | |
| 432 | + // If requested, insert energies at all event list energy boundaries | |
| 433 | + if (m_addbounds) { | |
| 434 | + | |
| 435 | + // Set logger | |
| 436 | + GLog* logger = NULL; | |
| 437 | + if (logTerse()) { | |
| 438 | + logger = &log; | |
| 439 | + } | |
| 440 | + | |
| 441 | + // Loop over all observations | |
| 442 | + for (int i = 0; i < m_obs.size(); ++i) { | |
| 443 | + | |
| 444 | + // Get observation and continue only if it is a CTA observation | |
| 445 | + const GCTAObservation* cta = dynamic_cast<const GCTAObservation*> | |
| 446 | + (m_obs[i]); | |
| 447 | + | |
| 448 | + // Skip observation if it's not a CTA observation | |
| 449 | + if (cta == NULL) { | |
| 450 | + continue; | |
| 451 | + } | |
| 452 | + | |
| 453 | + // Skip observation if it does not contain an event list | |
| 454 | + if (cta->eventtype() != "EventList") { | |
| 455 | + continue; | |
| 456 | + } | |
| 457 | + | |
| 458 | + // Insert energy boundaries | |
| 459 | + energies = insert_energy_boundaries(energies, *cta, logger); | |
| 460 | + | |
| 461 | + } // endfor: looped over all observations | |
| 462 | + | |
| 463 | + } // endif: energy bin insertion requested | |
| 464 | + | |
| 465 | + // Setup PSF cube | |
| 466 | + m_psfcube = GCTACubePsf(wcs, coords, x, y, dx, dy, nx, ny, energies, | |
| 467 | + dmax, ndbins); | |
| 468 | + | |
| 469 | + // Log PSF cube | |
| 470 | + if (logTerse()) { | |
| 471 | + log << m_psfcube.print(m_chatter) << std::endl; | |
| 472 | + } | |
| 473 | + | |
| 474 | + // Return | |
| 475 | + return; | |
| 476 | +}; | ... | ... |
src/ctpsfcube/ctpsfcube.hpp
| ... | ... | @@ -67,9 +67,12 @@ protected: |
| 67 | 67 | void copy_members(const ctpsfcube& app); |
| 68 | 68 | void free_members(void); |
| 69 | 69 | void get_parameters(void); |
| 70 | + void init_cube(void); | |
| 70 | 71 | |
| 71 | 72 | // User parameters |
| 72 | - GFilename m_outcube; //!< Output PSF cube file name | |
| 73 | + GFilename m_outcube; //!< Output PSF cube file name | |
| 74 | + bool m_addbounds; //!< Add energies at boundaries? | |
| 75 | + GChatter m_chatter; //!< Chattiness | |
| 73 | 76 | |
| 74 | 77 | // Protected members |
| 75 | 78 | GObservations m_obs; //!< Observation container | ... | ... |
src/ctpsfcube/ctpsfcube.par
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | # ------------------------------------------------------------------------- # |
| 6 | 6 | # # |
| 7 | 7 | # File: ctpsfcube.par # |
| 8 | -# Version: 1.0.0 # | |
| 8 | +# Version: 1.1.0 # | |
| 9 | 9 | # # |
| 10 | 10 | # Author: Chia-Chun Lu # |
| 11 | 11 | # c.lu@mpi-hd.mpg.de # |
| ... | ... | @@ -26,11 +26,12 @@ outcube, f, a, "psfcube.fits",,, "Output PSF cube file" |
| 26 | 26 | # |
| 27 | 27 | # Energy binning parameters |
| 28 | 28 | #========================== |
| 29 | -ebinalg, s, h, "LOG", FILE|LIN|LOG,, "Algorithm for defining energy bins" | |
| 30 | -emin, r, a, 0.1,,, "Lower energy limit (TeV)" | |
| 31 | -emax, r, a, 100.0,,, "Upper energy limit (TeV)" | |
| 32 | -enumbins, i, a, 20,,, "Number of energy bins" | |
| 33 | -ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | |
| 29 | +ebinalg, s, h, "LOG", FILE|LIN|LOG,, "Algorithm for defining energy bins" | |
| 30 | +emin, r, a, 0.1,,, "Lower energy limit (TeV)" | |
| 31 | +emax, r, a, 100.0,,, "Upper energy limit (TeV)" | |
| 32 | +enumbins, i, a, 20,,, "Number of energy bins" | |
| 33 | +ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | |
| 34 | +addbounds, b, h, yes,,, "Add energies at observation energy boundaries?" | |
| 34 | 35 | |
| 35 | 36 | # |
| 36 | 37 | # Spatial binning parameters | ... | ... |
src/support/ctool.cpp
| ... | ... | @@ -1303,6 +1303,81 @@ std::string ctool::get_obs_header(const GObservation* obs) |
| 1303 | 1303 | |
| 1304 | 1304 | |
| 1305 | 1305 | /***********************************************************************//** |
| 1306 | + * @brief Insert observation energy boundaries into list of energies | |
| 1307 | + * | |
| 1308 | + * @param[in] energies Energies. | |
| 1309 | + * @param[in] obs Observation container. | |
| 1310 | + * @return Energies. | |
| 1311 | + ***************************************************************************/ | |
| 1312 | +GEnergies ctool::insert_energy_boundaries(const GEnergies& energies, | |
| 1313 | + const GCTAObservation& obs, | |
| 1314 | + GLog* log) const | |
| 1315 | +{ | |
| 1316 | + // Create copy of input energies | |
| 1317 | + GEnergies engs = energies; | |
| 1318 | + | |
| 1319 | + // Get the energy boundaries of the event list | |
| 1320 | + GEbounds ebounds = obs.ebounds(); | |
| 1321 | + | |
| 1322 | + // Loop over all boundary energies | |
| 1323 | + for (int iebin = 0; iebin <= ebounds.size(); ++iebin) { | |
| 1324 | + | |
| 1325 | + // Get boundary energy | |
| 1326 | + GEnergy energy; | |
| 1327 | + if (iebin < ebounds.size()) { | |
| 1328 | + energy = ebounds.emin(iebin); | |
| 1329 | + } | |
| 1330 | + else { | |
| 1331 | + energy = ebounds.emax(); | |
| 1332 | + } | |
| 1333 | + | |
| 1334 | + // Get index before which the energy should be appended | |
| 1335 | + bool insert = true; | |
| 1336 | + int index = -1; | |
| 1337 | + for (int k = 0; k < engs.size(); ++k) { | |
| 1338 | + | |
| 1339 | + // If energy exists already then skip the boundary and examine the | |
| 1340 | + // next one. We consider here 1 MeV as being sufficiently close. | |
| 1341 | + if (std::abs(engs[k].MeV()-energy.MeV()) < 1.0) { | |
| 1342 | + insert = false; | |
| 1343 | + break; | |
| 1344 | + } | |
| 1345 | + | |
| 1346 | + // If energy is above the boundary energy we found the index | |
| 1347 | + if (engs[k] > energy) { | |
| 1348 | + index = k; | |
| 1349 | + break; | |
| 1350 | + } | |
| 1351 | + | |
| 1352 | + } // endfor: search index for insertion | |
| 1353 | + | |
| 1354 | + // Insert energy if requested | |
| 1355 | + if (insert) { | |
| 1356 | + | |
| 1357 | + // Insert or append energy | |
| 1358 | + if (index != -1) { | |
| 1359 | + engs.insert(index, energy); | |
| 1360 | + } | |
| 1361 | + else { | |
| 1362 | + engs.append(energy); | |
| 1363 | + } | |
| 1364 | + | |
| 1365 | + // Log energy insertion | |
| 1366 | + if (log != NULL) { | |
| 1367 | + *log << gammalib::parformat("Insert energy"); | |
| 1368 | + *log << energy.print() << std::endl; | |
| 1369 | + } | |
| 1370 | + | |
| 1371 | + } // endif: energy insertion requested | |
| 1372 | + | |
| 1373 | + } // endfor: looped over all energy boundaries | |
| 1374 | + | |
| 1375 | + // Return energies | |
| 1376 | + return engs; | |
| 1377 | +} | |
| 1378 | + | |
| 1379 | + | |
| 1380 | +/***********************************************************************//** | |
| 1306 | 1381 | * @brief Dumps help text in the console |
| 1307 | 1382 | ***************************************************************************/ |
| 1308 | 1383 | void ctool::provide_help(void) const | ... | ... |
src/support/ctool.hpp
| ... | ... | @@ -92,6 +92,9 @@ protected: |
| 92 | 92 | GSkyDir get_mean_pointing(const GObservations& obs); |
| 93 | 93 | size_t get_current_rss(void); |
| 94 | 94 | std::string get_obs_header(const GObservation* obs); |
| 95 | + GEnergies insert_energy_boundaries(const GEnergies& energies, | |
| 96 | + const GCTAObservation& obs, | |
| 97 | + GLog* log = NULL) const; | |
| 95 | 98 | |
| 96 | 99 | // Protected members |
| 97 | 100 | bool m_read_ahead; //!< Read ahead output parameters | ... | ... |