Commit 0eeff30e13dc9647d62bcb69d3e84fdca8b936fe
Merge branch 'devel' into pull-request-1982-add-phase-info-ctphase
# Conflicts: # src/Makefile.am
Showing
73 changed files
with
2785 additions
and
1366 deletions
.gitignore
AUTHORS
| ... | ... | @@ -2,6 +2,7 @@ Johan Bregeon (johan.bregeon@lupm.in2p3.fr) |
| 2 | 2 | Rolf Buehler (rolf.buehler@desy.de) |
| 3 | 3 | Jean-Baptiste Cayrou (cayrou@etud.insa-toulouse.fr) |
| 4 | 4 | Christoph Deil (Christoph.Deil@mpi-hd.mpg.de) |
| 5 | +Leonardo Di Venere (leonardo.divenere@ba.infn.it) | |
| 5 | 6 | Florent Forest (florent.forest@isae.fr) |
| 6 | 7 | Lucie Gerard (lgerard@wgs18.zeuthen.desy.de) |
| 7 | 8 | Maria Haupt (maria.haupt@desy.de) | ... | ... |
ChangeLog
| 1 | -2017-04-05 | |
| 1 | +2017-04-11 | |
| 2 | 2 | |
| 3 | 3 | * Version 1.3.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | + Add ctprob tool (#1991) | |
| 7 | + ctlike stores covariance matrix in either CSV or FITS format (#1863) | |
| 8 | + Use correct ROOT histograms in csroot2caldb | |
| 9 | + Implement regression scheme in cssens and remove num_avg parameter (#1989) | |
| 10 | + Implement Gaussian error propagation in ctbutterfly (#1862) | |
| 6 | 11 | Copy cscripts into bin directory instead of creating a symbolic links (#1987) |
| 7 | 12 | If code originates from Git, always compile the Python bindings (#1985) |
| 8 | 13 | Raise exception instead of exiting with return code in Python tests (#1983) | ... | ... |
NEWS
| 1 | 1 | New Features and Important Changes in ctools 1.3.0.dev1 |
| 2 | 2 | |
| 3 | -5 April 2017 | |
| 3 | +11 April 2017 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | Introduction |
| ... | ... | @@ -57,7 +57,10 @@ None |
| 57 | 57 | |
| 58 | 58 | ctlike - Maximum likelihood fitting |
| 59 | 59 | ----------------------------------- |
| 60 | -None | |
| 60 | +The tool now stores the covariance matrix in either FITS or CSV format, | |
| 61 | +depending on the file type specified in the file name. For file names | |
| 62 | +terminating with ".fits" or ".fit" a FITS file will be written, otherwise | |
| 63 | +a CSV file will be written (#1863). | |
| 61 | 64 | |
| 62 | 65 | |
| 63 | 66 | cttsmap - Generation of Test Statistic map |
| ... | ... | @@ -113,7 +116,11 @@ None |
| 113 | 116 | |
| 114 | 117 | ctbutterfly - Generate butterfly diagrams |
| 115 | 118 | ----------------------------------------- |
| 116 | -None | |
| 119 | +The tool now uses Gaussian error propagation as the standard method for the | |
| 120 | +computation of the butterfly diagram. The envelope method that existed before | |
| 121 | +is still available for power law spectral models as an option. The "method" | |
| 122 | +parameter has been added to allow the selection of the computation method | |
| 123 | +(#1862). | |
| 117 | 124 | |
| 118 | 125 | |
| 119 | 126 | ctulimit - Compute upper limit |
| ... | ... | @@ -126,6 +133,15 @@ cterror - Likelihood profile error computation |
| 126 | 133 | None |
| 127 | 134 | |
| 128 | 135 | |
| 136 | +ctprob - Event probability computation | |
| 137 | +-------------------------------------- | |
| 138 | +The ctprob tool has been added that computates for each event the probability | |
| 139 | +that the event originates from a given model component. The tool takes on input | |
| 140 | +either an event list or an observation definition XML file. It appends to each | |
| 141 | +event list a column for each model component that will contain the probability | |
| 142 | +that the event originates from that component (#1991). | |
| 143 | + | |
| 144 | + | |
| 129 | 145 | cscripts |
| 130 | 146 | -------- |
| 131 | 147 | The csebins script has been added that generates an energy boundaries |
| ... | ... | @@ -133,6 +149,15 @@ extension that can be used for a stacked analysis. The energy boundaries |
| 133 | 149 | are set as function of the variation in the effective area and background |
| 134 | 150 | rates of the Instrument Response Function (#1976). |
| 135 | 151 | |
| 152 | +A regression scheme now replaces the averaging scheme in cssens as this | |
| 153 | +allows more accurately the prediction of the flux value at the threshold | |
| 154 | +Test Statistic. The num_avg parameter has been removed (#1989). | |
| 155 | + | |
| 156 | +The names of some ROOT histograms has been changed in the Monte Carlo data | |
| 157 | +and the "EffectiveAreaEtrue_offaxis" needed to be changed to | |
| 158 | +"EffectiveAreaEtrueNoTheta2cut_offaxis" and "EffectiveAreaEtrue" to | |
| 159 | +"EffectiveAreaEtrueNoTheta2cut" in csroot2caldb. | |
| 160 | + | |
| 136 | 161 | |
| 137 | 162 | Examples |
| 138 | 163 | -------- | ... | ... |
cscripts/csroot2caldb.py
| ... | ... | @@ -536,7 +536,8 @@ class csroot2caldb(ctools.cscript): |
| 536 | 536 | Translate ROOT to CALDB effective area extension |
| 537 | 537 | |
| 538 | 538 | The following ROOT histograms are used: |
| 539 | - - EffectiveAreaEtrue_offaxis -> EFFAREA | |
| 539 | + - EffectiveAreaEtrueNoTheta2cut_offaxis -> EFFAREA | |
| 540 | + - EffectiveAreaEtrueNoTheta2cut (for normalization) | |
| 540 | 541 | |
| 541 | 542 | Parameters |
| 542 | 543 | ---------- |
| ... | ... | @@ -551,13 +552,13 @@ class csroot2caldb(ctools.cscript): |
| 551 | 552 | self._log_header1(gammalib.TERSE, 'Generate effective area extension') |
| 552 | 553 | |
| 553 | 554 | # Get relevant ROOT histograms |
| 554 | - etrue = tfile.Get('EffectiveAreaEtrue_offaxis') | |
| 555 | + etrue = tfile.Get('EffectiveAreaEtrueNoTheta2cut_offaxis') | |
| 555 | 556 | |
| 556 | 557 | # If requested then normalize the 2D histogram on the on-axis 1D |
| 557 | 558 | # histogram. This assures that the 2D histogram has the same on-axis |
| 558 | 559 | # effective area dependence as the 1D histogram. |
| 559 | 560 | if self['norm1d'].boolean(): |
| 560 | - etrue_1D = tfile.Get('EffectiveAreaEtrue') | |
| 561 | + etrue_1D = tfile.Get('EffectiveAreaEtrueNoTheta2cut') | |
| 561 | 562 | self._renorm_onaxis(etrue, etrue_1D) |
| 562 | 563 | |
| 563 | 564 | # If requested then rebin the effective area Etrue histogram. This | ... | ... |
cscripts/cssens.par
| ... | ... | @@ -20,7 +20,7 @@ inobs, f, h, NONE,,, "Input event list, counts cube, or observation definition |
| 20 | 20 | inmodel, f, a, $CTOOLS/share/models/crab.xml,,, "Input model definition XML file" |
| 21 | 21 | srcname, s, a, Crab,,, "Source name" |
| 22 | 22 | caldb, s, a, prod2,,, "Calibration database" |
| 23 | -irf, s, a, South_0.5h,,, "Instrument response function" | |
| 23 | +irf, s, a, South_50h,,, "Instrument response function" | |
| 24 | 24 | edisp, b, h, no,,, "Apply energy dispersion?" |
| 25 | 25 | deadc, r, h, 0.98,0,1, "Deadtime correction factor" |
| 26 | 26 | outfile, f, h, sensitivity.dat,,, "Output sensitivity ASCII file" |
| ... | ... | @@ -31,16 +31,15 @@ outfile, f, h, sensitivity.dat,,, "Output sensitivity ASCII file" |
| 31 | 31 | offset, r, h, 0.0,,, "Source offset angle (deg)" |
| 32 | 32 | duration, r, a, 180000.0,,, "Effective exposure time (s)" |
| 33 | 33 | rad, r, a, 5.0,,, "Radius of ROI (deg)" |
| 34 | -emin, r, a, 0.020,,, "Lower energy limit (TeV)" | |
| 35 | -emax, r, a, 200.0,,, "Upper energy limit (TeV)" | |
| 36 | -bins, i, a, 21,,, "Number of energy bins for differential sensitivity computation" | |
| 34 | +emin, r, a, 0.03163,,, "Lower energy limit (TeV)" | |
| 35 | +emax, r, a, 125.8925,,, "Upper energy limit (TeV)" | |
| 36 | +bins, i, a, 18,,, "Number of energy bins for differential sensitivity computation" | |
| 37 | 37 | enumbins, i, h, 0,,, "Number of energy bins for binned analysis (0=unbinned)" |
| 38 | 38 | npix, i, h, 200,,, "Number of pixels for binned analysis" |
| 39 | 39 | binsz, r, h, 0.05,,, "Pixel size for binned analysis (deg/pixel)" |
| 40 | 40 | type, s, h, Differential,Differential|Integral,, "Sensitivity type" |
| 41 | 41 | sigma, r, h, 5.0,,, "Significance threshold (Gaussian sigma)" |
| 42 | 42 | max_iter, i, h, 50,,, "Maximum number of iterations" |
| 43 | -num_avg, i, h, 3,,, "Number of iterations for sliding average" | |
| 44 | 43 | |
| 45 | 44 | # |
| 46 | 45 | # Standard parameters |
| ... | ... | @@ -49,6 +48,6 @@ chatter, i, h, 2,0,4, "Chattiness of output" |
| 49 | 48 | clobber, b, h, yes,,, "Overwrite existing output files with new output files?" |
| 50 | 49 | debug, b, h, no,,, "Debugging mode activated" |
| 51 | 50 | mode, s, h, ql,,, "Mode of automatic parameters" |
| 52 | -logfile, f, h, cspull.log,,, "Log filename" | |
| 51 | +logfile, f, h, cssens.log,,, "Log filename" | |
| 53 | 52 | |
| 54 | 53 | ... | ... |
cscripts/cssens.py
| 1 | 1 | #! /usr/bin/env python |
| 2 | 2 | # ========================================================================== |
| 3 | -# Computes the array sensitivity using a test source | |
| 3 | +# Computes the array sensitivity using the Test Statistic for a test source | |
| 4 | 4 | # |
| 5 | -# Copyright (C) 2011-2016 Juergen Knoedlseder | |
| 5 | +# Copyright (C) 2011-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 |
| ... | ... | @@ -40,7 +40,7 @@ class cssens(ctools.cscript): |
| 40 | 40 | and the flux level is determined that leads to a particular significance. |
| 41 | 41 | |
| 42 | 42 | The significance is determined using the Test Statistic, defined as twice |
| 43 | - the likelihood difference between fitting with and without the test source. | |
| 43 | + the likelihood difference between fitting with and without the test source. | |
| 44 | 44 | """ |
| 45 | 45 | |
| 46 | 46 | # Constructor |
| ... | ... | @@ -50,31 +50,20 @@ class cssens(ctools.cscript): |
| 50 | 50 | """ |
| 51 | 51 | # Set name |
| 52 | 52 | self._name = 'cssens' |
| 53 | - self._version = '1.2.0' | |
| 53 | + self._version = '1.3.0' | |
| 54 | 54 | |
| 55 | 55 | # Initialise class members |
| 56 | - self._obs = gammalib.GObservations() | |
| 57 | 56 | self._ebounds = gammalib.GEbounds() |
| 58 | 57 | self._obs_ebounds = [] |
| 59 | 58 | self._srcname = '' |
| 60 | - self._outfile = gammalib.GFilename() | |
| 61 | 59 | self._ra = None |
| 62 | 60 | self._dec = None |
| 63 | - self._edisp = False | |
| 64 | - self._emin = 0.020 | |
| 65 | - self._emax = 200.0 | |
| 66 | - self._bins = 21 | |
| 67 | - self._enumbins = 0 | |
| 68 | - self._npix = 200 | |
| 69 | - self._binsz = 0.05 | |
| 70 | - self._type = 'Differential' | |
| 71 | - self._ts_thres = 25.0 | |
| 72 | - self._max_iter = 50 | |
| 73 | - self._num_avg = 3 | |
| 74 | 61 | self._log_clients = False |
| 75 | - | |
| 76 | - # Initialise application by calling the appropriate base class | |
| 77 | - # constructor | |
| 62 | + | |
| 63 | + # Initialise observation container from constructor arguments | |
| 64 | + self._obs, argv = self._set_input_obs(argv) | |
| 65 | + | |
| 66 | + # Initialise application by calling the appropriate class constructor | |
| 78 | 67 | self._init_cscript(argv) |
| 79 | 68 | |
| 80 | 69 | # Return |
| ... | ... | @@ -87,8 +76,8 @@ class cssens(ctools.cscript): |
| 87 | 76 | Get user parameters from parfile |
| 88 | 77 | """ |
| 89 | 78 | # Set observation if not done before |
| 90 | - if self._obs == None or self._obs.size() == 0: | |
| 91 | - self._obs = self._set_obs() | |
| 79 | + if self._obs.size() == 0: | |
| 80 | + self._obs = self._set_obs(self['emin'].real(), self['emax'].real()) | |
| 92 | 81 | |
| 93 | 82 | # Set models if we have none |
| 94 | 83 | if self._obs.models().size() == 0: |
| ... | ... | @@ -98,31 +87,28 @@ class cssens(ctools.cscript): |
| 98 | 87 | self._srcname = self['srcname'].string() |
| 99 | 88 | |
| 100 | 89 | # Read further parameters |
| 101 | - self._outfile = self['outfile'].filename() | |
| 102 | - self._emin = self['emin'].real() | |
| 103 | - self._emax = self['emax'].real() | |
| 104 | - self._bins = self['bins'].integer() | |
| 105 | - | |
| 106 | - # Read parameters for binned if requested | |
| 107 | - self._enumbins = self['enumbins'].integer() | |
| 108 | - if not self._enumbins == 0: | |
| 109 | - self._npix = self['npix'].integer() | |
| 110 | - self._binsz = self['binsz'].real() | |
| 111 | - | |
| 112 | - # Read remaining parameters | |
| 113 | - self._edisp = self['edisp'].boolean() | |
| 114 | - self._ts_thres = self['sigma'].real() * self['sigma'].real() | |
| 115 | - self._max_iter = self['max_iter'].integer() | |
| 116 | - self._num_avg = self['num_avg'].integer() | |
| 117 | - self._type = self['type'].string() | |
| 118 | - | |
| 119 | - # Query remaining parameters | |
| 90 | + emin = self['emin'].real() | |
| 91 | + emax = self['emax'].real() | |
| 92 | + bins = self['bins'].integer() | |
| 93 | + | |
| 94 | + # Query parameters for binned if requested | |
| 95 | + enumbins = self['enumbins'].integer() | |
| 96 | + if not enumbins == 0: | |
| 97 | + self['npix'].integer() | |
| 98 | + self['binsz'].real() | |
| 99 | + | |
| 100 | + # Query input parameters | |
| 101 | + self['sigma'].real() | |
| 102 | + self['max_iter'].integer() | |
| 103 | + self['type'].string() | |
| 104 | + self['outfile'].filename() | |
| 105 | + self['edisp'].boolean() | |
| 120 | 106 | self['debug'].boolean() |
| 121 | 107 | |
| 122 | 108 | # Derive some parameters |
| 123 | - self._ebounds = gammalib.GEbounds(self._bins, | |
| 124 | - gammalib.GEnergy(self._emin, 'TeV'), | |
| 125 | - gammalib.GEnergy(self._emax, 'TeV')) | |
| 109 | + self._ebounds = gammalib.GEbounds(bins, | |
| 110 | + gammalib.GEnergy(emin, 'TeV'), | |
| 111 | + gammalib.GEnergy(emax, 'TeV')) | |
| 126 | 112 | |
| 127 | 113 | # Write input parameters into logger |
| 128 | 114 | self._log_parameters(gammalib.TERSE) |
| ... | ... | @@ -130,20 +116,20 @@ class cssens(ctools.cscript): |
| 130 | 116 | # Return |
| 131 | 117 | return |
| 132 | 118 | |
| 133 | - def _set_obs(self, lpnt=0.0, bpnt=0.0, emin=0.1, emax=100.0): | |
| 119 | + def _set_obs(self, emin, emax, lpnt=0.0, bpnt=0.0): | |
| 134 | 120 | """ |
| 135 | 121 | Set an observation container |
| 136 | 122 | |
| 137 | 123 | Parameters |
| 138 | 124 | ---------- |
| 125 | + emin : float | |
| 126 | + Minimum energy (TeV) | |
| 127 | + emax : float | |
| 128 | + Maximum energy (TeV) | |
| 139 | 129 | lpnt : float, optional |
| 140 | 130 | Galactic longitude of pointing (deg) |
| 141 | 131 | bpnt : float, optional |
| 142 | 132 | Galactic latitude of pointing (deg) |
| 143 | - emin : float, optional | |
| 144 | - Minimum energy (TeV) | |
| 145 | - emax : float, optional | |
| 146 | - Maximum energy (TeV) | |
| 147 | 133 | |
| 148 | 134 | Returns |
| 149 | 135 | ------- |
| ... | ... | @@ -205,23 +191,23 @@ class cssens(ctools.cscript): |
| 205 | 191 | |
| 206 | 192 | # Get energy boundaries of the observation |
| 207 | 193 | obs_ebounds = self._obs_ebounds[i] |
| 208 | - | |
| 194 | + | |
| 209 | 195 | # Get minimum and maximum energy of the observation |
| 210 | 196 | obs_emin = obs_ebounds.emin() |
| 211 | 197 | obs_emax = obs_ebounds.emax() |
| 212 | - | |
| 198 | + | |
| 213 | 199 | # If [emin,emax] is fully contained in the observation energy range |
| 214 | 200 | # the use [emin,emax] as energy boundaries |
| 215 | 201 | if obs_emin <= emin and obs_emax >= emax: |
| 216 | 202 | ebounds = gammalib.GEbounds(emin, emax) |
| 217 | - | |
| 203 | + | |
| 218 | 204 | # ... otherwise, if [emin,emax] is completely outside the |
| 219 | 205 | # observation energy range then set the energy boundaries to the |
| 220 | 206 | # zero-width interval [0,0] |
| 221 | 207 | elif emax < obs_emin or emin > obs_emax: |
| 222 | 208 | e0 = gammalib.GEnergy(0.0, 'TeV') |
| 223 | 209 | ebounds = gammalib.GEbounds(e0, e0) |
| 224 | - | |
| 210 | + | |
| 225 | 211 | # ... otherwise, if [emin,emax] overlaps partially with the |
| 226 | 212 | # observation energy range then set the energy boundaries to the |
| 227 | 213 | # overlapping part |
| ... | ... | @@ -229,10 +215,10 @@ class cssens(ctools.cscript): |
| 229 | 215 | # Set overlapping energy range |
| 230 | 216 | set_emin = max(emin, obs_emin) |
| 231 | 217 | set_emax = min(emax, obs_emax) |
| 232 | - | |
| 218 | + | |
| 233 | 219 | # Set energy boundaries |
| 234 | 220 | ebounds = gammalib.GEbounds(set_emin, set_emax) |
| 235 | - | |
| 221 | + | |
| 236 | 222 | # Set the energy boundaries as the boundaries of the observation |
| 237 | 223 | obs.events().ebounds(ebounds) |
| 238 | 224 | |
| ... | ... | @@ -286,13 +272,27 @@ class cssens(ctools.cscript): |
| 286 | 272 | # Set TeV->erg conversion factor |
| 287 | 273 | tev2erg = 1.6021764 |
| 288 | 274 | |
| 275 | + # Set parameters | |
| 276 | + ts_thres = self['sigma'].real() * self['sigma'].real() | |
| 277 | + max_iter = self['max_iter'].integer() | |
| 278 | + enumbins = self['enumbins'].integer() | |
| 279 | + if not enumbins == 0: | |
| 280 | + npix = self['npix'].integer() | |
| 281 | + binsz = self['binsz'].real() | |
| 282 | + else: | |
| 283 | + npix = 200 | |
| 284 | + binsz = 0.05 | |
| 285 | + | |
| 286 | + # Set flux ratio precision required for convergence to 5% | |
| 287 | + ratio_precision = 0.05 | |
| 288 | + | |
| 289 | 289 | # Set energy boundaries |
| 290 | 290 | self._set_obs_ebounds(emin, emax) |
| 291 | 291 | |
| 292 | - # Determine energy boundaries from first observation in the container | |
| 293 | - loge = math.log10(math.sqrt(emin.TeV()*emax.TeV())) | |
| 294 | - e_mean = math.pow(10.0, loge) | |
| 295 | - erg_mean = e_mean * tev2erg | |
| 292 | + # Determine mean energy for energy boundary | |
| 293 | + e_mean = math.sqrt(emin.TeV()*emax.TeV()) | |
| 294 | + loge = math.log10(e_mean) | |
| 295 | + erg_mean = e_mean * tev2erg | |
| 296 | 296 | |
| 297 | 297 | # Compute Crab unit. This is the factor with which the Prefactor needs |
| 298 | 298 | # to be multiplied to get 1 Crab. |
| ... | ... | @@ -300,20 +300,27 @@ class cssens(ctools.cscript): |
| 300 | 300 | src_flux = test_model[self._srcname].spectral().flux(emin, emax) |
| 301 | 301 | crab_unit = crab_flux/src_flux |
| 302 | 302 | |
| 303 | - # Write header and some introductory information into logger | |
| 303 | + # Initialise regression coefficient | |
| 304 | + regcoeff = 0.0 | |
| 305 | + | |
| 306 | + # Write header for energy bin | |
| 307 | + self._log_string(gammalib.TERSE, '') | |
| 304 | 308 | self._log_header2(gammalib.TERSE, 'Energies: '+str(emin)+' - '+str(emax)) |
| 309 | + | |
| 310 | + # Write initial parameters | |
| 311 | + self._log_header3(gammalib.TERSE, 'Initial parameters') | |
| 305 | 312 | self._log_value(gammalib.TERSE, 'Crab flux', str(crab_flux)+' ph/cm2/s') |
| 306 | - self._log_value(gammalib.TERSE, 'Source model flux', str(src_flux)+ | |
| 307 | - ' ph/cm2/s') | |
| 313 | + self._log_value(gammalib.TERSE, 'Source model flux', str(src_flux)+' ph/cm2/s') | |
| 308 | 314 | self._log_value(gammalib.TERSE, 'Crab unit factor', crab_unit) |
| 309 | 315 | |
| 310 | 316 | # Initialise loop |
| 311 | - crab_flux_value = [] | |
| 312 | - photon_flux_value = [] | |
| 313 | - energy_flux_value = [] | |
| 314 | - sensitivity_value = [] | |
| 315 | - iterations = 0 | |
| 316 | - test_crab_flux = 0.1 # Initial test flux in Crab units (100 mCrab) | |
| 317 | + results = [] | |
| 318 | + iterations = 0 | |
| 319 | + test_crab_flux = 0.1 # Initial test flux in Crab units (100 mCrab) | |
| 320 | + | |
| 321 | + # Write header for iterations for terse chatter level | |
| 322 | + if self._logTerse(): | |
| 323 | + self._log_header3(gammalib.TERSE, 'Iterations') | |
| 317 | 324 | |
| 318 | 325 | # Loop until we break |
| 319 | 326 | while True: |
| ... | ... | @@ -335,11 +342,11 @@ class cssens(ctools.cscript): |
| 335 | 342 | |
| 336 | 343 | # Simulate events for the models. "sim" holds an observation |
| 337 | 344 | # container with observations containing the simulated events. |
| 338 | - sim = obsutils.sim(self._obs, nbins=self._enumbins, seed=iterations, | |
| 339 | - binsz=self._binsz, npix=self._npix, | |
| 345 | + sim = obsutils.sim(self._obs, nbins=enumbins, seed=iterations, | |
| 346 | + binsz=binsz, npix=npix, | |
| 340 | 347 | log=self._log_clients, |
| 341 | 348 | debug=self['debug'].boolean(), |
| 342 | - edisp=self._edisp) | |
| 349 | + edisp=self['edisp'].boolean()) | |
| 343 | 350 | |
| 344 | 351 | # Determine number of events in simulation by summing the events |
| 345 | 352 | # over all observations in the observation container |
| ... | ... | @@ -354,7 +361,7 @@ class cssens(ctools.cscript): |
| 354 | 361 | # Fit test source to the simulated events in the observation |
| 355 | 362 | # container |
| 356 | 363 | fit = ctools.ctlike(sim) |
| 357 | - fit['edisp'] = edisp=self._edisp | |
| 364 | + fit['edisp'] = self['edisp'].boolean() | |
| 358 | 365 | fit['debug'] = self['debug'].boolean() |
| 359 | 366 | fit['chatter'] = self['chatter'].integer() |
| 360 | 367 | fit.run() |
| ... | ... | @@ -383,29 +390,24 @@ class cssens(ctools.cscript): |
| 383 | 390 | # Assess quality based on a comparison between Npred and Nevents |
| 384 | 391 | quality = npred - nevents |
| 385 | 392 | |
| 386 | - # Write test source fit results into logger | |
| 387 | - self._log_header3(gammalib.EXPLICIT, 'Test source model fit') | |
| 388 | - self._log_value(gammalib.EXPLICIT, 'Test statistics', ts) | |
| 389 | - self._log_value(gammalib.EXPLICIT, 'log likelihood', logL) | |
| 390 | - self._log_value(gammalib.EXPLICIT, 'Number of predicted events', quality) | |
| 391 | - self._log_value(gammalib.EXPLICIT, 'Fit quality', npred) | |
| 392 | - for model in models: | |
| 393 | - self._log_value(gammalib.EXPLICIT, 'Model', model.name()) | |
| 394 | - for par in model: | |
| 395 | - self._log_string(gammalib.EXPLICIT, str(par)) | |
| 396 | - | |
| 397 | - # If TS was non-positive then increase the test flux and start | |
| 398 | - # over | |
| 393 | + # Write fit results into logger | |
| 394 | + name = 'Iteration %d' % iterations | |
| 395 | + value = ('TS=%10.4f Sim=%9.4f mCrab Fit=%9.4f mCrab ' | |
| 396 | + 'Sens=%e erg/cm2/s' % | |
| 397 | + (ts, test_crab_flux*1000.0, crab_flux*1000.0, sensitivity)) | |
| 398 | + self._log_value(gammalib.TERSE, name, value) | |
| 399 | + | |
| 400 | + # If TS was non-positive then increase the test flux and start over | |
| 399 | 401 | if ts <= 0.0: |
| 400 | 402 | |
| 401 | 403 | # If the number of iterations was exceeded then stop |
| 402 | - if (iterations >= self._max_iter): | |
| 404 | + if (iterations >= max_iter): | |
| 403 | 405 | self._log_string(gammalib.TERSE, |
| 404 | - ' Test ended after %d iterations.' % self._max_iter) | |
| 406 | + ' Test ended after %d iterations.' % max_iter) | |
| 405 | 407 | break |
| 406 | 408 | |
| 407 | - # Increase test flux by a factor of 2 | |
| 408 | - test_crab_flux = test_crab_flux * 2.0 | |
| 409 | + # Increase test flux | |
| 410 | + test_crab_flux *= 3.0 | |
| 409 | 411 | |
| 410 | 412 | # Signal start we start over |
| 411 | 413 | self._log_string(gammalib.EXPLICIT, |
| ... | ... | @@ -414,95 +416,64 @@ class cssens(ctools.cscript): |
| 414 | 416 | # ... and start over |
| 415 | 417 | continue |
| 416 | 418 | |
| 417 | - # Compute flux correction factor based on average TS. We | |
| 418 | - # assume here that the significance is proportional to the source | |
| 419 | - # flux, and that the significance scales as the square root of | |
| 420 | - # the Test Statistic | |
| 421 | - correct = math.sqrt(self._ts_thres/ts) | |
| 419 | + # Append result entry to result list | |
| 420 | + result = {'ts': ts, 'crab_flux': crab_flux, | |
| 421 | + 'photon_flux': photon_flux, | |
| 422 | + 'energy_flux': energy_flux} | |
| 423 | + results.append(result) | |
| 424 | + | |
| 425 | + # Predict Crab flux at threshold TS using a linear regression of | |
| 426 | + # the log(TS) and log(crab_flux) values that have so far been | |
| 427 | + # computed. If not enough results are available than use a simple | |
| 428 | + # TS scaling relation. | |
| 429 | + if len(results) > 1: | |
| 430 | + pred_crab_flux, regcoeff = self._predict_flux(results, ts_thres) | |
| 431 | + correct = pred_crab_flux / crab_flux | |
| 432 | + else: | |
| 433 | + correct = math.sqrt(ts_thres/ts) | |
| 422 | 434 | |
| 423 | 435 | # Compute extrapolated fluxes based on the flux correction factor |
| 424 | 436 | crab_flux = correct * crab_flux |
| 425 | 437 | photon_flux = correct * photon_flux |
| 426 | 438 | energy_flux = correct * energy_flux |
| 427 | 439 | sensitivity = correct * sensitivity |
| 428 | - crab_flux_value.append(crab_flux) | |
| 429 | - photon_flux_value.append(photon_flux) | |
| 430 | - energy_flux_value.append(energy_flux) | |
| 431 | - sensitivity_value.append(sensitivity) | |
| 432 | - | |
| 433 | - # Write fit results | |
| 434 | - if self._logExplicit(): | |
| 435 | - self._log_value(gammalib.EXPLICIT, 'Photon flux', | |
| 436 | - str(photon_flux)+' ph/cm2/s') | |
| 437 | - self._log_value(gammalib.EXPLICIT, 'Energy flux', | |
| 438 | - str(energy_flux)+' erg/cm2/s') | |
| 439 | - self._log_value(gammalib.EXPLICIT, 'Crab flux', | |
| 440 | - str(crab_flux*1000.0)+' mCrab') | |
| 441 | - self._log_value(gammalib.EXPLICIT, 'Differential sensitivity', | |
| 442 | - str(sensitivity)+' erg/cm2/s') | |
| 443 | - for model in models: | |
| 444 | - self._log_value(gammalib.EXPLICIT, 'Model', model.name()) | |
| 445 | - for par in model: | |
| 446 | - self._log_string(gammalib.EXPLICIT, str(par)) | |
| 447 | - elif self._logTerse(): | |
| 448 | - name = 'Iteration %d' % iterations | |
| 449 | - value = ('TS=%.4f corr=%e %e ph/cm2/s = %e erg/cm2/s = %.2f ' | |
| 450 | - 'mCrab = %e erg/cm2/s' % (ts, correct, photon_flux, | |
| 451 | - energy_flux, crab_flux*1000.0, sensitivity)) | |
| 452 | - self._log_value(gammalib.TERSE, name, value) | |
| 453 | - | |
| 454 | - # Compute sliding average of extrapolated fitted prefactor, | |
| 455 | - # photon and energy flux. This damps out fluctuations and | |
| 456 | - # improves convergence. | |
| 457 | - crab_flux = 0.0 | |
| 458 | - photon_flux = 0.0 | |
| 459 | - energy_flux = 0.0 | |
| 460 | - sensitivity = 0.0 | |
| 461 | - num = 0.0 | |
| 462 | - for k in range(self._num_avg): | |
| 463 | - inx = len(crab_flux_value) - k - 1 | |
| 464 | - if inx >= 0: | |
| 465 | - crab_flux += crab_flux_value[inx] | |
| 466 | - photon_flux += photon_flux_value[inx] | |
| 467 | - energy_flux += energy_flux_value[inx] | |
| 468 | - sensitivity += sensitivity_value[inx] | |
| 469 | - num += 1.0 | |
| 470 | - crab_flux /= num | |
| 471 | - photon_flux /= num | |
| 472 | - energy_flux /= num | |
| 473 | - sensitivity /= num | |
| 474 | - | |
| 475 | - # Compare average flux to last average | |
| 476 | - if iterations > self._num_avg: | |
| 440 | + | |
| 441 | + # If we have at least 3 results then check if the flux determination | |
| 442 | + # at the TS threshold has converged | |
| 443 | + if len(results) > 3: | |
| 477 | 444 | if test_crab_flux > 0: |
| 445 | + | |
| 446 | + # Compute fractional change in the Crab flux between two | |
| 447 | + # iterations | |
| 478 | 448 | ratio = crab_flux/test_crab_flux |
| 479 | 449 | |
| 480 | - # We have 2 convergence criteria: | |
| 481 | - # 1. The average flux does not change | |
| 482 | - # 2. The flux correction factor is small | |
| 483 | - if ratio >= 0.99 and ratio <= 1.01 and \ | |
| 484 | - correct >= 0.9 and correct <= 1.1: | |
| 485 | - if self._logTerse(): | |
| 486 | - self._log(' Converged ('+str(ratio)+')\n') | |
| 450 | + # If fractional change is smaller than the required position | |
| 451 | + # the iterations are stopped | |
| 452 | + if ratio > 1.0-ratio_precision and \ | |
| 453 | + ratio < 1.0+ratio_precision: | |
| 454 | + value = ('TS=%10.4f Sim=%9.4f mCrab ' | |
| 455 | + ' Sens=%e erg/cm2/s' % | |
| 456 | + (ts, crab_flux*1000.0, sensitivity)) | |
| 457 | + self._log_value(gammalib.TERSE, 'Converged result', value) | |
| 458 | + self._log_value(gammalib.TERSE, 'Converged flux ratio', ratio) | |
| 459 | + self._log_value(gammalib.TERSE, 'Regression coefficient', | |
| 460 | + regcoeff) | |
| 487 | 461 | break |
| 488 | 462 | else: |
| 489 | - if self._logTerse(): | |
| 490 | - self._log(' Flux is zero.\n') | |
| 463 | + self._log_value(gammalib.TERSE, 'Not converged', 'Flux is zero') | |
| 491 | 464 | break |
| 492 | 465 | |
| 493 | - # Use average for next iteration | |
| 466 | + # Set test flux for next iteration | |
| 494 | 467 | test_crab_flux = crab_flux |
| 495 | 468 | |
| 496 | 469 | # Exit loop if number of trials exhausted |
| 497 | - if (iterations >= self._max_iter): | |
| 498 | - if self._logTerse(): | |
| 499 | - self._log(' Test ended after '+str(self._max_iter)+ | |
| 500 | - ' iterations.\n') | |
| 470 | + if (iterations >= max_iter): | |
| 471 | + self._log_string(gammalib.TERSE, | |
| 472 | + ' Test ended after %d iterations.' % max_iter) | |
| 501 | 473 | break |
| 502 | 474 | |
| 503 | 475 | # Write fit results into logger |
| 504 | 476 | self._log_header3(gammalib.TERSE, 'Fit results') |
| 505 | - self._log_value(gammalib.TERSE, 'Test statistics', ts) | |
| 506 | 477 | self._log_value(gammalib.TERSE, 'Photon flux', |
| 507 | 478 | str(photon_flux)+' ph/cm2/s') |
| 508 | 479 | self._log_value(gammalib.TERSE, 'Energy flux', |
| ... | ... | @@ -523,16 +494,84 @@ class cssens(ctools.cscript): |
| 523 | 494 | # Restore energy boundaries of observation container |
| 524 | 495 | for i, obs in enumerate(self._obs): |
| 525 | 496 | obs.events().ebounds(self._obs_ebounds[i]) |
| 526 | - | |
| 497 | + | |
| 527 | 498 | # Store result |
| 528 | 499 | result = {'loge': loge, 'emin': emin.TeV(), 'emax': emax.TeV(), \ |
| 529 | 500 | 'crab_flux': crab_flux, 'photon_flux': photon_flux, \ |
| 530 | 501 | 'energy_flux': energy_flux, \ |
| 531 | - 'sensitivity': sensitivity} | |
| 502 | + 'sensitivity': sensitivity, 'regcoeff': regcoeff, \ | |
| 503 | + 'nevents': nevents, 'npred': npred} | |
| 532 | 504 | |
| 533 | 505 | # Return result |
| 534 | 506 | return result |
| 535 | 507 | |
| 508 | + def _predict_flux(self, results, ts): | |
| 509 | + """ | |
| 510 | + Predict Crab flux for a given TS value | |
| 511 | + | |
| 512 | + The Crab flux at a given Test Statistic value is predicted by doing a | |
| 513 | + linear regression of the log(TS) and log(crab_flux) values in a results | |
| 514 | + list. | |
| 515 | + | |
| 516 | + See https://en.wikipedia.org/wiki/Simple_linear_regression | |
| 517 | + | |
| 518 | + Parameters | |
| 519 | + ---------- | |
| 520 | + results : list of dict | |
| 521 | + List of results | |
| 522 | + ts : float | |
| 523 | + Test Statistic value | |
| 524 | + | |
| 525 | + Returns | |
| 526 | + ------- | |
| 527 | + crab_flux_prediction, regcoeff : tuple of float | |
| 528 | + Predicted Crab flux and regression coefficient | |
| 529 | + """ | |
| 530 | + # Compute means and regression coefficient | |
| 531 | + mean_x = 0.0 | |
| 532 | + mean_y = 0.0 | |
| 533 | + mean_xy = 0.0 | |
| 534 | + mean_xx = 0.0 | |
| 535 | + mean_yy = 0.0 | |
| 536 | + for result in results: | |
| 537 | + x = math.log(float(result['ts'])) | |
| 538 | + y = math.log(float(result['crab_flux'])) | |
| 539 | + mean_x += x | |
| 540 | + mean_y += y | |
| 541 | + mean_xy += x * y | |
| 542 | + mean_xx += x * x | |
| 543 | + mean_yy += y * y | |
| 544 | + norm = 1.0 / float(len(results)) | |
| 545 | + mean_x *= norm | |
| 546 | + mean_y *= norm | |
| 547 | + mean_xy *= norm | |
| 548 | + mean_xx *= norm | |
| 549 | + mean_yy *= norm | |
| 550 | + rxy = (mean_xy - mean_x * mean_y) / \ | |
| 551 | + math.sqrt((mean_xx - mean_x*mean_x) * | |
| 552 | + (mean_yy - mean_y*mean_y)) | |
| 553 | + regcoeff = rxy*rxy | |
| 554 | + | |
| 555 | + # Compute regression line slope | |
| 556 | + beta_nom = 0.0 | |
| 557 | + beta_denom = 0.0 | |
| 558 | + for result in results: | |
| 559 | + x = math.log(float(result['ts'])) | |
| 560 | + y = math.log(float(result['crab_flux'])) | |
| 561 | + beta_nom += (x - mean_x) * (y - mean_y) | |
| 562 | + beta_denom += (x - mean_x) * (x - mean_x) | |
| 563 | + beta = beta_nom / beta_denom | |
| 564 | + | |
| 565 | + # Compute regression line offset | |
| 566 | + alpha = mean_y - beta * mean_x | |
| 567 | + | |
| 568 | + # Predict Crab flux at TS threshold | |
| 569 | + log_ts_thres = math.log(ts) | |
| 570 | + crab_flux_prediction = math.exp(alpha + beta * log_ts_thres) | |
| 571 | + | |
| 572 | + # Return | |
| 573 | + return (crab_flux_prediction, regcoeff) | |
| 574 | + | |
| 536 | 575 | |
| 537 | 576 | # Public methods |
| 538 | 577 | def run(self): |
| ... | ... | @@ -545,15 +584,16 @@ class cssens(ctools.cscript): |
| 545 | 584 | |
| 546 | 585 | # Get parameters |
| 547 | 586 | self._get_parameters() |
| 548 | - | |
| 587 | + | |
| 549 | 588 | # Loop over observations and store a deep copy of the energy |
| 550 | 589 | # boundaries for later use |
| 551 | 590 | for obs in self._obs: |
| 552 | 591 | self._obs_ebounds.append(obs.events().ebounds().copy()) |
| 553 | - | |
| 592 | + | |
| 554 | 593 | # Initialise script |
| 555 | 594 | colnames = ['loge', 'emin', 'emax', 'crab_flux', 'photon_flux', |
| 556 | - 'energy_flux', 'sensitivity'] | |
| 595 | + 'energy_flux', 'sensitivity', 'regcoeff', 'nevents', | |
| 596 | + 'npred'] | |
| 557 | 597 | results = [] |
| 558 | 598 | |
| 559 | 599 | # Set test source model for this observation |
| ... | ... | @@ -566,30 +606,35 @@ class cssens(ctools.cscript): |
| 566 | 606 | # Write models into logger |
| 567 | 607 | self._log_models(gammalib.NORMAL, models, 'Model') |
| 568 | 608 | |
| 609 | + # Get sensitivity type | |
| 610 | + sensitivity_type = self['type'].string() | |
| 611 | + | |
| 569 | 612 | # Write header |
| 570 | 613 | self._log_header1(gammalib.TERSE, 'Sensitivity determination') |
| 571 | - self._log_value(gammalib.TERSE, 'Type', str(self._type)) | |
| 614 | + self._log_value(gammalib.TERSE, 'Type', sensitivity_type) | |
| 572 | 615 | |
| 573 | 616 | # Loop over energy bins |
| 574 | 617 | for ieng in range(self._ebounds.size()): |
| 575 | 618 | |
| 576 | 619 | # Set energies |
| 577 | - if self._type == 'Differential': | |
| 620 | + if sensitivity_type == 'Differential': | |
| 578 | 621 | emin = self._ebounds.emin(ieng) |
| 579 | 622 | emax = self._ebounds.emax(ieng) |
| 580 | - elif self._type == 'Integral': | |
| 623 | + elif sensitivity_type == 'Integral': | |
| 581 | 624 | emin = self._ebounds.emin(ieng) |
| 582 | 625 | emax = self._ebounds.emax() |
| 583 | 626 | else: |
| 584 | 627 | msg = ('Invalid sensitivity type "%s" encountered. Either ' |
| 585 | - 'specify "Differential" or "Integral".' % self._type) | |
| 628 | + 'specify "Differential" or "Integral".' % | |
| 629 | + sensitivity_type) | |
| 586 | 630 | raise RuntimeError(msg) |
| 587 | 631 | |
| 588 | 632 | # Determine sensitivity |
| 589 | 633 | result = self._get_sensitivity(emin, emax, models) |
| 590 | 634 | |
| 591 | 635 | # Write out trial result |
| 592 | - ioutils.write_csv_row(self._outfile.url(), ieng, colnames, result) | |
| 636 | + ioutils.write_csv_row(self['outfile'].filename().url(), ieng, | |
| 637 | + colnames, result) | |
| 593 | 638 | |
| 594 | 639 | # Append results |
| 595 | 640 | results.append(result) | ... | ... |
doc/source/users/reference_manual/cssens.rst
doc/source/users/reference_manual/ctbutterfly.rst
| ... | ... | @@ -3,21 +3,25 @@ |
| 3 | 3 | ctbutterfly |
| 4 | 4 | =========== |
| 5 | 5 | |
| 6 | -Computes butterfly diagram for a power law model. | |
| 6 | +Computes butterfly diagram for a given spectral model. | |
| 7 | 7 | |
| 8 | 8 | |
| 9 | 9 | Synopsis |
| 10 | 10 | -------- |
| 11 | 11 | |
| 12 | -This tool calculates a butterfly diagram for a specific source with power law | |
| 13 | -spectral model. The butterfly diagram is the envelope of all power law models | |
| 14 | -that are within a given confidence limit compatible with the data. By default | |
| 15 | -a confidence level of 68% is used, but the level can be adjusted using the | |
| 16 | -hidden ``confidence`` parameter. ctbutterfly computes this envelope by | |
| 17 | -evaluating for each energy the minimum and maximum intensity of all power law | |
| 18 | -models that fall within the error ellipse of the prefactor and index parameters. | |
| 19 | -The error ellipse is derived from the covariance matrix of a maximum likelihood | |
| 20 | -fit. | |
| 12 | +This tool calculates a butterfly diagram for a specific source according to | |
| 13 | +its spectral model. The butterfly diagram is the envelope of all spectral | |
| 14 | +models that are within a given confidence limit compatible with the data. | |
| 15 | +The default method used for the calculation is Gaussian error propagation | |
| 16 | +using the covariance matrix from a maximum likelihood fit. By default a | |
| 17 | +confidence level of 68% is used, but the level can be adjusted using the | |
| 18 | +hidden ``confidence`` parameter. For power law models, an alternative | |
| 19 | +calculation method can be specified by setting the hidden parameter | |
| 20 | +``method=ENVELOPE``. By using this method, the envelope is computed by | |
| 21 | +evaluating for each energy the minimum and maximum intensity of all power | |
| 22 | +law models that fall within the error ellipse of the prefactor and index | |
| 23 | +parameters. The error ellipse is derived from the covariance matrix of a | |
| 24 | +maximum likelihood fit. | |
| 21 | 25 | |
| 22 | 26 | ctbutterfly assumes that the input model (parameter ``inmodel``) has been |
| 23 | 27 | adjusted using :doc:`ctlike` to the data, but if this is not the case you |
| ... | ... | @@ -68,11 +72,14 @@ General parameters |
| 68 | 72 | |
| 69 | 73 | ``outfile [file]`` |
| 70 | 74 | Output butterfly ASCII file name. |
| 71 | - | |
| 75 | + | |
| 72 | 76 | ``(fit = no) [boolean]`` |
| 73 | 77 | Performs maximum likelihood fitting of input model ignoring any provided |
| 74 | 78 | covariance matrix. |
| 75 | - | |
| 79 | + | |
| 80 | +``(method = "GAUSSIAN") <GAUSSIAN|ENVELOPE> [string]`` | |
| 81 | + Computation method. | |
| 82 | + | |
| 76 | 83 | ``(confidence = 0.68) [real]`` |
| 77 | 84 | Confidence level for error computation. |
| 78 | 85 | ... | ... |
doc/source/users/reference_manual/ctlike.rst
| ... | ... | @@ -48,13 +48,13 @@ the spatial model parameters can be kept fixed during that computation |
| 48 | 48 | ctlike generates an output model XML file that contains the values of the |
| 49 | 49 | best fitting model parameters. For all free parameters, an ``error`` attribute |
| 50 | 50 | is added that provides the statistical uncertainty in the parameter estimate. |
| 51 | -In addition, the entire output of the covariance matrix to a separate FITS file | |
| 52 | -can be queried (parameter ``outcovmat``). The parameter order given in the file | |
| 53 | -corresponds to the arrangement of the covariance matrix entries. If computation | |
| 54 | -of the Test Statistics has been requested for a model component, a ``ts`` | |
| 55 | -attribute providing the Test Statistics value is added. The output model can be | |
| 56 | -used as an input model for other ctools. | |
| 51 | +If computation of the Test Statistics has been requested for a model component, | |
| 52 | +a ``ts`` attribute providing the Test Statistics value is added. The output model | |
| 53 | +can be used as an input model for other ctools. | |
| 57 | 54 | |
| 55 | +In addition, the covariance matrix can be saved into a file by specifying a | |
| 56 | +file name for the ``outcovmat`` parameter. If the file name ends with ``.fits`` | |
| 57 | +or ``.fit`` a FITS file is written, otherwise a CSV file is written. | |
| 58 | 58 | |
| 59 | 59 | |
| 60 | 60 | General parameters |
| ... | ... | @@ -89,7 +89,7 @@ General parameters |
| 89 | 89 | the maximum likelihood fit. |
| 90 | 90 | |
| 91 | 91 | ``(outcovmat = NONE) [string]`` |
| 92 | - Output FITS file to store covariance matrix. | |
| 92 | + Output FITS or CSV file to store covariance matrix. | |
| 93 | 93 | |
| 94 | 94 | ``(stat = POISSON) [string]`` |
| 95 | 95 | Fitting statistics (POISSON or GAUSSIAN; only affects binned analysis). | ... | ... |
doc/source/users/reference_manual/ctprob.rst
0 → 100644
| 1 | +.. _ctprob: | |
| 2 | + | |
| 3 | +ctprob | |
| 4 | +======== | |
| 5 | + | |
| 6 | +Compute event probability for a given model. | |
| 7 | + | |
| 8 | + | |
| 9 | +Synopsis | |
| 10 | +-------- | |
| 11 | + | |
| 12 | +This tool takes an event list file (or an XML observation definition file) and | |
| 13 | +a model as input and computes for each event the probability that it originates | |
| 14 | +from a specific model component. The probability is computed by by evaluating | |
| 15 | +the differential event probability for a given model and normalizing these | |
| 16 | +probabilities so that the sum of the probabilities for all model components is | |
| 17 | +unity for each event. | |
| 18 | + | |
| 19 | +The tool appends for each model component a single precision column to the event | |
| 20 | +list that contains the event probabilities. The name of the column is build from | |
| 21 | +the model name prefixed with ``PROB_``. | |
| 22 | + | |
| 23 | + | |
| 24 | +General parameters | |
| 25 | +------------------ | |
| 26 | + | |
| 27 | +``inobs [file]`` | |
| 28 | + Input event list or observation definition XML file | |
| 29 | + | |
| 30 | +``outobs [file]`` | |
| 31 | + Output event list or observation definition XML file. | |
| 32 | + | |
| 33 | +``(prefix = "prob_") [string]`` | |
| 34 | + Prefix for output event lists in observation definition file. | |
| 35 | + | |
| 36 | +``inmodel [string]`` | |
| 37 | + Input model definition XML file. | |
| 38 | + | |
| 39 | +``caldb [string]`` | |
| 40 | + Calibration database. | |
| 41 | + | |
| 42 | +``irf [string]`` | |
| 43 | + Instrument response function. | |
| 44 | + | |
| 45 | +``(edisp = no) [boolean]`` | |
| 46 | + Applies energy dispersion to response computation. | |
| 47 | + | |
| 48 | + | |
| 49 | +Standard parameters | |
| 50 | +------------------- | |
| 51 | + | |
| 52 | +``(publish = no) [boolean]`` | |
| 53 | + Specifies whether the event list(s) should be published on VO Hub. | |
| 54 | + | |
| 55 | +``(chatter = 2) [integer]`` | |
| 56 | + Verbosity of the executable: | |
| 57 | + chatter = 0: no information will be logged | |
| 58 | + | |
| 59 | + chatter = 1: only errors will be logged | |
| 60 | + | |
| 61 | + chatter = 2: errors and actions will be logged | |
| 62 | + | |
| 63 | + chatter = 3: report about the task execution | |
| 64 | + | |
| 65 | + chatter = 4: detailed report about the task execution | |
| 66 | + | |
| 67 | +``(clobber = yes) [boolean]`` | |
| 68 | + Specifies whether existing output files should be overwritten. | |
| 69 | + | |
| 70 | +``(debug = no) [boolean]`` | |
| 71 | + Enables debug mode. In debug mode the executable will dump any log file output to the console. | |
| 72 | + | |
| 73 | +``(mode = ql) [string]`` | |
| 74 | + Mode of automatic parameters (default is "ql", i.e. "query and learn"). | |
| 75 | + | |
| 76 | +``(logfile = ctprob.log) [string]`` | |
| 77 | + Name of log file. | |
| 78 | + | |
| 79 | + | |
| 80 | +Related tools or scripts | |
| 81 | +------------------------ | |
| 82 | + | |
| 83 | +:doc:`ctphase` | |
| 84 | +:doc:`csphasecrv` | |
| 85 | + | ... | ... |
doc/source/users/reference_manual/index.rst
| ... | ... | @@ -27,6 +27,7 @@ ctools |
| 27 | 27 | ctmodel --- Computes model counts cube <ctmodel> |
| 28 | 28 | ctobssim --- Simulate observations <ctobssim> |
| 29 | 29 | ctpsfcube --- Generates point spread function cube <ctpsfcube> |
| 30 | + ctprob --- Computes event probability for a given model <ctprob> | |
| 30 | 31 | ctselect --- Selects event data <ctselect> |
| 31 | 32 | ctskymap --- Generates sky map <ctskymap> |
| 32 | 33 | cttsmap --- Generates Test Statistic map <cttsmap> | ... | ... |
pyext/Makefile.am
| ... | ... | @@ -59,6 +59,7 @@ testscripts = ctools/tests/__init__.py \ |
| 59 | 59 | $(top_srcdir)/test/test_ctbutterfly.py \ |
| 60 | 60 | $(top_srcdir)/test/test_ctulimit.py \ |
| 61 | 61 | $(top_srcdir)/test/test_cterror.py \ |
| 62 | + $(top_srcdir)/test/test_ctprob.py \ | |
| 62 | 63 | $(top_srcdir)/test/test_pipelines.py |
| 63 | 64 | |
| 64 | 65 | # Test data to be distributed in $(pyexecdir)/ctools/tests/data | ... | ... |
pyext/ctool.i
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctool - ctool base class * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2014-2016 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2014-2017 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -105,6 +105,8 @@ public: |
| 105 | 105 | %rename(_insert_energy_boundaries) insert_energy_boundaries; |
| 106 | 106 | %rename(_cube_layer_usage) cube_layer_usage; |
| 107 | 107 | %rename(_is_valid_filename) is_valid_filename; |
| 108 | + %rename(_get_gtiname) get_gtiname; | |
| 109 | + %rename(_save_event_list) save_event_list; | |
| 108 | 110 | %rename(_warn_too_few_energies) warn_too_few_energies; |
| 109 | 111 | %rename(_warn_xml_suffix) warn_xml_suffix; |
| 110 | 112 | |
| ... | ... | @@ -147,6 +149,13 @@ public: |
| 147 | 149 | std::vector<bool> cube_layer_usage(const GEbounds& cube_ebounds, |
| 148 | 150 | const GEbounds& list_ebounds) const; |
| 149 | 151 | bool is_valid_filename(const GFilename& filename) const; |
| 152 | + std::string get_gtiname(const std::string& filename, | |
| 153 | + const std::string& evtname) const; | |
| 154 | + void save_event_list(const GCTAObservation* obs, | |
| 155 | + const std::string& infile, | |
| 156 | + const std::string& evtname, | |
| 157 | + const std::string& gtiname, | |
| 158 | + const std::string& outfile) const; | |
| 150 | 159 | |
| 151 | 160 | // Protected warning strings |
| 152 | 161 | std::string warn_too_few_energies(const GEnergies& energies) const; | ... | ... |
pyext/ctools/tools.i
pyext/ctphase.i
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctphase - Append phase information to CTA events file * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2017 by Leonardo Di Venere * | |
| 4 | + * copyright (C) 2017 by Joshua Cardenzana * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | /** |
| 22 | 22 | * @file ctphase.i |
| 23 | 23 | * @brief Append phase information to CTA events file |
| 24 | - * @author Leonardo Di Venere | |
| 24 | + * @author Joshua Cardenzana | |
| 25 | 25 | */ |
| 26 | 26 | %{ |
| 27 | 27 | /* Put headers and other declarations here that are needed for compilation */ | ... | ... |
pyext/ctprob.i
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * ctprob - Computes probability for a given model * | |
| 3 | + * ----------------------------------------------------------------------- * | |
| 4 | + * copyright (C) 2012-2016 by Leonardo Di Venere * | |
| 5 | + * ----------------------------------------------------------------------- * | |
| 6 | + * * | |
| 7 | + * This program is free software: you can redistribute it and/or modify * | |
| 8 | + * it under the terms of the GNU General Public License as published by * | |
| 9 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 10 | + * (at your option) any later version. * | |
| 11 | + * * | |
| 12 | + * This program is distributed in the hope that it will be useful, * | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 15 | + * GNU General Public License for more details. * | |
| 16 | + * * | |
| 17 | + * You should have received a copy of the GNU General Public License * | |
| 18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 19 | + * * | |
| 20 | + ***************************************************************************/ | |
| 21 | +/** | |
| 22 | + * @file ctprob.i | |
| 23 | + * @brief Computes probability for a given model | |
| 24 | + * @author Leonardo Di Venere | |
| 25 | + */ | |
| 26 | +%{ | |
| 27 | +/* Put headers and other declarations here that are needed for compilation */ | |
| 28 | +#include "ctprob.hpp" | |
| 29 | +%} | |
| 30 | + | |
| 31 | + | |
| 32 | +/***********************************************************************//** | |
| 33 | + * @class ctprob | |
| 34 | + * | |
| 35 | + * @brief Data selection tool | |
| 36 | + ***************************************************************************/ | |
| 37 | +class ctprob : public ctobservation { | |
| 38 | +public: | |
| 39 | + // Constructors and destructors | |
| 40 | + ctprob(void); | |
| 41 | + explicit ctprob(const GObservations& obs); | |
| 42 | + ctprob(int argc, char *argv[]); | |
| 43 | + ctprob(const ctprob& app); | |
| 44 | + virtual ~ctprob(void); | |
| 45 | + | |
| 46 | + // Methods | |
| 47 | + void clear(void); | |
| 48 | + void run(void); | |
| 49 | + void save(void); | |
| 50 | + void publish(const std::string& name = ""); | |
| 51 | +}; | |
| 52 | + | |
| 53 | + | |
| 54 | +/***********************************************************************//** | |
| 55 | + * @brief Data selection tool Python extension | |
| 56 | + ***************************************************************************/ | |
| 57 | +%extend ctprob { | |
| 58 | + ctprob copy() { | |
| 59 | + return (*self); | |
| 60 | + } | |
| 61 | +} | ... | ... |
src/Makefile.am
| 1 | 1 | ############################################################################# |
| 2 | 2 | # Makefile.am for ctools module # |
| 3 | 3 | # ------------------------------------------------------------------------- # |
| 4 | -# Copyright (C) 2016 Juergen Knoedlseder # | |
| 4 | +# Copyright (C) 2016-2017 Juergen Knoedlseder # | |
| 5 | 5 | # ------------------------------------------------------------------------- # |
| 6 | 6 | # # |
| 7 | 7 | # This program is free software: you can redistribute it and/or modify # |
| ... | ... | @@ -41,7 +41,8 @@ SUBDIRS = support \ |
| 41 | 41 | ctbutterfly \ |
| 42 | 42 | ctulimit \ |
| 43 | 43 | cterror \ |
| 44 | - ctphase | |
| 44 | + ctphase \ | |
| 45 | + ctprob | |
| 45 | 46 | |
| 46 | 47 | # Scripts to be distributed |
| 47 | 48 | scripts = ctools-setup \ |
| ... | ... | @@ -70,7 +71,8 @@ libctools_la_LIBADD = support/libsupport.la \ |
| 70 | 71 | ctbutterfly/libctbutterfly.la \ |
| 71 | 72 | ctulimit/libctulimit.la \ |
| 72 | 73 | cterror/libcterror.la \ |
| 73 | - ctphase/libctphase.la | |
| 74 | + ctphase/libctphase.la \ | |
| 75 | + ctprob/libctprob.la | |
| 74 | 76 | |
| 75 | 77 | libctools_la_LDFLAGS = -version-info $(CTOOLS_LT_VERSION) @OPENMP_LIB_LDFLAGS@ |
| 76 | 78 | ... | ... |
src/ctbin/ctbin.cpp
| ... | ... | @@ -55,7 +55,7 @@ |
| 55 | 55 | * |
| 56 | 56 | * Constructs an empty event binning tool. |
| 57 | 57 | ***************************************************************************/ |
| 58 | -ctbin::ctbin(void) : ctobservation(CTBIN_NAME, CTBIN_VERSION) | |
| 58 | +ctbin::ctbin(void) : ctobservation(CTBIN_NAME, VERSION) | |
| 59 | 59 | { |
| 60 | 60 | // Initialise members |
| 61 | 61 | init_members(); |
| ... | ... | @@ -73,7 +73,7 @@ ctbin::ctbin(void) : ctobservation(CTBIN_NAME, CTBIN_VERSION) |
| 73 | 73 | * Constructs event binning tool from an observation container. |
| 74 | 74 | ***************************************************************************/ |
| 75 | 75 | ctbin::ctbin(const GObservations& obs) : |
| 76 | - ctobservation(CTBIN_NAME, CTBIN_VERSION, obs) | |
| 76 | + ctobservation(CTBIN_NAME, VERSION, obs) | |
| 77 | 77 | { |
| 78 | 78 | // Initialise members |
| 79 | 79 | init_members(); |
| ... | ... | @@ -94,7 +94,7 @@ ctbin::ctbin(const GObservations& obs) : |
| 94 | 94 | * parameter setting. |
| 95 | 95 | ***************************************************************************/ |
| 96 | 96 | ctbin::ctbin(int argc, char *argv[]) : |
| 97 | - ctobservation(CTBIN_NAME, CTBIN_VERSION, argc, argv) | |
| 97 | + ctobservation(CTBIN_NAME, VERSION, argc, argv) | |
| 98 | 98 | { |
| 99 | 99 | // Initialise members |
| 100 | 100 | init_members(); | ... | ... |
src/ctbin/ctbin.hpp
| ... | ... | @@ -31,8 +31,7 @@ |
| 31 | 31 | #include "ctobservation.hpp" |
| 32 | 32 | |
| 33 | 33 | /* __Definitions _________________________________________________________ */ |
| 34 | -#define CTBIN_NAME "ctbin" | |
| 35 | -#define CTBIN_VERSION "1.2.0" | |
| 34 | +#define CTBIN_NAME "ctbin" | |
| 36 | 35 | |
| 37 | 36 | |
| 38 | 37 | /***********************************************************************//** | ... | ... |
src/ctbkgcube/ctbkgcube.cpp
| ... | ... | @@ -50,7 +50,7 @@ |
| 50 | 50 | /***********************************************************************//** |
| 51 | 51 | * @brief Void constructor |
| 52 | 52 | ***************************************************************************/ |
| 53 | -ctbkgcube::ctbkgcube(void) : ctobservation(CTBKGCUBE_NAME, CTBKGCUBE_VERSION) | |
| 53 | +ctbkgcube::ctbkgcube(void) : ctobservation(CTBKGCUBE_NAME, VERSION) | |
| 54 | 54 | { |
| 55 | 55 | // Initialise members |
| 56 | 56 | init_members(); |
| ... | ... | @@ -69,7 +69,7 @@ ctbkgcube::ctbkgcube(void) : ctobservation(CTBKGCUBE_NAME, CTBKGCUBE_VERSION) |
| 69 | 69 | * observations container. |
| 70 | 70 | ***************************************************************************/ |
| 71 | 71 | ctbkgcube::ctbkgcube(const GObservations& obs) : |
| 72 | - ctobservation(CTBKGCUBE_NAME, CTBKGCUBE_VERSION, obs) | |
| 72 | + ctobservation(CTBKGCUBE_NAME, VERSION, obs) | |
| 73 | 73 | { |
| 74 | 74 | // Initialise members |
| 75 | 75 | init_members(); |
| ... | ... | @@ -87,7 +87,7 @@ ctbkgcube::ctbkgcube(const GObservations& obs) : |
| 87 | 87 | * @param[in] argv Array of command line arguments. |
| 88 | 88 | ***************************************************************************/ |
| 89 | 89 | ctbkgcube::ctbkgcube(int argc, char *argv[]) : |
| 90 | - ctobservation(CTBKGCUBE_NAME, CTBKGCUBE_VERSION, argc, argv) | |
| 90 | + ctobservation(CTBKGCUBE_NAME, VERSION, argc, argv) | |
| 91 | 91 | { |
| 92 | 92 | // Initialise members |
| 93 | 93 | init_members(); | ... | ... |
src/ctbkgcube/ctbkgcube.hpp
| ... | ... | @@ -33,8 +33,7 @@ |
| 33 | 33 | #include "ctobservation.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __Definitions _________________________________________________________ */ |
| 36 | -#define CTBKGCUBE_NAME "ctbkgcube" | |
| 37 | -#define CTBKGCUBE_VERSION "1.1.0" | |
| 36 | +#define CTBKGCUBE_NAME "ctbkgcube" | |
| 38 | 37 | |
| 39 | 38 | |
| 40 | 39 | /***********************************************************************//** | ... | ... |
src/ctbutterfly/ctbutterfly.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctbutterfly - butterfly calculation tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2014-2016 by Michael Mayer * | |
| 4 | + * copyright (C) 2014-2017 by Michael Mayer * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -52,7 +52,7 @@ |
| 52 | 52 | /***********************************************************************//** |
| 53 | 53 | * @brief Void constructor |
| 54 | 54 | ***************************************************************************/ |
| 55 | -ctbutterfly::ctbutterfly(void) : ctlikelihood(CTBUTTERFLY_NAME, CTBUTTERFLY_VERSION) | |
| 55 | +ctbutterfly::ctbutterfly(void) : ctlikelihood(CTBUTTERFLY_NAME, VERSION) | |
| 56 | 56 | { |
| 57 | 57 | // Initialise members |
| 58 | 58 | init_members(); |
| ... | ... | @@ -71,7 +71,7 @@ ctbutterfly::ctbutterfly(void) : ctlikelihood(CTBUTTERFLY_NAME, CTBUTTERFLY_VERS |
| 71 | 71 | * observations container. |
| 72 | 72 | ***************************************************************************/ |
| 73 | 73 | ctbutterfly::ctbutterfly(const GObservations& obs) : |
| 74 | - ctlikelihood(CTBUTTERFLY_NAME, CTBUTTERFLY_VERSION, obs) | |
| 74 | + ctlikelihood(CTBUTTERFLY_NAME, VERSION, obs) | |
| 75 | 75 | { |
| 76 | 76 | // Initialise members |
| 77 | 77 | init_members(); |
| ... | ... | @@ -89,7 +89,7 @@ ctbutterfly::ctbutterfly(const GObservations& obs) : |
| 89 | 89 | * @param[in] argv Array of command line arguments. |
| 90 | 90 | ***************************************************************************/ |
| 91 | 91 | ctbutterfly::ctbutterfly(int argc, char *argv[]) : |
| 92 | - ctlikelihood(CTBUTTERFLY_NAME, CTBUTTERFLY_VERSION, argc, argv) | |
| 92 | + ctlikelihood(CTBUTTERFLY_NAME, VERSION, argc, argv) | |
| 93 | 93 | { |
| 94 | 94 | // Initialise members |
| 95 | 95 | init_members(); |
| ... | ... | @@ -243,11 +243,14 @@ void ctbutterfly::run(void) |
| 243 | 243 | m_obs.optimize(m_opt); |
| 244 | 244 | m_obs.errors(m_opt); |
| 245 | 245 | |
| 246 | - // Get covariance matrix by inverting the curvature matrix. Note that | |
| 247 | - // the curvature matrix is for the unscaled parameters, hence we have | |
| 248 | - // to scale them before we can proceed. | |
| 246 | + // Get covariance matrix. | |
| 249 | 247 | GObservations::likelihood likelihood = m_obs.function(); |
| 250 | - m_covariance = likelihood.curvature()->invert(); | |
| 248 | + if (m_method == "GAUSSIAN") { | |
| 249 | + m_covariance = likelihood.curvature()->invert(); | |
| 250 | + } | |
| 251 | + else { | |
| 252 | + m_covariance = likelihood.covariance(); | |
| 253 | + } | |
| 251 | 254 | |
| 252 | 255 | // Write optimizer, optimised model and covariance matrix into logger |
| 253 | 256 | log_string(NORMAL, m_opt.print(m_chatter)); |
| ... | ... | @@ -271,157 +274,26 @@ void ctbutterfly::run(void) |
| 271 | 274 | GObservations::likelihood likelihood = m_obs.function(); |
| 272 | 275 | likelihood.eval(pars); |
| 273 | 276 | |
| 274 | - // Get covariance matrix by inverting the curvature matrix. Note that | |
| 275 | - // the curvature matrix is for the unscaled parameters, hence we have | |
| 276 | - // to scale them before we can proceed. | |
| 277 | - m_covariance = likelihood.curvature()->invert(); | |
| 277 | + // Get covariance matrix. | |
| 278 | + if (m_method == "GAUSSIAN") { | |
| 279 | + m_covariance = likelihood.curvature()->invert(); | |
| 280 | + } | |
| 281 | + else { | |
| 282 | + m_covariance = likelihood.covariance(); | |
| 283 | + } | |
| 278 | 284 | |
| 279 | 285 | // Write covariance matrix into logger |
| 280 | 286 | log_string(EXPLICIT, m_covariance.print(m_chatter)); |
| 281 | 287 | |
| 282 | 288 | } // endif: covariance computation needed |
| 283 | 289 | |
| 284 | - // Write header into logger | |
| 285 | - log_header1(TERSE, "Prepare butterfly computation"); | |
| 286 | - | |
| 287 | - // Find parameter indices. We do this by the memory location of the | |
| 288 | - // model parameters. | |
| 289 | - GModelSky* skymodel = dynamic_cast<GModelSky*>(models[m_srcname]); | |
| 290 | - GModelPar* par_prefactor = &(*skymodel)["Prefactor"]; | |
| 291 | - GModelPar* par_index = &(*skymodel)["Index"]; | |
| 292 | - int inx_prefactor = -1; | |
| 293 | - int inx_index = -1; | |
| 294 | - for (int i = 0; i < models.npars(); ++i) { | |
| 295 | - if (models.pars()[i] == par_prefactor) { | |
| 296 | - inx_prefactor = i; | |
| 297 | - } | |
| 298 | - if (models.pars()[i] == par_index) { | |
| 299 | - inx_index = i; | |
| 300 | - } | |
| 290 | + // Compute butterfly depending on selected method | |
| 291 | + if (m_method == "GAUSSIAN") { | |
| 292 | + gaussian_error_propagation(models); | |
| 293 | + } | |
| 294 | + else { | |
| 295 | + ellipsoid_boundary(models); | |
| 301 | 296 | } |
| 302 | - | |
| 303 | - // Store model values and scales | |
| 304 | - double prefactor_mean = (*skymodel)["Prefactor"].value(); | |
| 305 | - double index_mean = (*skymodel)["Index"].value(); | |
| 306 | - double pivot_mean = (*skymodel)["PivotEnergy"].value(); | |
| 307 | - double prefactor_scale = (*skymodel)["Prefactor"].scale(); | |
| 308 | - double index_scale = (*skymodel)["Index"].scale(); | |
| 309 | - GEnergy pivot(pivot_mean, "MeV"); | |
| 310 | - | |
| 311 | - // Write parameter indices into logger | |
| 312 | - log_value(NORMAL, "Prefactor", gammalib::str(prefactor_mean)+ | |
| 313 | - " ph/cm2/s/MeV ("+gammalib::str(inx_prefactor)+")"); | |
| 314 | - log_value(NORMAL, "Index", gammalib::str(index_mean)+ | |
| 315 | - " ("+gammalib::str(inx_index)+")"); | |
| 316 | - log_value(NORMAL, "Pivot energy", pivot.print()); | |
| 317 | - | |
| 318 | - // Extract covariance elements | |
| 319 | - double cov_pp = m_covariance(inx_prefactor,inx_prefactor); | |
| 320 | - double cov_pg = m_covariance(inx_prefactor,inx_index); | |
| 321 | - double cov_gg = m_covariance(inx_index,inx_index); | |
| 322 | - | |
| 323 | - // Compute eigenvectors and eigenvalues | |
| 324 | - double lambda1; | |
| 325 | - double lambda2; | |
| 326 | - GVector vector1(2); | |
| 327 | - GVector vector2(2); | |
| 328 | - eigenvectors(cov_pp, cov_pg, cov_pg, cov_gg, | |
| 329 | - &lambda1, &lambda2, &vector1, &vector2); | |
| 330 | - | |
| 331 | - // Write eigenvectors and eigenvalues into logger | |
| 332 | - log_value(NORMAL, "Eigenvalue 1", lambda1); | |
| 333 | - log_value(NORMAL, "Eigenvalue 2", lambda2); | |
| 334 | - log_value(NORMAL, "Eigenvector 1", vector1.print()); | |
| 335 | - log_value(NORMAL, "Eigenvector 2", vector2.print()); | |
| 336 | - | |
| 337 | - // Confidence scaling | |
| 338 | - double sigma = gammalib::erfinv(m_confidence) * gammalib::sqrt_two; | |
| 339 | - double scale = (sigma*sigma); | |
| 340 | - | |
| 341 | - // Write confidence level information into logger | |
| 342 | - log_value(NORMAL, "Confidence level", m_confidence); | |
| 343 | - log_value(NORMAL, "Corresponding scaling", scale); | |
| 344 | - | |
| 345 | - // Compute minor and major axes of error ellipse | |
| 346 | - double major = scale*std::sqrt(lambda1); | |
| 347 | - double minor = scale*std::sqrt(lambda2); | |
| 348 | - | |
| 349 | - // Write header into logger | |
| 350 | - log_header1(TERSE, "Generate butterfly"); | |
| 351 | - | |
| 352 | - // Initialise result arrays | |
| 353 | - m_energies.assign(m_ebounds.size(), 0.0); | |
| 354 | - m_intensities.assign(m_ebounds.size(), 0.0); | |
| 355 | - m_min_intensities.assign(m_ebounds.size(), 1e30); | |
| 356 | - m_max_intensities.assign(m_ebounds.size(), 0.0); | |
| 357 | - | |
| 358 | - // Walk around the error ellipse | |
| 359 | - int nt = 360; | |
| 360 | - double dt = gammalib::twopi/double(nt); | |
| 361 | - double t = 0.0; | |
| 362 | - for (int i = 0; i < nt; ++i, t += dt) { | |
| 363 | - | |
| 364 | - // Pre-compute sin and cosine | |
| 365 | - double sin_t = std::sin(t); | |
| 366 | - double cos_t = std::cos(t); | |
| 367 | - | |
| 368 | - // Compute prefactor and index | |
| 369 | - double prefactor = (major * cos_t * vector1[0] + | |
| 370 | - minor * sin_t * vector2[0]) * prefactor_scale + | |
| 371 | - prefactor_mean; | |
| 372 | - double index = (major * cos_t * vector1[1] + | |
| 373 | - minor * sin_t * vector2[1]) * index_scale + | |
| 374 | - index_mean; | |
| 375 | - | |
| 376 | - // Write prefactor and index into logger | |
| 377 | - log_value(EXPLICIT, "Angle "+gammalib::str(t*gammalib::rad2deg), | |
| 378 | - gammalib::str(prefactor)+" ph/cm2/s/MeV; "+ | |
| 379 | - gammalib::str(index)); | |
| 380 | - | |
| 381 | - // Setup power law model | |
| 382 | - GModelSpectralPlaw plaw(prefactor, index, pivot); | |
| 383 | - | |
| 384 | - // Evaluate power law at each energy and extract minimum and | |
| 385 | - // maximum intensity | |
| 386 | - for (int k = 0; k < m_ebounds.size(); ++k) { | |
| 387 | - | |
| 388 | - // Get the energy of current bin | |
| 389 | - GTime time; | |
| 390 | - GEnergy energy = m_ebounds.elogmean(k); | |
| 391 | - | |
| 392 | - // Evaluate power law | |
| 393 | - double intensity = plaw.eval(energy, time); | |
| 394 | - | |
| 395 | - // Get extremes | |
| 396 | - if (intensity < m_min_intensities[k]) { | |
| 397 | - m_min_intensities[k] = intensity; | |
| 398 | - } | |
| 399 | - if (intensity > m_max_intensities[k]) { | |
| 400 | - m_max_intensities[k] = intensity; | |
| 401 | - } | |
| 402 | - | |
| 403 | - } // endfor: looped over all energies | |
| 404 | - | |
| 405 | - } // endfor: looped over all angles | |
| 406 | - | |
| 407 | - // Setup power law model for mean prefactor and index | |
| 408 | - GModelSpectralPlaw plaw(prefactor_mean, index_mean, pivot); | |
| 409 | - | |
| 410 | - // Compute energy and intensity vectors for mean power law | |
| 411 | - for (int k = 0; k < m_ebounds.size(); ++k) { | |
| 412 | - | |
| 413 | - // Get the energy of current bin | |
| 414 | - GTime time; | |
| 415 | - GEnergy energy = m_ebounds.elogmean(k); | |
| 416 | - | |
| 417 | - // Evaluate power law | |
| 418 | - double intensity = plaw.eval(energy, time); | |
| 419 | - | |
| 420 | - // Store results | |
| 421 | - m_energies[k] = energy.MeV(); | |
| 422 | - m_intensities[k] = intensity; | |
| 423 | - | |
| 424 | - } // endfor: looped over energies | |
| 425 | 297 | |
| 426 | 298 | // Write header into logger |
| 427 | 299 | log_header1(TERSE, "Results"); |
| ... | ... | @@ -431,11 +303,11 @@ void ctbutterfly::run(void) |
| 431 | 303 | |
| 432 | 304 | // Write results into logger |
| 433 | 305 | log_value(NORMAL, "Intensity at "+gammalib::str(m_energies[k])+" MeV", |
| 434 | - gammalib::str(m_intensities[k])+" ("+ | |
| 435 | - gammalib::str(m_min_intensities[k])+", "+ | |
| 436 | - gammalib::str(m_max_intensities[k])+") ph/cm2/s/MeV"); | |
| 306 | + gammalib::str(m_intensities[k])+" ("+ | |
| 307 | + gammalib::str(m_min_intensities[k])+", "+ | |
| 308 | + gammalib::str(m_max_intensities[k])+") ph/cm2/s/MeV"); | |
| 437 | 309 | |
| 438 | - } // endfor: looped over energies | |
| 310 | + } //endfor: loop over energy bin | |
| 439 | 311 | |
| 440 | 312 | // Restore energy dispersion flag for all CTA observations |
| 441 | 313 | for (int i = 0; i < m_obs.size(); ++i) { |
| ... | ... | @@ -504,6 +376,7 @@ void ctbutterfly::init_members(void) |
| 504 | 376 | { |
| 505 | 377 | // Initialise members |
| 506 | 378 | m_srcname.clear(); |
| 379 | + m_method.clear(); | |
| 507 | 380 | m_confidence = 0.68; |
| 508 | 381 | m_max_iter = 50; |
| 509 | 382 | m_apply_edisp = false; |
| ... | ... | @@ -537,6 +410,7 @@ void ctbutterfly::copy_members(const ctbutterfly& app) |
| 537 | 410 | { |
| 538 | 411 | // Copy attributes |
| 539 | 412 | m_srcname = app.m_srcname; |
| 413 | + m_method = app.m_method; | |
| 540 | 414 | m_confidence = app.m_confidence; |
| 541 | 415 | m_max_iter = app.m_max_iter; |
| 542 | 416 | m_apply_edisp = app.m_apply_edisp; |
| ... | ... | @@ -544,7 +418,7 @@ void ctbutterfly::copy_members(const ctbutterfly& app) |
| 544 | 418 | m_chatter = app.m_chatter; |
| 545 | 419 | m_ebounds = app.m_ebounds; |
| 546 | 420 | m_outfile = app.m_outfile; |
| 547 | - | |
| 421 | + | |
| 548 | 422 | // Copy protected members |
| 549 | 423 | m_covariance = app.m_covariance; |
| 550 | 424 | m_energies = app.m_energies; |
| ... | ... | @@ -583,16 +457,13 @@ void ctbutterfly::get_parameters(void) |
| 583 | 457 | { |
| 584 | 458 | // Setup observations from "inobs" parameter |
| 585 | 459 | setup_observations(m_obs); |
| 586 | - | |
| 460 | + | |
| 587 | 461 | // Setup models from "inmodel" parameter |
| 588 | 462 | setup_models(m_obs, (*this)["srcname"].string()); |
| 589 | 463 | |
| 590 | 464 | // Get name of test source |
| 591 | 465 | m_srcname = (*this)["srcname"].string(); |
| 592 | 466 | |
| 593 | - // Check model name and type | |
| 594 | - check_model(); | |
| 595 | - | |
| 596 | 467 | // Create energy boundaries from user parameters |
| 597 | 468 | m_ebounds = create_ebounds(); |
| 598 | 469 | |
| ... | ... | @@ -600,18 +471,22 @@ void ctbutterfly::get_parameters(void) |
| 600 | 471 | std::string matrixfilename = (*this)["matrix"].filename(); |
| 601 | 472 | if (matrixfilename != "NONE") { |
| 602 | 473 | std::string msg = "Loading of matrix from file not implemented yet. " |
| 603 | - "Use filename = \"NONE\" to induce a recomputation of " | |
| 604 | - "the matrix internally."; | |
| 474 | + "Use filename = \"NONE\" to induce a recomputation of " | |
| 475 | + "the matrix internally."; | |
| 605 | 476 | throw GException::feature_not_implemented(G_GET_PARAMETERS, msg); |
| 606 | 477 | // m_covariance.load(matrixfilename); |
| 607 | 478 | } |
| 608 | 479 | |
| 609 | 480 | // Get remaining parameters |
| 610 | 481 | m_apply_edisp = (*this)["edisp"].boolean(); |
| 482 | + m_method = (*this)["method"].string(); | |
| 611 | 483 | m_confidence = (*this)["confidence"].real(); |
| 612 | 484 | m_fit = (*this)["fit"].boolean(); |
| 613 | 485 | m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); |
| 614 | 486 | |
| 487 | + // Check model name and type | |
| 488 | + check_model(); | |
| 489 | + | |
| 615 | 490 | // Optionally read ahead parameters so that they get correctly |
| 616 | 491 | // dumped into the log file |
| 617 | 492 | if (read_ahead()) { |
| ... | ... | @@ -627,6 +502,279 @@ void ctbutterfly::get_parameters(void) |
| 627 | 502 | |
| 628 | 503 | |
| 629 | 504 | /***********************************************************************//** |
| 505 | + * @brief Compute butterfly using the ellipsoid boundary method | |
| 506 | + ***************************************************************************/ | |
| 507 | +void ctbutterfly::ellipsoid_boundary(GModels& models) | |
| 508 | +{ | |
| 509 | + // Write header into logger | |
| 510 | + log_header1(TERSE, "Prepare butterfly computation"); | |
| 511 | + | |
| 512 | + // Find parameter indices. We do this by the memory location of the | |
| 513 | + // model parameters. | |
| 514 | + GModelSky* skymodel = dynamic_cast<GModelSky*>(models[m_srcname]); | |
| 515 | + GModelPar* par_prefactor = &(*skymodel)["Prefactor"]; | |
| 516 | + GModelPar* par_index = &(*skymodel)["Index"]; | |
| 517 | + int inx_prefactor = -1; | |
| 518 | + int inx_index = -1; | |
| 519 | + for (int i = 0; i < models.npars(); ++i) { | |
| 520 | + if (models.pars()[i] == par_prefactor) { | |
| 521 | + inx_prefactor = i; | |
| 522 | + } | |
| 523 | + if (models.pars()[i] == par_index) { | |
| 524 | + inx_index = i; | |
| 525 | + } | |
| 526 | + } | |
| 527 | + | |
| 528 | + // Store model values | |
| 529 | + double prefactor_mean = (*skymodel)["Prefactor"].value(); | |
| 530 | + double index_mean = (*skymodel)["Index"].value(); | |
| 531 | + double pivot_mean = (*skymodel)["PivotEnergy"].value(); | |
| 532 | + double prefactor_scale = (*skymodel)["Prefactor"].scale(); | |
| 533 | + double index_scale = (*skymodel)["Index"].scale(); | |
| 534 | + GEnergy pivot(pivot_mean, "MeV"); | |
| 535 | + | |
| 536 | + // Write parameter indices into logger | |
| 537 | + log_value(NORMAL, "Prefactor", gammalib::str(prefactor_mean)+ | |
| 538 | + " ph/cm2/s/MeV ("+ | |
| 539 | + gammalib::str(inx_prefactor)+")"); | |
| 540 | + log_value(NORMAL, "Index", gammalib::str(index_mean)+ | |
| 541 | + " ("+gammalib::str(inx_index)+")"); | |
| 542 | + log_value(NORMAL, "Pivot energy", pivot.print()); | |
| 543 | + | |
| 544 | + // Extract covariance elements | |
| 545 | + double cov_pp = m_covariance(inx_prefactor,inx_prefactor); | |
| 546 | + double cov_pg = m_covariance(inx_prefactor,inx_index); | |
| 547 | + double cov_gg = m_covariance(inx_index,inx_index); | |
| 548 | + | |
| 549 | + // Compute eigenvectors and eigenvalues | |
| 550 | + double lambda1; | |
| 551 | + double lambda2; | |
| 552 | + GVector vector1(2); | |
| 553 | + GVector vector2(2); | |
| 554 | + eigenvectors(cov_pp, cov_pg, cov_pg, cov_gg, | |
| 555 | + &lambda1, &lambda2, &vector1, &vector2); | |
| 556 | + | |
| 557 | + // Write eigenvectors and eigenvalues into logger | |
| 558 | + log_value(NORMAL, "Eigenvalue 1", lambda1); | |
| 559 | + log_value(NORMAL, "Eigenvalue 2", lambda2); | |
| 560 | + log_value(NORMAL, "Eigenvector 1", vector1.print()); | |
| 561 | + log_value(NORMAL, "Eigenvector 2", vector2.print()); | |
| 562 | + | |
| 563 | + // Confidence scaling, calculated from a Chi-Sqr. | |
| 564 | + // distribution with 2 dof | |
| 565 | + double scale = std::sqrt( -2. * std::log(1.-m_confidence) ); | |
| 566 | + | |
| 567 | + // Write confidence level information into logger | |
| 568 | + log_value(NORMAL, "Confidence level", m_confidence); | |
| 569 | + log_value(NORMAL, "Corresponding scaling", scale); | |
| 570 | + | |
| 571 | + // Compute minor and major axes of error ellipse | |
| 572 | + double major = scale*std::sqrt(lambda1); | |
| 573 | + double minor = scale*std::sqrt(lambda2); | |
| 574 | + | |
| 575 | + // Write header into logger | |
| 576 | + log_header1(TERSE, "Generate butterfly"); | |
| 577 | + | |
| 578 | + // Initialise result arrays | |
| 579 | + m_energies.assign(m_ebounds.size(), 0.0); | |
| 580 | + m_intensities.assign(m_ebounds.size(), 0.0); | |
| 581 | + m_min_intensities.assign(m_ebounds.size(), 1e30); | |
| 582 | + m_max_intensities.assign(m_ebounds.size(), 0.0); | |
| 583 | + | |
| 584 | + // Walk around the error ellipse | |
| 585 | + int nt = 360; | |
| 586 | + double dt = gammalib::twopi/double(nt); | |
| 587 | + double t = 0.0; | |
| 588 | + for (int i = 0; i < nt; ++i, t += dt) { | |
| 589 | + | |
| 590 | + // Pre-compute sin and cosine | |
| 591 | + double sin_t = std::sin(t); | |
| 592 | + double cos_t = std::cos(t); | |
| 593 | + | |
| 594 | + // Compute prefactor and index | |
| 595 | + double prefactor = (major * cos_t * vector1[0] + | |
| 596 | + minor * sin_t * vector2[0]) * prefactor_scale + | |
| 597 | + prefactor_mean; | |
| 598 | + double index = (major * cos_t * vector1[1] + | |
| 599 | + minor * sin_t * vector2[1]) * index_scale + | |
| 600 | + index_mean; | |
| 601 | + | |
| 602 | + // Write prefactor and index into logger | |
| 603 | + log_value(EXPLICIT, "Angle "+gammalib::str(t*gammalib::rad2deg), | |
| 604 | + gammalib::str(prefactor)+" ph/cm2/s/MeV; "+ | |
| 605 | + gammalib::str(index)); | |
| 606 | + | |
| 607 | + // Setup power law model | |
| 608 | + GModelSpectralPlaw plaw(prefactor, index, pivot); | |
| 609 | + | |
| 610 | + // Evaluate power law at each energy and extract minimum and | |
| 611 | + // maximum intensity | |
| 612 | + for (int k = 0; k < m_ebounds.size(); ++k) { | |
| 613 | + | |
| 614 | + // Get the energy of current bin | |
| 615 | + GTime time; | |
| 616 | + GEnergy energy = m_ebounds.elogmean(k); | |
| 617 | + | |
| 618 | + // Evaluate power law | |
| 619 | + double intensity = plaw.eval(energy, time); | |
| 620 | + | |
| 621 | + // Get extremes | |
| 622 | + if (intensity < m_min_intensities[k]) { | |
| 623 | + m_min_intensities[k] = intensity; | |
| 624 | + } | |
| 625 | + if (intensity > m_max_intensities[k]) { | |
| 626 | + m_max_intensities[k] = intensity; | |
| 627 | + } | |
| 628 | + | |
| 629 | + } // endfor: looped over all energies | |
| 630 | + | |
| 631 | + } // endfor: looped over all angles | |
| 632 | + | |
| 633 | + // Setup power law model for mean prefactor and index | |
| 634 | + GModelSpectralPlaw plaw(prefactor_mean, index_mean, pivot); | |
| 635 | + | |
| 636 | + // Compute energy and intensity vectors for mean power law | |
| 637 | + for (int k = 0; k < m_ebounds.size(); ++k) { | |
| 638 | + | |
| 639 | + // Get the energy of current bin | |
| 640 | + GTime time; | |
| 641 | + GEnergy energy = m_ebounds.elogmean(k); | |
| 642 | + | |
| 643 | + // Evaluate power law | |
| 644 | + double intensity = plaw.eval(energy, time); | |
| 645 | + | |
| 646 | + // Store results | |
| 647 | + m_energies[k] = energy.MeV(); | |
| 648 | + m_intensities[k] = intensity; | |
| 649 | + | |
| 650 | + } // endfor: looped over energies | |
| 651 | + | |
| 652 | + // Return | |
| 653 | + return; | |
| 654 | +} | |
| 655 | + | |
| 656 | + | |
| 657 | +/***********************************************************************//** | |
| 658 | + * @brief Compute butterfly using Gaussian error propagation | |
| 659 | + * | |
| 660 | + * Computes the butterfly diagram using Gaussian error propagation. This | |
| 661 | + * works for any kind of model. | |
| 662 | + ***************************************************************************/ | |
| 663 | +void ctbutterfly::gaussian_error_propagation(GModels& models) | |
| 664 | +{ | |
| 665 | + // Write header into logger | |
| 666 | + log_header1(TERSE, "Prepare butterfly computation"); | |
| 667 | + | |
| 668 | + // Confidence scaling | |
| 669 | + double scale = gammalib::erfinv(m_confidence) * gammalib::sqrt_two; | |
| 670 | + | |
| 671 | + // Write confidence level information into logger | |
| 672 | + log_value(NORMAL, "Confidence level", m_confidence); | |
| 673 | + log_value(NORMAL, "Corresponding scaling", scale); | |
| 674 | + | |
| 675 | + // Write header into logger | |
| 676 | + log_header1(TERSE, "Generate butterfly"); | |
| 677 | + | |
| 678 | + // Initialise result arrays | |
| 679 | + m_energies.clear(); | |
| 680 | + m_intensities.clear(); | |
| 681 | + m_min_intensities.clear(); | |
| 682 | + m_max_intensities.clear(); | |
| 683 | + | |
| 684 | + // Initialise dummy time to evaluate spectral model | |
| 685 | + GTime time = GTime(); | |
| 686 | + | |
| 687 | + // Initialise vector of gradients | |
| 688 | + GVector grad = GVector(m_obs.models().npars()); | |
| 689 | + | |
| 690 | + // Loop over energy bins | |
| 691 | + for (int i = 0; i < m_ebounds.size(); ++i) { | |
| 692 | + | |
| 693 | + // Initialise number of gradients | |
| 694 | + int num_gradient = 0; | |
| 695 | + | |
| 696 | + // Get the mean logarithmic energy of current bin | |
| 697 | + GEnergy energy = m_ebounds.elogmean(i); | |
| 698 | + | |
| 699 | + // Initialise model flux value | |
| 700 | + double model_flux = 0.0; | |
| 701 | + | |
| 702 | + // Loop over models | |
| 703 | + for (int j = 0; j < models.size(); ++j) { | |
| 704 | + | |
| 705 | + // Check wether model is a skymodel | |
| 706 | + GModelSky* skymodel = dynamic_cast<GModelSky*>(models[j]); | |
| 707 | + | |
| 708 | + // Yes ... | |
| 709 | + if (skymodel != NULL) { | |
| 710 | + | |
| 711 | + // Set flux value of source of interest, evaluate gradients | |
| 712 | + if (skymodel->name() == m_srcname) { | |
| 713 | + | |
| 714 | + // Get spectral component of model | |
| 715 | + GModelSpectral *spectral = skymodel->spectral(); | |
| 716 | + | |
| 717 | + // Get model flux | |
| 718 | + model_flux = spectral->eval(energy, time, true); | |
| 719 | + | |
| 720 | + // Loop over all model parameters | |
| 721 | + for (int k = 0; k < skymodel->size(); ++k) { | |
| 722 | + | |
| 723 | + // Set gradient if we deal with spectral component | |
| 724 | + bool parIsSpectral = false; | |
| 725 | + for (int l = 0; l < spectral->size(); ++l) { | |
| 726 | + if ((&((*spectral)[l])) == (&((*skymodel)[k]))) { | |
| 727 | + grad[num_gradient] = (*spectral)[l].gradient(); | |
| 728 | + num_gradient++; | |
| 729 | + parIsSpectral = true; | |
| 730 | + break; | |
| 731 | + } | |
| 732 | + } // endfor: looped over spectral parameters | |
| 733 | + | |
| 734 | + // If parameter is spatial or temporal, count up | |
| 735 | + if (!parIsSpectral) { | |
| 736 | + num_gradient++; | |
| 737 | + } | |
| 738 | + | |
| 739 | + } // endfor: looped over all model parameters | |
| 740 | + | |
| 741 | + } // endif: model was source of interest | |
| 742 | + else { | |
| 743 | + num_gradient += skymodel->size(); | |
| 744 | + } | |
| 745 | + | |
| 746 | + } // endif: model was sky model | |
| 747 | + | |
| 748 | + // Skip other models (e.g. GModelData instances) | |
| 749 | + else { | |
| 750 | + num_gradient += models[j]->size(); | |
| 751 | + } | |
| 752 | + | |
| 753 | + } // endfor: Looped over models | |
| 754 | + | |
| 755 | + // Multiply covariance to the gradient vector | |
| 756 | + GVector vector = m_covariance * grad; | |
| 757 | + | |
| 758 | + // Get the error from the scalar product | |
| 759 | + double error = std::sqrt(grad * vector); | |
| 760 | + | |
| 761 | + // Multiply with confidence scaling | |
| 762 | + error *= scale; | |
| 763 | + | |
| 764 | + // Store flux, value and energy for saving | |
| 765 | + m_intensities.push_back(model_flux); | |
| 766 | + m_energies.push_back(energy.MeV()); | |
| 767 | + m_min_intensities.push_back(model_flux-error); | |
| 768 | + m_max_intensities.push_back(model_flux+error); | |
| 769 | + | |
| 770 | + } // endfor: Looped over energy bins | |
| 771 | + | |
| 772 | + // Return | |
| 773 | + return; | |
| 774 | +} | |
| 775 | + | |
| 776 | + | |
| 777 | +/***********************************************************************//** | |
| 630 | 778 | * @brief Check if sky model is valid |
| 631 | 779 | * |
| 632 | 780 | * @exception GException::invalid_value |
| ... | ... | @@ -645,17 +793,22 @@ void ctbutterfly::check_model(void) |
| 645 | 793 | GModelSky* model = dynamic_cast<GModelSky*>(models[m_srcname]); |
| 646 | 794 | if (model == NULL) { |
| 647 | 795 | std::string msg = "Source \""+m_srcname+"\" is not a sky model. " |
| 648 | - "Please specify the name of a sky model for " | |
| 649 | - "butterfly computation."; | |
| 796 | + "Please specify the name of a sky model for " | |
| 797 | + "butterfly computation."; | |
| 650 | 798 | throw GException::invalid_value(G_CHECK_MODEL, msg); |
| 651 | 799 | } |
| 652 | 800 | |
| 653 | - // Check that the spectral model is a power law | |
| 654 | - if (model->spectral()->type() != "PowerLaw") { | |
| 655 | - std::string msg = "\""+model->spectral()->type()+"\" cannot be " | |
| 656 | - "used as spectral model for an butterfly " | |
| 657 | - "computation. Please specify a power law model."; | |
| 658 | - throw GException::invalid_value(G_CHECK_MODEL, msg); | |
| 801 | + // Check that the spectral model is a power law for the "ENVELOPE" | |
| 802 | + // method | |
| 803 | + if (m_method == "ENVELOPE") { | |
| 804 | + if (model->spectral()->type() != "PowerLaw") { | |
| 805 | + std::string msg = "\""+model->spectral()->type()+"\" cannot be " | |
| 806 | + "used as spectral model for an butterfly " | |
| 807 | + "computation with method=ENVELOPE. Please " | |
| 808 | + "specify a power law model or switch to " | |
| 809 | + "method=GAUSSIAN."; | |
| 810 | + throw GException::invalid_value(G_CHECK_MODEL, msg); | |
| 811 | + } | |
| 659 | 812 | } |
| 660 | 813 | |
| 661 | 814 | } // endif: source model existed |
| ... | ... | @@ -663,8 +816,8 @@ void ctbutterfly::check_model(void) |
| 663 | 816 | // Otherwise throw an exception |
| 664 | 817 | else { |
| 665 | 818 | std::string msg = "Source \""+m_srcname+"\" not found in model " |
| 666 | - "container. Please add a source with that name " | |
| 667 | - "or check for possible typos."; | |
| 819 | + "container. Please add a source with that name " | |
| 820 | + "or check for possible typos."; | |
| 668 | 821 | throw GException::invalid_value(G_CHECK_MODEL, msg); |
| 669 | 822 | } |
| 670 | 823 | |
| ... | ... | @@ -689,13 +842,13 @@ void ctbutterfly::check_model(void) |
| 689 | 842 | * http://www.math.harvard.edu/archive/21b_fall_04/exhibits/2dmatrices/index.html |
| 690 | 843 | ***************************************************************************/ |
| 691 | 844 | void ctbutterfly::eigenvectors(const double& a, |
| 692 | - const double& b, | |
| 693 | - const double& c, | |
| 694 | - const double& d, | |
| 695 | - double* lambda1, | |
| 696 | - double* lambda2, | |
| 697 | - GVector* vector1, | |
| 698 | - GVector* vector2) | |
| 845 | + const double& b, | |
| 846 | + const double& c, | |
| 847 | + const double& d, | |
| 848 | + double* lambda1, | |
| 849 | + double* lambda2, | |
| 850 | + GVector* vector1, | |
| 851 | + GVector* vector2) | |
| 699 | 852 | { |
| 700 | 853 | // Compute trace and determinant |
| 701 | 854 | double trace = a + d; |
| ... | ... | @@ -730,7 +883,7 @@ void ctbutterfly::eigenvectors(const double& a, |
| 730 | 883 | // Normalize eigenvectors |
| 731 | 884 | *vector1 /= norm(*vector1); |
| 732 | 885 | *vector2 /= norm(*vector2); |
| 733 | - | |
| 886 | + | |
| 734 | 887 | // Return |
| 735 | 888 | return; |
| 736 | 889 | } | ... | ... |
src/ctbutterfly/ctbutterfly.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctbutterfly - butterfly calculation tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2014-2016 by Michael Mayer * | |
| 4 | + * copyright (C) 2014-2017 by Michael Mayer * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -33,8 +33,7 @@ |
| 33 | 33 | #include "ctlikelihood.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __Definitions _________________________________________________________ */ |
| 36 | -#define CTBUTTERFLY_NAME "ctbutterfly" | |
| 37 | -#define CTBUTTERFLY_VERSION "1.1.0" | |
| 36 | +#define CTBUTTERFLY_NAME "ctbutterfly" | |
| 38 | 37 | |
| 39 | 38 | |
| 40 | 39 | /***********************************************************************//** |
| ... | ... | @@ -77,6 +76,10 @@ protected: |
| 77 | 76 | void copy_members(const ctbutterfly& app); |
| 78 | 77 | void free_members(void); |
| 79 | 78 | void get_parameters(void); |
| 79 | + void gaussian_error_propagation(GModels& models); | |
| 80 | + void ellipsoid_boundary(GModels& models); | |
| 81 | + | |
| 82 | + | |
| 80 | 83 | void check_model(void); |
| 81 | 84 | void eigenvectors(const double& a, |
| 82 | 85 | const double& b, |
| ... | ... | @@ -89,6 +92,7 @@ protected: |
| 89 | 92 | |
| 90 | 93 | // User parameters |
| 91 | 94 | std::string m_srcname; //!< Name of source to compute butterfly |
| 95 | + std::string m_method; //!< Computation method | |
| 92 | 96 | double m_confidence; //!< Confidence level |
| 93 | 97 | int m_max_iter; //!< Maximum number of iterations |
| 94 | 98 | bool m_apply_edisp; //!< Apply energy dispersion? | ... | ... |
src/ctbutterfly/ctbutterfly.par
| ... | ... | @@ -27,6 +27,7 @@ caldb, s, a, "prod2",,, "Calibration database" |
| 27 | 27 | irf, s, a, "South_0.5h",,, "Instrument response function" |
| 28 | 28 | edisp, b, h, no,,, "Apply energy dispersion?" |
| 29 | 29 | outfile, f, a, "butterfly.txt",,, "Output ASCII file" |
| 30 | +method, s, h, GAUSSIAN, GAUSSIAN|ENVELOPE,,"Butterfly computation method" | |
| 30 | 31 | |
| 31 | 32 | # |
| 32 | 33 | # Butterfly parameters | ... | ... |
src/ctcubemask/ctcubemask.cpp
| ... | ... | @@ -51,7 +51,7 @@ |
| 51 | 51 | /***********************************************************************//** |
| 52 | 52 | * @brief Void constructor |
| 53 | 53 | ***************************************************************************/ |
| 54 | -ctcubemask::ctcubemask(void) : ctobservation(CTCUBEMASK_NAME, CTCUBEMASK_VERSION) | |
| 54 | +ctcubemask::ctcubemask(void) : ctobservation(CTCUBEMASK_NAME, VERSION) | |
| 55 | 55 | { |
| 56 | 56 | // Initialise members |
| 57 | 57 | init_members(); |
| ... | ... | @@ -70,7 +70,7 @@ ctcubemask::ctcubemask(void) : ctobservation(CTCUBEMASK_NAME, CTCUBEMASK_VERSION |
| 70 | 70 | * an observation container. |
| 71 | 71 | ***************************************************************************/ |
| 72 | 72 | ctcubemask::ctcubemask(const GObservations& obs) : |
| 73 | - ctobservation(CTCUBEMASK_NAME, CTCUBEMASK_VERSION, obs) | |
| 73 | + ctobservation(CTCUBEMASK_NAME, VERSION, obs) | |
| 74 | 74 | { |
| 75 | 75 | // Initialise members |
| 76 | 76 | init_members(); |
| ... | ... | @@ -89,7 +89,7 @@ ctcubemask::ctcubemask(const GObservations& obs) : |
| 89 | 89 | * @param[in] argv Array of command line arguments. |
| 90 | 90 | ***************************************************************************/ |
| 91 | 91 | ctcubemask::ctcubemask(int argc, char *argv[]) : |
| 92 | - ctobservation(CTCUBEMASK_NAME, CTCUBEMASK_VERSION, argc, argv) | |
| 92 | + ctobservation(CTCUBEMASK_NAME, VERSION, argc, argv) | |
| 93 | 93 | { |
| 94 | 94 | // Initialise members |
| 95 | 95 | init_members(); | ... | ... |
src/ctcubemask/ctcubemask.hpp
| ... | ... | @@ -35,8 +35,7 @@ |
| 35 | 35 | #include "ctobservation.hpp" |
| 36 | 36 | |
| 37 | 37 | /* __Definitions _________________________________________________________ */ |
| 38 | -#define CTCUBEMASK_NAME "ctcubemask" | |
| 39 | -#define CTCUBEMASK_VERSION "1.2.0" | |
| 38 | +#define CTCUBEMASK_NAME "ctcubemask" | |
| 40 | 39 | |
| 41 | 40 | |
| 42 | 41 | /***********************************************************************//** | ... | ... |
src/ctedispcube/ctedispcube.cpp
| ... | ... | @@ -52,7 +52,7 @@ |
| 52 | 52 | * |
| 53 | 53 | * Constructs an empty energy dispersion tool. |
| 54 | 54 | ***************************************************************************/ |
| 55 | -ctedispcube::ctedispcube(void) : ctobservation(CTEDISPCUBE_NAME, CTEDISPCUBE_VERSION) | |
| 55 | +ctedispcube::ctedispcube(void) : ctobservation(CTEDISPCUBE_NAME, VERSION) | |
| 56 | 56 | { |
| 57 | 57 | // Initialise members |
| 58 | 58 | init_members(); |
| ... | ... | @@ -71,7 +71,7 @@ ctedispcube::ctedispcube(void) : ctobservation(CTEDISPCUBE_NAME, CTEDISPCUBE_VER |
| 71 | 71 | * in an observation container @p obs. |
| 72 | 72 | ***************************************************************************/ |
| 73 | 73 | ctedispcube::ctedispcube(const GObservations& obs) : |
| 74 | - ctobservation(CTEDISPCUBE_NAME, CTEDISPCUBE_VERSION, obs) | |
| 74 | + ctobservation(CTEDISPCUBE_NAME, VERSION, obs) | |
| 75 | 75 | { |
| 76 | 76 | // Initialise members |
| 77 | 77 | init_members(); |
| ... | ... | @@ -92,7 +92,7 @@ ctedispcube::ctedispcube(const GObservations& obs) : |
| 92 | 92 | * on the command line. |
| 93 | 93 | ***************************************************************************/ |
| 94 | 94 | ctedispcube::ctedispcube(int argc, char *argv[]) : |
| 95 | - ctobservation(CTEDISPCUBE_NAME, CTEDISPCUBE_VERSION, argc, argv) | |
| 95 | + ctobservation(CTEDISPCUBE_NAME, VERSION, argc, argv) | |
| 96 | 96 | { |
| 97 | 97 | // Initialise members |
| 98 | 98 | init_members(); | ... | ... |
src/ctedispcube/ctedispcube.hpp
| ... | ... | @@ -33,8 +33,7 @@ |
| 33 | 33 | #include "ctobservation.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __Definitions _________________________________________________________ */ |
| 36 | -#define CTEDISPCUBE_NAME "ctedispcube" | |
| 37 | -#define CTEDISPCUBE_VERSION "1.1.0" | |
| 36 | +#define CTEDISPCUBE_NAME "ctedispcube" | |
| 38 | 37 | |
| 39 | 38 | |
| 40 | 39 | /***********************************************************************//** | ... | ... |
src/cterror/cterror.cpp
| ... | ... | @@ -52,7 +52,7 @@ |
| 52 | 52 | * |
| 53 | 53 | * Constructs an empty cterror tool. |
| 54 | 54 | ***************************************************************************/ |
| 55 | -cterror::cterror(void) : ctlikelihood(CTERROR_NAME, CTERROR_VERSION) | |
| 55 | +cterror::cterror(void) : ctlikelihood(CTERROR_NAME, VERSION) | |
| 56 | 56 | { |
| 57 | 57 | // Initialise members |
| 58 | 58 | init_members(); |
| ... | ... | @@ -70,7 +70,7 @@ cterror::cterror(void) : ctlikelihood(CTERROR_NAME, CTERROR_VERSION) |
| 70 | 70 | * Constructs cterror tool from an observations container. |
| 71 | 71 | ***************************************************************************/ |
| 72 | 72 | cterror::cterror(const GObservations& obs) : |
| 73 | - ctlikelihood(CTERROR_NAME, CTERROR_VERSION, obs) | |
| 73 | + ctlikelihood(CTERROR_NAME, VERSION, obs) | |
| 74 | 74 | { |
| 75 | 75 | // Initialise members |
| 76 | 76 | init_members(); |
| ... | ... | @@ -90,7 +90,7 @@ cterror::cterror(const GObservations& obs) : |
| 90 | 90 | * parameters that are provided as command line arguments. |
| 91 | 91 | ***************************************************************************/ |
| 92 | 92 | cterror::cterror(int argc, char *argv[]) : |
| 93 | - ctlikelihood(CTERROR_NAME, CTERROR_VERSION, argc, argv) | |
| 93 | + ctlikelihood(CTERROR_NAME, VERSION, argc, argv) | |
| 94 | 94 | { |
| 95 | 95 | // Initialise members |
| 96 | 96 | init_members(); | ... | ... |
src/cterror/cterror.hpp
| ... | ... | @@ -31,8 +31,7 @@ |
| 31 | 31 | #include "ctlikelihood.hpp" |
| 32 | 32 | |
| 33 | 33 | /* __Definitions _________________________________________________________ */ |
| 34 | -#define CTERROR_NAME "cterror" | |
| 35 | -#define CTERROR_VERSION "1.2.0" | |
| 34 | +#define CTERROR_NAME "cterror" | |
| 36 | 35 | |
| 37 | 36 | |
| 38 | 37 | /***********************************************************************//** | ... | ... |
src/ctexpcube/ctexpcube.cpp
| ... | ... | @@ -50,7 +50,7 @@ |
| 50 | 50 | /***********************************************************************//** |
| 51 | 51 | * @brief Void constructor |
| 52 | 52 | ***************************************************************************/ |
| 53 | -ctexpcube::ctexpcube(void) : ctobservation(CTEXPCUBE_NAME, CTEXPCUBE_VERSION) | |
| 53 | +ctexpcube::ctexpcube(void) : ctobservation(CTEXPCUBE_NAME, VERSION) | |
| 54 | 54 | { |
| 55 | 55 | // Initialise members |
| 56 | 56 | init_members(); |
| ... | ... | @@ -69,7 +69,7 @@ ctexpcube::ctexpcube(void) : ctobservation(CTEXPCUBE_NAME, CTEXPCUBE_VERSION) |
| 69 | 69 | * observations container. |
| 70 | 70 | ***************************************************************************/ |
| 71 | 71 | ctexpcube::ctexpcube(const GObservations& obs) : |
| 72 | - ctobservation(CTEXPCUBE_NAME, CTEXPCUBE_VERSION, obs) | |
| 72 | + ctobservation(CTEXPCUBE_NAME, VERSION, obs) | |
| 73 | 73 | { |
| 74 | 74 | // Initialise members |
| 75 | 75 | init_members(); |
| ... | ... | @@ -87,7 +87,7 @@ ctexpcube::ctexpcube(const GObservations& obs) : |
| 87 | 87 | * @param[in] argv Array of command line arguments. |
| 88 | 88 | ***************************************************************************/ |
| 89 | 89 | ctexpcube::ctexpcube(int argc, char *argv[]) : |
| 90 | - ctobservation(CTEXPCUBE_NAME, CTEXPCUBE_VERSION, argc, argv) | |
| 90 | + ctobservation(CTEXPCUBE_NAME, VERSION, argc, argv) | |
| 91 | 91 | { |
| 92 | 92 | // Initialise members |
| 93 | 93 | init_members(); | ... | ... |
src/ctexpcube/ctexpcube.hpp
| ... | ... | @@ -33,8 +33,7 @@ |
| 33 | 33 | #include "ctobservation.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __Definitions _________________________________________________________ */ |
| 36 | -#define CTEXPCUBE_NAME "ctexpcube" | |
| 37 | -#define CTEXPCUBE_VERSION "1.1.0" | |
| 36 | +#define CTEXPCUBE_NAME "ctexpcube" | |
| 38 | 37 | |
| 39 | 38 | |
| 40 | 39 | /***********************************************************************//** | ... | ... |
src/ctlike/ctlike.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctlike - Maximum likelihood fitting tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2016 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2017 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -48,7 +48,7 @@ |
| 48 | 48 | /***********************************************************************//** |
| 49 | 49 | * @brief Void constructor |
| 50 | 50 | ***************************************************************************/ |
| 51 | -ctlike::ctlike(void) : ctlikelihood(CTLIKE_NAME, CTLIKE_VERSION) | |
| 51 | +ctlike::ctlike(void) : ctlikelihood(CTLIKE_NAME, VERSION) | |
| 52 | 52 | { |
| 53 | 53 | // Initialise members |
| 54 | 54 | init_members(); |
| ... | ... | @@ -66,7 +66,7 @@ ctlike::ctlike(void) : ctlikelihood(CTLIKE_NAME, CTLIKE_VERSION) |
| 66 | 66 | * Constructs ctlike tool from an observations container. |
| 67 | 67 | ***************************************************************************/ |
| 68 | 68 | ctlike::ctlike(const GObservations& obs) : |
| 69 | - ctlikelihood(CTLIKE_NAME, CTLIKE_VERSION, obs) | |
| 69 | + ctlikelihood(CTLIKE_NAME, VERSION, obs) | |
| 70 | 70 | { |
| 71 | 71 | // Initialise members |
| 72 | 72 | init_members(); |
| ... | ... | @@ -86,7 +86,7 @@ ctlike::ctlike(const GObservations& obs) : |
| 86 | 86 | * that are provided as command line arguments. |
| 87 | 87 | ***************************************************************************/ |
| 88 | 88 | ctlike::ctlike(int argc, char *argv[]) : |
| 89 | - ctlikelihood(CTLIKE_NAME, CTLIKE_VERSION, argc, argv) | |
| 89 | + ctlikelihood(CTLIKE_NAME, VERSION, argc, argv) | |
| 90 | 90 | { |
| 91 | 91 | // Initialise members |
| 92 | 92 | init_members(); |
| ... | ... | @@ -321,8 +321,13 @@ void ctlike::run(void) |
| 321 | 321 | /***********************************************************************//** |
| 322 | 322 | * @brief Save results |
| 323 | 323 | * |
| 324 | - * This method saves the fit results into a XML file and a FITS file. If | |
| 325 | - * the filename parameters are "NONE", the files are not saved. | |
| 324 | + * This method saves the fit results and the covariance matrix. The fit | |
| 325 | + * results are written into a XML file while the covariance matrix is written | |
| 326 | + * into either a FITS or a CSV file, depending on the file type extension | |
| 327 | + * (an extension of `.fits` or `.fit` produce a FITS file, any other | |
| 328 | + * extension produces a CSV file). | |
| 329 | + * | |
| 330 | + * If the filenames are `NONE` no information is saved. | |
| 326 | 331 | ***************************************************************************/ |
| 327 | 332 | void ctlike::save(void) |
| 328 | 333 | { | ... | ... |
src/ctlike/ctlike.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctlike - Maximum likelihood fitting tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2016 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2017 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -31,8 +31,7 @@ |
| 31 | 31 | #include "ctlikelihood.hpp" |
| 32 | 32 | |
| 33 | 33 | /* __Definitions _________________________________________________________ */ |
| 34 | -#define CTLIKE_NAME "ctlike" | |
| 35 | -#define CTLIKE_VERSION "1.2.0" | |
| 34 | +#define CTLIKE_NAME "ctlike" | |
| 36 | 35 | |
| 37 | 36 | |
| 38 | 37 | /***********************************************************************//** |
| ... | ... | @@ -68,17 +67,17 @@ protected: |
| 68 | 67 | double reoptimize_lm(void); |
| 69 | 68 | |
| 70 | 69 | // User parameters |
| 71 | - bool m_refit; //!< Refitting | |
| 72 | - GFilename m_outmodel; //!< Source model output XML file name | |
| 73 | - GFilename m_outcovmat; //!< Covariance matrix output FITS file name | |
| 74 | - bool m_apply_edisp; //!< Apply energy dispersion? | |
| 75 | - bool m_fix_spat_for_ts; //!< Fix spatial parameters for TS computation? | |
| 76 | - GChatter m_chatter; //!< Chattiness | |
| 70 | + bool m_refit; //!< Refitting | |
| 71 | + GFilename m_outmodel; //!< Source model output XML file name | |
| 72 | + GFilename m_outcovmat; //!< Covariance matrix output file name | |
| 73 | + bool m_apply_edisp; //!< Apply energy dispersion? | |
| 74 | + bool m_fix_spat_for_ts; //!< Fix spatial parameters for TS computation? | |
| 75 | + GChatter m_chatter; //!< Chattiness | |
| 77 | 76 | |
| 78 | 77 | // Members |
| 79 | - int m_max_iter; //!< Maximum number of iterations | |
| 80 | - int m_max_stall; //!< Maximum number of stalls | |
| 81 | - double m_logL; //!< Maximum log likelihood | |
| 78 | + int m_max_iter; //!< Maximum number of iterations | |
| 79 | + int m_max_stall; //!< Maximum number of stalls | |
| 80 | + double m_logL; //!< Maximum log likelihood | |
| 82 | 81 | }; |
| 83 | 82 | |
| 84 | 83 | #endif /* CTLIKE_HPP */ | ... | ... |
src/ctmapcube/ctmapcube.cpp
| ... | ... | @@ -50,7 +50,7 @@ |
| 50 | 50 | /***********************************************************************//** |
| 51 | 51 | * @brief Void constructor |
| 52 | 52 | ***************************************************************************/ |
| 53 | -ctmapcube::ctmapcube(void) : ctool(CTMAPCUBE_NAME, CTMAPCUBE_VERSION) | |
| 53 | +ctmapcube::ctmapcube(void) : ctool(CTMAPCUBE_NAME, VERSION) | |
| 54 | 54 | { |
| 55 | 55 | // Initialise members |
| 56 | 56 | init_members(); |
| ... | ... | @@ -67,7 +67,7 @@ ctmapcube::ctmapcube(void) : ctool(CTMAPCUBE_NAME, CTMAPCUBE_VERSION) |
| 67 | 67 | * @param[in] argv Array of command line arguments. |
| 68 | 68 | ***************************************************************************/ |
| 69 | 69 | ctmapcube::ctmapcube(int argc, char *argv[]) : |
| 70 | - ctool(CTMAPCUBE_NAME, CTMAPCUBE_VERSION, argc, argv) | |
| 70 | + ctool(CTMAPCUBE_NAME, VERSION, argc, argv) | |
| 71 | 71 | { |
| 72 | 72 | // Initialise members |
| 73 | 73 | init_members(); | ... | ... |
src/ctmapcube/ctmapcube.hpp
| ... | ... | @@ -33,8 +33,7 @@ |
| 33 | 33 | #include "ctool.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __Definitions _________________________________________________________ */ |
| 36 | -#define CTMAPCUBE_NAME "ctmapcube" | |
| 37 | -#define CTMAPCUBE_VERSION "1.3.0" | |
| 36 | +#define CTMAPCUBE_NAME "ctmapcube" | |
| 38 | 37 | |
| 39 | 38 | |
| 40 | 39 | /***********************************************************************//** | ... | ... |
src/ctmodel/ctmodel.cpp
| ... | ... | @@ -53,7 +53,7 @@ const GEnergy g_energy_margin(1.0e-12, "TeV"); |
| 53 | 53 | /***********************************************************************//** |
| 54 | 54 | * @brief Void constructor |
| 55 | 55 | ***************************************************************************/ |
| 56 | -ctmodel::ctmodel(void) : ctobservation(CTMODEL_NAME, CTMODEL_VERSION) | |
| 56 | +ctmodel::ctmodel(void) : ctobservation(CTMODEL_NAME, VERSION) | |
| 57 | 57 | { |
| 58 | 58 | // Initialise members |
| 59 | 59 | init_members(); |
| ... | ... | @@ -72,7 +72,7 @@ ctmodel::ctmodel(void) : ctobservation(CTMODEL_NAME, CTMODEL_VERSION) |
| 72 | 72 | * observations container. |
| 73 | 73 | ***************************************************************************/ |
| 74 | 74 | ctmodel::ctmodel(const GObservations& obs) : |
| 75 | - ctobservation(CTMODEL_NAME, CTMODEL_VERSION, obs) | |
| 75 | + ctobservation(CTMODEL_NAME, VERSION, obs) | |
| 76 | 76 | { |
| 77 | 77 | // Initialise members |
| 78 | 78 | init_members(); |
| ... | ... | @@ -90,7 +90,7 @@ ctmodel::ctmodel(const GObservations& obs) : |
| 90 | 90 | * @param[in] argv Array of command line arguments. |
| 91 | 91 | ***************************************************************************/ |
| 92 | 92 | ctmodel::ctmodel(int argc, char *argv[]) : |
| 93 | - ctobservation(CTMODEL_NAME, CTMODEL_VERSION, argc, argv) | |
| 93 | + ctobservation(CTMODEL_NAME, VERSION, argc, argv) | |
| 94 | 94 | { |
| 95 | 95 | // Initialise members |
| 96 | 96 | init_members(); | ... | ... |
src/ctmodel/ctmodel.hpp
| ... | ... | @@ -33,8 +33,7 @@ |
| 33 | 33 | #include "ctobservation.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __Definitions _________________________________________________________ */ |
| 36 | -#define CTMODEL_NAME "ctmodel" | |
| 37 | -#define CTMODEL_VERSION "1.1.0" | |
| 36 | +#define CTMODEL_NAME "ctmodel" | |
| 38 | 37 | |
| 39 | 38 | |
| 40 | 39 | /***********************************************************************//** | ... | ... |
src/ctobssim/ctobssim.cpp
| ... | ... | @@ -67,7 +67,7 @@ const double g_roi_margin = 0.5; //!< Simulation radius margin (degrees) |
| 67 | 67 | * |
| 68 | 68 | * Constructs an empty ctobssim tool. |
| 69 | 69 | ***************************************************************************/ |
| 70 | -ctobssim::ctobssim(void) : ctobservation(CTOBSSIM_NAME, CTOBSSIM_VERSION) | |
| 70 | +ctobssim::ctobssim(void) : ctobservation(CTOBSSIM_NAME, VERSION) | |
| 71 | 71 | { |
| 72 | 72 | // Initialise members |
| 73 | 73 | init_members(); |
| ... | ... | @@ -85,7 +85,7 @@ ctobssim::ctobssim(void) : ctobservation(CTOBSSIM_NAME, CTOBSSIM_VERSION) |
| 85 | 85 | * Constructs ctobssim tool from an observation container. |
| 86 | 86 | ***************************************************************************/ |
| 87 | 87 | ctobssim::ctobssim(const GObservations& obs) : |
| 88 | - ctobservation(CTOBSSIM_NAME, CTOBSSIM_VERSION, obs) | |
| 88 | + ctobservation(CTOBSSIM_NAME, VERSION, obs) | |
| 89 | 89 | { |
| 90 | 90 | // Initialise members |
| 91 | 91 | init_members(); |
| ... | ... | @@ -105,7 +105,7 @@ ctobssim::ctobssim(const GObservations& obs) : |
| 105 | 105 | * setting. |
| 106 | 106 | ***************************************************************************/ |
| 107 | 107 | ctobssim::ctobssim(int argc, char *argv[]) : |
| 108 | - ctobservation(CTOBSSIM_NAME, CTOBSSIM_VERSION, argc, argv) | |
| 108 | + ctobservation(CTOBSSIM_NAME, VERSION, argc, argv) | |
| 109 | 109 | { |
| 110 | 110 | // Initialise members |
| 111 | 111 | init_members(); |
| ... | ... | @@ -1471,7 +1471,8 @@ void ctobssim::simulate_background(GCTAObservation* obs, |
| 1471 | 1471 | |
| 1472 | 1472 | // Debug code: signal that we step into the response MC method |
| 1473 | 1473 | #if defined(G_BACKGROUND_DEBUG) |
| 1474 | - std::cout << "ctobssim::simulate_background: model->mc in" << std::endl; | |
| 1474 | + std::cout << "ctobssim::simulate_background: model->mc in" | |
| 1475 | + << std::endl; | |
| 1475 | 1476 | #endif |
| 1476 | 1477 | |
| 1477 | 1478 | // Get simulated CTA event list. Note that this method |
| ... | ... | @@ -1481,7 +1482,8 @@ void ctobssim::simulate_background(GCTAObservation* obs, |
| 1481 | 1482 | |
| 1482 | 1483 | // Debug code: signal that we came back |
| 1483 | 1484 | #if defined(G_BACKGROUND_DEBUG) |
| 1484 | - std::cout << "ctobssim::simulate_background: model->mc out" << std::endl; | |
| 1485 | + std::cout << "ctobssim::simulate_background: model->mc out" | |
| 1486 | + << std::endl; | |
| 1485 | 1487 | #endif |
| 1486 | 1488 | |
| 1487 | 1489 | // Continue only if we got a CTA event list | ... | ... |
src/ctobssim/ctobssim.hpp
| ... | ... | @@ -33,8 +33,7 @@ |
| 33 | 33 | #include "ctobservation.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __Definitions _________________________________________________________ */ |
| 36 | -#define CTOBSSIM_NAME "ctobssim" | |
| 37 | -#define CTOBSSIM_VERSION "1.2.0" | |
| 36 | +#define CTOBSSIM_NAME "ctobssim" | |
| 38 | 37 | |
| 39 | 38 | |
| 40 | 39 | /***********************************************************************//** | ... | ... |
src/ctphase/Makefile.am
| 1 | 1 | ############################################################################# |
| 2 | 2 | # Makefile.am for ctphase tool # |
| 3 | 3 | # ------------------------------------------------------------------------- # |
| 4 | -# Copyright (C) 2017 Leonardo Di Venere # | |
| 4 | +# Copyright (C) 2017 Joshua Cardenzana # | |
| 5 | 5 | # ------------------------------------------------------------------------- # |
| 6 | 6 | # # |
| 7 | 7 | # This program is free software: you can redistribute it and/or modify # | ... | ... |
src/ctphase/ctphase.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctphase - Append phase information to CTA events file * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2017 by Leonardo Di Venere * | |
| 4 | + * copyright (C) 2017 by Joshua Cardenzana * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | /** |
| 22 | 22 | * @file ctphase.cpp |
| 23 | 23 | * @brief Append phase information to CTA events file |
| 24 | - * @author Leonardo Di Venere | |
| 24 | + * @author Joshua Cardenzana | |
| 25 | 25 | */ |
| 26 | 26 | |
| 27 | 27 | /* __ Includes ___________________________________________________________ */ |
| ... | ... | @@ -33,15 +33,12 @@ |
| 33 | 33 | #include "GTools.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __ Method name definitions ____________________________________________ */ |
| 36 | -#define G_RUN "ctphase::run()" | |
| 37 | -#define G_PHASE_EVENTS "ctphase::phase_events(GCTAObservation*, "\ | |
| 38 | - "std::string&, std::string&, std::string&)" | |
| 39 | -#define G_SET_EBOUNDS "ctphase::set_ebounds(GCTAObservation*, GEbounds&)" | |
| 36 | +#define G_GET_PARAMETERS "ctphase::get_parameters()" | |
| 37 | +#define G_PHASE_EVENTS "ctphase::phase_events(GCTAObservation*)" | |
| 40 | 38 | |
| 41 | 39 | /* __ Debug definitions __________________________________________________ */ |
| 42 | 40 | |
| 43 | 41 | /* __ Coding definitions _________________________________________________ */ |
| 44 | -//#define G_USE_MKSTEMP //!< Use mkstemp for temporary filename | |
| 45 | 42 | |
| 46 | 43 | |
| 47 | 44 | /*========================================================================== |
| ... | ... | @@ -53,7 +50,7 @@ |
| 53 | 50 | /***********************************************************************//** |
| 54 | 51 | * @brief Void constructor |
| 55 | 52 | ***************************************************************************/ |
| 56 | -ctphase::ctphase(void) : ctobservation(CTPHASE_NAME, CTPHASE_VERSION) | |
| 53 | +ctphase::ctphase(void) : ctobservation(CTPHASE_NAME, VERSION) | |
| 57 | 54 | { |
| 58 | 55 | // Initialise members |
| 59 | 56 | init_members(); |
| ... | ... | @@ -72,7 +69,7 @@ ctphase::ctphase(void) : ctobservation(CTPHASE_NAME, CTPHASE_VERSION) |
| 72 | 69 | * provided in an observation container. |
| 73 | 70 | ***************************************************************************/ |
| 74 | 71 | ctphase::ctphase(const GObservations& obs) : |
| 75 | - ctobservation(CTPHASE_NAME, CTPHASE_VERSION, obs) | |
| 72 | + ctobservation(CTPHASE_NAME, VERSION, obs) | |
| 76 | 73 | { |
| 77 | 74 | // Initialise members |
| 78 | 75 | init_members(); |
| ... | ... | @@ -91,7 +88,7 @@ ctphase::ctphase(const GObservations& obs) : |
| 91 | 88 | * @param[in] argv Array of command line arguments. |
| 92 | 89 | ***************************************************************************/ |
| 93 | 90 | ctphase::ctphase(int argc, char *argv[]) : |
| 94 | - ctobservation(CTPHASE_NAME, CTPHASE_VERSION, argc, argv) | |
| 91 | + ctobservation(CTPHASE_NAME, VERSION, argc, argv) | |
| 95 | 92 | { |
| 96 | 93 | // Initialise members |
| 97 | 94 | init_members(); |
| ... | ... | @@ -203,10 +200,11 @@ void ctphase::clear(void) |
| 203 | 200 | |
| 204 | 201 | |
| 205 | 202 | /***********************************************************************//** |
| 206 | - * @brief Append phase information to event data | |
| 203 | + * @brief Runs the ctprob tool | |
| 207 | 204 | * |
| 208 | 205 | * This method reads in the application parameters and loops over all |
| 209 | - * observations that were found to append phase information to the data. | |
| 206 | + * unbinned observations to compute the phase information for each event | |
| 207 | + * based on an input model. | |
| 210 | 208 | ***************************************************************************/ |
| 211 | 209 | void ctphase::run(void) |
| 212 | 210 | { |
| ... | ... | @@ -222,118 +220,22 @@ void ctphase::run(void) |
| 222 | 220 | log_observations(NORMAL, m_obs, "Input observation"); |
| 223 | 221 | |
| 224 | 222 | // Write header into logger |
| 225 | - log_header1(TERSE, "Appending phase informaiton"); | |
| 223 | + log_header1(TERSE, "Compute event phase"); | |
| 226 | 224 | |
| 227 | 225 | // Initialise counters |
| 228 | 226 | int n_observations = 0; |
| 229 | 227 | |
| 230 | - // Loop over all observation in the container | |
| 231 | - for (int i = 0; i < m_obs.size(); ++i) { | |
| 232 | - | |
| 233 | - // Write header for the current observation | |
| 234 | - log_header3(TERSE, get_obs_header(m_obs[i])); | |
| 235 | - | |
| 236 | - // Initialise event input and output filenames and the event | |
| 237 | - // and GTI extension names | |
| 238 | - m_infiles.push_back(""); | |
| 239 | - m_evtname.push_back(gammalib::extname_cta_events); | |
| 240 | - m_gtiname.push_back(gammalib::extname_gti); | |
| 241 | - | |
| 242 | - // Get CTA observation | |
| 243 | - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | |
| 244 | - | |
| 245 | - // Skip observation if it's not CTA | |
| 246 | - if (obs == NULL) { | |
| 247 | - std::string msg = " Skipping "+m_obs[i]->instrument()+ | |
| 248 | - " observation"; | |
| 249 | - log_string(NORMAL, msg); | |
| 250 | - continue; | |
| 251 | - } | |
| 252 | - | |
| 253 | - // Skip observation if we have a binned observation | |
| 254 | - if (obs->eventtype() == "CountsCube") { | |
| 255 | - std::string msg = " Skipping binned "+m_obs[i]->instrument()+ | |
| 256 | - " observation"; | |
| 257 | - log_string(NORMAL, msg); | |
| 258 | - continue; | |
| 259 | - } | |
| 228 | + // Loop over all unbinned CTA observations in the container | |
| 229 | + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; | |
| 230 | + obs = next_unbinned_observation()) { | |
| 260 | 231 | |
| 261 | 232 | // Increment counter |
| 262 | 233 | n_observations++; |
| 263 | 234 | |
| 264 | - // Save event file name (for possible saving) | |
| 265 | - m_infiles[i] = obs->eventfile(); | |
| 266 | - | |
| 267 | - // Extract event and GTI extension names from input FITS file | |
| 268 | - GFilename fname(m_infiles[i]); | |
| 269 | - if (fname.has_extname()) { | |
| 270 | - m_evtname[i] = fname.extname(); | |
| 271 | - } | |
| 272 | - m_gtiname[i] = get_gtiname(fname.url(), m_evtname[i]); | |
| 273 | - | |
| 274 | - // Write input file information into logger | |
| 275 | - log_value(NORMAL, "Input filename", m_infiles[i]); | |
| 276 | - log_value(NORMAL, "Event extension name", m_evtname[i]); | |
| 277 | - log_value(NORMAL, "GTI extension name", m_gtiname[i]); | |
| 278 | - | |
| 279 | - // Fall through in case that the event file is empty | |
| 280 | - if (obs->events()->size() == 0) { | |
| 281 | - log_string(NORMAL, " Warning: No events in event file \""+ | |
| 282 | - m_infiles[i]+"\". Event phasing skipped."); | |
| 283 | - continue; | |
| 284 | - } | |
| 235 | + // Compute event phase | |
| 236 | + phase_events(obs); | |
| 285 | 237 | |
| 286 | - // If we have an input file then check it | |
| 287 | - if (!m_infiles[i].empty()) { | |
| 288 | - std::string message = check_infile(m_infiles[i], m_evtname[i]); | |
| 289 | - if (!message.empty()) { | |
| 290 | - throw GException::invalid_value(G_RUN, message); | |
| 291 | - } | |
| 292 | - } | |
| 293 | - | |
| 294 | - // Get temporary file name | |
| 295 | - #if G_USE_MKSTEMP | |
| 296 | - char tpl[] = "ctphaseXXXXXX"; | |
| 297 | - int fileid = mkstemp(tpl); | |
| 298 | - std::string filename(tpl); | |
| 299 | - #else | |
| 300 | - std::string filename = std::tmpnam(NULL); | |
| 301 | - #endif | |
| 302 | - | |
| 303 | - // Save observation in temporary file. We add here the events and | |
| 304 | - // GTI extension name so that the GCTAObservation::save method can | |
| 305 | - // use this information for writing the proper extension names into | |
| 306 | - // the temporary file | |
| 307 | - obs->save(filename+"["+m_evtname[i]+";"+ m_gtiname[i]+"]", true); | |
| 308 | - | |
| 309 | - // Log saved FITS file. | |
| 310 | - if (logExplicit()) { | |
| 311 | - GFits tmpfile(filename); | |
| 312 | - log.header3("FITS file content of temporary file"); | |
| 313 | - log << tmpfile << std::endl; | |
| 314 | - tmpfile.close(); | |
| 315 | - } | |
| 316 | - | |
| 317 | - // If we have a temporary file then check it | |
| 318 | - if (!filename.empty()) { | |
| 319 | - std::string message = check_infile(filename, m_evtname[i]); | |
| 320 | - if (!message.empty()) { | |
| 321 | - throw GException::invalid_value(G_RUN, message); | |
| 322 | - } | |
| 323 | - } | |
| 324 | - | |
| 325 | - // Load observation from temporary file and compute phase | |
| 326 | - phase_events(obs, filename, m_evtname[i], m_gtiname[i]); | |
| 327 | - | |
| 328 | - // Close temporary file | |
| 329 | - #if G_USE_MKSTEMP | |
| 330 | - close(fileid); | |
| 331 | - #endif | |
| 332 | - | |
| 333 | - // Remove temporary file | |
| 334 | - std::remove(filename.c_str()); | |
| 335 | - | |
| 336 | - } // endfor: looped over all observations | |
| 238 | + } // endfor: looped over observations | |
| 337 | 239 | |
| 338 | 240 | // If more than a single observation has been handled then make sure that |
| 339 | 241 | // an XML file will be used for storage |
| ... | ... | @@ -380,12 +282,12 @@ void ctphase::save(void) |
| 380 | 282 | |
| 381 | 283 | // Case A: Save event file(s) and XML metadata information |
| 382 | 284 | if (m_use_xml) { |
| 383 | - save_xml(); | |
| 285 | + save_events_xml(); | |
| 384 | 286 | } |
| 385 | 287 | |
| 386 | 288 | // Case B: Save event file as FITS file |
| 387 | 289 | else { |
| 388 | - save_fits(); | |
| 290 | + save_events_fits(); | |
| 389 | 291 | } |
| 390 | 292 | |
| 391 | 293 | // Return |
| ... | ... | @@ -459,15 +361,10 @@ void ctphase::publish(const std::string& name) |
| 459 | 361 | void ctphase::init_members(void) |
| 460 | 362 | { |
| 461 | 363 | // Initialise parameters |
| 462 | - m_outobs.clear(); | |
| 463 | - m_prefix.clear(); | |
| 464 | - m_phase.clear(); | |
| 465 | 364 | m_chatter = static_cast<GChatter>(2); |
| 466 | 365 | |
| 467 | 366 | // Initialise protected members |
| 468 | - m_infiles.clear(); | |
| 469 | - m_evtname.clear(); | |
| 470 | - m_gtiname.clear(); | |
| 367 | + m_phase.clear(); | |
| 471 | 368 | |
| 472 | 369 | // Return |
| 473 | 370 | return; |
| ... | ... | @@ -482,15 +379,10 @@ void ctphase::init_members(void) |
| 482 | 379 | void ctphase::copy_members(const ctphase& app) |
| 483 | 380 | { |
| 484 | 381 | // Copy parameters |
| 485 | - m_outobs = app.m_outobs; | |
| 486 | - m_prefix = app.m_prefix; | |
| 487 | - m_chatter = app.m_chatter; | |
| 382 | + m_chatter = app.m_chatter; | |
| 488 | 383 | |
| 489 | 384 | // Copy protected members |
| 490 | - m_infiles = app.m_infiles; | |
| 491 | - m_evtname = app.m_evtname; | |
| 492 | - m_gtiname = app.m_gtiname; | |
| 493 | - m_phase = app.m_phase; | |
| 385 | + m_phase = app.m_phase; | |
| 494 | 386 | |
| 495 | 387 | // Return |
| 496 | 388 | return; |
| ... | ... | @@ -502,8 +394,6 @@ void ctphase::copy_members(const ctphase& app) |
| 502 | 394 | ***************************************************************************/ |
| 503 | 395 | void ctphase::free_members(void) |
| 504 | 396 | { |
| 505 | - m_phase.clear(); | |
| 506 | - | |
| 507 | 397 | // Return |
| 508 | 398 | return; |
| 509 | 399 | } |
| ... | ... | @@ -526,381 +416,81 @@ void ctphase::get_parameters(void) |
| 526 | 416 | // information and do not accept counts cubes. |
| 527 | 417 | setup_observations(m_obs, false, true, false); |
| 528 | 418 | |
| 529 | - // Check whether a model XML file and source name were supplied | |
| 530 | - if (!((*this)["inmodel"].filename().file().empty()) && | |
| 531 | - !((*this)["source"].string().empty())) { | |
| 532 | - | |
| 533 | - // Get the information from an xml file | |
| 534 | - read_phase_info_from_xml(); | |
| 535 | - } | |
| 536 | - | |
| 537 | - // Check for sanity of frequency and phase information | |
| 538 | - else if ((*this)["p0"].is_valid() && | |
| 539 | - (*this)["mjd"].is_valid() && | |
| 540 | - (*this)["f0"].is_valid()&& | |
| 541 | - (*this)["f1"].is_valid()&& | |
| 542 | - (*this)["f2"].is_valid()) { | |
| 543 | - | |
| 544 | - // The following creates an XML object responsible for initializing | |
| 545 | - // 'm_phase'. This was done as the default values for the parameters in | |
| 546 | - // 'GModelTemporalPhaseCurve' are such that the ranges are predefined. | |
| 547 | - // Initializing 'm_phase' from an XML object circumvents this restriction. | |
| 548 | - | |
| 549 | - GXmlElement norm; | |
| 550 | - norm.name("parameter"); | |
| 551 | - norm.attribute("name", "Normalization"); | |
| 552 | - norm.attribute("value", "1"); | |
| 553 | - norm.attribute("min", "0"); | |
| 554 | - norm.attribute("max", "1000"); | |
| 555 | - | |
| 556 | - GXmlElement mjd; | |
| 557 | - mjd.name("parameter"); | |
| 558 | - mjd.attribute("name", "MJD"); | |
| 559 | - mjd.attribute("value", (*this)["mjd"].value()); | |
| 560 | - mjd.attribute("min", (*this)["mjd"].min()); | |
| 561 | - mjd.attribute("max", (*this)["mjd"].max()); | |
| 562 | - | |
| 563 | - GXmlElement p0; | |
| 564 | - p0.name("parameter"); | |
| 565 | - p0.attribute("name", "Phase"); | |
| 566 | - p0.attribute("value", (*this)["p0"].value()); | |
| 567 | - p0.attribute("min", (*this)["p0"].min()); | |
| 568 | - p0.attribute("max", (*this)["p0"].max()); | |
| 569 | - | |
| 570 | - GXmlElement f0; | |
| 571 | - f0.name("parameter"); | |
| 572 | - f0.attribute("name", "F0"); | |
| 573 | - f0.attribute("value", (*this)["f0"].value()); | |
| 574 | - f0.attribute("min", (*this)["f0"].min()); | |
| 575 | - f0.attribute("max", (*this)["f0"].max()); | |
| 576 | - | |
| 577 | - GXmlElement f1; | |
| 578 | - f1.name("parameter"); | |
| 579 | - f1.attribute("name", "F1"); | |
| 580 | - f1.attribute("value", (*this)["f1"].value()); | |
| 581 | - f1.attribute("min", (*this)["f1"].min()); | |
| 582 | - f1.attribute("max", (*this)["f1"].max()); | |
| 583 | - | |
| 584 | - GXmlElement f2; | |
| 585 | - f2.name("parameter"); | |
| 586 | - f2.attribute("name", "F2"); | |
| 587 | - f2.attribute("value", (*this)["f2"].value()); | |
| 588 | - f2.attribute("min", (*this)["f2"].min()); | |
| 589 | - f2.attribute("max", (*this)["f2"].max()); | |
| 590 | - | |
| 591 | - GXmlElement info; | |
| 592 | - info.append(norm); | |
| 593 | - info.append(mjd); | |
| 594 | - info.append(p0); | |
| 595 | - info.append(f0); | |
| 596 | - info.append(f1); | |
| 597 | - info.append(f2); | |
| 598 | - | |
| 599 | - info.attribute("file",""); | |
| 600 | - | |
| 601 | - m_phase = GModelTemporalPhaseCurve(); | |
| 602 | - m_phase.read(info); | |
| 603 | - } | |
| 604 | - else { | |
| 605 | - GException::invalid_value("ctphase::get_parameters()", | |
| 606 | - "Invalid parameter value for p0, mjd, f0, f1, or f2."); | |
| 607 | - } | |
| 608 | - | |
| 609 | - // Get other User parameters | |
| 610 | - m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 611 | - | |
| 612 | - // Optionally read ahead parameters so that they get correctly | |
| 613 | - // dumped into the log file | |
| 614 | - if (read_ahead()) { | |
| 615 | - m_outobs = (*this)["outobs"].filename(); | |
| 616 | - m_prefix = (*this)["prefix"].string(); | |
| 617 | - } | |
| 618 | - | |
| 619 | - // Write parameters into logger | |
| 620 | - log_parameters(TERSE); | |
| 621 | - | |
| 622 | - // Return | |
| 623 | - return; | |
| 624 | -} | |
| 625 | - | |
| 626 | -/************************************************************************* | |
| 627 | - * @brief Read phase information from XML file | |
| 628 | - * | |
| 629 | - * @exception GException::par_error | |
| 630 | - * Source does not have a temporal component with phase information. | |
| 631 | - ***************************************************************************/ | |
| 632 | -void ctphase::read_phase_info_from_xml(void) | |
| 633 | -{ | |
| 634 | - // Load the models from the xml file | |
| 635 | - GModels in_models((*this)["inmodel"].filename()); | |
| 636 | - | |
| 637 | - // Get the temporal component of this source | |
| 638 | - std::string src_name = (*this)["source"].string(); | |
| 639 | - GModelSky* model = dynamic_cast<GModelSky*>(in_models[src_name]); | |
| 640 | - GModelTemporalPhaseCurve* temporal_model = dynamic_cast<GModelTemporalPhaseCurve*>(model->temporal()); | |
| 641 | - | |
| 642 | - // Make sure the model has a temporal component with phase info | |
| 643 | - if (temporal_model != NULL) { | |
| 644 | - | |
| 645 | - // Copy the phase model | |
| 646 | - m_phase = GModelTemporalPhaseCurve(*temporal_model); | |
| 647 | - | |
| 648 | - } else { | |
| 649 | - // Throw an error as there is no temporal component for this source | |
| 650 | - throw GException::par_error("ctphase::get_parameters(void)", | |
| 651 | - "source", | |
| 652 | - "\"" + src_name + "\" source model " + | |
| 653 | - "does not have a temporal component with "+ | |
| 654 | - "phase information!"); | |
| 655 | - } | |
| 656 | -} | |
| 657 | - | |
| 658 | - | |
| 659 | -/***********************************************************************//** | |
| 660 | - * @brief Define phase for events | |
| 661 | - * | |
| 662 | - * @param[in,out] obs CTA observation. | |
| 663 | - * @param[in] filename File name. | |
| 664 | - * @param[in] evtname Event extension name. | |
| 665 | - * @param[in] gtiname GTI extension name. | |
| 666 | - * | |
| 667 | - * @exception GException::invalid_value | |
| 668 | - * No events extension found in FITS file. | |
| 669 | - * | |
| 670 | - * Append phase information to events from a FITS file by adding a "PHASE" | |
| 671 | - * column to the FITS file. | |
| 672 | - ***************************************************************************/ | |
| 673 | -void ctphase::phase_events(GCTAObservation* obs, | |
| 674 | - const std::string& filename, | |
| 675 | - const std::string& evtname, | |
| 676 | - const std::string& gtiname) | |
| 677 | -{ | |
| 678 | - // Get CTA event list pointer | |
| 679 | - GCTAEventList* list = | |
| 680 | - static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events())); | |
| 681 | - | |
| 682 | - GCTAEventAtom* event = (*list)[0]; | |
| 683 | - | |
| 684 | - // Print a warning into the log file if there are some precision concerns | |
| 685 | - double dt = std::abs(event->time() - m_phase.mjd()); | |
| 686 | - if (((m_phase.f1() * dt) > 1.0e8) || | |
| 687 | - (m_phase.f2() * dt * dt) > 1.0e8) { | |
| 688 | - log_string(NORMAL,"*** WARNING ***"); | |
| 689 | - log_string(NORMAL," Values supplied for reference MJD and/or f1 and/or f2"); | |
| 690 | - log_string(NORMAL," are large and may result in numerical precision issues."); | |
| 691 | - log_string(NORMAL," Consider using an ephemeris derived from a date closer"); | |
| 692 | - log_string(NORMAL," to the data being analyzed."); | |
| 693 | - log_value(NORMAL, " Observation ID", obs->obs_id()); | |
| 694 | - log_value(NORMAL, " Reference MJD", m_phase.mjd().mjd()); | |
| 695 | - log_value(NORMAL, " First event MJD", event->time().mjd()); | |
| 696 | - log_string(NORMAL,"*** WARNING ***"); | |
| 697 | - } | |
| 698 | - | |
| 699 | - for (int evnt=0; evnt<list->size(); evnt++) { | |
| 700 | - // Get the next event | |
| 701 | - event = (*list)[evnt]; | |
| 702 | - | |
| 703 | - // Get the event time | |
| 704 | - GTime time = event->time(); | |
| 705 | - | |
| 706 | - // Set the event phase | |
| 707 | - event->phase(m_phase.phase(time)); | |
| 708 | - } | |
| 709 | - | |
| 710 | - // Make sure the file knows to save the phase information | |
| 711 | - if (!list->has_phase()) { | |
| 712 | - list->has_phase(true); | |
| 713 | - } | |
| 714 | - | |
| 715 | - // Return | |
| 716 | - return; | |
| 717 | -} | |
| 718 | - | |
| 719 | - | |
| 720 | -/***********************************************************************//** | |
| 721 | - * @brief Check input filename | |
| 722 | - * | |
| 723 | - * @param[in] filename File name. | |
| 724 | - * @param[in] evtname Event extension name. | |
| 725 | - * | |
| 726 | - * This method checks if the input FITS file is correct. | |
| 727 | - ***************************************************************************/ | |
| 728 | -std::string ctphase::check_infile(const std::string& filename, | |
| 729 | - const std::string& evtname) const | |
| 730 | -{ | |
| 731 | - // Initialise message string | |
| 732 | - std::string message = ""; | |
| 733 | - | |
| 734 | - // Open FITS file | |
| 735 | - GFits fits(filename); | |
| 736 | - | |
| 737 | - // Check for existence of events extensions | |
| 738 | - if (!fits.contains(evtname)) { | |
| 739 | - message = "No \""+evtname+"\" extension found in input file \""+ | |
| 740 | - filename + "\"."; | |
| 741 | - } | |
| 742 | - | |
| 743 | - // ... otherwise check column names | |
| 744 | - else { | |
| 419 | + // If a model definition XML file is provided the | |
| 420 | + GFilename inmodel = (*this)["inmodel"].filename(); | |
| 421 | + if (is_valid_filename(inmodel)) { | |
| 745 | 422 | |
| 746 | - // Get pointer to FITS table | |
| 747 | - GFitsTable* table = fits.table(evtname); | |
| 423 | + // Load the models from the XML file | |
| 424 | + GModels models(inmodel); | |
| 748 | 425 | |
| 749 | - // Initialise list of missing columns | |
| 750 | - std::vector<std::string> missing; | |
| 426 | + // Get the source component | |
| 427 | + std::string source = (*this)["source"].string(); | |
| 751 | 428 | |
| 752 | - // Check for existence of TIME column | |
| 753 | - if (!table->contains("TIME")) { | |
| 754 | - missing.push_back("TIME"); | |
| 429 | + // Throw an exception if source is not found in the model container | |
| 430 | + if (!models.contains(source)) { | |
| 431 | + std::string msg = "Source model \""+source+"\" not found in model " | |
| 432 | + "definition XML file \""+inmodel.url()+"\"."; | |
| 433 | + throw GException::invalid_value(G_GET_PARAMETERS, msg); | |
| 755 | 434 | } |
| 756 | 435 | |
| 757 | - // Check for existence of ENERGY column | |
| 758 | - if (!table->contains("ENERGY")) { | |
| 759 | - missing.push_back("ENERGY"); | |
| 760 | - } | |
| 436 | + // Get pointer to source model | |
| 437 | + GModelSky* sky = dynamic_cast<GModelSky*>(models[source]); | |
| 761 | 438 | |
| 762 | - // Check for existence of RA column | |
| 763 | - if (!table->contains("RA")) { | |
| 764 | - missing.push_back("RA"); | |
| 439 | + // Throw an exception if model is not a sky model | |
| 440 | + if (sky == NULL) { | |
| 441 | + std::string msg = "Source model \""+source+"\" is not a sky model."; | |
| 442 | + throw GException::invalid_value(G_GET_PARAMETERS, msg); | |
| 765 | 443 | } |
| 766 | 444 | |
| 767 | - // Check for existence of DEC column | |
| 768 | - if (!table->contains("DEC")) { | |
| 769 | - missing.push_back("DEC"); | |
| 770 | - } | |
| 445 | + // Get pointer to temporal phase curve | |
| 446 | + GModelTemporalPhaseCurve* phasecurve = | |
| 447 | + dynamic_cast<GModelTemporalPhaseCurve*>(sky->temporal()); | |
| 771 | 448 | |
| 772 | - // Set error message for missing columns | |
| 773 | - if (!missing.empty()) { | |
| 774 | - message = "The following columns are missing in the " | |
| 775 | - "\""+evtname+"\" extension of input file \""+ | |
| 776 | - filename + "\": "; | |
| 777 | - for (int i = 0; i < missing.size(); ++i) { | |
| 778 | - message += "\"" + missing[i] + "\""; | |
| 779 | - if (i < missing.size()-1) { | |
| 780 | - message += ", "; | |
| 781 | - } | |
| 782 | - } | |
| 449 | + // Throw an exception if model has not a temporal phase curve | |
| 450 | + // component | |
| 451 | + if (phasecurve == NULL) { | |
| 452 | + std::string msg = "Source model \""+source+"\" does not have a " | |
| 453 | + "temporal component with phase information."; | |
| 454 | + throw GException::invalid_value(G_GET_PARAMETERS, msg); | |
| 783 | 455 | } |
| 784 | 456 | |
| 785 | - } // endelse: checked column names | |
| 786 | - | |
| 787 | - // Return | |
| 788 | - return message; | |
| 789 | -} | |
| 790 | - | |
| 791 | - | |
| 792 | -/***********************************************************************//** | |
| 793 | - * @brief Set output file name. | |
| 794 | - * | |
| 795 | - * @param[in] filename Input file name. | |
| 796 | - * | |
| 797 | - * Converts an input file name into an output filename by prepending the | |
| 798 | - * prefix stored in the member m_prefix to the input file name. Any path as | |
| 799 | - * well as extension will be stripped from the input file name. Also a | |
| 800 | - * trailing ".gz" will be stripped as one cannot write into gzipped files. | |
| 801 | - ***************************************************************************/ | |
| 802 | -std::string ctphase::set_outfile_name(const std::string& filename) const | |
| 803 | -{ | |
| 804 | - // Create filename | |
| 805 | - GFilename fname(filename); | |
| 806 | - | |
| 807 | - // Split input filename without any extensions into path elements | |
| 808 | - std::vector<std::string> elements = gammalib::split(fname.url(), "/"); | |
| 809 | - | |
| 810 | - // The last path element is the filename | |
| 811 | - std::string outname = m_prefix + elements[elements.size()-1]; | |
| 812 | - | |
| 813 | - // Strip any ".gz" | |
| 814 | - outname = gammalib::strip_chars(outname, ".gz"); | |
| 815 | - | |
| 816 | - // Return output filename | |
| 817 | - return outname; | |
| 818 | -} | |
| 819 | - | |
| 820 | - | |
| 821 | -/***********************************************************************//** | |
| 822 | - * @brief Get Good Time Intervals extension name | |
| 823 | - * | |
| 824 | - * @param[in] filename Input file name. | |
| 825 | - * @param[in] evtname Events extension name. | |
| 826 | - * | |
| 827 | - * Extracts the Good Time Intervals extension name from the event file. We | |
| 828 | - * do this by loading the events and accessing the Good Time Intervals | |
| 829 | - * extension name using the GCTAEventList::gtiname() method. If the file name | |
| 830 | - * is empty, the method returns `GTI`. | |
| 831 | - ***************************************************************************/ | |
| 832 | -std::string ctphase::get_gtiname(const std::string& filename, | |
| 833 | - const std::string& evtname) const | |
| 834 | -{ | |
| 835 | - // Initialise GTI name | |
| 836 | - std::string gtiname = gammalib::extname_gti; | |
| 837 | - | |
| 838 | - // Continue only if the filename is not empty | |
| 839 | - if (!filename.empty()) { | |
| 457 | + // Set phase curve | |
| 458 | + m_phase = GModelTemporalPhaseCurve(*phasecurve); | |
| 840 | 459 | |
| 841 | - // Load events | |
| 842 | - GCTAEventList events(filename+"["+evtname+"]"); | |
| 460 | + } // endif: model definition XML file provided | |
| 843 | 461 | |
| 844 | - // Get GTI name | |
| 845 | - gtiname = events.gtiname(); | |
| 846 | - | |
| 847 | - } // endif: filename was not empty | |
| 848 | - | |
| 849 | - // Return GTI name | |
| 850 | - return (gtiname); | |
| 851 | -} | |
| 852 | - | |
| 853 | - | |
| 854 | -/***********************************************************************//** | |
| 855 | - * @brief Save event list in FITS format. | |
| 856 | - * | |
| 857 | - * Save the event list as a FITS file. The file name of the FITS file is | |
| 858 | - * specified by the "outobs" parameter. | |
| 859 | - ***************************************************************************/ | |
| 860 | -void ctphase::save_fits(void) | |
| 861 | -{ | |
| 862 | - // Save only if there are observations | |
| 863 | - if (m_obs.size() > 0) { | |
| 864 | - | |
| 865 | - // Get output filename | |
| 866 | - m_outobs = (*this)["outobs"].filename(); | |
| 867 | - | |
| 868 | - // Get CTA observation from observation container | |
| 869 | - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]); | |
| 870 | - | |
| 871 | - // Save only if it's a CTA observation | |
| 872 | - if (obs != NULL) { | |
| 873 | - | |
| 874 | - // Save only if file name is non-empty | |
| 875 | - if (m_infiles[0].length() > 0) { | |
| 462 | + // Otherwise read phase curve information from the parameter files | |
| 463 | + else { | |
| 876 | 464 | |
| 877 | - // Create file name object | |
| 878 | - GFilename fname(m_outobs); | |
| 465 | + // Read phase curve user parameters | |
| 466 | + GFilename phasecurve = (*this)["phasecurve"].filename(); | |
| 467 | + double mjd_value = (*this)["mjd"].real(); | |
| 468 | + double phase = (*this)["phase"].real(); | |
| 469 | + double f0 = (*this)["f0"].real(); | |
| 470 | + double f1 = (*this)["f1"].real(); | |
| 471 | + double f2 = (*this)["f2"].real(); | |
| 879 | 472 | |
| 880 | - // Extract filename and event extension name | |
| 881 | - std::string outfile = fname.url(); | |
| 473 | + // Set reference time | |
| 474 | + GTime mjd; | |
| 475 | + mjd.mjd(mjd_value); | |
| 882 | 476 | |
| 883 | - // Append event extension name. We handle here the possibility | |
| 884 | - // to write the events into a different extension. | |
| 885 | - if (fname.has_extname()) { | |
| 886 | - outfile += "["+fname.extname()+"]"; | |
| 887 | - } | |
| 888 | - else { | |
| 889 | - outfile += "["+m_evtname[0]+"]"; | |
| 890 | - } | |
| 477 | + // Set phase curve | |
| 478 | + m_phase = GModelTemporalPhaseCurve(phasecurve, mjd, phase, f0, f1, f2); | |
| 891 | 479 | |
| 892 | - // Log filename | |
| 893 | - log_value(NORMAL, "Event list file", outfile); | |
| 480 | + } // endelse: read phase curve information from User parameters | |
| 894 | 481 | |
| 895 | - // Save event list | |
| 896 | - save_event_list(obs, m_infiles[0], m_evtname[0], m_gtiname[0], | |
| 897 | - outfile); | |
| 898 | - | |
| 899 | - } // endif: filename was non empty | |
| 482 | + // Get other User parameters | |
| 483 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 900 | 484 | |
| 901 | - } // endif: observation was CTA observation | |
| 485 | + // Optionally read ahead parameters so that they get correctly | |
| 486 | + // dumped into the log file | |
| 487 | + if (read_ahead()) { | |
| 488 | + (*this)["outobs"].filename(); | |
| 489 | + (*this)["prefix"].string(); | |
| 490 | + } | |
| 902 | 491 | |
| 903 | - } // endif: there were observations | |
| 492 | + // Write parameters into logger | |
| 493 | + log_parameters(TERSE); | |
| 904 | 494 | |
| 905 | 495 | // Return |
| 906 | 496 | return; |
| ... | ... | @@ -908,169 +498,68 @@ void ctphase::save_fits(void) |
| 908 | 498 | |
| 909 | 499 | |
| 910 | 500 | /***********************************************************************//** |
| 911 | - * @brief Save event list(s) in XML format. | |
| 501 | + * @brief Compute event phase for an observation | |
| 912 | 502 | * |
| 913 | - * Save the event list(s) into FITS files and write the file path information | |
| 914 | - * into a XML file. The filename of the XML file is specified by the outfile | |
| 915 | - * parameter, the filename(s) of the event lists are built by prepending a | |
| 916 | - * prefix to the input event list filenames. Any path present in the input | |
| 917 | - * filename will be stripped, i.e. the event list(s) will be written in the | |
| 918 | - * local working directory (unless a path is specified in the prefix). | |
| 503 | + * @param[in,out] obs CTA observation. | |
| 504 | + * | |
| 505 | + * @exception GException::invalid_value | |
| 506 | + * No events extension found in FITS file. | |
| 507 | + * | |
| 508 | + * Append phase information to events from a FITS file by adding a "PHASE" | |
| 509 | + * column to the FITS file. | |
| 919 | 510 | ***************************************************************************/ |
| 920 | -void ctphase::save_xml(void) | |
| 511 | +void ctphase::phase_events(GCTAObservation* obs) | |
| 921 | 512 | { |
| 922 | - // Get output filename and prefix | |
| 923 | - m_outobs = (*this)["outobs"].filename(); | |
| 924 | - m_prefix = (*this)["prefix"].string(); | |
| 925 | - | |
| 926 | - // Issue warning if output filename has no .xml suffix | |
| 927 | - log_string(TERSE, warn_xml_suffix(m_outobs)); | |
| 928 | - | |
| 929 | - // Loop over all observation in the container | |
| 930 | - for (int i = 0; i < m_obs.size(); ++i) { | |
| 931 | - | |
| 932 | - // Get CTA observation | |
| 933 | - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | |
| 934 | - | |
| 935 | - // Skip observations that are no CTA observations | |
| 936 | - if (obs == NULL) { | |
| 937 | - continue; | |
| 938 | - } | |
| 513 | + // Write header into logger | |
| 514 | + log_header3(NORMAL, "Compute event phases"); | |
| 515 | + | |
| 516 | + // Make sure that the observation holds a CTA event list. If this | |
| 517 | + // is not the case then throw an exception. | |
| 518 | + GCTAEventList* events = dynamic_cast<GCTAEventList*>(const_cast<GEvents*> | |
| 519 | + (obs->events())); | |
| 520 | + if (events == NULL) { | |
| 521 | + std::string msg = "CTA Observation does not contain an event list. An " | |
| 522 | + "event list is needed to compute the event phases."; | |
| 523 | + throw GException::invalid_value(G_PHASE_EVENTS, msg); | |
| 524 | + } | |
| 939 | 525 | |
| 940 | - // Skip observations that have empty names | |
| 941 | - if (m_infiles[i].length() == 0) { | |
| 942 | - continue; | |
| 526 | + // Continue only if there are events | |
| 527 | + if (events->size() > 0) { | |
| 528 | + | |
| 529 | + // Print a warning into the log file if there are some precision concerns | |
| 530 | + GCTAEventAtom* event = (*events)[0]; | |
| 531 | + double dt = std::abs(event->time() - m_phase.mjd()); | |
| 532 | + if (((m_phase.f1() * dt) > 1.0e8) || | |
| 533 | + (m_phase.f2() * dt * dt) > 1.0e8) { | |
| 534 | + log_string(NORMAL,"*** WARNING ***"); | |
| 535 | + log_string(NORMAL," Values supplied for reference MJD and/or f1 and/or f2"); | |
| 536 | + log_string(NORMAL," are large and may result in numerical precision issues."); | |
| 537 | + log_string(NORMAL," Consider using an ephemeris derived from a date closer"); | |
| 538 | + log_string(NORMAL," to the data being analyzed."); | |
| 539 | + log_value(NORMAL, " Observation ID", obs->obs_id()); | |
| 540 | + log_value(NORMAL, " Reference MJD", m_phase.mjd().mjd()); | |
| 541 | + log_value(NORMAL, " First event MJD", event->time().mjd()); | |
| 542 | + log_string(NORMAL,"*** WARNING ***"); | |
| 943 | 543 | } |
| 944 | 544 | |
| 945 | - // Set event output file name | |
| 946 | - std::string outfile = set_outfile_name(m_infiles[i]); | |
| 947 | - | |
| 948 | - // Append event extension name | |
| 949 | - outfile += "["+m_evtname[i]+"]"; | |
| 950 | - | |
| 951 | - // Log filename | |
| 952 | - log_value(NORMAL, "Event list file", outfile); | |
| 953 | - | |
| 954 | - // Store output file name in observation | |
| 955 | - obs->eventfile(outfile); | |
| 956 | - | |
| 957 | - // Save event list | |
| 958 | - save_event_list(obs, m_infiles[i], m_evtname[i], m_gtiname[i], | |
| 959 | - outfile); | |
| 960 | - | |
| 961 | - } // endfor: looped over observations | |
| 962 | - | |
| 963 | - // Write observation definition XML file name into logger | |
| 964 | - log_value(NORMAL, "Obs. definition file", m_outobs); | |
| 965 | - | |
| 966 | - // Save observations in XML file | |
| 967 | - m_obs.save(m_outobs); | |
| 968 | - | |
| 969 | - // Return | |
| 970 | - return; | |
| 971 | -} | |
| 972 | - | |
| 545 | + // Compute the phase for all events | |
| 546 | + for (int i = 0; i < events->size(); ++i) { | |
| 973 | 547 | |
| 974 | -/***********************************************************************//** | |
| 975 | - * @brief Save event list into FITS file | |
| 976 | - * | |
| 977 | - * @param[in] obs Pointer to CTA observation. | |
| 978 | - * @param[in] infile Input file name. | |
| 979 | - * @param[in] evtname Event extension name. | |
| 980 | - * @param[in] gtiname GTI extension name. | |
| 981 | - * @param[in] outfile Output file name. | |
| 982 | - * | |
| 983 | - * Saves an event list and the corresponding Good Time Intervals into a FITS | |
| 984 | - * file and copy all others extensions from the input file to the output | |
| 985 | - * file. | |
| 986 | - * | |
| 987 | - * If an extension name is specified in the @p outfile argument, the events | |
| 988 | - * and eventually also the Good Time Intervals will be extracted from the | |
| 989 | - * argument and used for writing the events. The format is | |
| 990 | - * | |
| 991 | - * <filename>[<event extension name;GTI extension name>] | |
| 992 | - * | |
| 993 | - * where <filename> needs to be replaced by the name of the FITS file, | |
| 994 | - * and <event extension name;GTI extension name> by the name of the events | |
| 995 | - * and Good Time Intervals extensions. For example | |
| 996 | - * | |
| 997 | - * myfits.fits[EVENTS1;GTI1] | |
| 998 | - * | |
| 999 | - * will write the updated events into the "EVENTS1" extension and the | |
| 1000 | - * Good Time Intervals into the "GTI1" extension of the "myfits.fits" FITS | |
| 1001 | - * file. If the Good Time Intervals extension name is skipped, e.g. | |
| 1002 | - * | |
| 1003 | - * myfits.fits[EVENTS1] | |
| 1004 | - * | |
| 1005 | - * the original extension name for the Good Time Intervals will be kept. | |
| 1006 | - * Analogously, only the Good Time Intervals extension name can be changed | |
| 1007 | - * by specifying | |
| 1008 | - * | |
| 1009 | - * myfits.fits[;GTI1] | |
| 1010 | - * | |
| 1011 | - * In none of the cases will the original events and Good Time Intervals be | |
| 1012 | - * copied over to the output file. | |
| 1013 | - ***************************************************************************/ | |
| 1014 | -void ctphase::save_event_list(const GCTAObservation* obs, | |
| 1015 | - const std::string& infile, | |
| 1016 | - const std::string& evtname, | |
| 1017 | - const std::string& gtiname, | |
| 1018 | - const std::string& outfile) const | |
| 1019 | -{ | |
| 1020 | - // Save only if we have an event list | |
| 1021 | - if (obs->eventtype() == "EventList") { | |
| 1022 | - | |
| 1023 | - // Set output FITS file event extension names | |
| 1024 | - GFilename outname(outfile); | |
| 1025 | - std::string outevt = evtname; | |
| 1026 | - std::string outgti = gtiname; | |
| 1027 | - if (outname.has_extname()) { | |
| 1028 | - std::vector<std::string> extnames = | |
| 1029 | - gammalib::split(outname.extname(), ";"); | |
| 1030 | - if (extnames.size() > 0) { | |
| 1031 | - std::string extname = gammalib::strip_whitespace(extnames[0]); | |
| 1032 | - if (!extname.empty()) { | |
| 1033 | - outevt = extname; | |
| 1034 | - } | |
| 1035 | - } | |
| 1036 | - if (extnames.size() > 1) { | |
| 1037 | - std::string extname = gammalib::strip_whitespace(extnames[1]); | |
| 1038 | - if (!extname.empty()) { | |
| 1039 | - outgti = extname; | |
| 1040 | - } | |
| 1041 | - } | |
| 1042 | - } | |
| 548 | + // Get pointer to the event | |
| 549 | + GCTAEventAtom* event = (*events)[i]; | |
| 1043 | 550 | |
| 1044 | - // Create output FITS file | |
| 1045 | - GFits outfits; | |
| 1046 | - | |
| 1047 | - // Write observation into FITS file | |
| 1048 | - obs->write(outfits, outevt, outgti); | |
| 1049 | - | |
| 1050 | - // Copy all extensions other than evtname and gtiname extensions | |
| 1051 | - // from the input to the output event list. The evtname and | |
| 1052 | - // gtiname extensions are written by the save method, all others | |
| 1053 | - // that may eventually be present have to be copied over | |
| 1054 | - // explicitly. | |
| 1055 | - GFits infits(infile); | |
| 1056 | - for (int extno = 1; extno < infits.size(); ++extno) { | |
| 1057 | - GFitsHDU* hdu = infits.at(extno); | |
| 1058 | - if (hdu->extname() != evtname && | |
| 1059 | - hdu->extname() != gtiname && | |
| 1060 | - hdu->extname() != outevt && | |
| 1061 | - hdu->extname() != outgti) { | |
| 1062 | - outfits.append(*hdu); | |
| 1063 | - } | |
| 1064 | - } | |
| 1065 | - | |
| 1066 | - // Close input file | |
| 1067 | - infits.close(); | |
| 551 | + // Get the event time | |
| 552 | + GTime time = event->time(); | |
| 553 | + | |
| 554 | + // Set the event phase | |
| 555 | + event->phase(m_phase.phase(time)); | |
| 1068 | 556 | |
| 1069 | - // Save file to disk and close it (we need both operations) | |
| 1070 | - outfits.saveto(outname.url(), clobber()); | |
| 1071 | - outfits.close(); | |
| 557 | + } // endfor: looped over events | |
| 1072 | 558 | |
| 1073 | - } // endif: observation was unbinned | |
| 559 | + } // endif: there were events | |
| 560 | + | |
| 561 | + // Signal that phase information is available | |
| 562 | + events->has_phase(true); | |
| 1074 | 563 | |
| 1075 | 564 | // Return |
| 1076 | 565 | return; | ... | ... |
src/ctphase/ctphase.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctphase - Append phase information to CTA events file * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2017 by Leonardo Di Venere * | |
| 4 | + * copyright (C) 2017 by Joshua Cardenzana * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | /** |
| 22 | 22 | * @file ctphase.hpp |
| 23 | 23 | * @brief Append phase information to CTA events file |
| 24 | - * @author Leonardo Di Venere | |
| 24 | + * @author Joshua Cardenzana | |
| 25 | 25 | */ |
| 26 | 26 | |
| 27 | 27 | #ifndef CTPHASE_HPP |
| ... | ... | @@ -35,8 +35,7 @@ |
| 35 | 35 | #include "ctobservation.hpp" |
| 36 | 36 | |
| 37 | 37 | /* __Definitions _________________________________________________________ */ |
| 38 | -#define CTPHASE_NAME "ctphase" | |
| 39 | -#define CTPHASE_VERSION "0.0.1" | |
| 38 | +#define CTPHASE_NAME "ctphase" | |
| 40 | 39 | |
| 41 | 40 | |
| 42 | 41 | /***********************************************************************//** |
| ... | ... | @@ -65,38 +64,17 @@ public: |
| 65 | 64 | |
| 66 | 65 | protected: |
| 67 | 66 | // Protected methods |
| 68 | - void init_members(void); | |
| 69 | - void copy_members(const ctphase& app); | |
| 70 | - void free_members(void); | |
| 71 | - void get_parameters(void); | |
| 72 | - void read_phase_info_from_xml(void); | |
| 73 | - void phase_events(GCTAObservation* obs, | |
| 74 | - const std::string& filename, | |
| 75 | - const std::string& evtname, | |
| 76 | - const std::string& gtiname); | |
| 77 | - std::string check_infile(const std::string& filename, | |
| 78 | - const std::string& evtname) const; | |
| 79 | - std::string set_outfile_name(const std::string& filename) const; | |
| 80 | - std::string get_gtiname(const std::string& filename, | |
| 81 | - const std::string& evtname) const; | |
| 82 | - void save_fits(void); | |
| 83 | - void save_xml(void); | |
| 84 | - void save_event_list(const GCTAObservation* obs, | |
| 85 | - const std::string& infile, | |
| 86 | - const std::string& evtname, | |
| 87 | - const std::string& gtiname, | |
| 88 | - const std::string& outfile) const; | |
| 67 | + void init_members(void); | |
| 68 | + void copy_members(const ctphase& app); | |
| 69 | + void free_members(void); | |
| 70 | + void get_parameters(void); | |
| 71 | + void phase_events(GCTAObservation* obs); | |
| 89 | 72 | |
| 90 | 73 | // User parameters |
| 91 | - std::string m_outobs; //!< Output event list or XML file | |
| 92 | - std::string m_prefix; //!< Prefix for multiple event lists | |
| 93 | - GModelTemporalPhaseCurve m_phase; //!< Phase information object | |
| 94 | - GChatter m_chatter; //!< Chattiness | |
| 74 | + GChatter m_chatter; //!< Chattiness | |
| 95 | 75 | |
| 96 | 76 | // Protected members |
| 97 | - std::vector<std::string> m_infiles; //!< Input event filenames | |
| 98 | - std::vector<std::string> m_evtname; //!< Event extension names | |
| 99 | - std::vector<std::string> m_gtiname; //!< GTI extension names | |
| 77 | + GModelTemporalPhaseCurve m_phase; //!< Phase curve model | |
| 100 | 78 | }; |
| 101 | 79 | |
| 102 | 80 | ... | ... |
src/ctphase/ctphase.par
| ... | ... | @@ -5,11 +5,10 @@ |
| 5 | 5 | # ------------------------------------------------------------------------- # |
| 6 | 6 | # # |
| 7 | 7 | # File: ctphase.par # |
| 8 | -# Version: 0.0.1 # | |
| 9 | 8 | # # |
| 10 | -# Author: Leonardo Di Venere # | |
| 11 | -# leonardo.divenere@ba.infn.it # | |
| 12 | -# INFN # | |
| 9 | +# Author: Joshua Cardenzana # | |
| 10 | +# jcardenzana@irap.omp.eu # | |
| 11 | +# IRAP # | |
| 13 | 12 | # # |
| 14 | 13 | # Purpose: Parameter file for the ctphase application # |
| 15 | 14 | # # |
| ... | ... | @@ -17,20 +16,21 @@ |
| 17 | 16 | # |
| 18 | 17 | # General parameters |
| 19 | 18 | #=================== |
| 20 | -inobs, f, a,events.fits,,, "Input event list or observation definition XML file" | |
| 21 | -outobs, f, a,phased_events.fits,,, "Output event list or observation definition XML file" | |
| 22 | -prefix, s, h, "phased_",,, "Prefix for event lists in observation definition XML file" | |
| 23 | -inmodel, f, h, ,,, "Model file defining the phase information" | |
| 24 | -source, s, h, ,,, "Source in model file to use for phase information" | |
| 19 | +inobs, f, a, "events.fits",,, "Input event list or observation definition XML file" | |
| 20 | +outobs, f, a, "phased_events.fits",,, "Output event list or observation definition XML file" | |
| 21 | +prefix, s, h, "phased_",,, "Prefix for event lists in observation definition XML file" | |
| 22 | +inmodel, f, a, "$CTOOLS/share/models/crab.xml",,, "Model file defining the phase information" | |
| 23 | +source, s, a, "Crab",,, "Source in model file to use for phase information" | |
| 25 | 24 | |
| 26 | 25 | # |
| 27 | 26 | # Phase information parameters |
| 28 | 27 | #===================== |
| 29 | -mjd, r, a, 51544.5,,, "Reference MJD for phase information" | |
| 30 | -p0, r, a, 0.0,0.0,1.0, "Phase at reference MJD" | |
| 31 | -f0, r, a, 1,,, "Frequency at reference MJD [Hz]" | |
| 32 | -f1, r, a, 0.0,,, "First freq. derivative at reference MJD [s^-1]" | |
| 33 | -f2, r, a, 0.0,,, "Second freq. derivative at reference MJD [s^-2]" | |
| 28 | +phasecurve, f, a, phase.fits,,, "Phase curve FITS file" | |
| 29 | +mjd, r, a, 51544.5,,, "Reference MJD for phase information" | |
| 30 | +phase, r, a, 0.0,0.0,1.0, "Phase at reference MJD" | |
| 31 | +f0, r, a, 1.0,,, "Frequency at reference MJD (Hz)" | |
| 32 | +f1, r, a, 0.1,,, "First freq. derivative at reference MJD (s^-1)" | |
| 33 | +f2, r, a, 0.01,,, "Second freq. derivative at reference MJD (s^-2)" | |
| 34 | 34 | |
| 35 | 35 | # |
| 36 | 36 | # Standard parameters | ... | ... |
src/ctphase/main.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctphase - Append phase information to CTA events file * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2017 by Leonardo Di Venere * | |
| 4 | + * copyright (C) 2017 by Joshua Cardenzana * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | /** |
| 22 | 22 | * @file ctphase/main.cpp |
| 23 | 23 | * @brief Append phase information to CTA events file |
| 24 | - * @author Leonardo Di Venere | |
| 24 | + * @author Joshua Cardenzana | |
| 25 | 25 | */ |
| 26 | 26 | |
| 27 | 27 | /* __ Includes ___________________________________________________________ */ | ... | ... |
src/ctprob/Makefile.am
0 → 100644
| 1 | +############################################################################# | |
| 2 | +# Makefile.am for ctprob tool # | |
| 3 | +# ------------------------------------------------------------------------- # | |
| 4 | +# Copyright (C) 2017 Leonardo Di Venere # | |
| 5 | +# ------------------------------------------------------------------------- # | |
| 6 | +# # | |
| 7 | +# This program is free software: you can redistribute it and/or modify # | |
| 8 | +# it under the terms of the GNU General Public License as published by # | |
| 9 | +# the Free Software Foundation, either version 3 of the License, or # | |
| 10 | +# (at your option) any later version. # | |
| 11 | +# # | |
| 12 | +# This program is distributed in the hope that it will be useful, # | |
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
| 15 | +# GNU General Public License for more details. # | |
| 16 | +# # | |
| 17 | +# You should have received a copy of the GNU General Public License # | |
| 18 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
| 19 | +# # | |
| 20 | +############################################################################# | |
| 21 | + | |
| 22 | +# Set include directories | |
| 23 | +INCLUDES = -I$(top_srcdir)/src/support | |
| 24 | + | |
| 25 | +# Program name | |
| 26 | +bin_PROGRAMS = ctprob | |
| 27 | + | |
| 28 | +# Sources | |
| 29 | +sources = ctprob.cpp ctprob.hpp | |
| 30 | + | |
| 31 | +# Libtool library | |
| 32 | +noinst_LTLIBRARIES = libctprob.la | |
| 33 | +libctprob_la_SOURCES = $(sources) | |
| 34 | +libctprob_la_LDFLAGS = @OPENMP_LIB_LDFLAGS@ | |
| 35 | + | |
| 36 | +# Program definition | |
| 37 | +ctprob_SOURCES = main.cpp | |
| 38 | +ctprob_LDFLAGS = $(LIB_LINK_OPTION) @LDFLAGS@ | |
| 39 | +ctprob_CPPFLAGS = @CPPFLAGS@ | |
| 40 | +ctprob_LDADD = libctprob.la $(top_builddir)/src/support/libsupport.la | |
| 41 | + | |
| 42 | +# Parameter files | |
| 43 | +pfilesdir = $(prefix)/syspfiles | |
| 44 | +pfiles_DATA = $(srcdir)/ctprob.par | |
| 45 | + | |
| 46 | +# Extra files to be distributed in the tar file | |
| 47 | +EXTRA_DIST = $(pfiles_DATA) | ... | ... |
src/ctprob/ctprob.cpp
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * ctprob - Computes event probability for a given model * | |
| 3 | + * ----------------------------------------------------------------------- * | |
| 4 | + * copyright (C) 2017 by Leonardo Di Venere * | |
| 5 | + * ----------------------------------------------------------------------- * | |
| 6 | + * * | |
| 7 | + * This program is free software: you can redistribute it and/or modify * | |
| 8 | + * it under the terms of the GNU General Public License as published by * | |
| 9 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 10 | + * (at your option) any later version. * | |
| 11 | + * * | |
| 12 | + * This program is distributed in the hope that it will be useful, * | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 15 | + * GNU General Public License for more details. * | |
| 16 | + * * | |
| 17 | + * You should have received a copy of the GNU General Public License * | |
| 18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 19 | + * * | |
| 20 | + ***************************************************************************/ | |
| 21 | +/** | |
| 22 | + * @file ctprob.cpp | |
| 23 | + * @brief Computes event probability for a given model | |
| 24 | + * @author Leonardo Di Venere | |
| 25 | + */ | |
| 26 | + | |
| 27 | +/* __ Includes ___________________________________________________________ */ | |
| 28 | +#ifdef HAVE_CONFIG_H | |
| 29 | +#include <config.h> | |
| 30 | +#endif | |
| 31 | +#include <cstdlib> | |
| 32 | +#include "ctprob.hpp" | |
| 33 | +#include "GTools.hpp" | |
| 34 | + | |
| 35 | +/* __ Method name definitions ____________________________________________ */ | |
| 36 | +#define G_GET_OBS "ctprob::get_obs()" | |
| 37 | +#define G_EVALUATE_PROB "ctprob::evaluate_probability(GCTAObservation*)" | |
| 38 | + | |
| 39 | +/* __ Debug definitions __________________________________________________ */ | |
| 40 | + | |
| 41 | +/* __ Coding definitions _________________________________________________ */ | |
| 42 | + | |
| 43 | + | |
| 44 | +/*========================================================================== | |
| 45 | + = = | |
| 46 | + = Constructors/destructors = | |
| 47 | + = = | |
| 48 | + ==========================================================================*/ | |
| 49 | + | |
| 50 | +/***********************************************************************//** | |
| 51 | + * @brief Void constructor | |
| 52 | + ***************************************************************************/ | |
| 53 | +ctprob::ctprob(void) : ctobservation(CTPROB_NAME, VERSION) | |
| 54 | +{ | |
| 55 | + // Initialise members | |
| 56 | + init_members(); | |
| 57 | + | |
| 58 | + // Return | |
| 59 | + return; | |
| 60 | +} | |
| 61 | + | |
| 62 | + | |
| 63 | +/***********************************************************************//** | |
| 64 | + * @brief Observations constructor | |
| 65 | + * | |
| 66 | + * param[in] obs Observation container. | |
| 67 | + * | |
| 68 | + * Creates an instance of the class that is initialised using the information | |
| 69 | + * provided in an observation container. | |
| 70 | + ***************************************************************************/ | |
| 71 | +ctprob::ctprob(const GObservations& obs) : | |
| 72 | + ctobservation(CTPROB_NAME, VERSION, obs) | |
| 73 | +{ | |
| 74 | + // Initialise members | |
| 75 | + init_members(); | |
| 76 | + | |
| 77 | + // Return | |
| 78 | + return; | |
| 79 | +} | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | +/***********************************************************************//** | |
| 85 | + * @brief Command line constructor | |
| 86 | + * | |
| 87 | + * @param[in] argc Number of arguments in command line. | |
| 88 | + * @param[in] argv Array of command line arguments. | |
| 89 | + ***************************************************************************/ | |
| 90 | +ctprob::ctprob(int argc, char *argv[]) : | |
| 91 | + ctobservation(CTPROB_NAME, VERSION, argc, argv) | |
| 92 | +{ | |
| 93 | + // Initialise members | |
| 94 | + init_members(); | |
| 95 | + | |
| 96 | + // Return | |
| 97 | + return; | |
| 98 | +} | |
| 99 | + | |
| 100 | + | |
| 101 | +/***********************************************************************//** | |
| 102 | + * @brief Copy constructor | |
| 103 | + * | |
| 104 | + * @param[in] app Application. | |
| 105 | + ***************************************************************************/ | |
| 106 | +ctprob::ctprob(const ctprob& app) : ctobservation(app) | |
| 107 | +{ | |
| 108 | + // Initialise members | |
| 109 | + init_members(); | |
| 110 | + | |
| 111 | + // Copy members | |
| 112 | + copy_members(app); | |
| 113 | + | |
| 114 | + // Return | |
| 115 | + return; | |
| 116 | +} | |
| 117 | + | |
| 118 | + | |
| 119 | +/***********************************************************************//** | |
| 120 | + * @brief Destructor | |
| 121 | + ***************************************************************************/ | |
| 122 | +ctprob::~ctprob(void) | |
| 123 | +{ | |
| 124 | + // Free members | |
| 125 | + free_members(); | |
| 126 | + | |
| 127 | + // Return | |
| 128 | + return; | |
| 129 | +} | |
| 130 | + | |
| 131 | + | |
| 132 | +/*========================================================================== | |
| 133 | + = = | |
| 134 | + = Operators = | |
| 135 | + = = | |
| 136 | + ==========================================================================*/ | |
| 137 | + | |
| 138 | +/***********************************************************************//** | |
| 139 | + * @brief Assignment operator | |
| 140 | + * | |
| 141 | + * @param[in] app Application. | |
| 142 | + * @return Application. | |
| 143 | + ***************************************************************************/ | |
| 144 | +ctprob& ctprob::operator=(const ctprob& app) | |
| 145 | +{ | |
| 146 | + // Execute only if object is not identical | |
| 147 | + if (this != &app) { | |
| 148 | + | |
| 149 | + // Copy base class members | |
| 150 | + this->ctobservation::operator=(app); | |
| 151 | + | |
| 152 | + // Free members | |
| 153 | + free_members(); | |
| 154 | + | |
| 155 | + // Initialise members | |
| 156 | + init_members(); | |
| 157 | + | |
| 158 | + // Copy members | |
| 159 | + copy_members(app); | |
| 160 | + | |
| 161 | + } // endif: object was not identical | |
| 162 | + | |
| 163 | + // Return this object | |
| 164 | + return *this; | |
| 165 | +} | |
| 166 | + | |
| 167 | + | |
| 168 | +/*========================================================================== | |
| 169 | + = = | |
| 170 | + = Public methods = | |
| 171 | + = = | |
| 172 | + ==========================================================================*/ | |
| 173 | + | |
| 174 | +/***********************************************************************//** | |
| 175 | + * @brief Clear ctprob tool | |
| 176 | + * | |
| 177 | + * Clears ctprob tool. | |
| 178 | + ***************************************************************************/ | |
| 179 | +void ctprob::clear(void) | |
| 180 | +{ | |
| 181 | + // Free members | |
| 182 | + free_members(); | |
| 183 | + this->ctobservation::free_members(); | |
| 184 | + this->ctool::free_members(); | |
| 185 | + | |
| 186 | + // Clear base class (needed to conserve tool name and version) | |
| 187 | + this->GApplication::clear(); | |
| 188 | + | |
| 189 | + // Initialise members | |
| 190 | + this->ctool::init_members(); | |
| 191 | + this->ctobservation::init_members(); | |
| 192 | + init_members(); | |
| 193 | + | |
| 194 | + // Write header into logger | |
| 195 | + log_header(); | |
| 196 | + | |
| 197 | + // Return | |
| 198 | + return; | |
| 199 | +} | |
| 200 | + | |
| 201 | + | |
| 202 | +/***********************************************************************//** | |
| 203 | + * @brief Runs the ctprob tool | |
| 204 | + * | |
| 205 | + * This method reads in the application parameters and loops over all | |
| 206 | + * unbinned observations to compute the probability for each event that it | |
| 207 | + * comes from one of the model components. | |
| 208 | + ***************************************************************************/ | |
| 209 | +void ctprob::run(void) | |
| 210 | +{ | |
| 211 | + // Switch screen logging on in debug mode | |
| 212 | + if (logDebug()) { | |
| 213 | + log.cout(true); | |
| 214 | + } | |
| 215 | + | |
| 216 | + // Get parameters | |
| 217 | + get_parameters(); | |
| 218 | + | |
| 219 | + // Set energy dispersion flags of all CTA observations and save old | |
| 220 | + // values in save_edisp vector | |
| 221 | + std::vector<bool> save_edisp = set_edisp(m_obs, m_apply_edisp); | |
| 222 | + | |
| 223 | + // Write input observation container into logger | |
| 224 | + log_observations(NORMAL, m_obs, "Input observation"); | |
| 225 | + | |
| 226 | + // Write header into logger | |
| 227 | + log_header1(TERSE, "Compute event probabilities"); | |
| 228 | + | |
| 229 | + // Initialise counters | |
| 230 | + int n_observations = 0; | |
| 231 | + | |
| 232 | + // Loop over all unbinned CTA observations in the container | |
| 233 | + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; | |
| 234 | + obs = next_unbinned_observation()) { | |
| 235 | + | |
| 236 | + // Increment counter | |
| 237 | + n_observations++; | |
| 238 | + | |
| 239 | + // Evaluate event probabilities | |
| 240 | + evaluate_probability(obs); | |
| 241 | + | |
| 242 | + } // endfor: looped over observations | |
| 243 | + | |
| 244 | + // If more than a single observation has been handled then make sure that | |
| 245 | + // an XML file will be used for storage | |
| 246 | + if (n_observations > 1) { | |
| 247 | + m_use_xml = true; | |
| 248 | + } | |
| 249 | + | |
| 250 | + // Write observation(s) into logger | |
| 251 | + log_observations(NORMAL, m_obs, "Output observation"); | |
| 252 | + | |
| 253 | + // Restore energy dispersion flags of all CTA observations | |
| 254 | + restore_edisp(m_obs, save_edisp); | |
| 255 | + | |
| 256 | + // Optionally publish event list(s) | |
| 257 | + if ((*this)["publish"].boolean()) { | |
| 258 | + publish(); | |
| 259 | + } | |
| 260 | + | |
| 261 | + // Return | |
| 262 | + return; | |
| 263 | +} | |
| 264 | + | |
| 265 | + | |
| 266 | +/***********************************************************************//** | |
| 267 | + * @brief Save the selected event list(s) | |
| 268 | + * | |
| 269 | + * This method saves the selected event list(s) into FITS file(s). There are | |
| 270 | + * two modes, depending on the m_use_xml flag. | |
| 271 | + * | |
| 272 | + * If m_use_xml is true, all selected event list(s) will be saved into FITS | |
| 273 | + * files, where the output filenames are constructued from the input | |
| 274 | + * filenames by prepending the m_prefix string to name. Any path information | |
| 275 | + * will be stripped form the input name, hence event files will be written | |
| 276 | + * into the local working directory (unless some path information is present | |
| 277 | + * in the prefix). In addition, an XML file will be created that gathers | |
| 278 | + * the filename information for the selected event list(s). If an XML file | |
| 279 | + * was present on input, all metadata information will be copied from this | |
| 280 | + * input file. | |
| 281 | + * | |
| 282 | + * If m_use_xml is false, the selected event list will be saved into a FITS | |
| 283 | + * file. | |
| 284 | + ***************************************************************************/ | |
| 285 | +void ctprob::save(void) | |
| 286 | +{ | |
| 287 | + // Write header into logger | |
| 288 | + log_header1(TERSE, gammalib::number("Save event list", m_obs.size())); | |
| 289 | + | |
| 290 | + // Case A: Save event file(s) and XML metadata information | |
| 291 | + if (m_use_xml) { | |
| 292 | + save_xml(); | |
| 293 | + } | |
| 294 | + | |
| 295 | + // Case B: Save event file as FITS file | |
| 296 | + else { | |
| 297 | + save_fits(); | |
| 298 | + } | |
| 299 | + | |
| 300 | + // Return | |
| 301 | + return; | |
| 302 | +} | |
| 303 | + | |
| 304 | + | |
| 305 | +/***********************************************************************//** | |
| 306 | + * @brief Publish event lists | |
| 307 | + * | |
| 308 | + * @param[in] name Event list name. | |
| 309 | + ***************************************************************************/ | |
| 310 | +void ctprob::publish(const std::string& name) | |
| 311 | +{ | |
| 312 | + // Write header into logger | |
| 313 | + log_header1(TERSE, gammalib::number("Publish event list", m_obs.size())); | |
| 314 | + | |
| 315 | + // Loop over all observation in the container | |
| 316 | + for (int i = 0; i < m_obs.size(); ++i) { | |
| 317 | + | |
| 318 | + // Get CTA observation | |
| 319 | + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | |
| 320 | + | |
| 321 | + // Handle only CTA observations | |
| 322 | + if (obs != NULL) { | |
| 323 | + | |
| 324 | + // Continue only if there is an event list | |
| 325 | + if (obs->events()->size() != 0) { | |
| 326 | + | |
| 327 | + // Set default name if user name is empty | |
| 328 | + std::string user_name(name); | |
| 329 | + if (user_name.empty()) { | |
| 330 | + user_name = CTPROB_NAME; | |
| 331 | + } | |
| 332 | + | |
| 333 | + // If there are several event lists then add an index | |
| 334 | + if (m_use_xml) { | |
| 335 | + user_name += gammalib::str(i); | |
| 336 | + } | |
| 337 | + | |
| 338 | + // Write event list name into logger | |
| 339 | + log_value(NORMAL, "Event list name", user_name); | |
| 340 | + | |
| 341 | + // Write events into in-memory FITS file | |
| 342 | + GFits fits; | |
| 343 | + obs->write(fits); | |
| 344 | + | |
| 345 | + // Publish | |
| 346 | + fits.publish(gammalib::extname_cta_events, user_name); | |
| 347 | + | |
| 348 | + } // endif: there were events | |
| 349 | + | |
| 350 | + } // endif: observation was a CTA observation | |
| 351 | + | |
| 352 | + } // endfor: looped over observations | |
| 353 | + | |
| 354 | + // Return | |
| 355 | + return; | |
| 356 | +} | |
| 357 | + | |
| 358 | + | |
| 359 | +/*========================================================================== | |
| 360 | + = = | |
| 361 | + = Private methods = | |
| 362 | + = = | |
| 363 | + ==========================================================================*/ | |
| 364 | + | |
| 365 | +/***********************************************************************//** | |
| 366 | + * @brief Initialise class members | |
| 367 | + ***************************************************************************/ | |
| 368 | +void ctprob::init_members(void) | |
| 369 | +{ | |
| 370 | + // Initialise parameters | |
| 371 | + m_outobs.clear(); | |
| 372 | + m_prefix.clear(); | |
| 373 | + m_chatter = static_cast<GChatter>(2); | |
| 374 | + | |
| 375 | + // Initialise protected members | |
| 376 | + m_infiles.clear(); | |
| 377 | + m_evtname.clear(); | |
| 378 | + m_gtiname.clear(); | |
| 379 | + | |
| 380 | + // Return | |
| 381 | + return; | |
| 382 | +} | |
| 383 | + | |
| 384 | + | |
| 385 | +/***********************************************************************//** | |
| 386 | + * @brief Copy class members | |
| 387 | + * | |
| 388 | + * @param[in] app Application. | |
| 389 | + ***************************************************************************/ | |
| 390 | +void ctprob::copy_members(const ctprob& app) | |
| 391 | +{ | |
| 392 | + // Copy parameters | |
| 393 | + m_outobs = app.m_outobs; | |
| 394 | + m_prefix = app.m_prefix; | |
| 395 | + m_chatter = app.m_chatter; | |
| 396 | + | |
| 397 | + // Copy protected members | |
| 398 | + m_infiles = app.m_infiles; | |
| 399 | + m_evtname = app.m_evtname; | |
| 400 | + m_gtiname = app.m_gtiname; | |
| 401 | + | |
| 402 | + // Return | |
| 403 | + return; | |
| 404 | +} | |
| 405 | + | |
| 406 | + | |
| 407 | +/***********************************************************************//** | |
| 408 | + * @brief Delete class members | |
| 409 | + ***************************************************************************/ | |
| 410 | +void ctprob::free_members(void) | |
| 411 | +{ | |
| 412 | + // Return | |
| 413 | + return; | |
| 414 | +} | |
| 415 | + | |
| 416 | + | |
| 417 | +/***********************************************************************//** | |
| 418 | + * @brief Get application parameters | |
| 419 | + * | |
| 420 | + * Get all user parameters from parameter file or (if required) by querying | |
| 421 | + * the user. Times are assumed to be in the native CTA MJD format. | |
| 422 | + * | |
| 423 | + * This method also loads observations if no observations are yet allocated. | |
| 424 | + * Observations are either loaded from a single CTA even list, or from a | |
| 425 | + * XML file using the metadata information that is stored in that file. | |
| 426 | + ***************************************************************************/ | |
| 427 | +void ctprob::get_parameters(void) | |
| 428 | +{ | |
| 429 | + // Setup observations from "inobs" parameter. Do not request response | |
| 430 | + // information and do not accept counts cubes. | |
| 431 | + if (m_obs.size() == 0) { | |
| 432 | + get_obs(); | |
| 433 | + } | |
| 434 | + // ... otherwise add response information and energy boundaries in case | |
| 435 | + // that they are missing | |
| 436 | + else { | |
| 437 | + setup_observations(m_obs); | |
| 438 | + } | |
| 439 | + | |
| 440 | + // Read model definition file if required | |
| 441 | + if (m_obs.models().size() == 0) { | |
| 442 | + | |
| 443 | + // Get model filename | |
| 444 | + std::string inmodel = (*this)["inmodel"].filename(); | |
| 445 | + | |
| 446 | + // Load models from file | |
| 447 | + m_obs.models(inmodel); | |
| 448 | + | |
| 449 | + } // endif: there were no models | |
| 450 | + | |
| 451 | + // Get energy dispersion flag parameters | |
| 452 | + m_apply_edisp = (*this)["edisp"].boolean(); | |
| 453 | + | |
| 454 | + | |
| 455 | + // Get remaining parameters | |
| 456 | + m_publish = (*this)["publish"].boolean(); | |
| 457 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 458 | + | |
| 459 | + // Optionally read ahead parameters so that they get correctly | |
| 460 | + // dumped into the log file | |
| 461 | + if (read_ahead()) { | |
| 462 | + m_outobs = (*this)["outobs"].filename(); | |
| 463 | + m_prefix = (*this)["prefix"].string(); | |
| 464 | + } | |
| 465 | + | |
| 466 | + // Write parameters into logger | |
| 467 | + log_parameters(TERSE); | |
| 468 | + | |
| 469 | + // Return | |
| 470 | + return; | |
| 471 | +} | |
| 472 | + | |
| 473 | + | |
| 474 | +/***********************************************************************//** | |
| 475 | + * @brief Get observation container | |
| 476 | + * | |
| 477 | + * @exception GException::invalid_value | |
| 478 | + * Invalid FITS file. | |
| 479 | + * | |
| 480 | + * Get an observation container according to the user parameters. The method | |
| 481 | + * supports loading of a individual FITS file or an observation definition | |
| 482 | + * file in XML format. | |
| 483 | + ***************************************************************************/ | |
| 484 | +void ctprob::get_obs(void) | |
| 485 | +{ | |
| 486 | + // Get the filename from the input parameters | |
| 487 | + std::string filename = (*this)["inobs"].filename(); | |
| 488 | + | |
| 489 | + // If no observation definition file throw an exception | |
| 490 | + if (!is_valid_filename(filename)) { | |
| 491 | + throw GException::invalid_value(G_GET_OBS, "Input event list is not valid."); | |
| 492 | + } // endif: filename was not valid | |
| 493 | + | |
| 494 | + // ... otherwise we have a file name | |
| 495 | + else { | |
| 496 | + | |
| 497 | + // If file is a FITS file then create an empty CTA observation | |
| 498 | + // and load file into observation | |
| 499 | + if (GFilename(filename).is_fits()) { | |
| 500 | + | |
| 501 | + // Allocate empty CTA observation | |
| 502 | + GCTAObservation cta; | |
| 503 | + | |
| 504 | + // Load data | |
| 505 | + cta.load(filename); | |
| 506 | + | |
| 507 | + // Set response | |
| 508 | + set_obs_response(&cta); | |
| 509 | + | |
| 510 | + // Append observation to container | |
| 511 | + m_obs.append(cta); | |
| 512 | + | |
| 513 | + // Signal that no XML file should be used for storage | |
| 514 | + m_use_xml = false; | |
| 515 | + | |
| 516 | + } | |
| 517 | + | |
| 518 | + // ... otherwise load file into observation container | |
| 519 | + else { | |
| 520 | + | |
| 521 | + // Load observations from XML file | |
| 522 | + m_obs.load(filename); | |
| 523 | + | |
| 524 | + // For all observations that have no response, set the response | |
| 525 | + // from the task parameters | |
| 526 | + set_response(m_obs); | |
| 527 | + | |
| 528 | + // Set observation boundary parameters (emin, emax, rad) | |
| 529 | + set_obs_bounds(m_obs); | |
| 530 | + | |
| 531 | + // Signal that XML file should be used for storage | |
| 532 | + m_use_xml = true; | |
| 533 | + | |
| 534 | + } // endelse: file was an XML file | |
| 535 | + | |
| 536 | + } | |
| 537 | + | |
| 538 | + // Return | |
| 539 | + return; | |
| 540 | + | |
| 541 | +} | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | +/***********************************************************************//** | |
| 546 | + * @brief Evaluate probability for events | |
| 547 | + * | |
| 548 | + * @param[in,out] obs CTA observation. | |
| 549 | + * | |
| 550 | + * @exception GException::invalid_value | |
| 551 | + * Observation does not contain an event list. | |
| 552 | + * | |
| 553 | + * Computes for all events the probability that an event arises from a | |
| 554 | + * specific model component. The computation is done by by evaluating the | |
| 555 | + * differential event probability for a given model and normalizing these | |
| 556 | + * probabilities so that the sum of the probabilities for all model | |
| 557 | + * components is unity for each event. | |
| 558 | + * | |
| 559 | + * The method appends for each model component a single precision column to | |
| 560 | + * the event list that contains the event probabilities. The name of the | |
| 561 | + * column is build from the model name prefixed with `PROB_`. | |
| 562 | + ***************************************************************************/ | |
| 563 | +void ctprob::evaluate_probability(GCTAObservation* obs) | |
| 564 | +{ | |
| 565 | + // Write header into logger | |
| 566 | + log_header3(NORMAL, "Evaluate events probabilities"); | |
| 567 | + | |
| 568 | + // Make sure that the observation holds a CTA event list. If this | |
| 569 | + // is not the case then throw an exception. | |
| 570 | + GCTAEventList* events = dynamic_cast<GCTAEventList*>(const_cast<GEvents*> | |
| 571 | + (obs->events())); | |
| 572 | + if (events == NULL) { | |
| 573 | + std::string msg = "CTA Observation does not contain an event list. An " | |
| 574 | + "event list is needed to compute the event " | |
| 575 | + "probabilities."; | |
| 576 | + throw GException::invalid_value(G_EVALUATE_PROB, msg); | |
| 577 | + } | |
| 578 | + | |
| 579 | + // Continue only if there are model components | |
| 580 | + int nmodels = m_obs.models().size(); | |
| 581 | + if (nmodels > 0) { | |
| 582 | + | |
| 583 | + // Allocate single precision FITS table columns for all model components | |
| 584 | + std::vector<GFitsTableFloatCol*> columns; | |
| 585 | + for (int k = 0; k < nmodels; ++k) { | |
| 586 | + const std::string colname = "PROB_" + m_obs.models()[k] ->name(); | |
| 587 | + GFitsTableFloatCol* col = | |
| 588 | + new GFitsTableFloatCol(colname, events->size()); | |
| 589 | + columns.push_back(col); | |
| 590 | + } | |
| 591 | + | |
| 592 | + // Loop over all events in the event list | |
| 593 | + for (int i = 0; i < events->size(); ++i) { | |
| 594 | + | |
| 595 | + // Initialise total probability | |
| 596 | + double total = 0.0; | |
| 597 | + | |
| 598 | + // Get point to event | |
| 599 | + const GEvent* event = (*events)[i]; | |
| 600 | + | |
| 601 | + // Initialise probability vector | |
| 602 | + std::vector<double> probabilities(nmodels, 0.0); | |
| 603 | + | |
| 604 | + // Loop over models | |
| 605 | + for (int k = 0; k < nmodels; ++k) { | |
| 606 | + double value = m_obs.models()[k]->eval(*event, *obs); | |
| 607 | + probabilities[k] = value; | |
| 608 | + total += value; | |
| 609 | + } | |
| 610 | + | |
| 611 | + // Normalize probabilities to unity | |
| 612 | + if (total > 0.0) { | |
| 613 | + for (int k = 0; k < nmodels; ++k) { | |
| 614 | + probabilities[k] /= total; | |
| 615 | + } | |
| 616 | + } | |
| 617 | + | |
| 618 | + // Store probabilities in FITS columns | |
| 619 | + for (int k = 0; k < nmodels; ++k) { | |
| 620 | + (*(columns[k]))(i) = probabilities[k]; | |
| 621 | + } | |
| 622 | + | |
| 623 | + } // endfor: looped over all events | |
| 624 | + | |
| 625 | + // Append columns to event list | |
| 626 | + for (int k = 0; k < nmodels; ++k) { | |
| 627 | + events->append_column(*columns[k]); | |
| 628 | + } | |
| 629 | + | |
| 630 | + } // endif: there were model components | |
| 631 | + | |
| 632 | + // Return | |
| 633 | + return; | |
| 634 | +} | |
| 635 | + | |
| 636 | + | |
| 637 | +/***********************************************************************//** | |
| 638 | + * @brief Set output file name. | |
| 639 | + * | |
| 640 | + * @param[in] filename Input file name. | |
| 641 | + * | |
| 642 | + * Converts an input file name into an output filename by prepending the | |
| 643 | + * prefix stored in the member m_prefix to the input file name. Any path as | |
| 644 | + * well as extension will be stripped from the input file name. Also a | |
| 645 | + * trailing ".gz" will be stripped as one cannot write into gzipped files. | |
| 646 | + ***************************************************************************/ | |
| 647 | +std::string ctprob::set_outfile_name(const std::string& filename) const | |
| 648 | +{ | |
| 649 | + // Create filename | |
| 650 | + GFilename fname(filename); | |
| 651 | + | |
| 652 | + // Split input filename without any extensions into path elements | |
| 653 | + std::vector<std::string> elements = gammalib::split(fname.url(), "/"); | |
| 654 | + | |
| 655 | + // The last path element is the filename | |
| 656 | + std::string outname = m_prefix + elements[elements.size()-1]; | |
| 657 | + | |
| 658 | + // Strip any ".gz" | |
| 659 | + outname = gammalib::strip_chars(outname, ".gz"); | |
| 660 | + | |
| 661 | + // Return output filename | |
| 662 | + return outname; | |
| 663 | +} | |
| 664 | + | |
| 665 | + | |
| 666 | +/***********************************************************************//** | |
| 667 | + * @brief Save event list in FITS format. | |
| 668 | + * | |
| 669 | + * Save the event list as a FITS file. The file name of the FITS file is | |
| 670 | + * specified by the `outobs` parameter. | |
| 671 | + ***************************************************************************/ | |
| 672 | +void ctprob::save_fits(void) | |
| 673 | +{ | |
| 674 | + // Save only if there are observations | |
| 675 | + if (m_obs.size() > 0) { | |
| 676 | + | |
| 677 | + // Get output filename | |
| 678 | + m_outobs = (*this)["outobs"].filename(); | |
| 679 | + | |
| 680 | + // Loop over all unbinned CTA observations in the container | |
| 681 | + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; | |
| 682 | + obs = next_unbinned_observation()) { | |
| 683 | + | |
| 684 | + // Get input file name and default extension names | |
| 685 | + std::string infile = obs->eventfile(); | |
| 686 | + std::string evtname = gammalib::extname_cta_events; | |
| 687 | + std::string gtiname = gammalib::extname_gti; | |
| 688 | + | |
| 689 | + // Create file name object | |
| 690 | + GFilename fname(m_outobs); | |
| 691 | + | |
| 692 | + // Extract filename and event extension name | |
| 693 | + std::string outfile = fname.url(); | |
| 694 | + | |
| 695 | + // Append event extension name. We handle here the possibility | |
| 696 | + // to write the events into a different extension. | |
| 697 | + if (fname.has_extname()) { | |
| 698 | + outfile += "["+fname.extname()+"]"; | |
| 699 | + } | |
| 700 | + else { | |
| 701 | + outfile += "["+gammalib::extname_cta_events+"]"; | |
| 702 | + } | |
| 703 | + | |
| 704 | + // Log filename | |
| 705 | + log_value(NORMAL, "Event list file", outfile); | |
| 706 | + | |
| 707 | + // Save event list | |
| 708 | + save_event_list(obs, infile, evtname, gtiname, outfile); | |
| 709 | + | |
| 710 | + // Exit the loop (if this method is called we should only | |
| 711 | + // have a single unbinned observation in the observation | |
| 712 | + // container | |
| 713 | + break; | |
| 714 | + | |
| 715 | + } // endfor: looped over all unbinned observations | |
| 716 | + | |
| 717 | + } // endif: there were observations | |
| 718 | + | |
| 719 | + // Return | |
| 720 | + return; | |
| 721 | +} | |
| 722 | + | |
| 723 | + | |
| 724 | +/***********************************************************************//** | |
| 725 | + * @brief Save event list(s) in XML format. | |
| 726 | + * | |
| 727 | + * Save the event list(s) into FITS files and write the file path information | |
| 728 | + * into a XML file. The filename of the XML file is specified by the `outobs` | |
| 729 | + * parameter, the filename(s) of the event lists are built by prepending a | |
| 730 | + * prefix to the input event list filenames. Any path present in the input | |
| 731 | + * filename will be stripped, i.e. the event list(s) will be written in the | |
| 732 | + * local working directory (unless a path is specified in the prefix). | |
| 733 | + ***************************************************************************/ | |
| 734 | +void ctprob::save_xml(void) | |
| 735 | +{ | |
| 736 | + // Get output filename and prefix | |
| 737 | + m_outobs = (*this)["outobs"].filename(); | |
| 738 | + m_prefix = (*this)["prefix"].string(); | |
| 739 | + | |
| 740 | + // Issue warning if output filename has no .xml suffix | |
| 741 | + log_string(TERSE, warn_xml_suffix(m_outobs)); | |
| 742 | + | |
| 743 | + // Loop over all unbinned CTA observations in the container | |
| 744 | + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; | |
| 745 | + obs = next_unbinned_observation()) { | |
| 746 | + | |
| 747 | + // Get input file name and default extension names | |
| 748 | + std::string infile = obs->eventfile(); | |
| 749 | + std::string evtname = gammalib::extname_cta_events; | |
| 750 | + std::string gtiname = gammalib::extname_gti; | |
| 751 | + | |
| 752 | + // Extract event and GTI extension names from input FITS file | |
| 753 | + GFilename fname(infile); | |
| 754 | + if (fname.has_extname()) { | |
| 755 | + evtname = fname.extname(); | |
| 756 | + } | |
| 757 | + gtiname = get_gtiname(fname.url(), evtname); | |
| 758 | + | |
| 759 | + // Set event output file name | |
| 760 | + std::string outfile = set_outfile_name(infile); | |
| 761 | + | |
| 762 | + // Append event extension name | |
| 763 | + outfile += "["+evtname+"]"; | |
| 764 | + | |
| 765 | + // Log filename | |
| 766 | + log_value(NORMAL, "Event list file", outfile); | |
| 767 | + | |
| 768 | + // Store output file name in observation | |
| 769 | + obs->eventfile(outfile); | |
| 770 | + | |
| 771 | + // Save event list | |
| 772 | + save_event_list(obs, infile, evtname, gtiname, outfile); | |
| 773 | + | |
| 774 | + } // endfor: looped over observations | |
| 775 | + | |
| 776 | + // Write observation definition XML file name into logger | |
| 777 | + log_value(NORMAL, "Obs. definition file", m_outobs); | |
| 778 | + | |
| 779 | + // Save observations in XML file | |
| 780 | + m_obs.save(m_outobs); | |
| 781 | + | |
| 782 | + // Return | |
| 783 | + return; | |
| 784 | +} | ... | ... |
src/ctprob/ctprob.hpp
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * ctprob - Computes event probability for a given model * | |
| 3 | + * ----------------------------------------------------------------------- * | |
| 4 | + * copyright (C) 2017 by Leonardo Di Venere * | |
| 5 | + * ----------------------------------------------------------------------- * | |
| 6 | + * * | |
| 7 | + * This program is free software: you can redistribute it and/or modify * | |
| 8 | + * it under the terms of the GNU General Public License as published by * | |
| 9 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 10 | + * (at your option) any later version. * | |
| 11 | + * * | |
| 12 | + * This program is distributed in the hope that it will be useful, * | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 15 | + * GNU General Public License for more details. * | |
| 16 | + * * | |
| 17 | + * You should have received a copy of the GNU General Public License * | |
| 18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 19 | + * * | |
| 20 | + ***************************************************************************/ | |
| 21 | +/** | |
| 22 | + * @file ctprob.hpp | |
| 23 | + * @brief Computes event probability for a given model | |
| 24 | + * @author Leonardo Di Venere | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#ifndef CTPROB_HPP | |
| 28 | +#define CTPROB_HPP | |
| 29 | + | |
| 30 | +/* __ Includes ___________________________________________________________ */ | |
| 31 | +#include <vector> | |
| 32 | +#include <string> | |
| 33 | +#include "GammaLib.hpp" | |
| 34 | +#include "GCTALib.hpp" | |
| 35 | +#include "ctobservation.hpp" | |
| 36 | + | |
| 37 | +/* __Definitions _________________________________________________________ */ | |
| 38 | +#define CTPROB_NAME "ctprob" | |
| 39 | + | |
| 40 | + | |
| 41 | +/***********************************************************************//** | |
| 42 | + * @class ctprob | |
| 43 | + * | |
| 44 | + * @brief Data selection tool | |
| 45 | + ***************************************************************************/ | |
| 46 | +class ctprob : public ctobservation { | |
| 47 | + | |
| 48 | +public: | |
| 49 | + // Constructors and destructors | |
| 50 | + ctprob(void); | |
| 51 | + explicit ctprob(const GObservations& obs); | |
| 52 | + ctprob(int argc, char *argv[]); | |
| 53 | + ctprob(const ctprob& app); | |
| 54 | + virtual ~ctprob(void); | |
| 55 | + | |
| 56 | + // Operators | |
| 57 | + ctprob& operator=(const ctprob& app); | |
| 58 | + | |
| 59 | + // Methods | |
| 60 | + void clear(void); | |
| 61 | + void run(void); | |
| 62 | + void save(void); | |
| 63 | + void publish(const std::string& name = ""); | |
| 64 | + | |
| 65 | +protected: | |
| 66 | + // Protected methods | |
| 67 | + void init_members(void); | |
| 68 | + void copy_members(const ctprob& app); | |
| 69 | + void free_members(void); | |
| 70 | + void get_parameters(void); | |
| 71 | + void get_obs(void); | |
| 72 | + void evaluate_probability(GCTAObservation* obs); | |
| 73 | + std::string set_outfile_name(const std::string& filename) const; | |
| 74 | + void save_fits(void); | |
| 75 | + void save_xml(void); | |
| 76 | + | |
| 77 | + // User parameters | |
| 78 | + std::string m_outobs; //!< Output event list or XML file | |
| 79 | + std::string m_prefix; //!< Prefix for multiple event lists | |
| 80 | + bool m_apply_edisp; //!< Apply energy dispersion? | |
| 81 | + bool m_publish; //!< Publish event list? | |
| 82 | + GChatter m_chatter; //!< Chattiness | |
| 83 | + | |
| 84 | + // Protected members | |
| 85 | + std::vector<std::string> m_infiles; //!< Input event filenames | |
| 86 | + std::vector<std::string> m_evtname; //!< Event extension names | |
| 87 | + std::vector<std::string> m_gtiname; //!< GTI extension names | |
| 88 | +}; | |
| 89 | + | |
| 90 | +#endif /* CTPROB_HPP */ | ... | ... |
src/ctprob/ctprob.par
0 → 100644
| 1 | +############################################################################# | |
| 2 | +# # | |
| 3 | +# CTA Science Analysis Tools # | |
| 4 | +# # | |
| 5 | +# ------------------------------------------------------------------------- # | |
| 6 | +# # | |
| 7 | +# File: ctprob.par # | |
| 8 | +# # | |
| 9 | +# Author: Leonardo Di Venere # | |
| 10 | +# leonardo.divenere@ba.infn.it # | |
| 11 | +# INFN # | |
| 12 | +# # | |
| 13 | +# Purpose: Parameter file for the ctprob application # | |
| 14 | +# # | |
| 15 | +############################################################################# | |
| 16 | +# | |
| 17 | +# General parameters | |
| 18 | +#=================== | |
| 19 | +inobs, f, a, "events.fits",,, "Input event list or observation definition XML file" | |
| 20 | +outobs, f, a, "prob_events.fits",,, "Output event list or observation definition XML file" | |
| 21 | +prefix, s, h, "prob_",,, "Prefix for event lists in observation definition XML file" | |
| 22 | +inmodel, f, a, "$CTOOLS/share/models/crab.xml",,, "Input model definition XML file" | |
| 23 | +caldb, s, a, "prod2",,, "Calibration database" | |
| 24 | +irf, s, a, "South_0.5h",,, "Instrument response function" | |
| 25 | +edisp, b, h, no,,, "Apply energy dispersion?" | |
| 26 | + | |
| 27 | +# | |
| 28 | +# Standard parameters | |
| 29 | +#==================== | |
| 30 | +publish, b, h, no,,, "Publish event list on VO Hub?" | |
| 31 | +chatter, i, h, 2,0,4, "Chattiness of output" | |
| 32 | +clobber, b, h, yes,,, "Overwrite existing output files with new output files?" | |
| 33 | +debug, b, h, no,,, "Debugging mode activated" | |
| 34 | +mode, s, h, "ql",,, "Mode of automatic parameters" | |
| 35 | +logfile, f, h, "ctprob.log",,, "Log filename" | ... | ... |
src/ctprob/main.cpp
0 → 100644
| 1 | +/*************************************************************************** | |
| 2 | + * ctprob - Computes event probability for a given model * | |
| 3 | + * ----------------------------------------------------------------------- * | |
| 4 | + * copyright (C) 2017 by Leonardo Di Venere * | |
| 5 | + * ----------------------------------------------------------------------- * | |
| 6 | + * * | |
| 7 | + * This program is free software: you can redistribute it and/or modify * | |
| 8 | + * it under the terms of the GNU General Public License as published by * | |
| 9 | + * the Free Software Foundation, either version 3 of the License, or * | |
| 10 | + * (at your option) any later version. * | |
| 11 | + * * | |
| 12 | + * This program is distributed in the hope that it will be useful, * | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| 15 | + * GNU General Public License for more details. * | |
| 16 | + * * | |
| 17 | + * You should have received a copy of the GNU General Public License * | |
| 18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
| 19 | + * * | |
| 20 | + ***************************************************************************/ | |
| 21 | +/** | |
| 22 | + * @file main.cpp | |
| 23 | + * @brief Computes event probability for a given model | |
| 24 | + * @author Leonardo Di Venere | |
| 25 | + */ | |
| 26 | + | |
| 27 | +/* __ Includes ___________________________________________________________ */ | |
| 28 | +#ifdef HAVE_CONFIG_H | |
| 29 | +#include <config.h> | |
| 30 | +#endif | |
| 31 | +#include "support.hpp" | |
| 32 | +#include "ctprob.hpp" | |
| 33 | + | |
| 34 | + | |
| 35 | +/***********************************************************************//** | |
| 36 | + * @brief Main entry point of application | |
| 37 | + * | |
| 38 | + * @param[in] argc Number of command line arguments. | |
| 39 | + * @param[in] argv Command line arguments. | |
| 40 | + * | |
| 41 | + * This is the main entry point of the ctprob application. It allocates a | |
| 42 | + * ctprob object and executes the application. Any exceptions that occur | |
| 43 | + * will be catched and corresponding error messages written in the | |
| 44 | + * application logger and into the standard output. | |
| 45 | + ***************************************************************************/ | |
| 46 | +int main (int argc, char *argv[]) | |
| 47 | +{ | |
| 48 | + // Initialise return code | |
| 49 | + int rc = 1; | |
| 50 | + | |
| 51 | + // Initialise pointer on application | |
| 52 | + ctprob* application = NULL; | |
| 53 | + | |
| 54 | + // Execute application | |
| 55 | + try { | |
| 56 | + | |
| 57 | + // Create instance of application | |
| 58 | + application = new ctprob(argc, argv); | |
| 59 | + | |
| 60 | + // Execute ctool | |
| 61 | + rc = execute_ctool(application); | |
| 62 | + | |
| 63 | + } | |
| 64 | + | |
| 65 | + catch (std::exception &e) { | |
| 66 | + | |
| 67 | + // Report exception | |
| 68 | + report_ctool_failure("ctprob", e.what()); | |
| 69 | + | |
| 70 | + } | |
| 71 | + | |
| 72 | + // Delete application | |
| 73 | + delete application; | |
| 74 | + | |
| 75 | + // Return | |
| 76 | + return rc; | |
| 77 | +} | ... | ... |
src/ctpsfcube/ctpsfcube.cpp
| ... | ... | @@ -49,7 +49,7 @@ |
| 49 | 49 | /***********************************************************************//** |
| 50 | 50 | * @brief Void constructor |
| 51 | 51 | ***************************************************************************/ |
| 52 | -ctpsfcube::ctpsfcube(void) : ctobservation(CTPSFCUBE_NAME, CTPSFCUBE_VERSION) | |
| 52 | +ctpsfcube::ctpsfcube(void) : ctobservation(CTPSFCUBE_NAME, VERSION) | |
| 53 | 53 | { |
| 54 | 54 | // Initialise members |
| 55 | 55 | init_members(); |
| ... | ... | @@ -68,7 +68,7 @@ ctpsfcube::ctpsfcube(void) : ctobservation(CTPSFCUBE_NAME, CTPSFCUBE_VERSION) |
| 68 | 68 | * observations container. |
| 69 | 69 | ***************************************************************************/ |
| 70 | 70 | ctpsfcube::ctpsfcube(const GObservations& obs) : |
| 71 | - ctobservation(CTPSFCUBE_NAME, CTPSFCUBE_VERSION, obs) | |
| 71 | + ctobservation(CTPSFCUBE_NAME, VERSION, obs) | |
| 72 | 72 | { |
| 73 | 73 | // Initialise members |
| 74 | 74 | init_members(); |
| ... | ... | @@ -86,7 +86,7 @@ ctpsfcube::ctpsfcube(const GObservations& obs) : |
| 86 | 86 | * @param[in] argv Array of command line arguments. |
| 87 | 87 | ***************************************************************************/ |
| 88 | 88 | ctpsfcube::ctpsfcube(int argc, char *argv[]) : |
| 89 | - ctobservation(CTPSFCUBE_NAME, CTPSFCUBE_VERSION, argc, argv) | |
| 89 | + ctobservation(CTPSFCUBE_NAME, VERSION, argc, argv) | |
| 90 | 90 | { |
| 91 | 91 | // Initialise members |
| 92 | 92 | init_members(); | ... | ... |
src/ctpsfcube/ctpsfcube.hpp
| ... | ... | @@ -33,8 +33,7 @@ |
| 33 | 33 | #include "ctobservation.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __Definitions _________________________________________________________ */ |
| 36 | -#define CTPSFCUBE_NAME "ctpsfcube" | |
| 37 | -#define CTPSFCUBE_VERSION "1.1.0" | |
| 36 | +#define CTPSFCUBE_NAME "ctpsfcube" | |
| 38 | 37 | |
| 39 | 38 | |
| 40 | 39 | /***********************************************************************//** | ... | ... |
src/ctselect/ctselect.cpp
| ... | ... | @@ -53,7 +53,7 @@ |
| 53 | 53 | /***********************************************************************//** |
| 54 | 54 | * @brief Void constructor |
| 55 | 55 | ***************************************************************************/ |
| 56 | -ctselect::ctselect(void) : ctobservation(CTSELECT_NAME, CTSELECT_VERSION) | |
| 56 | +ctselect::ctselect(void) : ctobservation(CTSELECT_NAME, VERSION) | |
| 57 | 57 | { |
| 58 | 58 | // Initialise members |
| 59 | 59 | init_members(); |
| ... | ... | @@ -72,7 +72,7 @@ ctselect::ctselect(void) : ctobservation(CTSELECT_NAME, CTSELECT_VERSION) |
| 72 | 72 | * provided in an observation container. |
| 73 | 73 | ***************************************************************************/ |
| 74 | 74 | ctselect::ctselect(const GObservations& obs) : |
| 75 | - ctobservation(CTSELECT_NAME, CTSELECT_VERSION, obs) | |
| 75 | + ctobservation(CTSELECT_NAME, VERSION, obs) | |
| 76 | 76 | { |
| 77 | 77 | // Initialise members |
| 78 | 78 | init_members(); |
| ... | ... | @@ -91,7 +91,7 @@ ctselect::ctselect(const GObservations& obs) : |
| 91 | 91 | * @param[in] argv Array of command line arguments. |
| 92 | 92 | ***************************************************************************/ |
| 93 | 93 | ctselect::ctselect(int argc, char *argv[]) : |
| 94 | - ctobservation(CTSELECT_NAME, CTSELECT_VERSION, argc, argv) | |
| 94 | + ctobservation(CTSELECT_NAME, VERSION, argc, argv) | |
| 95 | 95 | { |
| 96 | 96 | // Initialise members |
| 97 | 97 | init_members(); |
| ... | ... | @@ -1175,39 +1175,6 @@ std::string ctselect::set_outfile_name(const std::string& filename) const |
| 1175 | 1175 | |
| 1176 | 1176 | |
| 1177 | 1177 | /***********************************************************************//** |
| 1178 | - * @brief Get Good Time Intervals extension name | |
| 1179 | - * | |
| 1180 | - * @param[in] filename Input file name. | |
| 1181 | - * @param[in] evtname Events extension name. | |
| 1182 | - * | |
| 1183 | - * Extracts the Good Time Intervals extension name from the event file. We | |
| 1184 | - * do this by loading the events and accessing the Good Time Intervals | |
| 1185 | - * extension name using the GCTAEventList::gtiname() method. If the file name | |
| 1186 | - * is empty, the method returns `GTI`. | |
| 1187 | - ***************************************************************************/ | |
| 1188 | -std::string ctselect::get_gtiname(const std::string& filename, | |
| 1189 | - const std::string& evtname) const | |
| 1190 | -{ | |
| 1191 | - // Initialise GTI name | |
| 1192 | - std::string gtiname = gammalib::extname_gti; | |
| 1193 | - | |
| 1194 | - // Continue only if the filename is not empty | |
| 1195 | - if (!filename.empty()) { | |
| 1196 | - | |
| 1197 | - // Load events | |
| 1198 | - GCTAEventList events(filename+"["+evtname+"]"); | |
| 1199 | - | |
| 1200 | - // Get GTI name | |
| 1201 | - gtiname = events.gtiname(); | |
| 1202 | - | |
| 1203 | - } | |
| 1204 | - | |
| 1205 | - // Return GTI name | |
| 1206 | - return (gtiname); | |
| 1207 | -} | |
| 1208 | - | |
| 1209 | - | |
| 1210 | -/***********************************************************************//** | |
| 1211 | 1178 | * @brief Save event list in FITS format. |
| 1212 | 1179 | * |
| 1213 | 1180 | * Save the event list as a FITS file. The file name of the FITS file is |
| ... | ... | @@ -1325,109 +1292,3 @@ void ctselect::save_xml(void) |
| 1325 | 1292 | // Return |
| 1326 | 1293 | return; |
| 1327 | 1294 | } |
| 1328 | - | |
| 1329 | - | |
| 1330 | -/***********************************************************************//** | |
| 1331 | - * @brief Save event list into FITS file | |
| 1332 | - * | |
| 1333 | - * @param[in] obs Pointer to CTA observation. | |
| 1334 | - * @param[in] infile Input file name. | |
| 1335 | - * @param[in] evtname Event extension name. | |
| 1336 | - * @param[in] gtiname GTI extension name. | |
| 1337 | - * @param[in] outfile Output file name. | |
| 1338 | - * | |
| 1339 | - * Saves an event list and the corresponding Good Time Intervals into a FITS | |
| 1340 | - * file and copy all others extensions from the input file to the output | |
| 1341 | - * file. | |
| 1342 | - * | |
| 1343 | - * If an extension name is specified in the @p outfile argument, the events | |
| 1344 | - * and eventually also the Good Time Intervals will be extracted from the | |
| 1345 | - * argument and used for writing the events. The format is | |
| 1346 | - * | |
| 1347 | - * <filename>[<event extension name;GTI extension name>] | |
| 1348 | - * | |
| 1349 | - * where <filename> needs to be replaced by the name of the FITS file, | |
| 1350 | - * and <event extension name;GTI extension name> by the name of the events | |
| 1351 | - * and Good Time Intervals extensions. For example | |
| 1352 | - * | |
| 1353 | - * myfits.fits[EVENTS1;GTI1] | |
| 1354 | - * | |
| 1355 | - * will write the selected events into the "EVENTS1" extension and the | |
| 1356 | - * Good Time Intervals into the "GTI1" extension of the "myfits.fits" FITS | |
| 1357 | - * file. If the Good Time Intervals extension name is skipped, e.g. | |
| 1358 | - * | |
| 1359 | - * myfits.fits[EVENTS1] | |
| 1360 | - * | |
| 1361 | - * the original extension name for the Good Time Intervals will be kept. | |
| 1362 | - * Analogously, only the Good Time Intervals extension name can be changed | |
| 1363 | - * by specifying | |
| 1364 | - * | |
| 1365 | - * myfits.fits[;GTI1] | |
| 1366 | - * | |
| 1367 | - * In none of the cases will the original events and Good Time Intervals be | |
| 1368 | - * copied over to the output file. | |
| 1369 | - ***************************************************************************/ | |
| 1370 | -void ctselect::save_event_list(const GCTAObservation* obs, | |
| 1371 | - const std::string& infile, | |
| 1372 | - const std::string& evtname, | |
| 1373 | - const std::string& gtiname, | |
| 1374 | - const std::string& outfile) const | |
| 1375 | -{ | |
| 1376 | - // Save only if we have an event list | |
| 1377 | - if (obs->eventtype() == "EventList") { | |
| 1378 | - | |
| 1379 | - // Set output FITS file event extension names | |
| 1380 | - GFilename outname(outfile); | |
| 1381 | - std::string outevt = evtname; | |
| 1382 | - std::string outgti = gtiname; | |
| 1383 | - if (outname.has_extname()) { | |
| 1384 | - std::vector<std::string> extnames = | |
| 1385 | - gammalib::split(outname.extname(), ";"); | |
| 1386 | - if (extnames.size() > 0) { | |
| 1387 | - std::string extname = gammalib::strip_whitespace(extnames[0]); | |
| 1388 | - if (!extname.empty()) { | |
| 1389 | - outevt = extname; | |
| 1390 | - } | |
| 1391 | - } | |
| 1392 | - if (extnames.size() > 1) { | |
| 1393 | - std::string extname = gammalib::strip_whitespace(extnames[1]); | |
| 1394 | - if (!extname.empty()) { | |
| 1395 | - outgti = extname; | |
| 1396 | - } | |
| 1397 | - } | |
| 1398 | - } | |
| 1399 | - | |
| 1400 | - // Create output FITS file | |
| 1401 | - GFits outfits; | |
| 1402 | - | |
| 1403 | - // Write observation into FITS file | |
| 1404 | - obs->write(outfits, outevt, outgti); | |
| 1405 | - | |
| 1406 | - // Copy all extensions other than evtname and gtiname extensions | |
| 1407 | - // from the input to the output event list. The evtname and | |
| 1408 | - // gtiname extensions are written by the save method, all others | |
| 1409 | - // that may eventually be present have to be copied over | |
| 1410 | - // explicitly. | |
| 1411 | - GFits infits(infile); | |
| 1412 | - for (int extno = 1; extno < infits.size(); ++extno) { | |
| 1413 | - GFitsHDU* hdu = infits.at(extno); | |
| 1414 | - if (hdu->extname() != evtname && | |
| 1415 | - hdu->extname() != gtiname && | |
| 1416 | - hdu->extname() != outevt && | |
| 1417 | - hdu->extname() != outgti) { | |
| 1418 | - outfits.append(*hdu); | |
| 1419 | - } | |
| 1420 | - } | |
| 1421 | - | |
| 1422 | - // Close input file | |
| 1423 | - infits.close(); | |
| 1424 | - | |
| 1425 | - // Save file to disk and close it (we need both operations) | |
| 1426 | - outfits.saveto(outname.url(), clobber()); | |
| 1427 | - outfits.close(); | |
| 1428 | - | |
| 1429 | - } // endif: observation was unbinned | |
| 1430 | - | |
| 1431 | - // Return | |
| 1432 | - return; | |
| 1433 | -} | ... | ... |
src/ctselect/ctselect.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctselect - Data selection tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2016 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2017 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -35,8 +35,7 @@ |
| 35 | 35 | #include "ctobservation.hpp" |
| 36 | 36 | |
| 37 | 37 | /* __Definitions _________________________________________________________ */ |
| 38 | -#define CTSELECT_NAME "ctselect" | |
| 39 | -#define CTSELECT_VERSION "1.2.0" | |
| 38 | +#define CTSELECT_NAME "ctselect" | |
| 40 | 39 | |
| 41 | 40 | |
| 42 | 41 | /***********************************************************************//** |
| ... | ... | @@ -78,15 +77,8 @@ protected: |
| 78 | 77 | std::string check_infile(const std::string& filename, |
| 79 | 78 | const std::string& evtname) const; |
| 80 | 79 | std::string set_outfile_name(const std::string& filename) const; |
| 81 | - std::string get_gtiname(const std::string& filename, | |
| 82 | - const std::string& evtname) const; | |
| 83 | 80 | void save_fits(void); |
| 84 | 81 | void save_xml(void); |
| 85 | - void save_event_list(const GCTAObservation* obs, | |
| 86 | - const std::string& infile, | |
| 87 | - const std::string& evtname, | |
| 88 | - const std::string& gtiname, | |
| 89 | - const std::string& outfile) const; | |
| 90 | 82 | |
| 91 | 83 | // User parameters |
| 92 | 84 | std::string m_outobs; //!< Output event list or XML file | ... | ... |
src/ctskymap/ctskymap.cpp
| ... | ... | @@ -52,7 +52,7 @@ |
| 52 | 52 | * |
| 53 | 53 | * Constructs an empty sky mapping tool. |
| 54 | 54 | ***************************************************************************/ |
| 55 | -ctskymap::ctskymap(void) : ctobservation(CTSKYMAP_NAME, CTSKYMAP_VERSION) | |
| 55 | +ctskymap::ctskymap(void) : ctobservation(CTSKYMAP_NAME, VERSION) | |
| 56 | 56 | { |
| 57 | 57 | // Initialise members |
| 58 | 58 | init_members(); |
| ... | ... | @@ -70,7 +70,7 @@ ctskymap::ctskymap(void) : ctobservation(CTSKYMAP_NAME, CTSKYMAP_VERSION) |
| 70 | 70 | * Constructs sky mapping tool from an observation container. |
| 71 | 71 | ***************************************************************************/ |
| 72 | 72 | ctskymap::ctskymap(const GObservations& obs) : |
| 73 | - ctobservation(CTSKYMAP_NAME, CTSKYMAP_VERSION, obs) | |
| 73 | + ctobservation(CTSKYMAP_NAME, VERSION, obs) | |
| 74 | 74 | { |
| 75 | 75 | // Initialise members |
| 76 | 76 | init_members(); |
| ... | ... | @@ -91,7 +91,7 @@ ctskymap::ctskymap(const GObservations& obs) : |
| 91 | 91 | * parameter setting. |
| 92 | 92 | ***************************************************************************/ |
| 93 | 93 | ctskymap::ctskymap(int argc, char *argv[]) : |
| 94 | - ctobservation(CTSKYMAP_NAME, CTSKYMAP_VERSION, argc, argv) | |
| 94 | + ctobservation(CTSKYMAP_NAME, VERSION, argc, argv) | |
| 95 | 95 | { |
| 96 | 96 | // Initialise members |
| 97 | 97 | init_members(); | ... | ... |
src/ctskymap/ctskymap.hpp
| ... | ... | @@ -32,8 +32,7 @@ |
| 32 | 32 | #include "ctobservation.hpp" |
| 33 | 33 | |
| 34 | 34 | /* __Definitions _________________________________________________________ */ |
| 35 | -#define CTSKYMAP_NAME "ctskymap" | |
| 36 | -#define CTSKYMAP_VERSION "1.3.0" | |
| 35 | +#define CTSKYMAP_NAME "ctskymap" | |
| 37 | 36 | |
| 38 | 37 | |
| 39 | 38 | /***********************************************************************//** | ... | ... |
src/cttsmap/cttsmap.cpp
| ... | ... | @@ -51,7 +51,7 @@ |
| 51 | 51 | * |
| 52 | 52 | * Constructs an empty cttsmap tool. |
| 53 | 53 | ***************************************************************************/ |
| 54 | -cttsmap::cttsmap(void) : ctlikelihood(CTTSMAP_NAME, CTTSMAP_VERSION) | |
| 54 | +cttsmap::cttsmap(void) : ctlikelihood(CTTSMAP_NAME, VERSION) | |
| 55 | 55 | { |
| 56 | 56 | // Initialise members |
| 57 | 57 | init_members(); |
| ... | ... | @@ -69,7 +69,7 @@ cttsmap::cttsmap(void) : ctlikelihood(CTTSMAP_NAME, CTTSMAP_VERSION) |
| 69 | 69 | * Constructs cttsmap tool from an observations container. |
| 70 | 70 | ***************************************************************************/ |
| 71 | 71 | cttsmap::cttsmap(const GObservations& obs) : |
| 72 | - ctlikelihood(CTTSMAP_NAME, CTTSMAP_VERSION, obs) | |
| 72 | + ctlikelihood(CTTSMAP_NAME, VERSION, obs) | |
| 73 | 73 | { |
| 74 | 74 | // Initialise members |
| 75 | 75 | init_members(); |
| ... | ... | @@ -89,7 +89,7 @@ cttsmap::cttsmap(const GObservations& obs) : |
| 89 | 89 | * that are provided as command line arguments. |
| 90 | 90 | ***************************************************************************/ |
| 91 | 91 | cttsmap::cttsmap(int argc, char *argv[]) : |
| 92 | - ctlikelihood(CTTSMAP_NAME, CTTSMAP_VERSION, argc, argv) | |
| 92 | + ctlikelihood(CTTSMAP_NAME, VERSION, argc, argv) | |
| 93 | 93 | { |
| 94 | 94 | // Initialise members |
| 95 | 95 | init_members(); | ... | ... |
src/cttsmap/cttsmap.hpp
| ... | ... | @@ -31,8 +31,7 @@ |
| 31 | 31 | #include "ctlikelihood.hpp" |
| 32 | 32 | |
| 33 | 33 | /* __Definitions _________________________________________________________ */ |
| 34 | -#define CTTSMAP_NAME "cttsmap" | |
| 35 | -#define CTTSMAP_VERSION "1.2.0" | |
| 34 | +#define CTTSMAP_NAME "cttsmap" | |
| 36 | 35 | |
| 37 | 36 | |
| 38 | 37 | /***********************************************************************//** | ... | ... |
src/ctulimit/ctulimit.cpp
| ... | ... | @@ -53,7 +53,7 @@ |
| 53 | 53 | * |
| 54 | 54 | * Constructs an empty ctulimit tool. |
| 55 | 55 | ***************************************************************************/ |
| 56 | -ctulimit::ctulimit(void) : ctlikelihood(CTULIMIT_NAME, CTULIMIT_VERSION) | |
| 56 | +ctulimit::ctulimit(void) : ctlikelihood(CTULIMIT_NAME, VERSION) | |
| 57 | 57 | { |
| 58 | 58 | // Initialise members |
| 59 | 59 | init_members(); |
| ... | ... | @@ -71,7 +71,7 @@ ctulimit::ctulimit(void) : ctlikelihood(CTULIMIT_NAME, CTULIMIT_VERSION) |
| 71 | 71 | * Constructs ctulimit tool from an observations container. |
| 72 | 72 | ***************************************************************************/ |
| 73 | 73 | ctulimit::ctulimit(const GObservations& obs) : |
| 74 | - ctlikelihood(CTULIMIT_NAME, CTULIMIT_VERSION, obs) | |
| 74 | + ctlikelihood(CTULIMIT_NAME, VERSION, obs) | |
| 75 | 75 | { |
| 76 | 76 | // Initialise members |
| 77 | 77 | init_members(); |
| ... | ... | @@ -92,7 +92,7 @@ ctulimit::ctulimit(const GObservations& obs) : |
| 92 | 92 | * parameters that are provided as command line arguments. |
| 93 | 93 | ***************************************************************************/ |
| 94 | 94 | ctulimit::ctulimit(int argc, char *argv[]) : |
| 95 | - ctlikelihood(CTULIMIT_NAME, CTULIMIT_VERSION, argc, argv) | |
| 95 | + ctlikelihood(CTULIMIT_NAME, VERSION, argc, argv) | |
| 96 | 96 | { |
| 97 | 97 | // Initialise members |
| 98 | 98 | init_members(); | ... | ... |
src/ctulimit/ctulimit.hpp
| ... | ... | @@ -31,8 +31,7 @@ |
| 31 | 31 | #include "ctlikelihood.hpp" |
| 32 | 32 | |
| 33 | 33 | /* __Definitions _________________________________________________________ */ |
| 34 | -#define CTULIMIT_NAME "ctulimit" | |
| 35 | -#define CTULIMIT_VERSION "1.2.0" | |
| 34 | +#define CTULIMIT_NAME "ctulimit" | |
| 36 | 35 | |
| 37 | 36 | |
| 38 | 37 | /***********************************************************************//** | ... | ... |
src/support/ctobservation.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctobservation - Base class for observation tools * |
| 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 * |
| ... | ... | @@ -326,3 +326,123 @@ const GCTAObservation* ctobservation::next_unbinned_observation(void) const |
| 326 | 326 | // Return next CTA observation |
| 327 | 327 | return obs; |
| 328 | 328 | } |
| 329 | + | |
| 330 | + | |
| 331 | +/***********************************************************************//** | |
| 332 | + * @brief Save event list in FITS format. | |
| 333 | + * | |
| 334 | + * Save the event list as a FITS file. The file name of the FITS file is | |
| 335 | + * specified by the `outobs` parameter. | |
| 336 | + ***************************************************************************/ | |
| 337 | +void ctobservation::save_events_fits(void) | |
| 338 | +{ | |
| 339 | + // Save only if there are observations | |
| 340 | + if (m_obs.size() > 0) { | |
| 341 | + | |
| 342 | + // Get output filename | |
| 343 | + std::string outobs = (*this)["outobs"].filename(); | |
| 344 | + | |
| 345 | + // Loop over all unbinned CTA observations in the container | |
| 346 | + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; | |
| 347 | + obs = next_unbinned_observation()) { | |
| 348 | + | |
| 349 | + // Get input file name and default extension names | |
| 350 | + std::string infile = obs->eventfile(); | |
| 351 | + std::string evtname = gammalib::extname_cta_events; | |
| 352 | + std::string gtiname = gammalib::extname_gti; | |
| 353 | + | |
| 354 | + // Create file name object | |
| 355 | + GFilename fname(outobs); | |
| 356 | + | |
| 357 | + // Extract filename and event extension name | |
| 358 | + std::string outfile = fname.url(); | |
| 359 | + | |
| 360 | + // Append event extension name. We handle here the possibility | |
| 361 | + // to write the events into a different extension. | |
| 362 | + if (fname.has_extname()) { | |
| 363 | + outfile += "["+fname.extname()+"]"; | |
| 364 | + } | |
| 365 | + else { | |
| 366 | + outfile += "["+gammalib::extname_cta_events+"]"; | |
| 367 | + } | |
| 368 | + | |
| 369 | + // Log filename | |
| 370 | + log_value(NORMAL, "Event list file", outfile); | |
| 371 | + | |
| 372 | + // Save event list | |
| 373 | + save_event_list(obs, infile, evtname, gtiname, outfile); | |
| 374 | + | |
| 375 | + // Exit the loop (if this method is called we should only | |
| 376 | + // have a single unbinned observation in the observation | |
| 377 | + // container | |
| 378 | + break; | |
| 379 | + | |
| 380 | + } // endfor: looped over all unbinned observations | |
| 381 | + | |
| 382 | + } // endif: there were observations | |
| 383 | + | |
| 384 | + // Return | |
| 385 | + return; | |
| 386 | +} | |
| 387 | + | |
| 388 | + | |
| 389 | +/***********************************************************************//** | |
| 390 | + * @brief Save event list(s) in XML format. | |
| 391 | + * | |
| 392 | + * Save the event list(s) into FITS files and write the file path information | |
| 393 | + * into a XML file. The filename of the XML file is specified by the `outobs` | |
| 394 | + * parameter, the filename(s) of the event lists are built by prepending a | |
| 395 | + * prefix to the input event list filenames. Any path present in the input | |
| 396 | + * filename will be stripped, i.e. the event list(s) will be written in the | |
| 397 | + * local working directory (unless a path is specified in the prefix). | |
| 398 | + ***************************************************************************/ | |
| 399 | +void ctobservation::save_events_xml(void) | |
| 400 | +{ | |
| 401 | + // Get output filename and prefix | |
| 402 | + std::string outobs = (*this)["outobs"].filename(); | |
| 403 | + | |
| 404 | + // Issue warning if output filename has no .xml suffix | |
| 405 | + log_string(TERSE, warn_xml_suffix(outobs)); | |
| 406 | + | |
| 407 | + // Loop over all unbinned CTA observations in the container | |
| 408 | + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; | |
| 409 | + obs = next_unbinned_observation()) { | |
| 410 | + | |
| 411 | + // Get input file name and default extension names | |
| 412 | + std::string infile = obs->eventfile(); | |
| 413 | + std::string evtname = gammalib::extname_cta_events; | |
| 414 | + std::string gtiname = gammalib::extname_gti; | |
| 415 | + | |
| 416 | + // Extract event and GTI extension names from input FITS file | |
| 417 | + GFilename fname(infile); | |
| 418 | + if (fname.has_extname()) { | |
| 419 | + evtname = fname.extname(); | |
| 420 | + } | |
| 421 | + gtiname = get_gtiname(fname.url(), evtname); | |
| 422 | + | |
| 423 | + // Set event output file name | |
| 424 | + std::string outfile = set_outfile_name(infile); | |
| 425 | + | |
| 426 | + // Append event extension name | |
| 427 | + outfile += "["+evtname+"]"; | |
| 428 | + | |
| 429 | + // Log filename | |
| 430 | + log_value(NORMAL, "Event list file", outfile); | |
| 431 | + | |
| 432 | + // Store output file name in observation | |
| 433 | + obs->eventfile(outfile); | |
| 434 | + | |
| 435 | + // Save event list | |
| 436 | + save_event_list(obs, infile, evtname, gtiname, outfile); | |
| 437 | + | |
| 438 | + } // endfor: looped over observations | |
| 439 | + | |
| 440 | + // Write observation definition XML file name into logger | |
| 441 | + log_value(NORMAL, "Obs. definition file", outobs); | |
| 442 | + | |
| 443 | + // Save observations in XML file | |
| 444 | + m_obs.save(outobs); | |
| 445 | + | |
| 446 | + // Return | |
| 447 | + return; | |
| 448 | +} | ... | ... |
src/support/ctobservation.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctobservation - Base class for observation tools * |
| 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 * |
| ... | ... | @@ -78,6 +78,8 @@ protected: |
| 78 | 78 | void init_members(void); |
| 79 | 79 | void copy_members(const ctobservation& app); |
| 80 | 80 | void free_members(void); |
| 81 | + void save_events_fits(void); | |
| 82 | + void save_events_xml(void); | |
| 81 | 83 | |
| 82 | 84 | // Protected members |
| 83 | 85 | GObservations m_obs; //!< Observation container | ... | ... |
src/support/ctool.cpp
| ... | ... | @@ -1028,6 +1028,41 @@ GCTARoi ctool::get_roi(void) |
| 1028 | 1028 | |
| 1029 | 1029 | |
| 1030 | 1030 | /***********************************************************************//** |
| 1031 | + * @brief Set output file name. | |
| 1032 | + * | |
| 1033 | + * @param[in] filename Input file name. | |
| 1034 | + * | |
| 1035 | + * Required user parameters: | |
| 1036 | + * prefix | |
| 1037 | + * | |
| 1038 | + * Converts an input file name into an output filename by prepending the | |
| 1039 | + * prefix specified by the `prefix` parameter to the input file name. Any | |
| 1040 | + * path as well as extension will be stripped from the input file name. Also | |
| 1041 | + * a trailing `.gz` will be stripped as one cannot write into gzipped files. | |
| 1042 | + ***************************************************************************/ | |
| 1043 | +std::string ctool::set_outfile_name(const std::string& filename) | |
| 1044 | +{ | |
| 1045 | + // Get prefix User parameter | |
| 1046 | + std::string prefix = (*this)["prefix"].string(); | |
| 1047 | + | |
| 1048 | + // Create filename | |
| 1049 | + GFilename fname(filename); | |
| 1050 | + | |
| 1051 | + // Split input filename without any extensions into path elements | |
| 1052 | + std::vector<std::string> elements = gammalib::split(fname.url(), "/"); | |
| 1053 | + | |
| 1054 | + // The last path element is the filename | |
| 1055 | + std::string outname = prefix + elements[elements.size()-1]; | |
| 1056 | + | |
| 1057 | + // Strip any ".gz" | |
| 1058 | + outname = gammalib::strip_chars(outname, ".gz"); | |
| 1059 | + | |
| 1060 | + // Return output filename | |
| 1061 | + return outname; | |
| 1062 | +} | |
| 1063 | + | |
| 1064 | + | |
| 1065 | +/***********************************************************************//** | |
| 1031 | 1066 | * @brief Set response for all CTA observations in container |
| 1032 | 1067 | * |
| 1033 | 1068 | * @param[in,out] obs Observation container |
| ... | ... | @@ -1730,6 +1765,145 @@ std::vector<bool> ctool::cube_layer_usage(const GEbounds& cube_ebounds, |
| 1730 | 1765 | |
| 1731 | 1766 | |
| 1732 | 1767 | /***********************************************************************//** |
| 1768 | + * @brief Save event list into FITS file | |
| 1769 | + * | |
| 1770 | + * @param[in] obs Pointer to CTA observation. | |
| 1771 | + * @param[in] infile Input file name. | |
| 1772 | + * @param[in] evtname Event extension name. | |
| 1773 | + * @param[in] gtiname GTI extension name. | |
| 1774 | + * @param[in] outfile Output file name. | |
| 1775 | + * | |
| 1776 | + * Saves an event list and the corresponding Good Time Intervals into a FITS | |
| 1777 | + * file and copy all others extensions from the input file to the output | |
| 1778 | + * file. | |
| 1779 | + * | |
| 1780 | + * If an extension name is specified in the @p outfile argument, the events | |
| 1781 | + * and eventually also the Good Time Intervals will be extracted from the | |
| 1782 | + * argument and used for writing the events. The format is | |
| 1783 | + * | |
| 1784 | + * <filename>[<event extension name;GTI extension name>] | |
| 1785 | + * | |
| 1786 | + * where <filename> needs to be replaced by the name of the FITS file, | |
| 1787 | + * and <event extension name;GTI extension name> by the name of the events | |
| 1788 | + * and Good Time Intervals extensions. For example | |
| 1789 | + * | |
| 1790 | + * myfits.fits[EVENTS1;GTI1] | |
| 1791 | + * | |
| 1792 | + * will write the selected events into the `EVENTS1` extension and the | |
| 1793 | + * Good Time Intervals into the `GTI1` extension of the `myfits.fits` FITS | |
| 1794 | + * file. If the Good Time Intervals extension name is skipped, e.g. | |
| 1795 | + * | |
| 1796 | + * myfits.fits[EVENTS1] | |
| 1797 | + * | |
| 1798 | + * the original extension name for the Good Time Intervals will be kept. | |
| 1799 | + * Analogously, only the Good Time Intervals extension name can be changed | |
| 1800 | + * by specifying | |
| 1801 | + * | |
| 1802 | + * myfits.fits[;GTI1] | |
| 1803 | + * | |
| 1804 | + * In none of the cases will the original events and Good Time Intervals be | |
| 1805 | + * copied over to the output file. | |
| 1806 | + ***************************************************************************/ | |
| 1807 | +void ctool::save_event_list(const GCTAObservation* obs, | |
| 1808 | + const std::string& infile, | |
| 1809 | + const std::string& evtname, | |
| 1810 | + const std::string& gtiname, | |
| 1811 | + const std::string& outfile) const | |
| 1812 | +{ | |
| 1813 | + // Save only if we have an event list | |
| 1814 | + if (obs->eventtype() == "EventList") { | |
| 1815 | + | |
| 1816 | + // Set output FITS file event extension names | |
| 1817 | + GFilename outname(outfile); | |
| 1818 | + std::string outevt = evtname; | |
| 1819 | + std::string outgti = gtiname; | |
| 1820 | + if (outname.has_extname()) { | |
| 1821 | + std::vector<std::string> extnames = | |
| 1822 | + gammalib::split(outname.extname(), ";"); | |
| 1823 | + if (extnames.size() > 0) { | |
| 1824 | + std::string extname = gammalib::strip_whitespace(extnames[0]); | |
| 1825 | + if (!extname.empty()) { | |
| 1826 | + outevt = extname; | |
| 1827 | + } | |
| 1828 | + } | |
| 1829 | + if (extnames.size() > 1) { | |
| 1830 | + std::string extname = gammalib::strip_whitespace(extnames[1]); | |
| 1831 | + if (!extname.empty()) { | |
| 1832 | + outgti = extname; | |
| 1833 | + } | |
| 1834 | + } | |
| 1835 | + } | |
| 1836 | + | |
| 1837 | + // Create output FITS file | |
| 1838 | + GFits outfits; | |
| 1839 | + | |
| 1840 | + // Write observation into FITS file | |
| 1841 | + obs->write(outfits, outevt, outgti); | |
| 1842 | + | |
| 1843 | + // Copy all extensions other than evtname and gtiname extensions | |
| 1844 | + // from the input to the output event list. The evtname and | |
| 1845 | + // gtiname extensions are written by the save method, all others | |
| 1846 | + // that may eventually be present have to be copied over | |
| 1847 | + // explicitly. | |
| 1848 | + GFits infits(infile); | |
| 1849 | + for (int extno = 1; extno < infits.size(); ++extno) { | |
| 1850 | + GFitsHDU* hdu = infits.at(extno); | |
| 1851 | + if (hdu->extname() != evtname && | |
| 1852 | + hdu->extname() != gtiname && | |
| 1853 | + hdu->extname() != outevt && | |
| 1854 | + hdu->extname() != outgti) { | |
| 1855 | + outfits.append(*hdu); | |
| 1856 | + } | |
| 1857 | + } | |
| 1858 | + | |
| 1859 | + // Close input file | |
| 1860 | + infits.close(); | |
| 1861 | + | |
| 1862 | + // Save file to disk and close it (we need both operations) | |
| 1863 | + outfits.saveto(outname.url(), clobber()); | |
| 1864 | + outfits.close(); | |
| 1865 | + | |
| 1866 | + } // endif: observation was unbinned | |
| 1867 | + | |
| 1868 | + // Return | |
| 1869 | + return; | |
| 1870 | +} | |
| 1871 | + | |
| 1872 | + | |
| 1873 | +/***********************************************************************//** | |
| 1874 | + * @brief Get Good Time Intervals extension name | |
| 1875 | + * | |
| 1876 | + * @param[in] filename Input file name. | |
| 1877 | + * @param[in] evtname Events extension name. | |
| 1878 | + * | |
| 1879 | + * Extracts the Good Time Intervals extension name from the event file. We | |
| 1880 | + * do this by loading the events and accessing the Good Time Intervals | |
| 1881 | + * extension name using the GCTAEventList::gtiname() method. If the file name | |
| 1882 | + * is empty, the method returns `GTI`. | |
| 1883 | + ***************************************************************************/ | |
| 1884 | +std::string ctool::get_gtiname(const std::string& filename, | |
| 1885 | + const std::string& evtname) const | |
| 1886 | +{ | |
| 1887 | + // Initialise GTI name | |
| 1888 | + std::string gtiname = gammalib::extname_gti; | |
| 1889 | + | |
| 1890 | + // Continue only if the filename is not empty | |
| 1891 | + if (!filename.empty()) { | |
| 1892 | + | |
| 1893 | + // Load events | |
| 1894 | + GCTAEventList events(filename+"["+evtname+"]"); | |
| 1895 | + | |
| 1896 | + // Get GTI name | |
| 1897 | + gtiname = events.gtiname(); | |
| 1898 | + | |
| 1899 | + } | |
| 1900 | + | |
| 1901 | + // Return GTI name | |
| 1902 | + return (gtiname); | |
| 1903 | +} | |
| 1904 | + | |
| 1905 | + | |
| 1906 | +/***********************************************************************//** | |
| 1733 | 1907 | * @brief Set warning string if there are too few energies |
| 1734 | 1908 | * |
| 1735 | 1909 | * @param[in] energies Energies. | ... | ... |
src/support/ctool.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctool - ctool base class * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2014-2016 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2014-2017 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -104,6 +104,7 @@ protected: |
| 104 | 104 | |
| 105 | 105 | // Protected methods that extract user parameters |
| 106 | 106 | GCTARoi get_roi(void); |
| 107 | + std::string set_outfile_name(const std::string& filename); | |
| 107 | 108 | |
| 108 | 109 | // Protected support methods |
| 109 | 110 | void set_response(GObservations& obs); |
| ... | ... | @@ -121,6 +122,13 @@ protected: |
| 121 | 122 | std::vector<bool> cube_layer_usage(const GEbounds& cube_ebounds, |
| 122 | 123 | const GEbounds& list_ebounds) const; |
| 123 | 124 | bool is_valid_filename(const GFilename& filename) const; |
| 125 | + std::string get_gtiname(const std::string& filename, | |
| 126 | + const std::string& evtname) const; | |
| 127 | + void save_event_list(const GCTAObservation* obs, | |
| 128 | + const std::string& infile, | |
| 129 | + const std::string& evtname, | |
| 130 | + const std::string& gtiname, | |
| 131 | + const std::string& outfile) const; | |
| 124 | 132 | |
| 125 | 133 | // Protected warning strings |
| 126 | 134 | std::string warn_too_few_energies(const GEnergies& energies) const; | ... | ... |
test/data/irf.root
No preview for this file type
test/data/model_temporal_phasecurve.fits
0 → 100644
No preview for this file type
test/data/model_temporal_phasecurve.xml
0 → 100644
| 1 | +<?xml version="1.0" standalone="no"?> | |
| 2 | +<source_library title="source library"> | |
| 3 | + <source name="Crab" type="PointSource"> | |
| 4 | + <spectrum type="PowerLaw"> | |
| 5 | + <parameter name="Prefactor" scale="1e-16" value="5.7" min="1e-07" max="1000.0" free="1"/> | |
| 6 | + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="+5.0" free="1"/> | |
| 7 | + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | |
| 8 | + </spectrum> | |
| 9 | + <spatialModel type="PointSource"> | |
| 10 | + <parameter free="0" max="360" min="-360" name="RA" scale="1" value="83.6331" /> | |
| 11 | + <parameter free="0" max="90" min="-90" name="DEC" scale="1" value="22.0145" /> | |
| 12 | + </spatialModel> | |
| 13 | + <temporal type="PhaseCurve" file="model_temporal_phasecurve.fits"> | |
| 14 | + <parameter name="Normalization" scale="1" value="1.0" min="0.0" max="1000.0" free="0"/> | |
| 15 | + <parameter name="MJD" scale="1" value="51544.5" min="0.0" max="100000.0" free="0"/> | |
| 16 | + <parameter name="Phase" scale="1" value="0.0" min="0.0" max="1.0" free="0"/> | |
| 17 | + <parameter name="F0" scale="1" value="1.0" min="0.0" max="1000.0" free="0"/> | |
| 18 | + <parameter name="F1" scale="1" value="0.1" min="0.0" max="1000.0" free="0"/> | |
| 19 | + <parameter name="F2" scale="1" value="0.01" min="0.0" max="1000.0" free="0"/> | |
| 20 | + </temporal> | |
| 21 | + </source> | |
| 22 | +</source_library> | ... | ... |
test/test_cssens.py
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | # ========================================================================== |
| 3 | 3 | # This scripts performs unit tests for the cssens script |
| 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 |
| ... | ... | @@ -168,7 +168,7 @@ class Test(test): |
| 168 | 168 | # Check dimensions |
| 169 | 169 | self.test_value(results.nrows(), 2, |
| 170 | 170 | 'Check number of rows in sensitivity file') |
| 171 | - self.test_value(results.ncols(), 7, | |
| 171 | + self.test_value(results.ncols(), 10, | |
| 172 | 172 | 'Check number of columns in sensitivity file') |
| 173 | 173 | |
| 174 | 174 | # Return | ... | ... |
test/test_ctbutterfly.py
| ... | ... | @@ -168,6 +168,9 @@ class Test(test): |
| 168 | 168 | cpy_butterfly['outfile'] = 'ctbutterfly_py3.dat' |
| 169 | 169 | cpy_butterfly['logfile'] = 'ctbutterfly_py3.log' |
| 170 | 170 | cpy_butterfly['chatter'] = 4 |
| 171 | + | |
| 172 | + # Execute ctbutterfly tool | |
| 173 | + cpy_butterfly.logFileOpen() # Make sure we get a log file | |
| 171 | 174 | cpy_butterfly.execute() |
| 172 | 175 | |
| 173 | 176 | # Check result file | ... | ... |
test/test_ctphase.py
| 1 | 1 | #! /usr/bin/env python |
| 2 | 2 | # ========================================================================== |
| 3 | -# This scripts performs unit tests for the ctselect tool. | |
| 3 | +# This scripts performs unit tests for the ctphase tool. | |
| 4 | 4 | # |
| 5 | -# Copyright (C) 2014-2016 Juergen Knoedlseder | |
| 5 | +# Copyright (C) 2017 by Joshua Cardenzana | |
| 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 |
| ... | ... | @@ -40,6 +40,8 @@ class Test(test): |
| 40 | 40 | test.__init__(self) |
| 41 | 41 | |
| 42 | 42 | # Set test data |
| 43 | + self._model_file = self._datadir + '/model_temporal_phasecurve.xml' | |
| 44 | + self._phase_file = self._datadir + '/model_temporal_phasecurve.fits' | |
| 43 | 45 | self._invalid_events = self._datadir + '/invalid_event_list.fits' |
| 44 | 46 | |
| 45 | 47 | # Return |
| ... | ... | @@ -70,10 +72,9 @@ class Test(test): |
| 70 | 72 | |
| 71 | 73 | # Setup ctphase command |
| 72 | 74 | cmd = ctphase+' inobs="'+self._events+'"'+ \ |
| 73 | - ' outobs="ctphase_cmd1.fits"'+ \ | |
| 74 | - ' p0=0.1 mjd=51544.5'+ \ | |
| 75 | - ' f0=0.1 f1=0. f2=0.'+ \ | |
| 76 | - ' logfile="ctphase_cmd1.log" chatter=1' | |
| 75 | + ' outobs="ctphase_cmd1.fits"'+ \ | |
| 76 | + ' inmodel="'+self._model_file+'" source="Crab"'+ \ | |
| 77 | + ' logfile="ctphase_cmd1.log" chatter=1' | |
| 77 | 78 | |
| 78 | 79 | # Check if execution of wrong command fails |
| 79 | 80 | self.test_assert(self._execute('command_that_does_not_exist') != 0, |
| ... | ... | @@ -88,10 +89,9 @@ class Test(test): |
| 88 | 89 | |
| 89 | 90 | # Setup ctphase command |
| 90 | 91 | cmd = ctphase+' inobs="event_file_that_does_not_exist.fits"'+ \ |
| 91 | - ' outobs="ctphase_cmd2.fits"'+ \ | |
| 92 | - ' p0=0.1 mjd=51544.5'+ \ | |
| 93 | - ' f0=0.1 f1=0. f2=0.'+ \ | |
| 94 | - ' logfile="ctphase_cmd2.log" chatter=1' | |
| 92 | + ' outobs="ctphase_cmd2.fits"'+ \ | |
| 93 | + ' inmodel="'+self._model_file+'" source="Crab"'+ \ | |
| 94 | + ' logfile="ctphase_cmd2.log" chatter=1' | |
| 95 | 95 | |
| 96 | 96 | # Check if execution failed |
| 97 | 97 | self.test_assert(self._execute(cmd) != 0, |
| ... | ... | @@ -124,6 +124,8 @@ class Test(test): |
| 124 | 124 | self._check_obs(phase.obs(), nobs=0) |
| 125 | 125 | |
| 126 | 126 | # Check that saving does nothing |
| 127 | + phase['inmodel'] = self._model_file | |
| 128 | + phase['source'] = 'Crab' | |
| 127 | 129 | phase['outobs'] = 'ctphase_py0.fits' |
| 128 | 130 | phase['logfile'] = 'ctphase_py0.log' |
| 129 | 131 | phase.logFileOpen() |
| ... | ... | @@ -136,11 +138,8 @@ class Test(test): |
| 136 | 138 | |
| 137 | 139 | # Now set ctphase parameters |
| 138 | 140 | phase['inobs'] = self._events |
| 139 | - phase['p0'] = 0. | |
| 140 | - phase['mjd'] = 51544.5 | |
| 141 | - phase['f0'] = 1. | |
| 142 | - phase['f1'] = 0.0 | |
| 143 | - phase['f2'] = 0. | |
| 141 | + phase['inmodel'] = self._model_file | |
| 142 | + phase['source'] = 'Crab' | |
| 144 | 143 | phase['outobs'] = 'ctphase_py1.fits' |
| 145 | 144 | phase['logfile'] = 'ctphase_py1.log' |
| 146 | 145 | phase['chatter'] = 2 |
| ... | ... | @@ -151,34 +150,50 @@ class Test(test): |
| 151 | 150 | phase.save() |
| 152 | 151 | |
| 153 | 152 | # Check result file |
| 154 | - self._check_result_file('ctphase_py1.fits', nevents=6141) | |
| 153 | + self._check_result_file('ctphase_py1.fits') | |
| 154 | + | |
| 155 | + # Now run ctphase tool without a model file | |
| 156 | + phase['inmodel'] = 'NONE' | |
| 157 | + phase['source'] = 'NONE' | |
| 158 | + phase['phasecurve'] = self._phase_file | |
| 159 | + phase['mjd'] = 51544.5 | |
| 160 | + phase['phase'] = 0.0 | |
| 161 | + phase['f0'] = 1.0 | |
| 162 | + phase['f1'] = 0.1 | |
| 163 | + phase['f2'] = 0.01 | |
| 164 | + phase['outobs'] = 'ctphase_py2.fits' | |
| 165 | + phase['logfile'] = 'ctphase_py2.log' | |
| 166 | + phase['chatter'] = 3 | |
| 167 | + | |
| 168 | + # Execute ctphase tool | |
| 169 | + phase.logFileOpen() # Make sure we get a log file | |
| 170 | + phase.execute() | |
| 171 | + | |
| 172 | + # Check result file | |
| 173 | + self._check_result_file('ctphase_py2.fits') | |
| 155 | 174 | |
| 156 | 175 | # Copy ctphase tool |
| 157 | 176 | cpy_phase = phase.copy() |
| 158 | 177 | |
| 159 | - # Execute copy of ctphase tool again, now with a negative value | |
| 160 | - # of initial phase to test for invalid parameter value | |
| 161 | - self.test_try('Test invalid parameter value') | |
| 162 | - try: | |
| 163 | - cpy_phase['mjd'] = 51544.5 | |
| 164 | - cpy_phase['f0'] = 1. | |
| 165 | - cpy_phase['f1'] = 0.2 | |
| 166 | - cpy_phase['f2'] = 0. | |
| 167 | - cpy_phase['outobs'] = 'ctphase_py2.fits' | |
| 168 | - cpy_phase['logfile'] = 'ctphase_py2.log' | |
| 169 | - cpy_phase['chatter'] = 3 | |
| 170 | - cpy_phase['publish'] = True | |
| 171 | - cpy_phase.logFileOpen() # Needed to get a new log file | |
| 172 | - cpy_phase['p0'] = -0.5 | |
| 173 | - cpy_phase.execute() | |
| 174 | - self.test_try_failure('Exception not thrown') | |
| 175 | - except ValueError: | |
| 176 | - self.test_try_success() | |
| 178 | + # Clear phase tool | |
| 179 | + phase.clear() | |
| 180 | + | |
| 181 | + # Execute copy | |
| 182 | + cpy_phase['outobs'] = 'ctphase_py3.fits' | |
| 183 | + cpy_phase['logfile'] = 'ctphase_py3.log' | |
| 184 | + cpy_phase['chatter'] = 4 | |
| 185 | + cpy_phase['publish'] = True | |
| 186 | + cpy_phase.logFileOpen() # Needed to get a new log file | |
| 187 | + cpy_phase.execute() | |
| 177 | 188 | |
| 189 | + # Check result file | |
| 190 | + self._check_result_file('ctphase_py3.fits') | |
| 191 | + | |
| 192 | + # Return | |
| 178 | 193 | return |
| 179 | 194 | |
| 180 | 195 | # Check result file |
| 181 | - def _check_result_file(self, filename, nevents=591, dec=22.01, rad=3.0): | |
| 196 | + def _check_result_file(self, filename, nevents=6141): | |
| 182 | 197 | """ |
| 183 | 198 | Check result file |
| 184 | 199 | |
| ... | ... | @@ -188,14 +203,10 @@ class Test(test): |
| 188 | 203 | Event list file name |
| 189 | 204 | nevents : int, optional |
| 190 | 205 | Expected number of events |
| 191 | - dec : float, optional | |
| 192 | - Expected Declination (deg) | |
| 193 | - rad : float, optional | |
| 194 | - Expected radius (deg) | |
| 195 | 206 | """ |
| 196 | 207 | # Open result file |
| 197 | - events = gammalib.GCTAEventList(filename) | |
| 198 | - phases = [ events[i].phase() for i in range(events.size())] | |
| 208 | + events = gammalib.GCTAEventList(filename) | |
| 209 | + phases = [events[i].phase() for i in range(events.size())] | |
| 199 | 210 | test_result = int(sum(phases)>0) |
| 200 | 211 | self.test_value(test_result, 1, 'Check number of events') |
| 201 | 212 | |
| ... | ... | @@ -213,8 +224,6 @@ class Test(test): |
| 213 | 224 | Models |
| 214 | 225 | nobs : int, optional |
| 215 | 226 | Expected number of observations |
| 216 | - nevents : int, optional | |
| 217 | - Expected number of events | |
| 218 | 227 | """ |
| 219 | 228 | # Check number of observations |
| 220 | 229 | self.test_value(obs.size(), nobs, 'Check number of observations') | ... | ... |
test/test_ctprob.py
0 → 100755
| 1 | +#! /usr/bin/env python | |
| 2 | +# ========================================================================== | |
| 3 | +# This scripts performs unit tests for the ctprob tool. | |
| 4 | +# | |
| 5 | +# Copyright (C) 2017 by Leonardo Di Venere | |
| 6 | +# | |
| 7 | +# This program is free software: you can redistribute it and/or modify | |
| 8 | +# it under the terms of the GNU General Public License as published by | |
| 9 | +# the Free Software Foundation, either version 3 of the License, or | |
| 10 | +# (at your option) any later version. | |
| 11 | +# | |
| 12 | +# This program is distributed in the hope that it will be useful, | |
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | +# GNU General Public License for more details. | |
| 16 | +# | |
| 17 | +# You should have received a copy of the GNU General Public License | |
| 18 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 19 | +# | |
| 20 | +# ========================================================================== | |
| 21 | +import os | |
| 22 | +import gammalib | |
| 23 | +import ctools | |
| 24 | +from testing import test | |
| 25 | + | |
| 26 | + | |
| 27 | +# ============================ # | |
| 28 | +# Test class for ctprob tool # | |
| 29 | +# ============================ # | |
| 30 | +class Test(test): | |
| 31 | + """ | |
| 32 | + Test class for ctprob tool | |
| 33 | + """ | |
| 34 | + # Constructor | |
| 35 | + def __init__(self): | |
| 36 | + """ | |
| 37 | + Constructor | |
| 38 | + """ | |
| 39 | + # Call base class constructor | |
| 40 | + test.__init__(self) | |
| 41 | + | |
| 42 | + # Set test data | |
| 43 | + self._invalid_events = self._datadir + '/invalid_event_list.fits' | |
| 44 | + | |
| 45 | + # Return | |
| 46 | + return | |
| 47 | + | |
| 48 | + # Set test functions | |
| 49 | + def set(self): | |
| 50 | + """ | |
| 51 | + Set all test functions | |
| 52 | + """ | |
| 53 | + # Set test name | |
| 54 | + self.name('ctprob') | |
| 55 | + | |
| 56 | + # Append tests | |
| 57 | + self.append(self._test_cmd, 'Test ctprob on command line') | |
| 58 | + self.append(self._test_python, 'Test ctprob from Python') | |
| 59 | + | |
| 60 | + # Return | |
| 61 | + return | |
| 62 | + | |
| 63 | + # Test ctprob on command line | |
| 64 | + def _test_cmd(self): | |
| 65 | + """ | |
| 66 | + Test ctprob on the command line | |
| 67 | + """ | |
| 68 | + # Set tool name | |
| 69 | + ctprob = self._tool('ctprob') | |
| 70 | + | |
| 71 | + # Setup ctprob command | |
| 72 | + cmd = ctprob+' inobs="'+self._events+'"'+ \ | |
| 73 | + ' outobs="ctprob_cmd1.fits"'+ \ | |
| 74 | + ' inmodel='+self._model+ \ | |
| 75 | + ' caldb='+self._caldb+' irf='+self._irf+ \ | |
| 76 | + ' edisp=no'+ \ | |
| 77 | + ' logfile="ctprob_cmd1.log" chatter=1' | |
| 78 | + | |
| 79 | + # Check if execution was successful | |
| 80 | + self.test_assert(self._execute(cmd) == 0, | |
| 81 | + 'Check successful execution from command line') | |
| 82 | + | |
| 83 | + # Check result file | |
| 84 | + self._check_result_file('ctprob_cmd1.fits') | |
| 85 | + | |
| 86 | + # Setup ctprob command | |
| 87 | + cmd = ctprob+' inobs="event_file_that_does_not_exist.fits"'+ \ | |
| 88 | + ' outobs="ctprob_cmd2.fits"'+ \ | |
| 89 | + ' inmodel='+self._model+ \ | |
| 90 | + ' caldb='+self._caldb+' irf='+self._irf+ \ | |
| 91 | + ' edisp=no'+ \ | |
| 92 | + ' logfile="ctprob_cmd2.log" chatter=1' | |
| 93 | + | |
| 94 | + # Check if execution failed | |
| 95 | + self.test_assert(self._execute(cmd) != 0, | |
| 96 | + 'Check invalid input file when executed from command line') | |
| 97 | + | |
| 98 | + # Setup ctprob --help option | |
| 99 | + cmd = ctprob+' --help' | |
| 100 | + | |
| 101 | + # Check if execution was successful in case that the CTOOLS | |
| 102 | + # environment variable was set or failed otherwise | |
| 103 | + if 'CTOOLS' in os.environ: | |
| 104 | + self.test_value(self._execute(cmd), 0, | |
| 105 | + 'Check successful execution with --help option') | |
| 106 | + else: | |
| 107 | + self.test_assert(self._execute(cmd) != 0, | |
| 108 | + 'Check execution failure with --help option') | |
| 109 | + | |
| 110 | + # Return | |
| 111 | + return | |
| 112 | + | |
| 113 | + # Test ctprob from Python | |
| 114 | + def _test_python(self): | |
| 115 | + """ | |
| 116 | + Test ctprob from Python | |
| 117 | + """ | |
| 118 | + # Allocate empty ctprob tool | |
| 119 | + prob = ctools.ctprob() | |
| 120 | + | |
| 121 | + # Check that empty ctprob tool holds an empty observation | |
| 122 | + self._check_obs(prob.obs(), nobs=0) | |
| 123 | + | |
| 124 | + # Check that saving does nothing | |
| 125 | + prob['outobs'] = 'ctprob_py0.fits' | |
| 126 | + prob['logfile'] = 'ctprob_py0.log' | |
| 127 | + prob.logFileOpen() | |
| 128 | + prob.save() | |
| 129 | + self.test_assert(not os.path.isfile('ctprob_py0.fits'), | |
| 130 | + 'Check that no event list has been created') | |
| 131 | + | |
| 132 | + # Check that clearing does not lead to an exception or segfault | |
| 133 | + prob.clear() | |
| 134 | + | |
| 135 | + # Now set ctprob parameters | |
| 136 | + prob['inobs'] = self._events | |
| 137 | + prob['outobs'] = 'ctprob_py1.fits' | |
| 138 | + prob['inmodel'] = self._model | |
| 139 | + prob['caldb'] = self._caldb | |
| 140 | + prob['irf'] = self._irf | |
| 141 | + prob['edisp'] = False | |
| 142 | + prob['logfile'] = 'ctprob_py1.log' | |
| 143 | + prob['chatter'] = 2 | |
| 144 | + | |
| 145 | + # Run ctprob tool | |
| 146 | + prob.logFileOpen() # Make sure we get a log file | |
| 147 | + prob.run() | |
| 148 | + prob.save() | |
| 149 | + | |
| 150 | + # Check result file | |
| 151 | + self._check_result_file('ctprob_py1.fits') | |
| 152 | + | |
| 153 | + # Setup ctprob tool for an invalid event file | |
| 154 | + prob = ctools.ctprob() | |
| 155 | + prob['inobs'] = self._invalid_events | |
| 156 | + prob['outobs'] = 'ctprob_py2.fits' | |
| 157 | + prob['inmodel'] = self._model | |
| 158 | + prob['caldb'] = self._caldb | |
| 159 | + prob['irf'] = self._irf | |
| 160 | + prob['edisp'] = False | |
| 161 | + prob['logfile'] = 'ctprob_py2.log' | |
| 162 | + prob['chatter'] = 3 | |
| 163 | + | |
| 164 | + # Execute tool | |
| 165 | + prob.logFileOpen() # Needed to get a new log file | |
| 166 | + self.test_try('Test invalid event file') | |
| 167 | + try: | |
| 168 | + prob.execute() | |
| 169 | + self.test_try_failure('Exception not thrown') | |
| 170 | + except RuntimeError: | |
| 171 | + self.test_try_success() | |
| 172 | + | |
| 173 | + # Setup ctprob with a list of observations and test prefix | |
| 174 | + prob = ctools.ctprob() | |
| 175 | + prob['inobs'] = self._datadir + '/obs_unbinned.xml' | |
| 176 | + prob['prefix'] = 'ctprob_py3_' | |
| 177 | + prob['outobs'] = 'ctprob_py3_obs.xml' | |
| 178 | + prob['inmodel'] = self._model | |
| 179 | + prob['caldb'] = self._caldb | |
| 180 | + prob['irf'] = self._irf | |
| 181 | + prob['edisp'] = True | |
| 182 | + prob['logfile'] = 'ctprob_py3.log' | |
| 183 | + prob['chatter'] = 4 | |
| 184 | + | |
| 185 | + # Run ctprob tool | |
| 186 | + prob.logFileOpen() # Make sure we get a log file | |
| 187 | + prob.execute() | |
| 188 | + | |
| 189 | + # Check result file | |
| 190 | + self._check_result_file('ctprob_py3_crab_events.fits') | |
| 191 | + | |
| 192 | + # Return | |
| 193 | + return | |
| 194 | + | |
| 195 | + # Check result file | |
| 196 | + def _check_result_file(self, filename, nevents=6141): | |
| 197 | + """ | |
| 198 | + Check result file | |
| 199 | + | |
| 200 | + Parameters | |
| 201 | + ---------- | |
| 202 | + filename : str | |
| 203 | + Event list file name | |
| 204 | + nevents : int, optional | |
| 205 | + Expected number of events | |
| 206 | + """ | |
| 207 | + # Open result file | |
| 208 | + events = gammalib.GCTAEventList(filename) | |
| 209 | + | |
| 210 | + # Check event list | |
| 211 | + self._check_events(events, nevents=nevents) | |
| 212 | + | |
| 213 | + # Check that probability columns exist | |
| 214 | + colname1 = 'PROB_Background' | |
| 215 | + colname2 = 'PROB_Crab' | |
| 216 | + self._check_column(filename, colname1) | |
| 217 | + self._check_column(filename, colname2) | |
| 218 | + | |
| 219 | + # Check that the probability values are correctly normalized | |
| 220 | + self._check_normalization(filename, [colname1,colname2]) | |
| 221 | + | |
| 222 | + # Return | |
| 223 | + return | |
| 224 | + | |
| 225 | + # Check observation and event list | |
| 226 | + def _check_obs(self, obs, nobs=1, nevents=6141): | |
| 227 | + """ | |
| 228 | + Check observation and event list | |
| 229 | + | |
| 230 | + Parameters | |
| 231 | + ---------- | |
| 232 | + obs : `~gammalib.GObservations` | |
| 233 | + Models | |
| 234 | + nobs : int, optional | |
| 235 | + Expected number of observations | |
| 236 | + nevents : int, optional | |
| 237 | + Expected number of events | |
| 238 | + """ | |
| 239 | + # Check number of observations | |
| 240 | + self.test_value(obs.size(), nobs, 'Check number of observations') | |
| 241 | + | |
| 242 | + # If there is an observation then check the event list of the first | |
| 243 | + # one | |
| 244 | + if obs.size() > 0: | |
| 245 | + self._check_events(obs[0].events(), nevents=nevents) | |
| 246 | + | |
| 247 | + # Return | |
| 248 | + return | |
| 249 | + | |
| 250 | + # Check events | |
| 251 | + def _check_events(self, events, nevents=6141): | |
| 252 | + """ | |
| 253 | + Check event list | |
| 254 | + | |
| 255 | + Parameters | |
| 256 | + ---------- | |
| 257 | + events : `~gammalib.GCTAEventList` | |
| 258 | + Event list | |
| 259 | + nevents : int, optional | |
| 260 | + Expected number of events | |
| 261 | + """ | |
| 262 | + # Check event list | |
| 263 | + self.test_value(events.size(), nevents, 'Check number of events') | |
| 264 | + | |
| 265 | + # Return | |
| 266 | + return | |
| 267 | + | |
| 268 | + | |
| 269 | + def _check_column(self, filename, colname): | |
| 270 | + """ | |
| 271 | + Check that column colname exists. | |
| 272 | + | |
| 273 | + Parameters | |
| 274 | + ---------- | |
| 275 | + filename : str | |
| 276 | + Event list file name | |
| 277 | + colname : str | |
| 278 | + Name of the column to check | |
| 279 | + """ | |
| 280 | + # Check that column exists | |
| 281 | + gfits = gammalib.GFits(filename) | |
| 282 | + gtable = gfits[1] | |
| 283 | + check = int(gtable.contains(colname)) | |
| 284 | + self.test_value(check, 1, 'Check column '+colname) | |
| 285 | + | |
| 286 | + # Return | |
| 287 | + return | |
| 288 | + | |
| 289 | + | |
| 290 | + def _check_normalization(self, filename, colnames): | |
| 291 | + """ | |
| 292 | + Check that the probability values in columns identified by colnames are | |
| 293 | + correctly normalized. | |
| 294 | + | |
| 295 | + Parameters | |
| 296 | + ---------- | |
| 297 | + filename : str | |
| 298 | + Event list file name | |
| 299 | + colnames : list | |
| 300 | + Names of the columns to check | |
| 301 | + """ | |
| 302 | + # Check that the probability values are correctly normalized | |
| 303 | + | |
| 304 | + # Open fits table | |
| 305 | + gfits = gammalib.GFits(filename) | |
| 306 | + gtable = gfits[1] | |
| 307 | + ncols = gtable.ncols() | |
| 308 | + nevt = gtable.nrows() | |
| 309 | + srcs = [] | |
| 310 | + | |
| 311 | + # Loop over colnames | |
| 312 | + for colname in colnames: | |
| 313 | + | |
| 314 | + # Get the correct column corresponding to colname from the table | |
| 315 | + for icol in range(ncols): | |
| 316 | + gcol = gtable[icol] | |
| 317 | + if gcol.name()==colname: | |
| 318 | + break | |
| 319 | + | |
| 320 | + # Read and save column content | |
| 321 | + src1 = [] | |
| 322 | + for ievt in range(nevt): | |
| 323 | + src1.append(gcol[ievt]) | |
| 324 | + srcs.extend(src1) | |
| 325 | + | |
| 326 | + # Compute sum | |
| 327 | + tot = sum(srcs) | |
| 328 | + self.test_value(int(tot+0.5), nevt, 'Check that probability columns ' | |
| 329 | + 'are normalized') | |
| 330 | + | |
| 331 | + # Return | |
| 332 | + return | |
| 333 | + | ... | ... |
test/test_python_ctools.py
| ... | ... | @@ -40,6 +40,7 @@ import test_ctcubemask |
| 40 | 40 | import test_ctbutterfly |
| 41 | 41 | import test_ctulimit |
| 42 | 42 | import test_cterror |
| 43 | +import test_ctprob | |
| 43 | 44 | import test_pipelines |
| 44 | 45 | |
| 45 | 46 | |
| ... | ... | @@ -118,6 +119,7 @@ def test(installed=False): |
| 118 | 119 | test_ctbutterfly.Test(), |
| 119 | 120 | test_ctulimit.Test(), |
| 120 | 121 | test_cterror.Test(), |
| 122 | + test_ctprob.Test(), | |
| 121 | 123 | test_pipelines.Test()] |
| 122 | 124 | |
| 123 | 125 | # Allocate test suite container | ... | ... |