Commit b17eaf02157e070096055cd99bb7bfe95174f98d
1 parent
ab0848b3
Integrate csphagen script (#2208)
Showing
9 changed files
with
387 additions
and
256 deletions
AUTHORS
| ... | ... | @@ -15,4 +15,5 @@ Michael Mayer (michael.mayer@physik.hu-berlin.de) |
| 15 | 15 | Stefan Ohm (stefan.ohm81@gmail.com) |
| 16 | 16 | David Sanchez (david.sanchez@lapp.in2p3.fr) |
| 17 | 17 | Hubert Siejkowski (h.siejkowski@cyfronet.pl) |
| 18 | +Luigi Tibaldo (luigi.tibaldo@irap.omp.eu) | |
| 18 | 19 | Alexander Ziegler (alexander.ziegler@fau.de) | ... | ... |
ChangeLog
NEWS
| 1 | 1 | New Features and Important Changes in ctools 1.5.0 |
| 2 | 2 | |
| 3 | -8 August 2017 | |
| 3 | +16 October 2017 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | Introduction |
| ... | ... | @@ -122,6 +122,9 @@ cscripts |
| 122 | 122 | Use t-type parameters for "tmin" and "tmax" to all specifying times in various |
| 123 | 123 | formats (#1864). |
| 124 | 124 | |
| 125 | +The script csphagen was added to allow the generation of PHA, ARF and RMF datasets | |
| 126 | +for classical On/Off IACT analysis (#2208). | |
| 127 | + | |
| 125 | 128 | |
| 126 | 129 | Examples |
| 127 | 130 | -------- | ... | ... |
cscripts/csobsselect.py
| ... | ... | @@ -320,7 +320,7 @@ class csobsselect(ctools.cscript): |
| 320 | 320 | # Otherwise log filename and save file |
| 321 | 321 | else: |
| 322 | 322 | # Log filename |
| 323 | - self._log_value(gammalib.NORMAL, 'Observation definition XML file', | |
| 323 | + self._log_value(gammalib.NORMAL, 'Obs. definition XML file', | |
| 324 | 324 | outobs.url()) |
| 325 | 325 | |
| 326 | 326 | # Save observations | ... | ... |
cscripts/csphagen.par
| ... | ... | @@ -16,11 +16,12 @@ |
| 16 | 16 | # |
| 17 | 17 | # Input and output parameters |
| 18 | 18 | #============================ |
| 19 | -inobs, f, a, obs.xml,,, "Input event list or observation definition XML file" | |
| 20 | -caldb, s, a, prod2,,, "Calibration database" | |
| 21 | -irf, s, a, South_0.5h,,, "Instrument response function" | |
| 22 | -exclusion, f, h, NONE,,, "FITS with WCS map of exclusion regions" | |
| 23 | -outroot, s, a, spectrum,,, "Root of the name for output PHA, ARF, RMF, XML, and ds9 reg files" | |
| 19 | +inobs, f, a, obs.xml,,, "Input event list or observation definition XML file" | |
| 20 | +caldb, s, a, prod2,,, "Calibration database" | |
| 21 | +irf, s, a, South_0.5h,,, "Instrument response function" | |
| 22 | +inexclusion, f, h, NONE,,, "Sky map of exclusion regions" | |
| 23 | +outobs, s, a, onoff_obs.xml,,, "Output observation definition XML file" | |
| 24 | +prefix, s, h, onoff,,, "Prefix for output files" | |
| 24 | 25 | |
| 25 | 26 | # |
| 26 | 27 | # Script parameters |
| ... | ... | @@ -30,7 +31,6 @@ emax, r, a, 100.0,,, "Upper energy limit (TeV)" |
| 30 | 31 | enumbins, i, a, 120,,, "Number of energy bins" |
| 31 | 32 | ebinalg, s, a, LOG,LIN|LOG|FILE,, "Binning algorithm" |
| 32 | 33 | ebinfile, f, a, NONE,,, "Name of the file containing the energy bin definition" |
| 33 | -bkgmethod, s, h, REFLECTED,REFLECTED,, "Method for background estimation" | |
| 34 | 34 | srcshape, s, h, CIRCLE,CIRCLE,, "Shape of the source region" |
| 35 | 35 | coordsys, s, a, CEL,CEL|GAL,, "Coordinate system (CEL - celestial, GAL - galactic)" |
| 36 | 36 | ra, r, a, 83.63,0,360, "Right Ascension of source region centre (deg)" |
| ... | ... | @@ -38,9 +38,10 @@ dec, r, a, 22.01,-90,90, "Declination of source region centre (deg)" |
| 38 | 38 | glon, r, a, 184.56,0,360, "Galactic longitude of source region centre (deg)" |
| 39 | 39 | glat, r, a, -5.79,-90,90, "Galactic latitude of source region centre (deg)" |
| 40 | 40 | rad, r, a, 0.2,0,180, "Radius of source region circle (deg)" |
| 41 | -bkgregmin, i, h, 2,1,1000, "Minimum number of background region for REFLECTED method" | |
| 42 | -maxoffset, r, h, 4.,,, "Maximum offset of source from camera center to accept observation" | |
| 43 | -stack, b, a, no,,, "Stack multiple observations into single On/Off PHA (if no produce run-by-run files)" | |
| 41 | +bkgmethod, s, h, REFLECTED,REFLECTED,, "Method for background estimation" | |
| 42 | +bkgregmin, i, h, 2,1,1000, "Minimum number of background regions" | |
| 43 | +maxoffset, r, h, 4.0,,, "Maximum offset of source from camera center to accept observation" | |
| 44 | +stack, b, a, no,,, "Stack multiple observations into single PHA, ARF and RMF files?" | |
| 44 | 45 | |
| 45 | 46 | # |
| 46 | 47 | # Standard parameters | ... | ... |
cscripts/csphagen.py
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | # Computes the PHA spectra for source/background and ARF/RMF files using the |
| 4 | 4 | # reflected region method |
| 5 | 5 | # |
| 6 | -# Copyright (C) 2017- Luigi Tibaldo | |
| 6 | +# Copyright (C) 2017 Luigi Tibaldo | |
| 7 | 7 | # |
| 8 | 8 | # This program is free software: you can redistribute it and/or modify |
| 9 | 9 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -30,7 +30,7 @@ import sys |
| 30 | 30 | # =============== # |
| 31 | 31 | class csphagen(ctools.cscript): |
| 32 | 32 | """ |
| 33 | - Generate pha files for classical IACT spectral analysis | |
| 33 | + Generate PHA, ARF and RMF files for classical IACT spectral analysis | |
| 34 | 34 | """ |
| 35 | 35 | |
| 36 | 36 | # Constructor |
| ... | ... | @@ -48,6 +48,15 @@ class csphagen(ctools.cscript): |
| 48 | 48 | # Initialise application by calling the appropriate class constructor |
| 49 | 49 | self._init_cscript(argv) |
| 50 | 50 | |
| 51 | + # Initialise other variables | |
| 52 | + self._outobs = gammalib.GObservations() | |
| 53 | + self._ebounds = gammalib.GEbounds() | |
| 54 | + self._src_dir = gammalib.GSkyDir() | |
| 55 | + self._src_reg = gammalib.GSkyRegions() | |
| 56 | + self._bkg_regs = [] | |
| 57 | + self._excl_reg = None | |
| 58 | + self._has_exclusion = False | |
| 59 | + | |
| 51 | 60 | # Return |
| 52 | 61 | return |
| 53 | 62 | |
| ... | ... | @@ -63,49 +72,43 @@ class csphagen(ctools.cscript): |
| 63 | 72 | # Set energy bounds |
| 64 | 73 | self._ebounds = self._create_ebounds() |
| 65 | 74 | |
| 66 | - # Initialise background estimation method | |
| 67 | - self._bkgmethod = self["bkgmethod"].string() | |
| 68 | - if self._bkgmethod == "REFLECTED": | |
| 69 | - self._bkgregmin = self["bkgregmin"].integer() | |
| 70 | - self._maxoffset = self["maxoffset"].real() | |
| 71 | - | |
| 72 | 75 | # Initialise source position/region querying relevant parameters |
| 73 | 76 | self._src_dir = gammalib.GSkyDir() |
| 74 | 77 | self._src_reg = gammalib.GSkyRegions() |
| 75 | 78 | coordsys = self['coordsys'].string() |
| 76 | - if coordsys == "CEL": | |
| 77 | - ra = self['ra'].real() | |
| 79 | + if coordsys == 'CEL': | |
| 80 | + ra = self['ra'].real() | |
| 78 | 81 | dec = self['dec'].real() |
| 79 | 82 | self._src_dir.radec_deg(ra, dec) |
| 80 | - elif coordsys == "GAL": | |
| 83 | + elif coordsys == 'GAL': | |
| 81 | 84 | glon = self['glon'].real() |
| 82 | 85 | glat = self['glat'].real() |
| 83 | 86 | self._src_dir.lb_deg(glon, glat) |
| 84 | 87 | self._srcshape = self['srcshape'].string() |
| 85 | - if self._srcshape == "CIRCLE": | |
| 88 | + if self._srcshape == 'CIRCLE': | |
| 86 | 89 | self._rad = self['rad'].real() |
| 87 | - self._src_reg.append( | |
| 88 | - gammalib.GSkyRegionCircle(self._src_dir, self._rad)) | |
| 90 | + self._src_reg.append(gammalib.GSkyRegionCircle(self._src_dir, self._rad)) | |
| 91 | + | |
| 92 | + # Query background estimation method and parameters | |
| 93 | + bkgmethod = self['bkgmethod'].string() | |
| 94 | + if bkgmethod == 'REFLECTED': | |
| 95 | + self['bkgregmin'].integer() | |
| 96 | + self['maxoffset'].real() | |
| 89 | 97 | |
| 90 | - # exclusion map | |
| 91 | - if self["exclusion"].filename().is_fits(): | |
| 92 | - self._excl_reg = gammalib.GSkyRegionMap( | |
| 93 | - self["exclusion"].filename()) | |
| 98 | + # Exclusion map | |
| 99 | + if self['inexclusion'].filename().is_fits(): | |
| 100 | + self._excl_reg = gammalib.GSkyRegionMap(self['inexclusion'].filename()) | |
| 94 | 101 | self._has_exclusion = True |
| 95 | 102 | else: |
| 96 | 103 | self._has_exclusion = False |
| 97 | 104 | |
| 98 | - # Stacking | |
| 99 | - self._stack = self['stack'].boolean() | |
| 105 | + # Query remaining parametersStacking | |
| 106 | + self['stack'].boolean() | |
| 100 | 107 | |
| 101 | 108 | # Query ahead output parameters |
| 102 | 109 | if (self._read_ahead()): |
| 103 | - self._outroot = self['outroot'].string() | |
| 104 | - | |
| 105 | - # Set some fixed parameters | |
| 106 | - self._chatter = self["chatter"].integer() | |
| 107 | - self._clobber = self["clobber"].boolean() | |
| 108 | - self._debug = self["debug"].boolean() | |
| 110 | + self['outobs'].string() | |
| 111 | + self['prefix'].string() | |
| 109 | 112 | |
| 110 | 113 | # If there are no observations in container then get them from the |
| 111 | 114 | # parameter file |
| ... | ... | @@ -121,50 +124,66 @@ class csphagen(ctools.cscript): |
| 121 | 124 | def _reflected_regions(self, obs): |
| 122 | 125 | """ |
| 123 | 126 | Calculate list of reflected regions for a single observation (pointing) |
| 124 | - :param obs: observation | |
| 125 | - :return: list of reflected regions | |
| 127 | + | |
| 128 | + Parameters | |
| 129 | + ---------- | |
| 130 | + obs : `~gammalib.GObservation()` | |
| 131 | + CTA observation | |
| 132 | + | |
| 133 | + Returns | |
| 134 | + ------- | |
| 135 | + regions : `~gammalib.GSkyRegions` | |
| 136 | + List of reflected regions | |
| 126 | 137 | """ |
| 127 | - outregions = [] | |
| 138 | + # Initialise list of reflected regions | |
| 139 | + regions = gammalib.GSkyRegions() | |
| 140 | + | |
| 141 | + # Get offset angle of source | |
| 128 | 142 | pnt_dir = obs.pointing().dir() |
| 129 | - offset = pnt_dir.dist_deg(self._src_dir) | |
| 130 | - if offset <= self._rad or offset >= self["maxoffset"].real(): | |
| 131 | - if self._logExplicit(): | |
| 132 | - msg = 'Observation {} pointed at {} deg from source\n'.format( | |
| 133 | - obs.id(), offset) | |
| 134 | - self._log(msg) | |
| 143 | + offset = pnt_dir.dist_deg(self._src_dir) | |
| 144 | + | |
| 145 | + # If ... | |
| 146 | + if offset <= self._rad or offset >= self['maxoffset'].real(): | |
| 147 | + self._log_string(gammalib.EXPLICIT, 'Observation {} pointed at {} ' | |
| 148 | + 'deg from source'.format(obs.id(), offset)) | |
| 149 | + | |
| 150 | + # ... otherwise | |
| 135 | 151 | else: |
| 136 | 152 | posang = pnt_dir.posang_deg(self._src_dir) |
| 137 | - if self._srcshape == "CIRCLE": | |
| 153 | + if self._srcshape == 'CIRCLE': | |
| 138 | 154 | # angular separation of reflected regions wrt camera center |
| 139 | 155 | # and number |
| 140 | 156 | alpha = 1.05 * 2 * self._rad / offset |
| 141 | - # 1.05 ensures background regions do not overlap due to numerical precision issues | |
| 142 | - N = int(2 * math.pi / alpha) | |
| 143 | - if N < self._bkgregmin + 3: | |
| 144 | - if self._logExplicit(): | |
| 145 | - msg = 'Observation {}: insufficient regions for background estimation\n'.format( | |
| 146 | - obs.id(), offset) | |
| 147 | - self._log = (msg) | |
| 157 | + # 1.05 ensures background regions do not overlap due to | |
| 158 | + # numerical precision issues | |
| 159 | + N = int(2.0 * math.pi / alpha) | |
| 160 | + if N < self['bkgregmin'].integer() + 3: | |
| 161 | + self._log_string(gammalib.EXPLICIT, 'Observation {}: ' | |
| 162 | + 'insufficient regions for background ' | |
| 163 | + 'estimation'.format(obs.id(), offset)) | |
| 164 | + | |
| 165 | + # Otherwise loop over position angle to create reflected | |
| 166 | + # regions | |
| 148 | 167 | else: |
| 149 | - alpha = 360. / N | |
| 150 | - # loop to create reflected regions | |
| 168 | + alpha = 360.0 / N | |
| 151 | 169 | for s in range(2, N - 1): |
| 152 | - dphi = s * alpha | |
| 170 | + dphi = s * alpha | |
| 153 | 171 | ctr_dir = pnt_dir.clone() |
| 154 | 172 | ctr_dir.rotate_deg(posang + dphi, offset) |
| 155 | 173 | region = gammalib.GSkyRegionCircle(ctr_dir, self._rad) |
| 156 | 174 | if self._has_exclusion: |
| 157 | 175 | if self._excl_reg.overlaps(region): |
| 158 | - if self._logVerbose(): | |
| 159 | - msg = 'Observation {}: reflected region overlaps with exclusion region\n'.format( | |
| 160 | - obs.id(), offset) | |
| 161 | - self._log(msg) | |
| 176 | + self._log_string(gammalib.VERBOSE, 'Observation ' | |
| 177 | + '{}: reflected region overlaps ' | |
| 178 | + 'with exclusion region'. | |
| 179 | + format(obs.id(), offset)) | |
| 162 | 180 | else: |
| 163 | - outregions.append(region) | |
| 181 | + regions.append(region) | |
| 164 | 182 | else: |
| 165 | - outregions.append(region) | |
| 183 | + regions.append(region) | |
| 166 | 184 | |
| 167 | - return outregions | |
| 185 | + # Return reflected regions | |
| 186 | + return regions | |
| 168 | 187 | |
| 169 | 188 | # Public methods |
| 170 | 189 | def run(self): |
| ... | ... | @@ -181,74 +200,135 @@ class csphagen(ctools.cscript): |
| 181 | 200 | # Write observation into logger |
| 182 | 201 | self._log_observations(gammalib.NORMAL, self._obs, 'Observation') |
| 183 | 202 | |
| 203 | + # Write header | |
| 184 | 204 | self._log_header1(gammalib.NORMAL, |
| 185 | 205 | 'Generation of source and background spectra') |
| 206 | + | |
| 207 | + # Initialise run variables | |
| 208 | + self._outobs = gammalib.GObservations() | |
| 209 | + self._bkg_regs = [] | |
| 210 | + | |
| 186 | 211 | # Loop through observations and generate pha, arf, rmf files |
| 187 | - # Save ON/OFF regions in ds9 reg files | |
| 188 | - outobs = gammalib.GObservations() | |
| 189 | - etrue = self._ebounds | |
| 190 | - ereco = self._ebounds | |
| 191 | 212 | for obs in self._obs: |
| 213 | + | |
| 214 | + # Initialise background regions for this observation | |
| 192 | 215 | bkg_reg = gammalib.GSkyRegions() |
| 193 | - if self._bkgmethod == "REFLECTED": | |
| 194 | - regions = self._reflected_regions(obs) | |
| 195 | - for region in regions: | |
| 196 | - bkg_reg.append(region) | |
| 197 | - if bkg_reg.size() >= 1 or ( | |
| 198 | - self._bkgmethod == "REFLECTED" and bkg_reg.size() >= self._bkgregmin): | |
| 199 | - onoff = gammalib.GCTAOnOffObservation(obs, self._src_dir, etrue, | |
| 200 | - ereco, self._src_reg, | |
| 216 | + | |
| 217 | + # If reflected background is requested then created reflected | |
| 218 | + # background regions | |
| 219 | + if self['bkgmethod'].string() == 'REFLECTED': | |
| 220 | + bkg_reg = self._reflected_regions(obs) | |
| 221 | + | |
| 222 | + # If there are reflected regions then create On/Off observation | |
| 223 | + # and append it to the output container | |
| 224 | + if bkg_reg.size() >= self['bkgregmin'].integer(): | |
| 225 | + onoff = gammalib.GCTAOnOffObservation(obs, self._src_dir, | |
| 226 | + self._ebounds, | |
| 227 | + self._ebounds, | |
| 228 | + self._src_reg, | |
| 201 | 229 | bkg_reg) |
| 202 | 230 | onoff.id(obs.id()) |
| 203 | - outobs.append(onoff) | |
| 204 | - self._src_reg.save( | |
| 205 | - self._outroot + '_{}_on.reg'.format(obs.id())) | |
| 206 | - bkg_reg.save(self._outroot + '_{}_off.reg'.format(obs.id())) | |
| 231 | + self._outobs.append(onoff) | |
| 232 | + self._bkg_regs.append({'regions': bkg_reg, 'id': obs.id()}) | |
| 207 | 233 | else: |
| 208 | - if self._logNormal(): | |
| 209 | - msg = 'Observation {} not included in spectra generation\n'.format( | |
| 210 | - obs.id()) | |
| 211 | - self._log(msg) | |
| 212 | - | |
| 213 | - # Save PHA, ARF and RMFs | |
| 214 | - if outobs.size() < 2 or self._stack == False: | |
| 215 | - for obs in outobs: | |
| 216 | - obs.on_spec().save( | |
| 217 | - self._outroot + '_{}_pha_on.fits'.format(obs.id()), | |
| 218 | - True) | |
| 219 | - obs.off_spec().save( | |
| 220 | - self._outroot + '_{}_pha_off.fits'.format(obs.id()), | |
| 221 | - True) | |
| 222 | - obs.arf().save(self._outroot + '_{}_arf.fits'.format(obs.id()), | |
| 223 | - True) | |
| 224 | - obs.rmf().save(self._outroot + '_{}_rmf.fits'.format(obs.id()), | |
| 225 | - True) | |
| 226 | - else: | |
| 227 | - if self._logVerbose(): | |
| 228 | - msg = 'Stacking {} observations\n'.format( | |
| 229 | - outobs.size()) | |
| 230 | - self._log(msg) | |
| 231 | - stackobs = gammalib.GCTAOnOffObservation(outobs) | |
| 232 | - stackobs.on_spec().save( | |
| 233 | - self._outroot + '_stacked_pha_on.fits', | |
| 234 | - True) | |
| 235 | - stackobs.off_spec().save( | |
| 236 | - self._outroot + '_stacked_pha_off.fits', | |
| 237 | - True) | |
| 238 | - stackobs.arf().save(self._outroot + '_stacked_arf.fits', | |
| 239 | - True) | |
| 240 | - stackobs.rmf().save(self._outroot + '_stacked_rmf.fits', | |
| 241 | - True) | |
| 242 | - outobs = gammalib.GObservations() | |
| 243 | - outobs.append(stackobs) | |
| 244 | - | |
| 245 | - # Save On/Off observations | |
| 246 | - outname = self._outroot + '.xml' | |
| 247 | - outobs.save(outname) | |
| 248 | - # Log filename | |
| 249 | - if self._logNormal(): | |
| 250 | - self._log( | |
| 251 | - 'Output observation definition XML file: {}\n'.format(outname)) | |
| 234 | + self._log_string(gammalib.NORMAL, 'Observation {} not included ' | |
| 235 | + 'in spectra generation'.format(obs.id())) | |
| 236 | + | |
| 237 | + # Stack observations | |
| 238 | + if self._outobs.size() > 1 and self['stack'].boolean() == True: | |
| 239 | + | |
| 240 | + # Write header | |
| 241 | + self._log_header1(gammalib.NORMAL, | |
| 242 | + 'Stacking {} observations'.format(self._outobs.size())) | |
| 243 | + | |
| 244 | + # Stack observations | |
| 245 | + stacked_obs = gammalib.GCTAOnOffObservation(self._outobs) | |
| 246 | + | |
| 247 | + # Put stacked observations in output container | |
| 248 | + self._outobs = gammalib.GObservations() | |
| 249 | + self._outobs.append(stacked_obs) | |
| 250 | + | |
| 251 | + # Return | |
| 252 | + return | |
| 253 | + | |
| 254 | + def save(self): | |
| 255 | + """ | |
| 256 | + Save data | |
| 257 | + """ | |
| 258 | + # Write header | |
| 259 | + self._log_header1(gammalib.TERSE, 'Save data') | |
| 260 | + | |
| 261 | + # Get XMK output filename, prefix and clobber | |
| 262 | + outobs = self['outobs'].string() | |
| 263 | + prefix = self['prefix'].string() | |
| 264 | + clobber = self['clobber'].boolean() | |
| 265 | + | |
| 266 | + # Loop over all observation in container | |
| 267 | + for obs in self._outobs: | |
| 268 | + | |
| 269 | + # Set filenames | |
| 270 | + if self['stack'].boolean(): | |
| 271 | + onname = prefix + '_stacked_pha_on.fits' | |
| 272 | + offname = prefix + '_stacked_pha_off.fits' | |
| 273 | + arfname = prefix + '_stacked_arf.fits' | |
| 274 | + rmfname = prefix + '_stacked_rmf.fits' | |
| 275 | + elif self._outobs.size() > 1: | |
| 276 | + onname = prefix + '_{}_pha_on.fits'.format(obs.id()) | |
| 277 | + offname = prefix + '_{}_pha_off.fits'.format(obs.id()) | |
| 278 | + arfname = prefix + '_{}_arf.fits'.format(obs.id()) | |
| 279 | + rmfname = prefix + '_{}_rmf.fits'.format(obs.id()) | |
| 280 | + else: | |
| 281 | + onname = prefix + '_pha_on.fits' | |
| 282 | + offname = prefix + '_pha_off.fits' | |
| 283 | + arfname = prefix + '_arf.fits' | |
| 284 | + rmfname = prefix + '_rmf.fits' | |
| 285 | + | |
| 286 | + # Save files | |
| 287 | + obs.on_spec().save(onname, clobber) | |
| 288 | + obs.off_spec().save(offname, clobber) | |
| 289 | + obs.arf().save(arfname, clobber) | |
| 290 | + obs.rmf().save(rmfname, clobber) | |
| 291 | + | |
| 292 | + # Log file names | |
| 293 | + self._log_value(gammalib.NORMAL, 'PHA on file', onname) | |
| 294 | + self._log_value(gammalib.NORMAL, 'PHA off file', offname) | |
| 295 | + self._log_value(gammalib.NORMAL, 'ARF file', arfname) | |
| 296 | + self._log_value(gammalib.NORMAL, 'RMF file', arfname) | |
| 297 | + | |
| 298 | + # Save observation definition XML file | |
| 299 | + self._outobs.save(outobs) | |
| 300 | + | |
| 301 | + # Log file name | |
| 302 | + self._log_value(gammalib.NORMAL, 'Obs. definition XML file', outobs) | |
| 303 | + | |
| 304 | + # Save ds9 On region file | |
| 305 | + regname = prefix + '_on.reg' | |
| 306 | + self._src_reg.save(regname) | |
| 307 | + self._log_value(gammalib.NORMAL, 'On region file', regname) | |
| 308 | + | |
| 309 | + # Save ds9 Off region files | |
| 310 | + for bkg_reg in self._bkg_regs: | |
| 311 | + | |
| 312 | + # Set filename | |
| 313 | + if len(self._bkg_regs) > 1: | |
| 314 | + regname = prefix + '_{}_off.reg'.format(bkg_reg['id']) | |
| 315 | + else: | |
| 316 | + regname = prefix + '_off.reg' | |
| 317 | + | |
| 318 | + # Save ds9 region file | |
| 319 | + bkg_reg['regions'].save(regname) | |
| 320 | + | |
| 321 | + # Log file name | |
| 322 | + self._log_value(gammalib.NORMAL, 'Off region file', regname) | |
| 323 | + | |
| 324 | + # Return | |
| 325 | + return | |
| 326 | + | |
| 327 | + def obs(self): | |
| 328 | + """ | |
| 329 | + Return observation container | |
| 330 | + """ | |
| 331 | + return self._outobs | |
| 252 | 332 | |
| 253 | 333 | def execute(self): |
| 254 | 334 | """ |
| ... | ... | @@ -263,6 +343,9 @@ class csphagen(ctools.cscript): |
| 263 | 343 | # Run the script |
| 264 | 344 | self.run() |
| 265 | 345 | |
| 346 | + # Save result | |
| 347 | + self.save() | |
| 348 | + | |
| 266 | 349 | # Return |
| 267 | 350 | return |
| 268 | 351 | |
| ... | ... | @@ -271,6 +354,7 @@ class csphagen(ctools.cscript): |
| 271 | 354 | # Main routine entry point # |
| 272 | 355 | # ======================== # |
| 273 | 356 | if __name__ == '__main__': |
| 357 | + | |
| 274 | 358 | # Create instance of application |
| 275 | 359 | app = csphagen(sys.argv) |
| 276 | 360 | ... | ... |
doc/source/admin/release_history/1.5.rst
| ... | ... | @@ -10,6 +10,7 @@ ctools 1.5 is a major release that adds significant functionality. |
| 10 | 10 | |
| 11 | 11 | In particular, this release provides: |
| 12 | 12 | |
| 13 | +* Support of classical IACT analysis | |
| 13 | 14 | * Specifcation of times in various formats (UTC, MJD, JD, MET) |
| 14 | 15 | |
| 15 | 16 | |
| ... | ... | @@ -28,5 +29,7 @@ Improvements |
| 28 | 29 | New features |
| 29 | 30 | ------------ |
| 30 | 31 | |
| 32 | +* [`2208 <https://cta-redmine.irap.omp.eu/issues/2208>`_] - | |
| 33 | + Add :ref:`csphagen` script | |
| 31 | 34 | * [`1864 <https://cta-redmine.irap.omp.eu/issues/1864>`_] - |
| 32 | 35 | Use t-type parameters for all ``tmin`` and ``tmax`` parameters | ... | ... |
doc/source/users/reference_manual/csphagen.rst
| 1 | 1 | .. _csphagen: |
| 2 | 2 | |
| 3 | 3 | csphagen |
| 4 | -========= | |
| 4 | +======== | |
| 5 | 5 | |
| 6 | -Creates files necessary to perform a classical region-based spectral analysis on IACT data, i.e., source and background PHA files, ARF and RMF files. | |
| 6 | +Creates files necessary to perform a classical region-based spectral analysis | |
| 7 | +on IACT data, i.e., source and background PHA files, ARF and RMF files. | |
| 7 | 8 | |
| 8 | 9 | |
| 9 | 10 | Synopsis |
| 10 | 11 | -------- |
| 11 | 12 | |
| 12 | -This script can be used to derive from an observation or a set of observations the count spectra in a source region and in background regions, as well as the detector response (effective area, energy redistribution matrix), that can be used to perform a classical 1D spectral analysis. The output files are saved in the OGIP format normally used in X-ray astronomy (PHA, ARF, RMF). `See here <https://heasarc.gsfc.nasa.gov/docs/heasarc/ofwg/docs/spectra/ogip_92_007/node5.html>`__. | |
| 13 | +This script can be used to derive from an observation or a set of observations | |
| 14 | +the count spectra in a source region and in background regions, as well as the | |
| 15 | +detector response (effective area, energy redistribution matrix), that can be | |
| 16 | +used to perform a classical 1D spectral analysis. The output files are saved in | |
| 17 | +the OGIP format normally used in X-ray astronomy (PHA, ARF, RMF). | |
| 18 | +`See here <https://heasarc.gsfc.nasa.gov/docs/heasarc/ofwg/docs/spectra/ogip_92_007/node5.html>`__. | |
| 13 | 19 | |
| 14 | -The outputs are: 1) the PHA, ARF, RMF files, either separately for each observation, or stacked for a set of observations, 2) DS9 regions files listing the source and background regions for each observation; 3) a new observation definition XML file. | |
| 20 | +The outputs are: | |
| 21 | +1) the PHA, ARF, RMF files, either separately for each observation, or stacked | |
| 22 | + for a set of observations, | |
| 23 | +2) DS9 regions files listing the source and background regions for each | |
| 24 | + observation; | |
| 25 | +3) a new observation definition XML file. | |
| 15 | 26 | |
| 16 | 27 | |
| 17 | 28 | General parameters |
| 18 | 29 | ------------------ |
| 19 | 30 | |
| 20 | 31 | ``inobs [file]`` |
| 21 | - Input event list or observation definition XML file | |
| 32 | + Input event list or observation definition XML file. | |
| 22 | 33 | |
| 23 | 34 | ``caldb [string]`` |
| 24 | 35 | Calibration database. |
| 25 | - | |
| 36 | + | |
| 26 | 37 | ``irf [string]`` |
| 27 | 38 | Instrument response function. |
| 28 | 39 | |
| 29 | -``(exclusion = NONE) [file]`` | |
| 30 | - Optional FITS file containing a WCS map in the first hdu that defines sky regions not to be used for background estimation (where map value > 0) | |
| 40 | +``(inexclusion = NONE) [file]`` | |
| 41 | + Optional FITS file containing a WCS map in the first hdu that defines sky | |
| 42 | + regions not to be used for background estimation (where map value != 0). | |
| 31 | 43 | |
| 32 | -``outroot [string]`` | |
| 33 | - Root of the file name for output PHA, ARF, RMF, XML, and ds9 reg files | |
| 44 | +``outobs [string]`` | |
| 45 | + Output observation definition XML file. | |
| 46 | + | |
| 47 | +``(prefix = onoff) [string]`` | |
| 48 | + Prefix of the file name for output PHA, ARF, RMF, XML, and DS9 region files. | |
| 34 | 49 | |
| 35 | 50 | ``emin [real]`` |
| 36 | - Lower energy limit (TeV) if LIN or LOG binning algorithms are used | |
| 51 | + Lower energy limit (TeV) if LIN or LOG binning algorithms are used. | |
| 37 | 52 | |
| 38 | 53 | ``emax [real]`` |
| 39 | - Upper energy limit (TeV) if LIN or LOG binning algorithms are used | |
| 54 | + Upper energy limit (TeV) if LIN or LOG binning algorithms are used. | |
| 40 | 55 | |
| 41 | 56 | ``enumbins [integer]`` |
| 42 | - Number of energy bins. At least 30 bins per decade are recommended for proper evaluation of the instrument response | |
| 57 | + Number of energy bins. At least 30 bins per decade are recommended for | |
| 58 | + proper evaluation of the instrument response. | |
| 43 | 59 | |
| 44 | 60 | ``ebinalg [string]’’ |
| 45 | - Energy binning algorithm: LOG - logarithmically spaced energy bins; LIN - linearly spaced energy bins; FILE - energy bounds retrieved from file | |
| 61 | + Energy binning algorithm: LOG - logarithmically spaced energy bins; | |
| 62 | + LIN - linearly spaced energy bins; FILE - energy bounds retrieved from file. | |
| 46 | 63 | |
| 47 | 64 | ``ebinfile [file]`` |
| 48 | - Name of the file containing the energy bin definition if FILE algorithm is used | |
| 49 | - | |
| 50 | -``(bkgmethod = REFLECTED) [string]’’ | |
| 51 | - Method for background estimation. REFLECTED: background evaluated in regions with the same shape as source region reflected w.r.t. pointing direction for each observation | |
| 65 | + Name of the file containing the energy bin definition if FILE algorithm | |
| 66 | + is used. | |
| 52 | 67 | |
| 53 | 68 | ``(srcshape = CIRCLE) [string]`` |
| 54 | - Shape of the source region. CIRCLE: circular region around given position | |
| 69 | + Shape of the source region. | |
| 70 | + CIRCLE: circular region around given position. | |
| 55 | 71 | |
| 56 | 72 | ``coordsys [string]`` |
| 57 | 73 | Coordinate system (CEL - celestial, GAL - galactic) |
| ... | ... | @@ -71,14 +87,23 @@ General parameters |
| 71 | 87 | ``rad [real]`` |
| 72 | 88 | Radius of source region circle (deg) |
| 73 | 89 | |
| 90 | +``(bkgmethod = REFLECTED) [string]’’ | |
| 91 | + Method for background estimation. | |
| 92 | + REFLECTED: background evaluated in regions with the same shape as source | |
| 93 | + region reflected w.r.t. pointing direction for each observation. | |
| 94 | + | |
| 74 | 95 | ``(bkgregmin = 2) [integer]`` |
| 75 | - Minimum number of background regions for REFLECTED method. If not available, observation is skipped. (Default: 2) | |
| 96 | + Minimum number of background regions that are required for an observation. | |
| 97 | + If this number of background regions is not available the observation is | |
| 98 | + skipped. | |
| 76 | 99 | |
| 77 | -``(maxoffset = 4.) [real]`` | |
| 78 | - Maximum offset of source from camera center to accept observation | |
| 100 | +``(maxoffset = 4.0) [real]`` | |
| 101 | + Maximum offset in degrees of source from camera center to accept the | |
| 102 | + observation. | |
| 79 | 103 | |
| 80 | 104 | ``stack [boolean]`` |
| 81 | - Yes: Stack multiple observations into single PHA. No: produce run-by-run PHA files | |
| 105 | + Specifies whether multiple observations should be stacked (``yes``) or | |
| 106 | + whether run-wise PHA, ARF and RMF files should be produced (``no``). | |
| 82 | 107 | |
| 83 | 108 | |
| 84 | 109 | Standard parameters |
| ... | ... | @@ -100,13 +125,13 @@ Standard parameters |
| 100 | 125 | Specifies whether an existing output runlist should be overwritten. |
| 101 | 126 | |
| 102 | 127 | ``(debug = no) [boolean]`` |
| 103 | - Enables debug mode. In debug mode the executable will dump any log file output to the console. | |
| 128 | + Enables debug mode. In debug mode the executable will dump any log file | |
| 129 | + output to the console. | |
| 104 | 130 | |
| 105 | 131 | ``(mode = ql) [string]`` |
| 106 | 132 | Mode of automatic parameters (default is "ql", i.e. "query and learn"). |
| 107 | 133 | |
| 108 | -``(logfile = csfindobs.log) [filename]`` | |
| 134 | +``(logfile = csphagen.log) [filename]`` | |
| 109 | 135 | Log filename. |
| 110 | 136 | |
| 111 | 137 | |
| 112 | - | ... | ... |
test/test_csphagen.py
| ... | ... | @@ -41,12 +41,13 @@ class Test(test): |
| 41 | 41 | """ |
| 42 | 42 | # Call base class constructor |
| 43 | 43 | test.__init__(self) |
| 44 | - self._myevents1 = self._datadir + '/crab_offaxis1.fits' | |
| 45 | - self._myevents2 = self._datadir + '/crab_offaxis2.fits' | |
| 46 | - self._exclusion = self._datadir + '/crab_exclusion.fits' | |
| 44 | + self._myevents1 = self._datadir + '/crab_offaxis1.fits' | |
| 45 | + self._myevents2 = self._datadir + '/crab_offaxis2.fits' | |
| 46 | + self._exclusion = self._datadir + '/crab_exclusion.fits' | |
| 47 | 47 | self._nreg_with_excl = 5 |
| 48 | - self._nreg_wo_excl = 8 | |
| 49 | - self._nreg_mul = [self._nreg_with_excl, 6] | |
| 48 | + self._nreg_wo_excl = 8 | |
| 49 | + self._nreg_mul = [self._nreg_with_excl, 6] | |
| 50 | + self._nbins = 20 | |
| 50 | 51 | # number of expected background regions with/wo exclusion, |
| 51 | 52 | # and for two different runs |
| 52 | 53 | |
| ... | ... | @@ -75,14 +76,17 @@ class Test(test): |
| 75 | 76 | """ |
| 76 | 77 | # Set script name |
| 77 | 78 | csphagen = self._script('csphagen') |
| 78 | - nbins = 120 | |
| 79 | 79 | |
| 80 | - cmd = csphagen + ' inobs="' + self._myevents1 + '" caldb="' + \ | |
| 81 | - self._caldb + '" irf="' + self._irf + \ | |
| 82 | - '" ebinalg="LOG" emin=0.1 emax=100. enumbins=' + \ | |
| 83 | - str(nbins) + ' coordsys="CEL" ra=83.633 dec=22.0145' + \ | |
| 84 | - ' rad=0.2 stack="no" exclusion="' + self._exclusion + \ | |
| 85 | - '" outroot="phagen_cmd1" logfile="csphagen_cmd1.log" chatter=1' | |
| 80 | + # Setup csphagen command | |
| 81 | + cmd = csphagen + ' inobs="' + self._myevents1 + \ | |
| 82 | + '" caldb="' + self._caldb + '" irf="' + self._irf + \ | |
| 83 | + '" ebinalg="LOG" emin=0.1 emax=100. enumbins=' + \ | |
| 84 | + str(self._nbins) + \ | |
| 85 | + ' coordsys="CEL" ra=83.633 dec=22.0145' + \ | |
| 86 | + ' rad=0.2 stack="no" inexclusion="' + \ | |
| 87 | + self._exclusion + \ | |
| 88 | + '" outobs="csphagen_cmd1.xml" prefix="csphagen_cmd1" ' + \ | |
| 89 | + 'logfile="csphagen_cmd1.log" chatter=2' | |
| 86 | 90 | |
| 87 | 91 | # Check if execution of wrong command fails |
| 88 | 92 | self.test_assert(self._execute('command_that_does_not_exist') != 0, |
| ... | ... | @@ -93,15 +97,19 @@ class Test(test): |
| 93 | 97 | 'Check successful execution from command line') |
| 94 | 98 | |
| 95 | 99 | # Check output files |
| 96 | - self._check_output('phagen_cmd1_', nbins, self._nreg_with_excl) | |
| 97 | - self._check_outobs('phagen_cmd1', 1) | |
| 98 | - | |
| 99 | - cmd = csphagen + ' inobs="events_that_do_not_exist.fits" caldb="' + \ | |
| 100 | - self._caldb + '" irf="' + self._irf + \ | |
| 101 | - '" ebinalg="LOG" emin=0.1 emax=100. enumbins=' + \ | |
| 102 | - str(nbins) + ' coordsys="CEL" ra=83.633 dec=22.0145' + \ | |
| 103 | - ' rad=0.2 stack="no" exclusion="' + self._exclusion + \ | |
| 104 | - '" outroot="phagen_cmd1" logfile="csphagen_cmd1.log" chatter=1' | |
| 100 | + self._check_output('csphagen_cmd1', self._nbins, self._nreg_with_excl) | |
| 101 | + self._check_outobs('csphagen_cmd1', 1) | |
| 102 | + | |
| 103 | + # Setup csphagen command | |
| 104 | + cmd = csphagen + ' inobs="events_that_do_not_exist.fits" ' + \ | |
| 105 | + 'caldb="' + self._caldb + '" irf="' + self._irf + \ | |
| 106 | + '" ebinalg="LOG" emin=0.1 emax=100. enumbins=' + \ | |
| 107 | + str(self._nbins) + \ | |
| 108 | + ' coordsys="CEL" ra=83.633 dec=22.0145' + \ | |
| 109 | + ' rad=0.2 stack="no" inexclusion="' + \ | |
| 110 | + self._exclusion + \ | |
| 111 | + '" outobs="csphagen_cmd2.xml" prefix="csphagen_cmd2" ' + \ | |
| 112 | + 'logfile="csphagen_cmd2.log" chatter=1' | |
| 105 | 113 | |
| 106 | 114 | # Check if execution failed |
| 107 | 115 | self.test_assert(self._execute(cmd) != 0, |
| ... | ... | @@ -117,58 +125,58 @@ class Test(test): |
| 117 | 125 | """ |
| 118 | 126 | Test csphagen from Python |
| 119 | 127 | """ |
| 120 | - nbins = 120 | |
| 121 | - | |
| 122 | 128 | # Same test as from command line |
| 123 | 129 | phagen = cscripts.csphagen() |
| 124 | - phagen['inobs'] = self._myevents1 | |
| 125 | - phagen['caldb'] = self._caldb | |
| 126 | - phagen['irf'] = self._irf | |
| 127 | - phagen['ebinalg'] = 'LOG' | |
| 128 | - phagen['emin'] = 0.1 | |
| 129 | - phagen['emax'] = 100. | |
| 130 | - phagen['enumbins'] = nbins | |
| 131 | - phagen['coordsys'] = 'CEL' | |
| 132 | - phagen['ra'] = 83.633 | |
| 133 | - phagen['dec'] = 22.0145 | |
| 134 | - phagen['rad'] = 0.2 | |
| 135 | - phagen['stack'] = False | |
| 136 | - phagen['exclusion'] = self._exclusion | |
| 137 | - phagen['outroot'] = 'phagen_py1' | |
| 138 | - phagen['logfile'] = 'csphagen_py1.log' | |
| 139 | - phagen['chatter'] = 1 | |
| 130 | + phagen['inobs'] = self._myevents1 | |
| 131 | + phagen['caldb'] = self._caldb | |
| 132 | + phagen['irf'] = self._irf | |
| 133 | + phagen['ebinalg'] = 'LOG' | |
| 134 | + phagen['emin'] = 0.1 | |
| 135 | + phagen['emax'] = 100.0 | |
| 136 | + phagen['enumbins'] = self._nbins | |
| 137 | + phagen['coordsys'] = 'CEL' | |
| 138 | + phagen['ra'] = 83.633 | |
| 139 | + phagen['dec'] = 22.0145 | |
| 140 | + phagen['rad'] = 0.2 | |
| 141 | + phagen['stack'] = False | |
| 142 | + phagen['inexclusion'] = self._exclusion | |
| 143 | + phagen['outobs'] = 'csphagen_py1.xml' | |
| 144 | + phagen['prefix'] = 'csphagen_py1' | |
| 145 | + phagen['logfile'] = 'csphagen_py1.log' | |
| 146 | + phagen['chatter'] = 1 | |
| 140 | 147 | |
| 141 | 148 | # Run script |
| 142 | 149 | phagen.execute() |
| 143 | 150 | |
| 144 | 151 | # Check output |
| 145 | - self._check_output('phagen_py1_', nbins, self._nreg_with_excl) | |
| 146 | - self._check_outobs('phagen_py1', 1) | |
| 152 | + self._check_output('csphagen_py1', self._nbins, self._nreg_with_excl) | |
| 153 | + self._check_outobs('csphagen_py1', 1) | |
| 147 | 154 | |
| 148 | 155 | # Now test without exclusion region |
| 149 | 156 | phagen = cscripts.csphagen() |
| 150 | - phagen['inobs'] = self._myevents1 | |
| 151 | - phagen['caldb'] = self._caldb | |
| 152 | - phagen['irf'] = self._irf | |
| 153 | - phagen['ebinalg'] = 'LOG' | |
| 154 | - phagen['emin'] = 0.1 | |
| 155 | - phagen['emax'] = 100. | |
| 156 | - phagen['enumbins'] = nbins | |
| 157 | + phagen['inobs'] = self._myevents1 | |
| 158 | + phagen['caldb'] = self._caldb | |
| 159 | + phagen['irf'] = self._irf | |
| 160 | + phagen['ebinalg'] = 'LOG' | |
| 161 | + phagen['emin'] = 0.1 | |
| 162 | + phagen['emax'] = 100.0 | |
| 163 | + phagen['enumbins'] = self._nbins | |
| 157 | 164 | phagen['coordsys'] = 'CEL' |
| 158 | - phagen['ra'] = 83.633 | |
| 159 | - phagen['dec'] = 22.0145 | |
| 160 | - phagen['rad'] = 0.2 | |
| 161 | - phagen['stack'] = False | |
| 162 | - phagen['outroot'] = 'phagen_py2' | |
| 163 | - phagen['logfile'] = 'csphagen_py2.log' | |
| 164 | - phagen['chatter'] = 1 | |
| 165 | + phagen['ra'] = 83.633 | |
| 166 | + phagen['dec'] = 22.0145 | |
| 167 | + phagen['rad'] = 0.2 | |
| 168 | + phagen['stack'] = False | |
| 169 | + phagen['outobs'] = 'csphagen_py2.xml' | |
| 170 | + phagen['prefix'] = 'csphagen_py2' | |
| 171 | + phagen['logfile'] = 'csphagen_py2.log' | |
| 172 | + phagen['chatter'] = 2 | |
| 165 | 173 | |
| 166 | 174 | # Run script |
| 167 | 175 | phagen.execute() |
| 168 | 176 | |
| 169 | 177 | # Check output |
| 170 | - self._check_output('phagen_py2_', nbins, self._nreg_wo_excl) | |
| 171 | - self._check_outobs('phagen_py2', 1) | |
| 178 | + self._check_output('csphagen_py2', self._nbins, self._nreg_wo_excl) | |
| 179 | + self._check_outobs('csphagen_py2', 1) | |
| 172 | 180 | |
| 173 | 181 | # Test with multiple input observations, no stacking |
| 174 | 182 | # Create observation container |
| ... | ... | @@ -181,55 +189,57 @@ class Test(test): |
| 181 | 189 | |
| 182 | 190 | # Setup csphagen |
| 183 | 191 | phagen = cscripts.csphagen(obs) |
| 184 | - phagen['ebinalg'] = 'LOG' | |
| 185 | - phagen['emin'] = 0.1 | |
| 186 | - phagen['emax'] = 100. | |
| 187 | - phagen['enumbins'] = nbins | |
| 188 | - phagen['coordsys'] = 'CEL' | |
| 189 | - phagen['ra'] = 83.633 | |
| 190 | - phagen['dec'] = 22.0145 | |
| 191 | - phagen['rad'] = 0.2 | |
| 192 | - phagen['stack'] = False | |
| 193 | - phagen['exclusion'] = self._exclusion | |
| 194 | - phagen['outroot'] = 'phagen_py3' | |
| 195 | - phagen['logfile'] = 'csphagen_py3.log' | |
| 196 | - phagen['chatter'] = 1 | |
| 192 | + phagen['ebinalg'] = 'LOG' | |
| 193 | + phagen['emin'] = 0.1 | |
| 194 | + phagen['emax'] = 100.0 | |
| 195 | + phagen['enumbins'] = self._nbins | |
| 196 | + phagen['coordsys'] = 'CEL' | |
| 197 | + phagen['ra'] = 83.633 | |
| 198 | + phagen['dec'] = 22.0145 | |
| 199 | + phagen['rad'] = 0.2 | |
| 200 | + phagen['stack'] = False | |
| 201 | + phagen['inexclusion'] = self._exclusion | |
| 202 | + phagen['outobs'] = 'csphagen_py3.xml' | |
| 203 | + phagen['prefix'] = 'csphagen_py3' | |
| 204 | + phagen['logfile'] = 'csphagen_py3.log' | |
| 205 | + phagen['chatter'] = 3 | |
| 197 | 206 | |
| 198 | 207 | # Run script |
| 199 | 208 | phagen.execute() |
| 200 | 209 | |
| 201 | 210 | # Check output |
| 202 | 211 | for s in range(2): |
| 203 | - self._check_output('phagen_py3_' + str(s + 1), nbins, | |
| 212 | + self._check_output('csphagen_py3_' + str(s + 1), self._nbins, | |
| 204 | 213 | self._nreg_mul[s]) |
| 205 | - self._check_outobs('phagen_py3', 2) | |
| 214 | + self._check_outobs('csphagen_py3', 2) | |
| 206 | 215 | |
| 207 | 216 | # Test with multiple input observations and stacking |
| 208 | 217 | |
| 209 | 218 | # Setup csphagen |
| 210 | 219 | phagen = cscripts.csphagen(obs) |
| 211 | - phagen['ebinalg'] = 'LOG' | |
| 212 | - phagen['emin'] = 0.1 | |
| 213 | - phagen['emax'] = 100. | |
| 214 | - phagen['enumbins'] = nbins | |
| 215 | - phagen['coordsys'] = 'CEL' | |
| 216 | - phagen['ra'] = 83.633 | |
| 217 | - phagen['dec'] = 22.0145 | |
| 218 | - phagen['rad'] = 0.2 | |
| 219 | - phagen['stack'] = True | |
| 220 | - phagen['exclusion'] = self._exclusion | |
| 221 | - phagen['outroot'] = 'phagen_py4' | |
| 222 | - phagen['logfile'] = 'csphagen_py4.log' | |
| 223 | - phagen['chatter'] = 1 | |
| 220 | + phagen['ebinalg'] = 'LOG' | |
| 221 | + phagen['emin'] = 0.1 | |
| 222 | + phagen['emax'] = 100.0 | |
| 223 | + phagen['enumbins'] = self._nbins | |
| 224 | + phagen['coordsys'] = 'CEL' | |
| 225 | + phagen['ra'] = 83.633 | |
| 226 | + phagen['dec'] = 22.0145 | |
| 227 | + phagen['rad'] = 0.2 | |
| 228 | + phagen['stack'] = True | |
| 229 | + phagen['inexclusion'] = self._exclusion | |
| 230 | + phagen['outobs'] = 'csphagen_py4.xml' | |
| 231 | + phagen['prefix'] = 'csphagen_py4' | |
| 232 | + phagen['logfile'] = 'csphagen_py4.log' | |
| 233 | + phagen['chatter'] = 4 | |
| 224 | 234 | |
| 225 | 235 | # Run script |
| 226 | 236 | phagen.execute() |
| 227 | 237 | |
| 228 | 238 | # Check output |
| 229 | 239 | for s in range(2): |
| 230 | - self._check_output('phagen_py4_stacked', nbins, | |
| 240 | + self._check_output('csphagen_py4_stacked', self._nbins, | |
| 231 | 241 | 0, check_regions=False) |
| 232 | - self._check_outobs('phagen_py4', 1) | |
| 242 | + self._check_outobs('csphagen_py4', 1) | |
| 233 | 243 | |
| 234 | 244 | return |
| 235 | 245 | |
| ... | ... | @@ -274,8 +284,7 @@ class Test(test): |
| 274 | 284 | |
| 275 | 285 | # Check FITS table structure |
| 276 | 286 | self.test_value(table.ncols(), len(cols), |
| 277 | - 'Check for %d columns in PHA table' % len( | |
| 278 | - cols)) | |
| 287 | + 'Check for %d columns in PHA table' % len(cols)) | |
| 279 | 288 | self.test_value(table.nrows(), bins, |
| 280 | 289 | 'Check for %d rows in PHA table' % bins) |
| 281 | 290 | for col in cols: |
| ... | ... | @@ -313,8 +322,7 @@ class Test(test): |
| 313 | 322 | |
| 314 | 323 | # Check FITS table structure |
| 315 | 324 | self.test_value(table.ncols(), len(cols), |
| 316 | - 'Check for %d columns in ARF table' % len( | |
| 317 | - cols)) | |
| 325 | + 'Check for %d columns in ARF table' % len(cols)) | |
| 318 | 326 | self.test_value(table.nrows(), bins, |
| 319 | 327 | 'Check for %d rows in ARF table' % bins) |
| 320 | 328 | for col in cols: |
| ... | ... | @@ -350,8 +358,7 @@ class Test(test): |
| 350 | 358 | |
| 351 | 359 | # Check FITS table structure |
| 352 | 360 | self.test_value(table.ncols(), len(cols), |
| 353 | - 'Check for %d columns in RMF table' % len( | |
| 354 | - cols)) | |
| 361 | + 'Check for %d columns in RMF table' % len(cols)) | |
| 355 | 362 | self.test_value(table.nrows(), bins, |
| 356 | 363 | 'Check for %d rows in RMF table' % bins) |
| 357 | 364 | for col in cols: |
| ... | ... | @@ -372,33 +379,39 @@ class Test(test): |
| 372 | 379 | """ |
| 373 | 380 | Check the output from a csphagen run |
| 374 | 381 | """ |
| 375 | - | |
| 376 | 382 | # OGIP files |
| 377 | 383 | self._check_pha(filenameroot + '_pha_on.fits', bins) |
| 378 | 384 | self._check_pha(filenameroot + '_pha_off.fits', bins) |
| 379 | 385 | self._check_arf(filenameroot + '_arf.fits', bins) |
| 380 | 386 | self._check_rmf(filenameroot + '_rmf.fits', bins) |
| 381 | 387 | |
| 382 | - # Observations | |
| 388 | + # Optionally check for regions | |
| 389 | + if check_regions: | |
| 383 | 390 | |
| 391 | + # Check On region | |
| 392 | + onregion = (filenameroot+'_on.reg').replace('_1_', '_').replace('_2_', '_') | |
| 393 | + reg = gammalib.GSkyRegions(onregion) | |
| 394 | + self.test_value(reg.size(), 1, 'Check for 1 region in source region file') | |
| 384 | 395 | |
| 385 | - # Regions | |
| 386 | - if check_regions: | |
| 387 | - reg = gammalib.GSkyRegions(filenameroot + "_on.reg") | |
| 388 | - self.test_value(reg.size(), 1, 'Check for ' + str( | |
| 389 | - 1) + ' region in source region file') | |
| 390 | - reg = gammalib.GSkyRegions(filenameroot + "_off.reg") | |
| 391 | - self.test_value(reg.size(), nreg, 'Check for ' + str( | |
| 392 | - nreg) + ' region in background region file') | |
| 396 | + # Check for Off region | |
| 397 | + offregion = filenameroot + '_off.reg' | |
| 398 | + reg = gammalib.GSkyRegions(offregion) | |
| 399 | + self.test_value(reg.size(), nreg, 'Check for ' + str(nreg) + | |
| 400 | + ' region in background region file') | |
| 393 | 401 | |
| 402 | + # Return | |
| 394 | 403 | return |
| 395 | 404 | |
| 396 | 405 | def _check_outobs(self, filenameroot, nout): |
| 397 | 406 | """ |
| 398 | 407 | Check the output XML file containing ON/OFF observations |
| 399 | 408 | """ |
| 409 | + # Load observation container | |
| 400 | 410 | obs = gammalib.GObservations(filenameroot + '.xml') |
| 401 | - self.test_value(obs.size(), nout, 'Check for ' + str( | |
| 402 | - nout) + ' observations in XML file') | |
| 403 | 411 | |
| 412 | + # Check container size | |
| 413 | + self.test_value(obs.size(), nout, 'Check for ' + str(nout) + | |
| 414 | + ' observations in XML file') | |
| 415 | + | |
| 416 | + # Return | |
| 404 | 417 | return | ... | ... |