Commit 8085434844f98fec0e64fce3729f5e718ce65901
1 parent
003f01cc
Refactor cscripts and add some functions to obsutils (#1828)
The obsutils.sim() function does not correctly handle stacked observations. It appends stacked response cubes to a counts cube in case that multiple observations have been simulated and stacked analysis was requested. The stacked response cube computation is done using the obsutils.get_stacked_response() function. The function obsutils.set_ts_model() has been added to setup a model for TS determination. This is used by some of the cscripts, and avoids code duplication. Finally, the cstsdist and cspull scripts have been refactored.
Showing
6 changed files
with
701 additions
and
579 deletions
cscripts/cspull.py
| @@ -36,25 +36,19 @@ class cspull(ctools.cscript): | @@ -36,25 +36,19 @@ class cspull(ctools.cscript): | ||
| 36 | # Constructor | 36 | # Constructor |
| 37 | def __init__(self, *argv): | 37 | def __init__(self, *argv): |
| 38 | """ | 38 | """ |
| 39 | - Constructor. | 39 | + Constructor |
| 40 | """ | 40 | """ |
| 41 | # Set name | 41 | # Set name |
| 42 | self._name = 'cspull' | 42 | self._name = 'cspull' |
| 43 | - self._version = '1.1.0' | 43 | + self._version = '1.2.0' |
| 44 | 44 | ||
| 45 | # Initialise some members | 45 | # Initialise some members |
| 46 | self._edisp = False | 46 | self._edisp = False |
| 47 | - self._exposure = None | ||
| 48 | - self._psfcube = None | ||
| 49 | - self._bckcube = None | ||
| 50 | - self._edispcube = None | ||
| 51 | - self._stackmodels = None | ||
| 52 | self._coordsys = 'CEL' | 47 | self._coordsys = 'CEL' |
| 53 | self._proj = 'TAN' | 48 | self._proj = 'TAN' |
| 54 | self._log_clients = False # Static parameter | 49 | self._log_clients = False # Static parameter |
| 55 | self._offset = 0.0 | 50 | self._offset = 0.0 |
| 56 | self._ntrials = 0 | 51 | self._ntrials = 0 |
| 57 | - self._outfile = gammalib.GFilename() | ||
| 58 | self._npix = 0 | 52 | self._npix = 0 |
| 59 | self._binsz = 0.0 | 53 | self._binsz = 0.0 |
| 60 | self._pattern = 'single' | 54 | self._pattern = 'single' |
| @@ -62,11 +56,10 @@ class cspull(ctools.cscript): | @@ -62,11 +56,10 @@ class cspull(ctools.cscript): | ||
| 62 | self._seed = 1 | 56 | self._seed = 1 |
| 63 | self._chatter = 2 | 57 | self._chatter = 2 |
| 64 | 58 | ||
| 65 | - # Initialise observation container from constructor arguments. | 59 | + # Initialise observation container from constructor arguments |
| 66 | self._obs, argv = self._set_input_obs(argv) | 60 | self._obs, argv = self._set_input_obs(argv) |
| 67 | 61 | ||
| 68 | - # Initialise application by calling the appropriate class | ||
| 69 | - # constructor. | 62 | + # Initialise application by calling the appropriate class constructor |
| 70 | self._init_cscript(argv) | 63 | self._init_cscript(argv) |
| 71 | 64 | ||
| 72 | # Return | 65 | # Return |
| @@ -108,7 +101,6 @@ class cspull(ctools.cscript): | @@ -108,7 +101,6 @@ class cspull(ctools.cscript): | ||
| 108 | self._obs.models(self['inmodel'].filename()) | 101 | self._obs.models(self['inmodel'].filename()) |
| 109 | 102 | ||
| 110 | # Read other parameters | 103 | # Read other parameters |
| 111 | - self._outfile = self['outfile'].filename() | ||
| 112 | self._ntrials = self['ntrials'].integer() | 104 | self._ntrials = self['ntrials'].integer() |
| 113 | self._edisp = self['edisp'].boolean() | 105 | self._edisp = self['edisp'].boolean() |
| 114 | self._offset = self['offset'].real() | 106 | self._offset = self['offset'].real() |
| @@ -116,6 +108,7 @@ class cspull(ctools.cscript): | @@ -116,6 +108,7 @@ class cspull(ctools.cscript): | ||
| 116 | self._chatter = self['chatter'].integer() | 108 | self._chatter = self['chatter'].integer() |
| 117 | 109 | ||
| 118 | # Query some parameters | 110 | # Query some parameters |
| 111 | + self['outfile'].filename() | ||
| 119 | self['profile'].boolean() | 112 | self['profile'].boolean() |
| 120 | 113 | ||
| 121 | # Write input parameters into logger | 114 | # Write input parameters into logger |
| @@ -135,6 +128,9 @@ class cspull(ctools.cscript): | @@ -135,6 +128,9 @@ class cspull(ctools.cscript): | ||
| 135 | obs : `~gammalib.GObservations` | 128 | obs : `~gammalib.GObservations` |
| 136 | Observation container. | 129 | Observation container. |
| 137 | """ | 130 | """ |
| 131 | + # Set duration | ||
| 132 | + duration = self['tmax'].real() - self['tmin'].real() | ||
| 133 | + | ||
| 138 | # Setup observation definition list | 134 | # Setup observation definition list |
| 139 | obsdeflist = obsutils.set_obs_patterns(self._pattern, | 135 | obsdeflist = obsutils.set_obs_patterns(self._pattern, |
| 140 | ra=self['ra'].real(), | 136 | ra=self['ra'].real(), |
| @@ -144,7 +140,7 @@ class cspull(ctools.cscript): | @@ -144,7 +140,7 @@ class cspull(ctools.cscript): | ||
| 144 | # Create list of observations | 140 | # Create list of observations |
| 145 | obs = obsutils.set_obs_list(obsdeflist, | 141 | obs = obsutils.set_obs_list(obsdeflist, |
| 146 | tstart=self['tmin'].real(), | 142 | tstart=self['tmin'].real(), |
| 147 | - duration=self['tmax'].real()-self['tmin'].real(), | 143 | + duration=duration, |
| 148 | deadc=self['deadc'].real(), | 144 | deadc=self['deadc'].real(), |
| 149 | emin=self['emin'].real(), | 145 | emin=self['emin'].real(), |
| 150 | emax=self['emax'].real(), | 146 | emax=self['emax'].real(), |
| @@ -155,128 +151,6 @@ class cspull(ctools.cscript): | @@ -155,128 +151,6 @@ class cspull(ctools.cscript): | ||
| 155 | # Return observation container | 151 | # Return observation container |
| 156 | return obs | 152 | return obs |
| 157 | 153 | ||
| 158 | - def _set_stacked_irf(self): | ||
| 159 | - """ | ||
| 160 | - Prepare stacked IRFs for stacked analysis | ||
| 161 | - """ | ||
| 162 | - # Write header into logger | ||
| 163 | - if self._logTerse(): | ||
| 164 | - self._log('\n') | ||
| 165 | - self._log.header1('Compute stacked response') | ||
| 166 | - | ||
| 167 | - # Set number of energy bins to at least 30 per energy decade | ||
| 168 | - enumbins = int((math.log10(self['emax'].real()) - | ||
| 169 | - math.log10(self['emin'].real())) * 30.0) | ||
| 170 | - if self._enumbins > enumbins: | ||
| 171 | - enumbins = self._enumbins | ||
| 172 | - | ||
| 173 | - # Compute spatial binning for point spread function and | ||
| 174 | - # energy dispersion cubes | ||
| 175 | - binsz = 10.0 * self['binsz'].real() | ||
| 176 | - nxpix = self['npix'].integer() // 10 # Make sure result is int | ||
| 177 | - nypix = self['npix'].integer() // 10 # Make sure result is int | ||
| 178 | - if nxpix < 2: | ||
| 179 | - nxpix = 2 | ||
| 180 | - if nypix < 2: | ||
| 181 | - nypix = 2 | ||
| 182 | - | ||
| 183 | - # Get stacked exposure | ||
| 184 | - expcube = ctools.ctexpcube(self._obs) | ||
| 185 | - expcube['incube'] = 'NONE' | ||
| 186 | - expcube['usepnt'] = True | ||
| 187 | - expcube['ebinalg'] = 'LOG' | ||
| 188 | - expcube['binsz'] = self._binsz | ||
| 189 | - expcube['nxpix'] = self._npix | ||
| 190 | - expcube['nypix'] = self._npix | ||
| 191 | - expcube['enumbins'] = enumbins | ||
| 192 | - expcube['emin'] = self['emin'].real() | ||
| 193 | - expcube['emax'] = self['emax'].real() | ||
| 194 | - expcube['coordsys'] = self._coordsys | ||
| 195 | - expcube['proj'] = self._proj | ||
| 196 | - expcube['chatter'] = self._chatter | ||
| 197 | - expcube['debug'] = self._logDebug() | ||
| 198 | - expcube.run() | ||
| 199 | - | ||
| 200 | - # Notify exposure computation | ||
| 201 | - if self._logTerse(): | ||
| 202 | - self._log('Computed exposure cube\n') | ||
| 203 | - | ||
| 204 | - # Get stacked Psf | ||
| 205 | - psfcube = ctools.ctpsfcube(self._obs) | ||
| 206 | - psfcube['incube'] = 'NONE' | ||
| 207 | - psfcube['usepnt'] = True | ||
| 208 | - psfcube['ebinalg'] = 'LOG' | ||
| 209 | - psfcube['binsz'] = binsz | ||
| 210 | - psfcube['nxpix'] = nxpix | ||
| 211 | - psfcube['nypix'] = nypix | ||
| 212 | - psfcube['enumbins'] = enumbins | ||
| 213 | - psfcube['emin'] = self['emin'].real() | ||
| 214 | - psfcube['emax'] = self['emax'].real() | ||
| 215 | - psfcube['coordsys'] = self._coordsys | ||
| 216 | - psfcube['proj'] = self._proj | ||
| 217 | - psfcube['chatter'] = self._chatter | ||
| 218 | - psfcube['debug'] = self._logDebug() | ||
| 219 | - psfcube.run() | ||
| 220 | - | ||
| 221 | - # Notify Psf computation | ||
| 222 | - if self._logTerse(): | ||
| 223 | - self._log('Computed point spread function cube\n') | ||
| 224 | - | ||
| 225 | - # Optionally get stacked Edisp | ||
| 226 | - if self._edisp: | ||
| 227 | - edispcube = ctools.ctedispcube(self._obs) | ||
| 228 | - edispcube['incube'] = 'NONE' | ||
| 229 | - edispcube['usepnt'] = True | ||
| 230 | - edispcube['ebinalg'] = 'LOG' | ||
| 231 | - edispcube['binsz'] = binsz | ||
| 232 | - edispcube['nxpix'] = nxpix | ||
| 233 | - edispcube['nypix'] = nypix | ||
| 234 | - edispcube['enumbins'] = enumbins | ||
| 235 | - edispcube['emin'] = self['emin'].real() | ||
| 236 | - edispcube['emax'] = self['emax'].real() | ||
| 237 | - edispcube['coordsys'] = self._coordsys | ||
| 238 | - edispcube['proj'] = self._proj | ||
| 239 | - edispcube['chatter'] = self._chatter | ||
| 240 | - edispcube['debug'] = self._logDebug() | ||
| 241 | - edispcube.run() | ||
| 242 | - | ||
| 243 | - # Store result | ||
| 244 | - self._edispcube = edispcube.edispcube().copy() | ||
| 245 | - | ||
| 246 | - # Logging | ||
| 247 | - if self._logTerse(): | ||
| 248 | - self._log('Computed energy dispersion cube\n') | ||
| 249 | - | ||
| 250 | - # Get stacked background | ||
| 251 | - bkgcube = ctools.ctbkgcube(self._obs) | ||
| 252 | - bkgcube['incube'] = 'NONE' | ||
| 253 | - bkgcube['usepnt'] = True | ||
| 254 | - bkgcube['ebinalg'] = 'LOG' | ||
| 255 | - bkgcube['binsz'] = self._binsz | ||
| 256 | - bkgcube['nxpix'] = self._npix | ||
| 257 | - bkgcube['nypix'] = self._npix | ||
| 258 | - bkgcube['enumbins'] = enumbins | ||
| 259 | - bkgcube['emin'] = self['emin'].real() | ||
| 260 | - bkgcube['emax'] = self['emax'].real() | ||
| 261 | - bkgcube['coordsys'] = self._coordsys | ||
| 262 | - bkgcube['proj'] = self._proj | ||
| 263 | - bkgcube['chatter'] = self._chatter | ||
| 264 | - bkgcube['debug'] = self._logDebug() | ||
| 265 | - bkgcube.run() | ||
| 266 | - | ||
| 267 | - # Notify background cube computation | ||
| 268 | - if self._logTerse(): | ||
| 269 | - self._log('Computed background cube\n') | ||
| 270 | - | ||
| 271 | - # Store results | ||
| 272 | - self._exposure = expcube.expcube().copy() | ||
| 273 | - self._psfcube = psfcube.psfcube().copy() | ||
| 274 | - self._bckcube = bkgcube.bkgcube().copy() | ||
| 275 | - self._stackmodels = bkgcube.models().copy() | ||
| 276 | - | ||
| 277 | - # Return | ||
| 278 | - return | ||
| 279 | - | ||
| 280 | def _obs_string(self, obs): | 154 | def _obs_string(self, obs): |
| 281 | """ | 155 | """ |
| 282 | Generate summary string for observation | 156 | Generate summary string for observation |
| @@ -310,7 +184,7 @@ class cspull(ctools.cscript): | @@ -310,7 +184,7 @@ class cspull(ctools.cscript): | ||
| 310 | # Return summary string | 184 | # Return summary string |
| 311 | return text | 185 | return text |
| 312 | 186 | ||
| 313 | - def _trial(self, seed, stacked): | 187 | + def _trial(self, seed): |
| 314 | """ | 188 | """ |
| 315 | Compute the pull for a single trial | 189 | Compute the pull for a single trial |
| 316 | 190 | ||
| @@ -318,8 +192,6 @@ class cspull(ctools.cscript): | @@ -318,8 +192,6 @@ class cspull(ctools.cscript): | ||
| 318 | ---------- | 192 | ---------- |
| 319 | seed : int | 193 | seed : int |
| 320 | Random number generator seed | 194 | Random number generator seed |
| 321 | - stacked : bool | ||
| 322 | - Use stacked analysis | ||
| 323 | 195 | ||
| 324 | Returns | 196 | Returns |
| 325 | ------- | 197 | ------- |
| @@ -354,16 +226,6 @@ class cspull(ctools.cscript): | @@ -354,16 +226,6 @@ class cspull(ctools.cscript): | ||
| 354 | debug=self._logDebug(), | 226 | debug=self._logDebug(), |
| 355 | chatter=self._chatter) | 227 | chatter=self._chatter) |
| 356 | 228 | ||
| 357 | - # Set response for a stacked observation | ||
| 358 | - if stacked: | ||
| 359 | - if self._edisp: | ||
| 360 | - obs[0].response(self._exposure, self._psfcube, | ||
| 361 | - self._edispcube, self._bckcube) | ||
| 362 | - else: | ||
| 363 | - obs[0].response(self._exposure, self._psfcube, | ||
| 364 | - self._bckcube) | ||
| 365 | - obs.models(self._stackmodels) | ||
| 366 | - | ||
| 367 | # Determine number of events in simulation | 229 | # Determine number of events in simulation |
| 368 | nevents = 0.0 | 230 | nevents = 0.0 |
| 369 | for run in obs: | 231 | for run in obs: |
| @@ -427,10 +289,10 @@ class cspull(ctools.cscript): | @@ -427,10 +289,10 @@ class cspull(ctools.cscript): | ||
| 427 | # Set parameter name | 289 | # Set parameter name |
| 428 | name = model_name+'_'+par.name() | 290 | name = model_name+'_'+par.name() |
| 429 | 291 | ||
| 430 | - # Append parameter, Pull_parameter and Unc_parameter | 292 | + # Append parameter, Pull_parameter and e_parameter |
| 431 | colnames.append(name) | 293 | colnames.append(name) |
| 432 | colnames.append('Pull_'+name) | 294 | colnames.append('Pull_'+name) |
| 433 | - colnames.append('Unc_'+name) | 295 | + colnames.append('e_'+name) |
| 434 | 296 | ||
| 435 | # Compute pull | 297 | # Compute pull |
| 436 | fitted_value = par.value() | 298 | fitted_value = par.value() |
| @@ -444,7 +306,7 @@ class cspull(ctools.cscript): | @@ -444,7 +306,7 @@ class cspull(ctools.cscript): | ||
| 444 | # Store results | 306 | # Store results |
| 445 | values[name] = fitted_value | 307 | values[name] = fitted_value |
| 446 | values['Pull_'+name] = pull | 308 | values['Pull_'+name] = pull |
| 447 | - values['Unc_'+name] = error | 309 | + values['e_'+name] = error |
| 448 | 310 | ||
| 449 | # Write result | 311 | # Write result |
| 450 | if self._logNormal(): | 312 | if self._logNormal(): |
| @@ -481,13 +343,10 @@ class cspull(ctools.cscript): | @@ -481,13 +343,10 @@ class cspull(ctools.cscript): | ||
| 481 | self._log.header1(gammalib.number('Observation',len(self._obs))) | 343 | self._log.header1(gammalib.number('Observation',len(self._obs))) |
| 482 | self._log(str(self._obs)) | 344 | self._log(str(self._obs)) |
| 483 | self._log('\n') | 345 | self._log('\n') |
| 484 | - | ||
| 485 | - # Signal if stacked analysis is requested | ||
| 486 | - stacked = self._obs.size() > 1 and self._enumbins > 0 | ||
| 487 | - | ||
| 488 | - # If several observations and binned: prepare stacked irfs | ||
| 489 | - if stacked: | ||
| 490 | - self._set_stacked_irf() | 346 | + if self._logExplicit(): |
| 347 | + for obs in self._obs: | ||
| 348 | + self._log(str(obs)) | ||
| 349 | + self._log('\n') | ||
| 491 | 350 | ||
| 492 | # Write header | 351 | # Write header |
| 493 | if self._logTerse(): | 352 | if self._logTerse(): |
| @@ -498,18 +357,21 @@ class cspull(ctools.cscript): | @@ -498,18 +357,21 @@ class cspull(ctools.cscript): | ||
| 498 | for seed in range(self._ntrials): | 357 | for seed in range(self._ntrials): |
| 499 | 358 | ||
| 500 | # Make a trial and add initial seed | 359 | # Make a trial and add initial seed |
| 501 | - result = self._trial(seed + self._seed, stacked) | 360 | + result = self._trial(seed + self._seed) |
| 361 | + | ||
| 362 | + # Set output filename | ||
| 363 | + outfile = self['outfile'].filename().url() | ||
| 502 | 364 | ||
| 503 | # Write out result immediately | 365 | # Write out result immediately |
| 504 | if seed == 0: | 366 | if seed == 0: |
| 505 | - f = open(self._outfile.url(), 'w') | 367 | + f = open(outfile, 'w') |
| 506 | writer = csv.DictWriter(f, result['colnames']) | 368 | writer = csv.DictWriter(f, result['colnames']) |
| 507 | headers = {} | 369 | headers = {} |
| 508 | for n in result['colnames']: | 370 | for n in result['colnames']: |
| 509 | headers[n] = n | 371 | headers[n] = n |
| 510 | writer.writerow(headers) | 372 | writer.writerow(headers) |
| 511 | else: | 373 | else: |
| 512 | - f = open(self._outfile.url(), 'a') | 374 | + f = open(outfile, 'a') |
| 513 | writer = csv.DictWriter(f, result['colnames']) | 375 | writer = csv.DictWriter(f, result['colnames']) |
| 514 | writer.writerow(result['values']) | 376 | writer.writerow(result['values']) |
| 515 | f.close() | 377 | f.close() |
cscripts/cstsdist.par
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | # ------------------------------------------------------------------------- # | 5 | # ------------------------------------------------------------------------- # |
| 6 | # # | 6 | # # |
| 7 | # File: cstsdist.par # | 7 | # File: cstsdist.par # |
| 8 | -# Version: 1.1.0 # | 8 | +# Version: 1.2.0 # |
| 9 | # # | 9 | # # |
| 10 | # Author: Juergen Knoedlseder # | 10 | # Author: Juergen Knoedlseder # |
| 11 | # Jurgen.Knodlseder@irap.omp.eu # | 11 | # Jurgen.Knodlseder@irap.omp.eu # |
| @@ -36,6 +36,8 @@ outfile, f, a, ts.dat,,, "Output Test Statistic distribution file" | @@ -36,6 +36,8 @@ outfile, f, a, ts.dat,,, "Output Test Statistic distribution file" | ||
| 36 | ntrials, i, a, 10,,, "Number of trials" | 36 | ntrials, i, a, 10,,, "Number of trials" |
| 37 | ra, r, a, 83.63,0,360, "RA of pointing (deg)" | 37 | ra, r, a, 83.63,0,360, "RA of pointing (deg)" |
| 38 | dec, r, a, 22.01,-90,90, "Dec of pointing (deg)" | 38 | dec, r, a, 22.01,-90,90, "Dec of pointing (deg)" |
| 39 | +coordsys, s, a, CEL,CEL|GAL,, "Coordinate system (CEL - celestial, GAL - galactic)" | ||
| 40 | +proj, s, a, TAN,AIT|AZP|CAR|MER|MOL|STG|TAN,, "Projection method" | ||
| 39 | emin, r, a, 0.1,,, "Lower energy limit (TeV)" | 41 | emin, r, a, 0.1,,, "Lower energy limit (TeV)" |
| 40 | emax, r, a, 100.0,,, "Upper energy limit (TeV)" | 42 | emax, r, a, 100.0,,, "Upper energy limit (TeV)" |
| 41 | enumbins, i, a, 0,,, "Number of energy bins (0=unbinned)" | 43 | enumbins, i, a, 0,,, "Number of energy bins (0=unbinned)" |
cscripts/cstsdist.py
| @@ -30,13 +30,7 @@ from cscripts import obsutils | @@ -30,13 +30,7 @@ from cscripts import obsutils | ||
| 30 | # ============== # | 30 | # ============== # |
| 31 | class cstsdist(ctools.cscript): | 31 | class cstsdist(ctools.cscript): |
| 32 | """ | 32 | """ |
| 33 | - Generates Test Statistic distribution for a model. | ||
| 34 | - | ||
| 35 | - | ||
| 36 | - This class implements the TS distribution generation script. It derives | ||
| 37 | - from the ctools.cscript class which provides support for parameter | ||
| 38 | - files, command line arguments, and logging. In that way the Python | ||
| 39 | - script behaves just as a regular ctool. | 33 | + Generates Test Statistic distribution for a model |
| 40 | """ | 34 | """ |
| 41 | 35 | ||
| 42 | # Constructor | 36 | # Constructor |
| @@ -45,24 +39,17 @@ class cstsdist(ctools.cscript): | @@ -45,24 +39,17 @@ class cstsdist(ctools.cscript): | ||
| 45 | Constructor. | 39 | Constructor. |
| 46 | """ | 40 | """ |
| 47 | # Set name | 41 | # Set name |
| 48 | - self._name = "cstsdist" | ||
| 49 | - self._version = "1.1.0" | 42 | + self._name = 'cstsdist' |
| 43 | + self._version = '1.2.0' | ||
| 50 | 44 | ||
| 51 | # Initialise some members | 45 | # Initialise some members |
| 52 | - self._obs = gammalib.GObservations() | ||
| 53 | - self._pattern = "single" | ||
| 54 | - self._srcname = "" | ||
| 55 | - self._enumbins = 0 | ||
| 56 | - self._npix = 0 | ||
| 57 | - self._binsz = 0.0 | ||
| 58 | - self._outfile = gammalib.GFilename("ts.dat") | ||
| 59 | - self._ntrials = 10 | ||
| 60 | - self._edisp = False | ||
| 61 | - self._debug = False | ||
| 62 | - self._log_clients = False | ||
| 63 | - | ||
| 64 | - # Initialise application by calling the appropriate class | ||
| 65 | - # constructor. | 46 | + self._srcname = '' |
| 47 | + self._log_clients = False | ||
| 48 | + | ||
| 49 | + # Initialise observation container from constructor arguments | ||
| 50 | + self._obs, argv = self._set_input_obs(argv) | ||
| 51 | + | ||
| 52 | + # Initialise application by calling the appropriate class constructor | ||
| 66 | self._init_cscript(argv) | 53 | self._init_cscript(argv) |
| 67 | 54 | ||
| 68 | # Return | 55 | # Return |
| @@ -74,165 +61,116 @@ class cstsdist(ctools.cscript): | @@ -74,165 +61,116 @@ class cstsdist(ctools.cscript): | ||
| 74 | """ | 61 | """ |
| 75 | Get parameters from parfile and setup the observation. | 62 | Get parameters from parfile and setup the observation. |
| 76 | """ | 63 | """ |
| 77 | - | ||
| 78 | # Set observation if not done before | 64 | # Set observation if not done before |
| 79 | if self._obs == None or self._obs.size() == 0: | 65 | if self._obs == None or self._obs.size() == 0: |
| 80 | self._obs = self._get_observations() | 66 | self._obs = self._get_observations() |
| 81 | 67 | ||
| 82 | - # Check for requested pattern and use above | ||
| 83 | - # observation parameters to set wobble pattern | ||
| 84 | - self._pattern = self["pattern"].string() | ||
| 85 | - if self._pattern == "four": | 68 | + # Check for requested pattern and use above observation parameters |
| 69 | + # to set wobble pattern | ||
| 70 | + if self['pattern'].string() == 'four': | ||
| 86 | self._obs = self._set_obs() | 71 | self._obs = self._set_obs() |
| 87 | 72 | ||
| 88 | # Get source name | 73 | # Get source name |
| 89 | - self._srcname = self["srcname"].string() | ||
| 90 | - | ||
| 91 | - # Get number of energy bins | ||
| 92 | - self._enumbins = self["enumbins"].integer() | 74 | + self._srcname = self['srcname'].string() |
| 93 | 75 | ||
| 94 | - # Read parameters for binned if requested | ||
| 95 | - if not self._enumbins == 0: | ||
| 96 | - self._npix = self["npix"].integer() | ||
| 97 | - self._binsz = self["binsz"].real() | 76 | + # Query parameters for binned if requested |
| 77 | + if self['enumbins'].integer() != 0: | ||
| 78 | + self['npix'].integer() | ||
| 79 | + self['binsz'].real() | ||
| 80 | + self['coordsys'].string() | ||
| 81 | + self['proj'].string() | ||
| 98 | 82 | ||
| 99 | # Set models if we have none | 83 | # Set models if we have none |
| 100 | if self._obs.models().size() == 0: | 84 | if self._obs.models().size() == 0: |
| 101 | - self._obs.models(self["inmodel"].filename()) | 85 | + self._obs.models(self['inmodel'].filename()) |
| 102 | 86 | ||
| 103 | - # Get other parameters | ||
| 104 | - self._outfile = self["outfile"].filename() | ||
| 105 | - self._ntrials = self["ntrials"].integer() | ||
| 106 | - self._edisp = self["edisp"].boolean() | ||
| 107 | - self._debug = self["debug"].boolean() | 87 | + # Query parameters |
| 88 | + self['edisp'].boolean() | ||
| 89 | + self['ntrials'].integer() | ||
| 90 | + self['outfile'].filename() | ||
| 91 | + self['debug'].boolean() | ||
| 108 | 92 | ||
| 109 | # Write input parameters into logger | 93 | # Write input parameters into logger |
| 110 | if self._logTerse(): | 94 | if self._logTerse(): |
| 111 | self._log_parameters() | 95 | self._log_parameters() |
| 112 | - self._log("\n") | 96 | + self._log('\n') |
| 113 | 97 | ||
| 114 | # Return | 98 | # Return |
| 115 | return | 99 | return |
| 116 | 100 | ||
| 117 | def _set_obs(self): | 101 | def _set_obs(self): |
| 118 | """ | 102 | """ |
| 119 | - Set an observation container. | 103 | + Set an observation container |
| 120 | 104 | ||
| 121 | - Returns: | ||
| 122 | - Observation container. | 105 | + Returns |
| 106 | + ------- | ||
| 107 | + obs : `~gammalib.GObservations` | ||
| 108 | + Observation container | ||
| 123 | """ | 109 | """ |
| 110 | + # Set duration | ||
| 111 | + duration = self['tmax'].real() - self['tmin'].real() | ||
| 124 | 112 | ||
| 125 | # Setup observation definition list | 113 | # Setup observation definition list |
| 126 | - obsdeflist = obsutils.set_obs_patterns(self._pattern, | ||
| 127 | - ra=self["ra"].real(), | ||
| 128 | - dec=self["dec"].real(), | ||
| 129 | - offset=self["offset"].real()) | 114 | + obsdeflist = obsutils.set_obs_patterns(self['pattern'].string(), |
| 115 | + ra = self['ra'].real(), | ||
| 116 | + dec = self['dec'].real(), | ||
| 117 | + offset = self['offset'].real()) | ||
| 130 | 118 | ||
| 131 | # Create list of observations | 119 | # Create list of observations |
| 132 | obs = obsutils.set_obs_list(obsdeflist, | 120 | obs = obsutils.set_obs_list(obsdeflist, |
| 133 | - tstart=self["tmin"].real(), | ||
| 134 | - duration=self["tmax"].real()-self["tmin"].real(), | ||
| 135 | - deadc=self["deadc"].real(), | ||
| 136 | - emin=self["emin"].real(), | ||
| 137 | - emax=self["emax"].real(), | ||
| 138 | - rad=self["rad"].real(), | ||
| 139 | - irf=self["irf"].string(), | ||
| 140 | - caldb=self["caldb"].string()) | 121 | + tstart = self['tmin'].real(), |
| 122 | + duration = duration, | ||
| 123 | + deadc = self['deadc'].real(), | ||
| 124 | + emin = self['emin'].real(), | ||
| 125 | + emax = self['emax'].real(), | ||
| 126 | + rad = self['rad'].real(), | ||
| 127 | + irf = self['irf'].string(), | ||
| 128 | + caldb = self['caldb'].string()) | ||
| 141 | 129 | ||
| 142 | # Return observation container | 130 | # Return observation container |
| 143 | return obs | 131 | return obs |
| 144 | 132 | ||
| 145 | - def _set_models(self, fitspat=False, fitspec=False): | 133 | + def _trial(self, seed): |
| 146 | """ | 134 | """ |
| 147 | - Set full model and background model. | 135 | + Create the TS for a single trial |
| 148 | 136 | ||
| 149 | - Kwargs: | ||
| 150 | - fitspat: Fit spatial parameter (default: False). | ||
| 151 | - fitspec: Fit spectral parameters (default: False). | ||
| 152 | - | ||
| 153 | - Returns: | ||
| 154 | - Tuple containing full model and background model. | ||
| 155 | - """ | ||
| 156 | - # Retrieve full model from observation container | ||
| 157 | - full_model = self._obs.models().copy() | ||
| 158 | - | ||
| 159 | - # Get source model | ||
| 160 | - model = full_model[self._srcname] | ||
| 161 | - | ||
| 162 | - # Check that model has a Prefactor | ||
| 163 | - if not model.has_par("Prefactor"): | ||
| 164 | - msg = "Model \""+self._srcname+"\" has no parameter "+\ | ||
| 165 | - "\"Prefactor\". Only spectral models with a "+\ | ||
| 166 | - "\"Prefactor\" parameter are supported." | ||
| 167 | - raise RuntimeError(msg) | ||
| 168 | - | ||
| 169 | - # Fit or fix spatial parameters | ||
| 170 | - if fitspat: | ||
| 171 | - if model.has_par("RA"): | ||
| 172 | - model["RA"].free() | ||
| 173 | - if model.has_par("DEC"): | ||
| 174 | - model["DEC"].free() | ||
| 175 | - if model.has_par("Sigma"): | ||
| 176 | - model["Sigma"].free() | ||
| 177 | - if model.has_par("Radius"): | ||
| 178 | - model["Radius"].free() | ||
| 179 | - if model.has_par("Width"): | ||
| 180 | - model["Width"].free() | ||
| 181 | - else: | ||
| 182 | - if model.has_par("RA"): | ||
| 183 | - model["RA"].fix() | ||
| 184 | - if model.has_par("DEC"): | ||
| 185 | - model["DEC"].fix() | ||
| 186 | - if model.has_par("Sigma"): | ||
| 187 | - model["Sigma"].fix() | ||
| 188 | - if model.has_par("Radius"): | ||
| 189 | - model["Radius"].fix() | ||
| 190 | - if model.has_par("Width"): | ||
| 191 | - model["Width"].fix() | ||
| 192 | - | ||
| 193 | - # Fit or fix spectral parameters | ||
| 194 | - if fitspec: | ||
| 195 | - if model.has_par("Index"): | ||
| 196 | - model["Index"].free() | ||
| 197 | - if model.has_par("Cutoff"): | ||
| 198 | - model["Cutoff"].free() | ||
| 199 | - else: | ||
| 200 | - if model.has_par("Index"): | ||
| 201 | - model["Index"].fix() | ||
| 202 | - if model.has_par("Cutoff"): | ||
| 203 | - model["Cutoff"].fix() | ||
| 204 | - | ||
| 205 | - # Create background model | ||
| 206 | - bkg_model = full_model.copy() | ||
| 207 | - bkg_model.remove(self._srcname) | ||
| 208 | - | ||
| 209 | - # Return models | ||
| 210 | - return full_model, bkg_model | ||
| 211 | - | ||
| 212 | - def _trial(self, seed, full_model, bkg_model): | ||
| 213 | - """ | ||
| 214 | - Create the TS for a single trial. | 137 | + Parameters |
| 138 | + ---------- | ||
| 139 | + seed : int | ||
| 140 | + Random number generator seed | ||
| 215 | 141 | ||
| 216 | - Args: | ||
| 217 | - seed: Random number generator seed | ||
| 218 | - full_model: Full model | ||
| 219 | - bkg_model: Background model | ||
| 220 | - | ||
| 221 | - Returns: | 142 | + Returns |
| 143 | + ------- | ||
| 144 | + result : dict | ||
| 222 | Result dictionary | 145 | Result dictionary |
| 223 | """ | 146 | """ |
| 224 | # Write header | 147 | # Write header |
| 225 | if self._logExplicit(): | 148 | if self._logExplicit(): |
| 226 | - self._log.header2("Trial "+str(seed+1)) | 149 | + self._log.header2('Trial '+str(seed+1)) |
| 150 | + | ||
| 151 | + # Set default binned parameters | ||
| 152 | + coordsys = 'CEL' | ||
| 153 | + proj = 'TAN' | ||
| 154 | + npix = 0 | ||
| 155 | + binsz = 0.0 | ||
| 156 | + | ||
| 157 | + # If binned analysis is requested the read the binned parameters | ||
| 158 | + if self['enumbins'].integer() != 0: | ||
| 159 | + npix = self['npix'].integer() | ||
| 160 | + binsz = self['binsz'].real() | ||
| 161 | + coordsys = self['coordsys'].string() | ||
| 162 | + proj = self['proj'].string() | ||
| 227 | 163 | ||
| 228 | # Simulate events | 164 | # Simulate events |
| 229 | sim = obsutils.sim(self._obs, | 165 | sim = obsutils.sim(self._obs, |
| 230 | - nbins=self._enumbins, | ||
| 231 | - seed=seed, | ||
| 232 | - binsz=self._binsz, | ||
| 233 | - npix=self._npix, | ||
| 234 | - log=self._log_clients, | ||
| 235 | - debug=self._debug) | 166 | + nbins = self['enumbins'].integer(), |
| 167 | + seed = seed, | ||
| 168 | + proj = proj, | ||
| 169 | + coord = coordsys, | ||
| 170 | + binsz = binsz, | ||
| 171 | + npix = npix, | ||
| 172 | + log = self._log_clients, | ||
| 173 | + debug = self['debug'].boolean()) | ||
| 236 | 174 | ||
| 237 | # Determine number of events in simulation | 175 | # Determine number of events in simulation |
| 238 | nevents = 0.0 | 176 | nevents = 0.0 |
| @@ -241,110 +179,70 @@ class cstsdist(ctools.cscript): | @@ -241,110 +179,70 @@ class cstsdist(ctools.cscript): | ||
| 241 | 179 | ||
| 242 | # Write simulation results | 180 | # Write simulation results |
| 243 | if self._logExplicit(): | 181 | if self._logExplicit(): |
| 244 | - self._log.header3("Simulation") | ||
| 245 | - self._log.parformat("Number of simulated events") | 182 | + self._log.header3('Simulation') |
| 183 | + self._log.parformat('Number of simulated events') | ||
| 246 | self._log(nevents) | 184 | self._log(nevents) |
| 247 | - self._log("\n") | ||
| 248 | - | ||
| 249 | - # Fit background only | ||
| 250 | - sim.models(bkg_model) | ||
| 251 | - like_bgm = obsutils.fit(sim, | ||
| 252 | - log=self._log_clients, | ||
| 253 | - debug=self._debug) | ||
| 254 | - result_bgm = like_bgm.obs().models().copy() | ||
| 255 | - LogL_bgm = like_bgm.opt().value() | ||
| 256 | - npred_bgm = like_bgm.obs().npred() | ||
| 257 | - | ||
| 258 | - # Write background fit results | ||
| 259 | - if self._logExplicit(): | ||
| 260 | - self._log.header3("Background model fit") | ||
| 261 | - self._log.parformat("log likelihood") | ||
| 262 | - self._log(LogL_bgm) | ||
| 263 | - self._log("\n") | ||
| 264 | - self._log.parformat("Number of predicted events") | ||
| 265 | - self._log(npred_bgm) | ||
| 266 | - self._log("\n") | ||
| 267 | - for model in result_bgm: | ||
| 268 | - self._log.parformat("Model") | ||
| 269 | - self._log(model.name()) | ||
| 270 | - self._log("\n") | ||
| 271 | - for par in model: | ||
| 272 | - self._log(str(par)+"\n") | ||
| 273 | - | ||
| 274 | - # Fit background and test source | ||
| 275 | - sim.models(full_model) | ||
| 276 | - like_all = obsutils.fit(sim, | ||
| 277 | - log=self._log_clients, | ||
| 278 | - debug=self._debug) | ||
| 279 | - result_all = like_all.obs().models().copy() | ||
| 280 | - LogL_all = like_all.opt().value() | ||
| 281 | - npred_all = like_all.obs().npred() | ||
| 282 | - ts = 2.0*(LogL_bgm-LogL_all) | ||
| 283 | - | ||
| 284 | - # Write background and test source fit results | 185 | + self._log('\n') |
| 186 | + | ||
| 187 | + # Fit model | ||
| 188 | + fit = obsutils.fit(sim, log = self._log_clients, | ||
| 189 | + debug = self['debug'].boolean()) | ||
| 190 | + | ||
| 191 | + # Get model fitting results | ||
| 192 | + logL = fit.opt().value() | ||
| 193 | + npred = fit.obs().npred() | ||
| 194 | + models = fit.obs().models() | ||
| 195 | + model = models[self._srcname] | ||
| 196 | + ts = model.ts() | ||
| 197 | + | ||
| 198 | + # Write fit results, either explicit or normal | ||
| 285 | if self._logExplicit(): | 199 | if self._logExplicit(): |
| 286 | - self._log.header3("Background and test source model fit") | ||
| 287 | - self._log.parformat("Test statistics") | 200 | + self._log.header3('Test source model fit') |
| 201 | + self._log.parformat('Test statistics') | ||
| 288 | self._log(ts) | 202 | self._log(ts) |
| 289 | - self._log("\n") | ||
| 290 | - self._log.parformat("log likelihood") | ||
| 291 | - self._log(LogL_all) | ||
| 292 | - self._log("\n") | ||
| 293 | - self._log.parformat("Number of predicted events") | ||
| 294 | - self._log(npred_all) | ||
| 295 | - self._log("\n") | ||
| 296 | - for model in result_all: | ||
| 297 | - self._log.parformat("Model") | 203 | + self._log('\n') |
| 204 | + self._log.parformat('log likelihood') | ||
| 205 | + self._log(logL) | ||
| 206 | + self._log('\n') | ||
| 207 | + self._log.parformat('Number of predicted events') | ||
| 208 | + self._log(npred) | ||
| 209 | + self._log('\n') | ||
| 210 | + for model in models: | ||
| 211 | + self._log.parformat('Model') | ||
| 298 | self._log(model.name()) | 212 | self._log(model.name()) |
| 299 | - self._log("\n") | 213 | + self._log('\n') |
| 300 | for par in model: | 214 | for par in model: |
| 301 | - self._log(str(par)+"\n") | ||
| 302 | - | ||
| 303 | - # Write result | ||
| 304 | - elif self._logTerse(): | ||
| 305 | - self._log.parformat("Trial "+str(seed)) | ||
| 306 | - self._log("TS=") | 215 | + self._log(str(par)+'\n') |
| 216 | + elif self._logNormal(): | ||
| 217 | + self._log.parformat('Trial '+str(seed)) | ||
| 218 | + self._log('TS=') | ||
| 307 | self._log(ts) | 219 | self._log(ts) |
| 308 | - self._log(" Prefactor=") | ||
| 309 | - self._log(result_all[self._srcname]["Prefactor"].value()) | ||
| 310 | - self._log("+/-") | ||
| 311 | - self._log(result_all[self._srcname]["Prefactor"].error()) | ||
| 312 | - self._log("\n") | 220 | + self._log(' Prefactor=') |
| 221 | + self._log(model['Prefactor'].value()) | ||
| 222 | + self._log('+/-') | ||
| 223 | + self._log(model['Prefactor'].error()) | ||
| 224 | + self._log('\n') | ||
| 313 | 225 | ||
| 314 | # Initialise results | 226 | # Initialise results |
| 315 | colnames = [] | 227 | colnames = [] |
| 316 | values = {} | 228 | values = {} |
| 317 | 229 | ||
| 318 | # Set TS value | 230 | # Set TS value |
| 319 | - colnames.append("TS") | ||
| 320 | - values["TS"] = ts | ||
| 321 | - | ||
| 322 | - # Set logL for background fit | ||
| 323 | - colnames.append("LogL_bgm") | ||
| 324 | - values["LogL_bgm"] = LogL_bgm | ||
| 325 | - | ||
| 326 | - # Set logL for full fit | ||
| 327 | - colnames.append("LogL_all") | ||
| 328 | - values["LogL_all"] = LogL_all | 231 | + colnames.append('TS') |
| 232 | + values['TS'] = ts | ||
| 329 | 233 | ||
| 330 | # Set Nevents | 234 | # Set Nevents |
| 331 | - colnames.append("Nevents") | ||
| 332 | - values["Nevents"] = nevents | ||
| 333 | - | ||
| 334 | - # Set Npred for background fit | ||
| 335 | - colnames.append("Npred_bkg") | ||
| 336 | - values["Npred_bkg"] = npred_bgm | 235 | + colnames.append('Nevents') |
| 236 | + values['Nevents'] = nevents | ||
| 337 | 237 | ||
| 338 | - # Set Npred for full fit | ||
| 339 | - colnames.append("Npred_all") | ||
| 340 | - values["Npred_all"] = npred_all | 238 | + # Set Npred |
| 239 | + colnames.append('Npred') | ||
| 240 | + values['Npred'] = npred | ||
| 341 | 241 | ||
| 342 | # Gather free full fit parameters | 242 | # Gather free full fit parameters |
| 343 | - for i in range(result_all.size()): | ||
| 344 | - model = result_all[i] | 243 | + for model in models: |
| 345 | model_name = model.name() | 244 | model_name = model.name() |
| 346 | - for k in range(model.size()): | ||
| 347 | - par = model[k] | 245 | + for par in model: |
| 348 | if par.is_free(): | 246 | if par.is_free(): |
| 349 | 247 | ||
| 350 | # Set parameter name | 248 | # Set parameter name |
| @@ -355,7 +253,7 @@ class cstsdist(ctools.cscript): | @@ -355,7 +253,7 @@ class cstsdist(ctools.cscript): | ||
| 355 | values[name] = par.value() | 253 | values[name] = par.value() |
| 356 | 254 | ||
| 357 | # Append error | 255 | # Append error |
| 358 | - name = "Unc_"+name | 256 | + name = 'e_'+name |
| 359 | colnames.append(name) | 257 | colnames.append(name) |
| 360 | values[name] = par.error() | 258 | values[name] = par.error() |
| 361 | 259 | ||
| @@ -369,7 +267,7 @@ class cstsdist(ctools.cscript): | @@ -369,7 +267,7 @@ class cstsdist(ctools.cscript): | ||
| 369 | # Public methods | 267 | # Public methods |
| 370 | def run(self): | 268 | def run(self): |
| 371 | """ | 269 | """ |
| 372 | - Run the script. | 270 | + Run the script |
| 373 | """ | 271 | """ |
| 374 | # Switch screen logging on in debug mode | 272 | # Switch screen logging on in debug mode |
| 375 | if self._logDebug(): | 273 | if self._logDebug(): |
| @@ -378,55 +276,51 @@ class cstsdist(ctools.cscript): | @@ -378,55 +276,51 @@ class cstsdist(ctools.cscript): | ||
| 378 | # Get parameters | 276 | # Get parameters |
| 379 | self._get_parameters() | 277 | self._get_parameters() |
| 380 | 278 | ||
| 381 | - # Initialise models | ||
| 382 | - full_model, bkg_model = self._set_models() | 279 | + # Set models for this observation |
| 280 | + self.models(obsutils.set_ts_model(self._obs.models(), self._srcname)) | ||
| 383 | 281 | ||
| 384 | # Write models into logger | 282 | # Write models into logger |
| 385 | if self._logTerse(): | 283 | if self._logTerse(): |
| 386 | - self._log("\n") | ||
| 387 | - self._log.header1("Models") | ||
| 388 | - self._log.header2("Background model") | ||
| 389 | - self._log(str(bkg_model)) | ||
| 390 | - self._log("\n\n") | ||
| 391 | - self._log.header2("Full model") | ||
| 392 | - self._log(str(full_model)) | ||
| 393 | - self._log("\n") | 284 | + self._log('\n') |
| 285 | + self._log.header1('Models') | ||
| 286 | + self._log(str(self._obs.models())) | ||
| 287 | + self._log('\n') | ||
| 394 | 288 | ||
| 395 | # Write observation into logger | 289 | # Write observation into logger |
| 396 | if self._logTerse(): | 290 | if self._logTerse(): |
| 397 | - self._log("\n") | ||
| 398 | - self._log.header1("Observation") | 291 | + self._log('\n') |
| 292 | + self._log.header1(gammalib.number('Observation',len(self._obs))) | ||
| 399 | self._log(str(self._obs)) | 293 | self._log(str(self._obs)) |
| 400 | - self._log("\n") | ||
| 401 | - | ||
| 402 | - # Write models into logger | ||
| 403 | - if self._logTerse(): | ||
| 404 | - self._log("\n") | ||
| 405 | - self._log.header1("Test model") | ||
| 406 | - self._log(str(full_model)) | ||
| 407 | - self._log("\n") | 294 | + self._log('\n') |
| 295 | + if self._logExplicit(): | ||
| 296 | + for obs in self._obs: | ||
| 297 | + self._log(str(obs)) | ||
| 298 | + self._log('\n') | ||
| 408 | 299 | ||
| 409 | # Write header | 300 | # Write header |
| 410 | if self._logTerse(): | 301 | if self._logTerse(): |
| 411 | - self._log("\n") | ||
| 412 | - self._log.header1("Generate TS distribution") | 302 | + self._log('\n') |
| 303 | + self._log.header1('Generate TS distribution') | ||
| 413 | 304 | ||
| 414 | # Loop over trials | 305 | # Loop over trials |
| 415 | - for seed in range(self._ntrials): | 306 | + for seed in range(self['ntrials'].integer()): |
| 416 | 307 | ||
| 417 | # Make a trial | 308 | # Make a trial |
| 418 | - result = self._trial(seed, full_model, bkg_model) | 309 | + result = self._trial(seed) |
| 310 | + | ||
| 311 | + # Set output filename | ||
| 312 | + outfile = self['outfile'].filename().url() | ||
| 419 | 313 | ||
| 420 | # Write out result immediately | 314 | # Write out result immediately |
| 421 | if seed == 0: | 315 | if seed == 0: |
| 422 | - f = open(self._outfile.url(), 'w') | 316 | + f = open(outfile, 'w') |
| 423 | writer = csv.DictWriter(f, result['colnames']) | 317 | writer = csv.DictWriter(f, result['colnames']) |
| 424 | headers = {} | 318 | headers = {} |
| 425 | for n in result['colnames']: | 319 | for n in result['colnames']: |
| 426 | headers[n] = n | 320 | headers[n] = n |
| 427 | writer.writerow(headers) | 321 | writer.writerow(headers) |
| 428 | else: | 322 | else: |
| 429 | - f = open(self._outfile.url(), 'a') | 323 | + f = open(outfile, 'a') |
| 430 | writer = csv.DictWriter(f, result['colnames']) | 324 | writer = csv.DictWriter(f, result['colnames']) |
| 431 | writer.writerow(result['values']) | 325 | writer.writerow(result['values']) |
| 432 | f.close() | 326 | f.close() |
| @@ -436,17 +330,22 @@ class cstsdist(ctools.cscript): | @@ -436,17 +330,22 @@ class cstsdist(ctools.cscript): | ||
| 436 | 330 | ||
| 437 | def models(self, models): | 331 | def models(self, models): |
| 438 | """ | 332 | """ |
| 439 | - Set model. | 333 | + Set model |
| 334 | + | ||
| 335 | + Parameters | ||
| 336 | + ---------- | ||
| 337 | + models : `~gammalib.GModels` | ||
| 338 | + Model container | ||
| 440 | """ | 339 | """ |
| 441 | # Copy models | 340 | # Copy models |
| 442 | - self._obs.models(models.copy()) | 341 | + self._obs.models(models) |
| 443 | 342 | ||
| 444 | # Return | 343 | # Return |
| 445 | return | 344 | return |
| 446 | 345 | ||
| 447 | def execute(self): | 346 | def execute(self): |
| 448 | """ | 347 | """ |
| 449 | - Execute the script. | 348 | + Execute the script |
| 450 | """ | 349 | """ |
| 451 | # Open logfile | 350 | # Open logfile |
| 452 | self.logFileOpen() | 351 | self.logFileOpen() |
cscripts/obsutils.py
| 1 | # ========================================================================== | 1 | # ========================================================================== |
| 2 | -# CTA observation handling support functions. | 2 | +# CTA observation handling support functions |
| 3 | # | 3 | # |
| 4 | # Copyright (C) 2011-2016 Juergen Knoedlseder | 4 | # Copyright (C) 2011-2016 Juergen Knoedlseder |
| 5 | # | 5 | # |
| @@ -30,6 +30,14 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | @@ -30,6 +30,14 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | ||
| 30 | """ | 30 | """ |
| 31 | Simulate events for all observations in the container | 31 | Simulate events for all observations in the container |
| 32 | 32 | ||
| 33 | + Simulate events for all observations using ctobssim. If the number of | ||
| 34 | + energy bins is positive, the events are then binned in a counts cube | ||
| 35 | + using ctbin. If multiple observations are simulated, the counts cube is | ||
| 36 | + a stacked cube and the corresponding response cubes are computed using | ||
| 37 | + ctexpcube, ctpsfcube, ctbkgcube and optionally ctedispcube. The response | ||
| 38 | + cubes are attached to the first observation in the container, which | ||
| 39 | + normally is the observation with the counts cube. | ||
| 40 | + | ||
| 33 | Parameters | 41 | Parameters |
| 34 | ---------- | 42 | ---------- |
| 35 | obs : `~gammalib.GObservations` | 43 | obs : `~gammalib.GObservations` |
| @@ -42,7 +50,7 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | @@ -42,7 +50,7 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | ||
| 42 | Chatter level | 50 | Chatter level |
| 43 | edisp : bool, optional | 51 | edisp : bool, optional |
| 44 | Apply energy dispersion? | 52 | Apply energy dispersion? |
| 45 | - seed : int, integer | 53 | + seed : int, optional |
| 46 | Seed value for simulations | 54 | Seed value for simulations |
| 47 | emin : float, optional | 55 | emin : float, optional |
| 48 | Minimum energy of counts cube for binned (TeV) | 56 | Minimum energy of counts cube for binned (TeV) |
| @@ -64,7 +72,6 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | @@ -64,7 +72,6 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | ||
| 64 | obs : `~gammalib.GObservations` | 72 | obs : `~gammalib.GObservations` |
| 65 | Observation container filled with simulated events | 73 | Observation container filled with simulated events |
| 66 | """ | 74 | """ |
| 67 | - | ||
| 68 | # Allocate ctobssim application and set parameters | 75 | # Allocate ctobssim application and set parameters |
| 69 | sim = ctools.ctobssim(obs) | 76 | sim = ctools.ctobssim(obs) |
| 70 | sim['seed'] = seed | 77 | sim['seed'] = seed |
| @@ -125,6 +132,48 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | @@ -125,6 +132,48 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | ||
| 125 | # the container and bin the events in counts maps | 132 | # the container and bin the events in counts maps |
| 126 | bin.run() | 133 | bin.run() |
| 127 | 134 | ||
| 135 | + # If we have multiple input observations then create stacked response | ||
| 136 | + # cubes and append them to the observation | ||
| 137 | + if len(sim.obs()) > 1: | ||
| 138 | + | ||
| 139 | + # First get the cube. We need this because ctbin builds a cube on | ||
| 140 | + # the fly. We should avoid this and make the cube part of ctbin | ||
| 141 | + cube = bin.cube() | ||
| 142 | + | ||
| 143 | + # Get xref, yref, coordsys and proj from counts cube | ||
| 144 | + _xref = cube.counts().projection().crval(0) | ||
| 145 | + _yref = cube.counts().projection().crval(1) | ||
| 146 | + _coordsys = cube.counts().projection().coordsys() | ||
| 147 | + _proj = cube.counts().projection().code() | ||
| 148 | + | ||
| 149 | + # Kluge: map "EQU" to "CEL" coordinate system (not sure why the | ||
| 150 | + # GSkyProjection::coordsys returns "EQU" instead of "CEL" | ||
| 151 | + if _coordsys == 'EQU': | ||
| 152 | + _coordsys = 'CEL' | ||
| 153 | + | ||
| 154 | + # Get stacked response | ||
| 155 | + response = get_stacked_response(sim.obs(), _xref, _yref, | ||
| 156 | + binsz=binsz, nxpix=npix, nypix=npix, | ||
| 157 | + emin=emin, emax=emax, enumbins=nbins, | ||
| 158 | + edisp=edisp, | ||
| 159 | + coordsys=_coordsys, proj=_proj, | ||
| 160 | + log=log, debug=debug, | ||
| 161 | + chatter=chatter) | ||
| 162 | + | ||
| 163 | + # Set stacked response | ||
| 164 | + if edisp: | ||
| 165 | + bin.obs()[0].response(response['expcube'], | ||
| 166 | + response['psfcube'], | ||
| 167 | + response['edispcube'], | ||
| 168 | + response['bkgcube']) | ||
| 169 | + else: | ||
| 170 | + bin.obs()[0].response(response['expcube'], | ||
| 171 | + response['psfcube'], | ||
| 172 | + response['bkgcube']) | ||
| 173 | + | ||
| 174 | + # Set new models | ||
| 175 | + bin.obs().models(response['models']) | ||
| 176 | + | ||
| 128 | # Make a deep copy of the observation that will be returned | 177 | # Make a deep copy of the observation that will be returned |
| 129 | # (the ctbin object will go out of scope one the function is | 178 | # (the ctbin object will go out of scope one the function is |
| 130 | # left) | 179 | # left) |
| @@ -149,33 +198,36 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | @@ -149,33 +198,36 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | ||
| 149 | # ================ # | 198 | # ================ # |
| 150 | def fit(obs, log=False, debug=False, chatter=2, edisp=False): | 199 | def fit(obs, log=False, debug=False, chatter=2, edisp=False): |
| 151 | """ | 200 | """ |
| 152 | - Perform maximum likelihood fitting of observations in the container. | ||
| 153 | - | ||
| 154 | - Parameters: | ||
| 155 | - obs - Observation container | ||
| 156 | - Keywords: | ||
| 157 | - log - Create log file(s) | ||
| 158 | - debug - Create screen dump | ||
| 159 | - chatter - Chatter level | ||
| 160 | - edisp - Apply energy dispersion? | 201 | + Perform maximum likelihood fitting of observations in the container |
| 202 | + | ||
| 203 | + Parameters | ||
| 204 | + ---------- | ||
| 205 | + obs : `~gammalib.GObservations` | ||
| 206 | + Observation container | ||
| 207 | + log : bool, optional | ||
| 208 | + Create log file(s) | ||
| 209 | + debug : bool, optional | ||
| 210 | + Create console dump? | ||
| 211 | + chatter : int, optional | ||
| 212 | + Chatter level | ||
| 213 | + edisp : bool, optional | ||
| 214 | + Apply energy dispersion? | ||
| 215 | + | ||
| 216 | + Returns | ||
| 217 | + ------- | ||
| 218 | + like : `~ctools.ctlike` | ||
| 219 | + ctlike application | ||
| 161 | """ | 220 | """ |
| 162 | - # Allocate ctlike application | 221 | + # Allocate ctlike application and set parameters |
| 163 | like = ctools.ctlike(obs) | 222 | like = ctools.ctlike(obs) |
| 223 | + like['debug'] = debug | ||
| 224 | + like['chatter'] = chatter | ||
| 225 | + like['edisp'] = edisp | ||
| 164 | 226 | ||
| 165 | # Optionally open the log file | 227 | # Optionally open the log file |
| 166 | if log: | 228 | if log: |
| 167 | like.logFileOpen() | 229 | like.logFileOpen() |
| 168 | 230 | ||
| 169 | - # Optionally switch-on debugging model | ||
| 170 | - if debug: | ||
| 171 | - like["debug"] = True | ||
| 172 | - | ||
| 173 | - # Set chatter level | ||
| 174 | - like["chatter"] = chatter | ||
| 175 | - | ||
| 176 | - # Optionally apply energy dispersion | ||
| 177 | - like["edisp"] = edisp | ||
| 178 | - | ||
| 179 | # Run ctlike application. | 231 | # Run ctlike application. |
| 180 | like.run() | 232 | like.run() |
| 181 | 233 | ||
| @@ -188,34 +240,36 @@ def fit(obs, log=False, debug=False, chatter=2, edisp=False): | @@ -188,34 +240,36 @@ def fit(obs, log=False, debug=False, chatter=2, edisp=False): | ||
| 188 | # ============================================================== # | 240 | # ============================================================== # |
| 189 | def cterror(obs, srcname, log=False, debug=False, chatter=2): | 241 | def cterror(obs, srcname, log=False, debug=False, chatter=2): |
| 190 | """ | 242 | """ |
| 191 | - Perform maximum likelihood fitting of observations in the container. | ||
| 192 | - | ||
| 193 | - Parameters: | ||
| 194 | - obs - Observation container | ||
| 195 | - srcname - Source name | ||
| 196 | - Keywords: | ||
| 197 | - log - Create log file(s) | ||
| 198 | - debug - Create screen dump | ||
| 199 | - chatter - Chatter level | ||
| 200 | - edisp - Apply energy dispersion? | 243 | + Fit observations and determine errors using likelihood profile |
| 244 | + | ||
| 245 | + Parameters | ||
| 246 | + ---------- | ||
| 247 | + obs : `~gammalib.GObservations` | ||
| 248 | + Observation container | ||
| 249 | + srcname : str | ||
| 250 | + Source name | ||
| 251 | + log : bool, optional | ||
| 252 | + Create log file(s) | ||
| 253 | + debug : bool, optional | ||
| 254 | + Create console dump? | ||
| 255 | + chatter : int, optional | ||
| 256 | + Chatter level | ||
| 257 | + | ||
| 258 | + Returns | ||
| 259 | + ------- | ||
| 260 | + error : `~ctools.cterror` | ||
| 261 | + cterror application | ||
| 201 | """ | 262 | """ |
| 202 | - # Allocate cterror application | 263 | + # Allocate cterror application and set parameters |
| 203 | error = ctools.cterror(obs) | 264 | error = ctools.cterror(obs) |
| 204 | - | ||
| 205 | - # Set cterror parameters | ||
| 206 | - error["srcname"] = srcname | 265 | + error['srcname'] = srcname |
| 266 | + error['debug'] = debug | ||
| 267 | + error['chatter'] = chatter | ||
| 207 | 268 | ||
| 208 | # Optionally open the log file | 269 | # Optionally open the log file |
| 209 | if log: | 270 | if log: |
| 210 | error.logFileOpen() | 271 | error.logFileOpen() |
| 211 | 272 | ||
| 212 | - # Optionally switch-on debugging model | ||
| 213 | - if debug: | ||
| 214 | - error["debug"] = True | ||
| 215 | - | ||
| 216 | - # Set chatter level | ||
| 217 | - error["chatter"] = chatter | ||
| 218 | - | ||
| 219 | # Run cterror application. | 273 | # Run cterror application. |
| 220 | error.run() | 274 | error.run() |
| 221 | 275 | ||
| @@ -226,24 +280,39 @@ def cterror(obs, srcname, log=False, debug=False, chatter=2): | @@ -226,24 +280,39 @@ def cterror(obs, srcname, log=False, debug=False, chatter=2): | ||
| 226 | # ================= # | 280 | # ================= # |
| 227 | # Create counts map # | 281 | # Create counts map # |
| 228 | # ================= # | 282 | # ================= # |
| 229 | -def cntmap(obs, proj="TAN", coord="GAL", xval=0.0, yval=0.0, \ | 283 | +def cntmap(obs, proj='TAN', coord='GAL', xval=0.0, yval=0.0, \ |
| 230 | binsz=0.05, nxpix=200, nypix=200, \ | 284 | binsz=0.05, nxpix=200, nypix=200, \ |
| 231 | - outname="cntmap.fits"): | 285 | + outname='cntmap.fits'): |
| 232 | """ | 286 | """ |
| 233 | - Creates a counts map by combining the events of all observations. | ||
| 234 | - The counts map will be a summed map over all energies. | ||
| 235 | - | ||
| 236 | - Parameters: | ||
| 237 | - obs - Observation container | ||
| 238 | - Keywords: | ||
| 239 | - proj - Projection type (e.g. TAN, CAR, STG, ...) (default: TAN) | ||
| 240 | - coord - Coordinate type (GAL, CEL) (default: GAL) | ||
| 241 | - xval - Reference longitude value [deg] (default: 0.0) | ||
| 242 | - yval - Reference latitude value [deg] (default: 0.0) | ||
| 243 | - binsz - Pixel size [deg/pixel] (default: 0.05) | ||
| 244 | - nxpix - Number of pixels in X direction (default: 200) | ||
| 245 | - nypix - Number of pixels in Y direction (default: 200) | ||
| 246 | - outname - Counts map FITS filename (default: cntmap.fits) | 287 | + Creates a counts map by combining the events of all observations |
| 288 | + | ||
| 289 | + The counts map will be a summed map over all energies | ||
| 290 | + | ||
| 291 | + Parameters | ||
| 292 | + ---------- | ||
| 293 | + obs : `~gammalib.GObservations` | ||
| 294 | + Observation container without events | ||
| 295 | + proj : str, optional | ||
| 296 | + Projection for binned simulation | ||
| 297 | + coord : str, optional | ||
| 298 | + Coordinate system for binned simulation | ||
| 299 | + xval : float, optional | ||
| 300 | + Counts map centre of X direction (deg) | ||
| 301 | + yval : float, optional | ||
| 302 | + Counts map centre of Y direction (deg) | ||
| 303 | + binsz : float, optional | ||
| 304 | + Pixel size for binned simulation (deg/pixel) | ||
| 305 | + nxpix : int, optional | ||
| 306 | + Number of pixels in X direction | ||
| 307 | + nypix : int, optional | ||
| 308 | + Number of pixels in Y direction | ||
| 309 | + outname : str, optional | ||
| 310 | + Counts map file name | ||
| 311 | + | ||
| 312 | + Returns | ||
| 313 | + ------- | ||
| 314 | + map : `~gammalib.GSkyMap` | ||
| 315 | + Counts map | ||
| 247 | """ | 316 | """ |
| 248 | # Allocate counts map | 317 | # Allocate counts map |
| 249 | map = gammalib.GSkyMap(proj, coord, xval, yval, -binsz, binsz, nxpix, nypix, 1) | 318 | map = gammalib.GSkyMap(proj, coord, xval, yval, -binsz, binsz, nxpix, nypix, 1) |
| @@ -276,26 +345,42 @@ def cntmap(obs, proj="TAN", coord="GAL", xval=0.0, yval=0.0, \ | @@ -276,26 +345,42 @@ def cntmap(obs, proj="TAN", coord="GAL", xval=0.0, yval=0.0, \ | ||
| 276 | # ================ # | 345 | # ================ # |
| 277 | # Create model map # | 346 | # Create model map # |
| 278 | # ================ # | 347 | # ================ # |
| 279 | -def modmap(obs, eref=0.1, proj="TAN", coord="GAL", xval=0.0, yval=0.0, \ | 348 | +def modmap(obs, eref=0.1, proj='TAN', coord='GAL', xval=0.0, yval=0.0, \ |
| 280 | binsz=0.05, nxpix=200, nypix=200, \ | 349 | binsz=0.05, nxpix=200, nypix=200, \ |
| 281 | - outname="modmap.fits"): | 350 | + outname='modmap.fits'): |
| 282 | """ | 351 | """ |
| 283 | - Make model map for a given reference energy by combining all observations. | 352 | + Make model map for a given reference energy by combining all observations |
| 353 | + | ||
| 284 | The model map will be evaluated for a given reference energy 'eref' and will | 354 | The model map will be evaluated for a given reference energy 'eref' and will |
| 285 | be given in units of [counts/(sr MeV s)]. | 355 | be given in units of [counts/(sr MeV s)]. |
| 286 | 356 | ||
| 287 | - Parameters: | ||
| 288 | - obs - Observation container | ||
| 289 | - Keywords: | ||
| 290 | - eref - Reference energy for which model is created [TeV] (default: 0.1) | ||
| 291 | - proj - Projection type (e.g. TAN, CAR, STG, ...) (default: TAN) | ||
| 292 | - coord - Coordinate type (GAL, CEL) (default: GAL) | ||
| 293 | - xval - Reference longitude value [deg] (default: 0.0) | ||
| 294 | - yval - Reference latitude value [deg] (default: 0.0) | ||
| 295 | - binsz - Pixel size [deg/pixel] (default: 0.05) | ||
| 296 | - nxpix - Number of pixels in X direction (default: 200) | ||
| 297 | - nypix - Number of pixels in Y direction (default: 200) | ||
| 298 | - outname - Model map FITS filename (default: modmap.fits) | 357 | + Parameters |
| 358 | + ---------- | ||
| 359 | + obs : `~gammalib.GObservations` | ||
| 360 | + Observation container without events | ||
| 361 | + eref : float, optional | ||
| 362 | + Reference energy for which model is created (TeV) | ||
| 363 | + proj : str, optional | ||
| 364 | + Projection for binned simulation | ||
| 365 | + coord : str, optional | ||
| 366 | + Coordinate system for binned simulation | ||
| 367 | + xval : float, optional | ||
| 368 | + Counts map centre of X direction (deg) | ||
| 369 | + yval : float, optional | ||
| 370 | + Counts map centre of Y direction (deg) | ||
| 371 | + binsz : float, optional | ||
| 372 | + Pixel size for binned simulation (deg/pixel) | ||
| 373 | + nxpix : int, optional | ||
| 374 | + Number of pixels in X direction | ||
| 375 | + nypix : int, optional | ||
| 376 | + Number of pixels in Y direction | ||
| 377 | + outname : str, optional | ||
| 378 | + Model map file name | ||
| 379 | + | ||
| 380 | + Returns | ||
| 381 | + ------- | ||
| 382 | + map : `~gammalib.GSkyMap` | ||
| 383 | + Model map | ||
| 299 | """ | 384 | """ |
| 300 | # Allocate model map | 385 | # Allocate model map |
| 301 | map = gammalib.GSkyMap(proj, coord, xval, yval, -binsz, binsz, nxpix, nypix, 1) | 386 | map = gammalib.GSkyMap(proj, coord, xval, yval, -binsz, binsz, nxpix, nypix, 1) |
| @@ -338,53 +423,46 @@ def modmap(obs, eref=0.1, proj="TAN", coord="GAL", xval=0.0, yval=0.0, \ | @@ -338,53 +423,46 @@ def modmap(obs, eref=0.1, proj="TAN", coord="GAL", xval=0.0, yval=0.0, \ | ||
| 338 | return map | 423 | return map |
| 339 | 424 | ||
| 340 | 425 | ||
| 341 | -# ===================================== # | ||
| 342 | -# Set one CTA observation (old version) # | ||
| 343 | -# ===================================== # | ||
| 344 | -def set(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ | ||
| 345 | - emin=0.1, emax=100.0, rad=5.0, \ | ||
| 346 | - irf="South_50h", caldb="prod2"): | ||
| 347 | - """ | ||
| 348 | - Obsolete function, use set_obs instead. | ||
| 349 | - """ | ||
| 350 | - # Print warning | ||
| 351 | - print("Warning: obsutils.set is obsolete, use obsutils.set_obs instead.") | ||
| 352 | - | ||
| 353 | - # Call new function | ||
| 354 | - obs_cta = set_obs(pntdir, tstart=tstart, duration=duration, deadc=deadc, \ | ||
| 355 | - emin=emin, emax=emax, rad=rad, \ | ||
| 356 | - irf=irf, caldb=caldb) | ||
| 357 | - | ||
| 358 | - # Return CTA observation | ||
| 359 | - return obs_cta | ||
| 360 | - | ||
| 361 | - | ||
| 362 | # ======================= # | 426 | # ======================= # |
| 363 | # Set one CTA observation # | 427 | # Set one CTA observation # |
| 364 | # ======================= # | 428 | # ======================= # |
| 365 | def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ | 429 | def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ |
| 366 | emin=0.1, emax=100.0, rad=5.0, \ | 430 | emin=0.1, emax=100.0, rad=5.0, \ |
| 367 | - irf="South_50h", caldb="prod2", id="000000"): | 431 | + irf='South_50h', caldb='prod2', id='000000'): |
| 368 | """ | 432 | """ |
| 369 | - Set a single CTA observation. | 433 | + Set a single CTA observation |
| 370 | 434 | ||
| 371 | The function sets a single CTA observation containing an empty CTA | 435 | The function sets a single CTA observation containing an empty CTA |
| 372 | event list. By looping over this function you can add CTA observations | 436 | event list. By looping over this function you can add CTA observations |
| 373 | to the observation container. | 437 | to the observation container. |
| 374 | 438 | ||
| 375 | - Args: | ||
| 376 | - pntdir: Pointing direction [GSkyDir] | ||
| 377 | - | ||
| 378 | - Kwargs: | ||
| 379 | - tstart: Start time (seconds) (default: 0.0) | ||
| 380 | - duration: Duration of observation (seconds) (default: 1800.0) | ||
| 381 | - deadc: Deadtime correction factor (default: 0.95) | ||
| 382 | - emin: Minimum event energy (TeV) (default: 0.1) | ||
| 383 | - emax: Maximum event energy (TeV) (default: 100.0) | ||
| 384 | - rad: ROI radius used for analysis (deg) (default: 5.0) | ||
| 385 | - irf: Instrument response function (default: "South_50h") | ||
| 386 | - caldb: Calibration database path (default: "prod2") | ||
| 387 | - id: Run identifier (default: "000000") | 439 | + Parameters |
| 440 | + ---------- | ||
| 441 | + pntdir : `~gammalib.GSkyDir` | ||
| 442 | + Pointing direction | ||
| 443 | + tstart : float, optional | ||
| 444 | + Start time (seconds) | ||
| 445 | + duration : float, optional | ||
| 446 | + Duration of observation (seconds) | ||
| 447 | + deadc : float, optional | ||
| 448 | + Deadtime correction factor | ||
| 449 | + emin : float, optional | ||
| 450 | + Minimum event energy (TeV) | ||
| 451 | + emax : float, optional | ||
| 452 | + Maximum event energy (TeV) | ||
| 453 | + rad : float, optional | ||
| 454 | + ROI radius used for analysis (deg) | ||
| 455 | + irf : str, optional | ||
| 456 | + Instrument response function | ||
| 457 | + caldb : str, optional | ||
| 458 | + Calibration database path | ||
| 459 | + id : str, optional | ||
| 460 | + Observation identifier | ||
| 461 | + | ||
| 462 | + Returns | ||
| 463 | + ------- | ||
| 464 | + obs : `~gammalib.GCTAObservation` | ||
| 465 | + CTA observation | ||
| 388 | """ | 466 | """ |
| 389 | # Allocate CTA observation | 467 | # Allocate CTA observation |
| 390 | obs_cta = gammalib.GCTAObservation() | 468 | obs_cta = gammalib.GCTAObservation() |
| @@ -394,7 +472,7 @@ def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ | @@ -394,7 +472,7 @@ def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ | ||
| 394 | if (gammalib.dir_exists(caldb)): | 472 | if (gammalib.dir_exists(caldb)): |
| 395 | db.rootdir(caldb) | 473 | db.rootdir(caldb) |
| 396 | else: | 474 | else: |
| 397 | - db.open("cta", caldb) | 475 | + db.open('cta', caldb) |
| 398 | 476 | ||
| 399 | # Set pointing direction | 477 | # Set pointing direction |
| 400 | pnt = gammalib.GCTAPointing() | 478 | pnt = gammalib.GCTAPointing() |
| @@ -413,8 +491,8 @@ def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ | @@ -413,8 +491,8 @@ def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ | ||
| 413 | gti.append(gammalib.GTime(tstart), gammalib.GTime(tstart+duration)) | 491 | gti.append(gammalib.GTime(tstart), gammalib.GTime(tstart+duration)) |
| 414 | 492 | ||
| 415 | # Set energy boundaries | 493 | # Set energy boundaries |
| 416 | - ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, "TeV"), | ||
| 417 | - gammalib.GEnergy(emax, "TeV")) | 494 | + ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, 'TeV'), |
| 495 | + gammalib.GEnergy(emax, 'TeV')) | ||
| 418 | 496 | ||
| 419 | # Allocate event list | 497 | # Allocate event list |
| 420 | events = gammalib.GCTAEventList() | 498 | events = gammalib.GCTAEventList() |
| @@ -440,10 +518,11 @@ def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ | @@ -440,10 +518,11 @@ def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ | ||
| 440 | # Set list of CTA observations # | 518 | # Set list of CTA observations # |
| 441 | # ============================ # | 519 | # ============================ # |
| 442 | def set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.95, \ | 520 | def set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.95, \ |
| 443 | - emin=0.1, emax=100.0, rad=5.0, \ | ||
| 444 | - irf="South_50h", caldb="prod2"): | 521 | + emin=0.1, emax=100.0, rad=5.0, \ |
| 522 | + irf='South_50h', caldb='prod2'): | ||
| 445 | """ | 523 | """ |
| 446 | - Returns an observation container filled with a list of CTA observations. | 524 | + Returns an observation container filled with a list of CTA observations |
| 525 | + | ||
| 447 | The list is defined by the obsdeflist parameter which is a dictionnary | 526 | The list is defined by the obsdeflist parameter which is a dictionnary |
| 448 | containing the mandatory keywords 'ra' and 'dec' that specify the | 527 | containing the mandatory keywords 'ra' and 'dec' that specify the |
| 449 | pointing direction for a given observation. Optional keyword give control | 528 | pointing direction for a given observation. Optional keyword give control |
| @@ -451,27 +530,31 @@ def set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.95, \ | @@ -451,27 +530,31 @@ def set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.95, \ | ||
| 451 | energy range, etc. If an optional keyword is not specified, the function | 530 | energy range, etc. If an optional keyword is not specified, the function |
| 452 | keyword is used instead. | 531 | keyword is used instead. |
| 453 | 532 | ||
| 454 | - Parameters: | ||
| 455 | - obsdeflist - Observation definition list [{'ra': x.xx, 'dec': x.xx}] | ||
| 456 | - The directory can take the following optional keywords: | ||
| 457 | - - duration: Duration of CTA observation [seconds] | ||
| 458 | - - deadc: Deadtime correction factor | ||
| 459 | - - emin: Minimum event energy [TeV] | ||
| 460 | - - emax: Maximum event energy [TeV] | ||
| 461 | - - rad: ROI radius used for analysis [deg] | ||
| 462 | - - irf: Instrument response function | ||
| 463 | - - caldb: Calibration database path | ||
| 464 | - Optional keywords overwrite keywords specified in the | ||
| 465 | - function call. | ||
| 466 | - Keywords: | ||
| 467 | - tstart - Start time [seconds] (default: 0.0) | ||
| 468 | - duration - Duration of one CTA observation [seconds] (default: 1800.0) | ||
| 469 | - deadc - Deadtime correction factor (default: 0.95) | ||
| 470 | - emin - Minimum event energy [TeV] (default: 0.1) | ||
| 471 | - emax - Maximum event energy [TeV] (default: 100.0) | ||
| 472 | - rad - ROI radius used for analysis [deg] (default: 5.0) | ||
| 473 | - irf - Instrument response function (default: cta_dummy_irf) | ||
| 474 | - caldb - Calibration database path (default: "dummy") | 533 | + Parameters |
| 534 | + ---------- | ||
| 535 | + obsdeflist : list of dict | ||
| 536 | + Observation definition list | ||
| 537 | + tstart : float, optional | ||
| 538 | + Start time (seconds) | ||
| 539 | + duration : float, optional | ||
| 540 | + Duration of observation (seconds) | ||
| 541 | + deadc : float, optional | ||
| 542 | + Deadtime correction factor | ||
| 543 | + emin : float, optional | ||
| 544 | + Minimum event energy (TeV) | ||
| 545 | + emax : float, optional | ||
| 546 | + Maximum event energy (TeV) | ||
| 547 | + rad : float, optional | ||
| 548 | + ROI radius used for analysis (deg) | ||
| 549 | + irf : str, optional | ||
| 550 | + Instrument response function | ||
| 551 | + caldb : str, optional | ||
| 552 | + Calibration database path | ||
| 553 | + | ||
| 554 | + Returns | ||
| 555 | + ------- | ||
| 556 | + obs : `~gammalib.GObservations` | ||
| 557 | + Observation container filled with CTA observation | ||
| 475 | """ | 558 | """ |
| 476 | # Initialise empty observation container | 559 | # Initialise empty observation container |
| 477 | obs = gammalib.GObservations() | 560 | obs = gammalib.GObservations() |
| @@ -530,7 +613,7 @@ def set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.95, \ | @@ -530,7 +613,7 @@ def set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.95, \ | ||
| 530 | obs_irf = irf | 613 | obs_irf = irf |
| 531 | 614 | ||
| 532 | # Generate identifier string | 615 | # Generate identifier string |
| 533 | - id = "%6.6d" % obs_id | 616 | + id = '%6.6d' % obs_id |
| 534 | 617 | ||
| 535 | # Set CTA observation | 618 | # Set CTA observation |
| 536 | obs_cta = set_obs(pntdir, tstart=obs_start, duration=obs_duration, \ | 619 | obs_cta = set_obs(pntdir, tstart=obs_start, duration=obs_duration, \ |
| @@ -553,26 +636,38 @@ def set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.95, \ | @@ -553,26 +636,38 @@ def set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.95, \ | ||
| 553 | # ============================ # | 636 | # ============================ # |
| 554 | def set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5): | 637 | def set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5): |
| 555 | """ | 638 | """ |
| 556 | - Sets a number of standard patterns. | ||
| 557 | - | ||
| 558 | - Parameters: | ||
| 559 | - pattern - Observation pattern. Possible options are: | ||
| 560 | - - "single": single pointing | ||
| 561 | - - "four": four pointings 'offset' around pattern centre | 639 | + Sets a number of standard patterns |
| 640 | + | ||
| 641 | + Parameters | ||
| 642 | + ---------- | ||
| 643 | + pattern : str | ||
| 644 | + Observation pattern ("single", "four") | ||
| 645 | + ra : float, optional | ||
| 646 | + Right Ascension of pattern centre (deg) | ||
| 647 | + dec : float, optional | ||
| 648 | + Declination of pattern centre (deg) | ||
| 649 | + offset : float, optional | ||
| 650 | + Offset from pattern centre (deg) | ||
| 562 | 651 | ||
| 563 | - Keywords: | ||
| 564 | - ra - Right Ascension of pattern centre [deg] (default: 83.6331) | ||
| 565 | - dec - Declination of pattern centre [deg] (default: 22.0145) | ||
| 566 | - offset - Offset from pattern centre [deg] (default: 1.5) | 652 | + Returns |
| 653 | + ------- | ||
| 654 | + obsdeflist : list | ||
| 655 | + Observation definition list | ||
| 567 | """ | 656 | """ |
| 568 | # Initialise observation definition list | 657 | # Initialise observation definition list |
| 569 | obsdeflist = [] | 658 | obsdeflist = [] |
| 570 | 659 | ||
| 571 | - # Add patterns | ||
| 572 | - if pattern == "single": | 660 | + # If the pattern is a single observation then append the Right Ascension |
| 661 | + # and Declination to the observation definition list | ||
| 662 | + if pattern == 'single': | ||
| 573 | obsdef = {'ra': ra, 'dec': dec} | 663 | obsdef = {'ra': ra, 'dec': dec} |
| 574 | obsdeflist.append(obsdef) | 664 | obsdeflist.append(obsdef) |
| 575 | - elif pattern == "four": | 665 | + |
| 666 | + # ... otherwise, if the pattern is four observations then append four | ||
| 667 | + # observations offset by a certain amount from the pattern centre to the | ||
| 668 | + # observation definition list | ||
| 669 | + elif pattern == 'four': | ||
| 670 | + | ||
| 576 | # Set pattern centre | 671 | # Set pattern centre |
| 577 | centre = gammalib.GSkyDir() | 672 | centre = gammalib.GSkyDir() |
| 578 | centre.radec_deg(ra, dec) | 673 | centre.radec_deg(ra, dec) |
| @@ -582,8 +677,232 @@ def set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5): | @@ -582,8 +677,232 @@ def set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5): | ||
| 582 | pntdir = centre.copy() | 677 | pntdir = centre.copy() |
| 583 | pntdir.rotate_deg(phi, offset) | 678 | pntdir.rotate_deg(phi, offset) |
| 584 | obsdeflist.append({'ra': pntdir.ra_deg(), 'dec': pntdir.dec_deg()}) | 679 | obsdeflist.append({'ra': pntdir.ra_deg(), 'dec': pntdir.dec_deg()}) |
| 680 | + | ||
| 681 | + # ... otherwise we have an unknown pattern | ||
| 585 | else: | 682 | else: |
| 586 | - print("Warning: Observation pattern '"+str(pattern)+"' not recognized.") | 683 | + print('Warning: Observation pattern "'+str(pattern)+'" not recognized.') |
| 587 | 684 | ||
| 588 | # Return observation definition list | 685 | # Return observation definition list |
| 589 | return obsdeflist | 686 | return obsdeflist |
| 687 | + | ||
| 688 | + | ||
| 689 | +# ======================== # | ||
| 690 | +# Set model for TS fitting # | ||
| 691 | +# ======================== # | ||
| 692 | +def set_ts_model(models, srcname, ra=None, dec=None, fitspat=False, fitspec=False): | ||
| 693 | + """ | ||
| 694 | + Set model for TS fitting | ||
| 695 | + | ||
| 696 | + Parameters | ||
| 697 | + ---------- | ||
| 698 | + models : `~gammalib.GModels` | ||
| 699 | + Input model container | ||
| 700 | + srcname : str | ||
| 701 | + Test source name | ||
| 702 | + ra : float, optional | ||
| 703 | + Right Ascension of test source (deg) | ||
| 704 | + dec : float, optional | ||
| 705 | + Declination of test source (deg) | ||
| 706 | + fitspat : bool, optional | ||
| 707 | + Fit spatial parameter? | ||
| 708 | + fitspec : bool, optional | ||
| 709 | + Fit spectral parameters? | ||
| 710 | + | ||
| 711 | + Returns | ||
| 712 | + ------- | ||
| 713 | + model : `~gammalib.GModels` | ||
| 714 | + Model container for TS fitting | ||
| 715 | + """ | ||
| 716 | + # Create a clone of the input model | ||
| 717 | + outmodels = models.copy() | ||
| 718 | + | ||
| 719 | + # Disable TS computation for all model components (will enable the | ||
| 720 | + # test source later) | ||
| 721 | + for model in outmodels: | ||
| 722 | + model.tscalc(False) | ||
| 723 | + | ||
| 724 | + # Get source model and enable TS computation | ||
| 725 | + model = outmodels[srcname] | ||
| 726 | + model.tscalc(True) | ||
| 727 | + | ||
| 728 | + # If source model has no "Prefactor" parameter then raise an exception | ||
| 729 | + if not model.has_par('Prefactor'): | ||
| 730 | + msg = ('Model "%s" has no parameter "Prefactor". Only spectral ' | ||
| 731 | + 'models with a "Prefactor" parameter are supported.' % | ||
| 732 | + srcname) | ||
| 733 | + raise RuntimeError(msg) | ||
| 734 | + | ||
| 735 | + # Set position of test source | ||
| 736 | + if ra != None and dec != None: | ||
| 737 | + if model.has_par('RA') and model.has_par('DEC'): | ||
| 738 | + model['RA'].value(ra) | ||
| 739 | + model['DEC'].value(dec) | ||
| 740 | + | ||
| 741 | + # Set possible spatial and spectral parameters | ||
| 742 | + spatial = ['RA', 'DEC', 'Sigma', 'Radius', 'Width', 'PA', | ||
| 743 | + 'MinorRadius', 'MajorRadius'] | ||
| 744 | + spectral = ['Index', 'Index1', 'Index2', 'BreakEnergy', 'CutoffEnergy', | ||
| 745 | + 'InverseCutoffEnergy'] | ||
| 746 | + | ||
| 747 | + # Fit or fix spatial parameters | ||
| 748 | + for par in spatial: | ||
| 749 | + if model.has_par(par): | ||
| 750 | + if fitspat: | ||
| 751 | + model[par].free() | ||
| 752 | + else: | ||
| 753 | + model[par].fix() | ||
| 754 | + | ||
| 755 | + # Fit or fix spectral parameters | ||
| 756 | + for par in spectral: | ||
| 757 | + if model.has_par(par): | ||
| 758 | + if fitspec: | ||
| 759 | + model[par].free() | ||
| 760 | + else: | ||
| 761 | + model[par].fix() | ||
| 762 | + | ||
| 763 | + # Return model container | ||
| 764 | + return outmodels | ||
| 765 | + | ||
| 766 | + | ||
| 767 | +# ==================== # | ||
| 768 | +# Get stacked response # | ||
| 769 | +# ==================== # | ||
| 770 | +def get_stacked_response(obs, xref, yref, binsz=0.05, nxpix=200, nypix=200, | ||
| 771 | + emin=0.1, emax=100.0, enumbins=20, edisp=False, | ||
| 772 | + coordsys='GAL', proj='TAN', | ||
| 773 | + log=False, debug=False, chatter=2): | ||
| 774 | + """ | ||
| 775 | + Get stacked response cubes | ||
| 776 | + | ||
| 777 | + Parameters | ||
| 778 | + ---------- | ||
| 779 | + obs : `~gammalib.GObservations` | ||
| 780 | + Observation container | ||
| 781 | + xref : float | ||
| 782 | + Right Ascension or Galactic longitude of response centre (deg) | ||
| 783 | + yref : float | ||
| 784 | + Declination or Galactic latitude of response centre (deg) | ||
| 785 | + binsz : float, optional | ||
| 786 | + Pixel size (deg/pixel) | ||
| 787 | + nxpix : int, optional | ||
| 788 | + Number of pixels in X direction | ||
| 789 | + nypix : int, optional | ||
| 790 | + Number of pixels in Y direction | ||
| 791 | + emin : float, optional | ||
| 792 | + Minimum energy (TeV) | ||
| 793 | + emax : float, optional | ||
| 794 | + Maximum energy (TeV) | ||
| 795 | + enumbins : int, optional | ||
| 796 | + Number of energy bins | ||
| 797 | + edisp : bool, optional | ||
| 798 | + Apply energy dispersion? | ||
| 799 | + coordsys : str, optional | ||
| 800 | + Coordinate system | ||
| 801 | + proj : str, optional | ||
| 802 | + Projection | ||
| 803 | + log : bool, optional | ||
| 804 | + Create log file(s) | ||
| 805 | + debug : bool, optional | ||
| 806 | + Create console dump? | ||
| 807 | + chatter : int, optional | ||
| 808 | + Chatter level | ||
| 809 | + | ||
| 810 | + Returns | ||
| 811 | + ------- | ||
| 812 | + result : dict | ||
| 813 | + Dictionary of response cubes | ||
| 814 | + """ | ||
| 815 | + # Compute spatial binning for point spread function and | ||
| 816 | + # energy dispersion cubes | ||
| 817 | + psf_binsz = 10.0 * binsz | ||
| 818 | + psf_nxpix = min(nxpix // 10, 2) # Make sure result is int | ||
| 819 | + psf_nypix = min(nypix // 10, 2) # Make sure result is int | ||
| 820 | + | ||
| 821 | + # Create exposure cube | ||
| 822 | + expcube = ctools.ctexpcube(obs) | ||
| 823 | + expcube['incube'] = 'NONE' | ||
| 824 | + expcube['usepnt'] = False | ||
| 825 | + expcube['ebinalg'] = 'LOG' | ||
| 826 | + expcube['xref'] = xref | ||
| 827 | + expcube['yref'] = yref | ||
| 828 | + expcube['binsz'] = binsz | ||
| 829 | + expcube['nxpix'] = nxpix | ||
| 830 | + expcube['nypix'] = nypix | ||
| 831 | + expcube['enumbins'] = enumbins | ||
| 832 | + expcube['emin'] = emin | ||
| 833 | + expcube['emax'] = emax | ||
| 834 | + expcube['coordsys'] = coordsys | ||
| 835 | + expcube['proj'] = proj | ||
| 836 | + if log: | ||
| 837 | + expcube.logFileOpen() | ||
| 838 | + expcube.run() | ||
| 839 | + | ||
| 840 | + # Create point spread function cube | ||
| 841 | + psfcube = ctools.ctpsfcube(obs) | ||
| 842 | + psfcube['incube'] = 'NONE' | ||
| 843 | + psfcube['usepnt'] = False | ||
| 844 | + psfcube['ebinalg'] = 'LOG' | ||
| 845 | + psfcube['xref'] = xref | ||
| 846 | + psfcube['yref'] = yref | ||
| 847 | + psfcube['binsz'] = psf_binsz | ||
| 848 | + psfcube['nxpix'] = psf_nxpix | ||
| 849 | + psfcube['nypix'] = psf_nypix | ||
| 850 | + psfcube['enumbins'] = enumbins | ||
| 851 | + psfcube['emin'] = emin | ||
| 852 | + psfcube['emax'] = emax | ||
| 853 | + psfcube['coordsys'] = coordsys | ||
| 854 | + psfcube['proj'] = proj | ||
| 855 | + if log: | ||
| 856 | + psfcube.logFileOpen() | ||
| 857 | + psfcube.run() | ||
| 858 | + | ||
| 859 | + # Create background cube | ||
| 860 | + bkgcube = ctools.ctbkgcube(obs) | ||
| 861 | + bkgcube['incube'] = 'NONE' | ||
| 862 | + bkgcube['usepnt'] = False | ||
| 863 | + bkgcube['ebinalg'] = 'LOG' | ||
| 864 | + bkgcube['xref'] = xref | ||
| 865 | + bkgcube['yref'] = yref | ||
| 866 | + bkgcube['binsz'] = binsz | ||
| 867 | + bkgcube['nxpix'] = nxpix | ||
| 868 | + bkgcube['nypix'] = nypix | ||
| 869 | + bkgcube['enumbins'] = enumbins | ||
| 870 | + bkgcube['emin'] = emin | ||
| 871 | + bkgcube['emax'] = emax | ||
| 872 | + bkgcube['coordsys'] = coordsys | ||
| 873 | + bkgcube['proj'] = proj | ||
| 874 | + if log: | ||
| 875 | + bkgcube.logFileOpen() | ||
| 876 | + bkgcube.run() | ||
| 877 | + | ||
| 878 | + # If energy dispersion is requested then create energy dispersion cube | ||
| 879 | + if edisp: | ||
| 880 | + edispcube = ctools.ctedispcube(obs) | ||
| 881 | + edispcube['incube'] = 'NONE' | ||
| 882 | + edispcube['usepnt'] = False | ||
| 883 | + edispcube['ebinalg'] = 'LOG' | ||
| 884 | + edispcube['xref'] = xref | ||
| 885 | + edispcube['yref'] = yref | ||
| 886 | + edispcube['binsz'] = psf_binsz | ||
| 887 | + edispcube['nxpix'] = psf_nxpix | ||
| 888 | + edispcube['nypix'] = psf_nypix | ||
| 889 | + edispcube['enumbins'] = enumbins | ||
| 890 | + edispcube['emin'] = emin | ||
| 891 | + edispcube['emax'] = emax | ||
| 892 | + edispcube['coordsys'] = coordsys | ||
| 893 | + edispcube['proj'] = proj | ||
| 894 | + if log: | ||
| 895 | + edispcube.logFileOpen() | ||
| 896 | + edispcube.run() | ||
| 897 | + | ||
| 898 | + # Build response dictionary | ||
| 899 | + response = {} | ||
| 900 | + response['expcube'] = expcube.expcube().copy() | ||
| 901 | + response['psfcube'] = psfcube.psfcube().copy() | ||
| 902 | + response['bkgcube'] = bkgcube.bkgcube().copy() | ||
| 903 | + response['models'] = bkgcube.models().copy() | ||
| 904 | + if edisp: | ||
| 905 | + response['edispcube'] = edispcube.expcube().copy() | ||
| 906 | + | ||
| 907 | + # Return response cubes | ||
| 908 | + return response |
doc/source/users/reference_manual/cstsdist.rst
| @@ -75,6 +75,12 @@ General parameters | @@ -75,6 +75,12 @@ General parameters | ||
| 75 | ``dec [real]`` | 75 | ``dec [real]`` |
| 76 | Declination of CTA pointing (J2000, in degrees). | 76 | Declination of CTA pointing (J2000, in degrees). |
| 77 | 77 | ||
| 78 | +``coordsys <CEL|GAL> [string]`` | ||
| 79 | + Coordinate system (CEL - celestial, GAL - galactic). | ||
| 80 | + | ||
| 81 | +``proj <AIT|AZP|CAR|MER|MOL|STG|TAN> [string]`` | ||
| 82 | + Projection method. | ||
| 83 | + | ||
| 78 | ``emin [real]`` | 84 | ``emin [real]`` |
| 79 | Lower energy limit (in TeV). | 85 | Lower energy limit (in TeV). |
| 80 | 86 |
test/test_cstsdist.py
| @@ -76,7 +76,7 @@ class Test(test): | @@ -76,7 +76,7 @@ class Test(test): | ||
| 76 | ' enumbins=0 tmax=1800.0 rad=5.0 npix=200 npix=200'+ \ | 76 | ' enumbins=0 tmax=1800.0 rad=5.0 npix=200 npix=200'+ \ |
| 77 | ' binsz=0.05'+ \ | 77 | ' binsz=0.05'+ \ |
| 78 | ' outfile="cstsdist_cmd1.dat"'+ \ | 78 | ' outfile="cstsdist_cmd1.dat"'+ \ |
| 79 | - ' logfile="cstsdist_cmd1.log" chatter=1' | 79 | + ' logfile="cstsdist_cmd1.log" chatter=2' |
| 80 | 80 | ||
| 81 | # Check if execution of wrong command fails | 81 | # Check if execution of wrong command fails |
| 82 | self.test_assert(self._execute('command_that_does_not_exist') != 0, | 82 | self.test_assert(self._execute('command_that_does_not_exist') != 0, |
| @@ -117,7 +117,6 @@ class Test(test): | @@ -117,7 +117,6 @@ class Test(test): | ||
| 117 | tsdist['srcname'] = 'Crab' | 117 | tsdist['srcname'] = 'Crab' |
| 118 | tsdist['caldb'] = self._caldb | 118 | tsdist['caldb'] = self._caldb |
| 119 | tsdist['irf'] = self._irf | 119 | tsdist['irf'] = self._irf |
| 120 | - tsdist['outfile'] = 'cstsdist_py1.dat' | ||
| 121 | tsdist['ntrials'] = 1 | 120 | tsdist['ntrials'] = 1 |
| 122 | tsdist['ra'] = 83.63 | 121 | tsdist['ra'] = 83.63 |
| 123 | tsdist['dec'] = 22.01 | 122 | tsdist['dec'] = 22.01 |
| @@ -126,10 +125,9 @@ class Test(test): | @@ -126,10 +125,9 @@ class Test(test): | ||
| 126 | tsdist['enumbins'] = 0 | 125 | tsdist['enumbins'] = 0 |
| 127 | tsdist['tmax'] = 1800.0 | 126 | tsdist['tmax'] = 1800.0 |
| 128 | tsdist['rad'] = 5.0 | 127 | tsdist['rad'] = 5.0 |
| 129 | - tsdist['npix'] = 200 | ||
| 130 | - tsdist['binsz'] = 0.05 | 128 | + tsdist['outfile'] = 'cstsdist_py1.dat' |
| 131 | tsdist['logfile'] = 'cstsdist_py1.log' | 129 | tsdist['logfile'] = 'cstsdist_py1.log' |
| 132 | - tsdist['chatter'] = 2 | 130 | + tsdist['chatter'] = 3 |
| 133 | 131 | ||
| 134 | # Run cstsdist script | 132 | # Run cstsdist script |
| 135 | tsdist.logFileOpen() # Make sure we get a log file | 133 | tsdist.logFileOpen() # Make sure we get a log file |
| @@ -139,20 +137,56 @@ class Test(test): | @@ -139,20 +137,56 @@ class Test(test): | ||
| 139 | # Check pull distribution file | 137 | # Check pull distribution file |
| 140 | self._check_result_file('cstsdist_py1.dat') | 138 | self._check_result_file('cstsdist_py1.dat') |
| 141 | 139 | ||
| 140 | + # Set-up binned cstsdist in four observation wobble mode | ||
| 141 | + tsdist = cscripts.cstsdist() | ||
| 142 | + tsdist['inmodel'] = self._model | ||
| 143 | + tsdist['srcname'] = 'Crab' | ||
| 144 | + tsdist['caldb'] = self._caldb | ||
| 145 | + tsdist['irf'] = self._irf | ||
| 146 | + tsdist['ntrials'] = 1 | ||
| 147 | + tsdist['ra'] = 83.63 | ||
| 148 | + tsdist['dec'] = 22.01 | ||
| 149 | + tsdist['coordsys'] = 'CEL' | ||
| 150 | + tsdist['proj'] = 'TAN' | ||
| 151 | + tsdist['emin'] = 0.1 | ||
| 152 | + tsdist['emax'] = 100.0 | ||
| 153 | + tsdist['enumbins'] = 10 | ||
| 154 | + tsdist['tmax'] = 1800.0 | ||
| 155 | + tsdist['rad'] = 5.0 | ||
| 156 | + tsdist['npix'] = 50 | ||
| 157 | + tsdist['binsz'] = 0.1 | ||
| 158 | + tsdist['pattern'] = 'four' | ||
| 159 | + tsdist['outfile'] = 'cstsdist_py2.dat' | ||
| 160 | + tsdist['logfile'] = 'cstsdist_py2.log' | ||
| 161 | + tsdist['chatter'] = 4 | ||
| 162 | + | ||
| 163 | + # Execute cstsdist script | ||
| 164 | + tsdist.execute() | ||
| 165 | + | ||
| 166 | + # Check pull distribution file | ||
| 167 | + self._check_result_file('cstsdist_py2.dat', ncols=9) | ||
| 168 | + | ||
| 142 | # Return | 169 | # Return |
| 143 | return | 170 | return |
| 144 | 171 | ||
| 145 | # Check result file | 172 | # Check result file |
| 146 | - def _check_result_file(self, filename): | 173 | + def _check_result_file(self, filename, ncols=11): |
| 147 | """ | 174 | """ |
| 148 | Check result file | 175 | Check result file |
| 176 | + | ||
| 177 | + Parameters | ||
| 178 | + ---------- | ||
| 179 | + filename : str | ||
| 180 | + Name of result file | ||
| 181 | + ncols : int, optional | ||
| 182 | + Required number of columns | ||
| 149 | """ | 183 | """ |
| 150 | # Open result file as CSV file | 184 | # Open result file as CSV file |
| 151 | results = gammalib.GCsv(filename, ',') | 185 | results = gammalib.GCsv(filename, ',') |
| 152 | 186 | ||
| 153 | # Check dimensions | 187 | # Check dimensions |
| 154 | - self.test_value(results.nrows(), 2, 'Check for 2 rows in TS file') | ||
| 155 | - self.test_value(results.ncols(), 14, 'Check for 14 columns in TS file') | 188 | + self.test_value(results.nrows(), 2, 'Check rows in TS file') |
| 189 | + self.test_value(results.ncols(), ncols, 'Check columns in TS file') | ||
| 156 | 190 | ||
| 157 | # Return | 191 | # Return |
| 158 | return | 192 | return |