Commit 6473def5bf7fa14d901be473a69568a8b6884179

Authored by Jürgen Knödlseder
1 parent 8efc6377

Integrate code

@@ -15,5 +15,6 @@ Michael Mayer (michael.mayer@physik.hu-berlin.de) @@ -15,5 +15,6 @@ Michael Mayer (michael.mayer@physik.hu-berlin.de)
15 Stefan Ohm (stefan.ohm81@gmail.com) 15 Stefan Ohm (stefan.ohm81@gmail.com)
16 David Sanchez (david.sanchez@lapp.in2p3.fr) 16 David Sanchez (david.sanchez@lapp.in2p3.fr)
17 Hubert Siejkowski (h.siejkowski@cyfronet.pl) 17 Hubert Siejkowski (h.siejkowski@cyfronet.pl)
  18 +Andreas Specovius (andreas.specovius@fau.de)
18 Luigi Tibaldo (luigi.tibaldo@irap.omp.eu) 19 Luigi Tibaldo (luigi.tibaldo@irap.omp.eu)
19 Alexander Ziegler (alexander.ziegler@fau.de) 20 Alexander Ziegler (alexander.ziegler@fau.de)
ChangeLog
1 -2017-11-28 1 +2018-01-12
2 2
3 * Version 1.5.0 released 3 * Version 1.5.0 released
4 ======================== 4 ========================
5 5
  6 + Add CUSTOM background method to csphagen script (#2284)
6 Support On/Off analysis in cslightcrv and csphasecrv (#2273) 7 Support On/Off analysis in cslightcrv and csphasecrv (#2273)
7 Add tutorial for classical analysis (#2267) 8 Add tutorial for classical analysis (#2267)
8 Fix chatter level handling in ctpsfcube (#2262) 9 Fix chatter level handling in ctpsfcube (#2262)
1 New Features and Important Changes in ctools 1.5.0 1 New Features and Important Changes in ctools 1.5.0
2 2
3 -28 November 2017 3 +12 January 2018
4 4
5 5
6 Introduction 6 Introduction
@@ -219,6 +219,11 @@ None @@ -219,6 +219,11 @@ None
219 219
220 csphagen - Generate On/Off observations 220 csphagen - Generate On/Off observations
221 --------------------------------------- 221 ---------------------------------------
  222 +The CUSTOM background method was added to allow specifying On and Off regions
  223 +from a region file or FITS WCS map. For multiple observations, a custom Off
  224 +region per observation can be specified in the observation definition XML file
  225 +using the OffRegions parameter (#2284).
  226 +
222 The script was added to allow the generation of PHA, ARF and RMF datasets for classical On/Off IACT analysis (#2208). 227 The script was added to allow the generation of PHA, ARF and RMF datasets for classical On/Off IACT analysis (#2208).
223 228
224 229
cscripts/csphagen.par
@@ -26,27 +26,27 @@ prefix, s, h, onoff,,, "Prefix for output files" @@ -26,27 +26,27 @@ prefix, s, h, onoff,,, "Prefix for output files"
26 # 26 #
27 # Script parameters 27 # Script parameters
28 #================== 28 #==================
29 -emin, r, a, 0.1,,, "Lower energy limit (TeV)"  
30 -emax, r, a, 100.0,,, "Upper energy limit (TeV)"  
31 -enumbins, i, a, 120,,, "Number of energy bins"  
32 -ebinalg, s, a, LOG,LIN|LOG|FILE,, "Binning algorithm"  
33 -ebinfile, f, a, NONE,,, "Name of the file containing the energy bin definition"  
34 -srcshape, s, h, CIRCLE,CIRCLE,, "Shape of the source region"  
35 -coordsys, s, a, CEL,CEL|GAL,, "Coordinate system (CEL - celestial, GAL - galactic)"  
36 -ra, r, a, 83.63,0,360, "Right Ascension of source region centre (deg)"  
37 -dec, r, a, 22.01,-90,90, "Declination of source region centre (deg)"  
38 -glon, r, a, 184.56,0,360, "Galactic longitude of source region centre (deg)"  
39 -glat, r, a, -5.79,-90,90, "Galactic latitude of source region centre (deg)"  
40 -rad, r, a, 0.2,0,180, "Radius of source region circle (deg)"  
41 -bkgmethod, s, h, REFLECTED,REFLECTED|CUSTOM,, "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?"  
45 -etruemin, r, h, 0.01,,, "Minimum true energy (TeV)"  
46 -etruemax, r, h, 300.0,,, "Maximum true energy (TeV)"  
47 -etruebins, i, h, 30,,, "Number of bins per decade for true energy bins"  
48 -bkgreg, f, a, bkg.reg,,, "Background regions file (ds9 or FITS WCS)"  
49 -srcreg, f, a, on.reg,,, "Source region file (ds9 or FITS WCS)" 29 +emin, r, a, 0.1,,, "Lower energy limit (TeV)"
  30 +emax, r, a, 100.0,,, "Upper energy limit (TeV)"
  31 +enumbins, i, a, 120,,, "Number of energy bins"
  32 +ebinalg, s, a, LOG,LIN|LOG|FILE,, "Binning algorithm"
  33 +ebinfile, f, a, NONE,,, "Name of the file containing the energy bin definition"
  34 +srcshape, s, h, CIRCLE,CIRCLE,, "Shape of the source region"
  35 +coordsys, s, a, CEL,CEL|GAL,, "Coordinate system (CEL - celestial, GAL - galactic)"
  36 +ra, r, a, 83.63,0,360, "Right Ascension of source region centre (deg)"
  37 +dec, r, a, 22.01,-90,90, "Declination of source region centre (deg)"
  38 +glon, r, a, 184.56,0,360, "Galactic longitude of source region centre (deg)"
  39 +glat, r, a, -5.79,-90,90, "Galactic latitude of source region centre (deg)"
  40 +rad, r, a, 0.2,0,180, "Radius of source region circle (deg)"
  41 +srcregfile, f, a, on.reg,,, "Source region file (ds9 or FITS WCS)"
  42 +bkgmethod, s, a, REFLECTED,REFLECTED|CUSTOM,, "Method for background estimation"
  43 +bkgregfile, f, a, bkg.reg,,, "Background regions file (ds9 or FITS WCS)"
  44 +bkgregmin, i, h, 2,1,1000, "Minimum number of background regions"
  45 +maxoffset, r, h, 4.0,,, "Maximum offset of source from camera center to accept observation"
  46 +stack, b, a, no,,, "Stack multiple observations into single PHA, ARF and RMF files?"
  47 +etruemin, r, h, 0.01,,, "Minimum true energy (TeV)"
  48 +etruemax, r, h, 300.0,,, "Maximum true energy (TeV)"
  49 +etruebins, i, h, 30,,, "Number of bins per decade for true energy bins"
50 50
51 # 51 #
52 # Standard parameters 52 # Standard parameters
cscripts/csphagen.py
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 # Computes the PHA spectra for source/background and ARF/RMF files using the 3 # Computes the PHA spectra for source/background and ARF/RMF files using the
4 # reflected region method 4 # reflected region method
5 # 5 #
6 -# Copyright (C) 2017 Luigi Tibaldo 6 +# Copyright (C) 2017-2018 Luigi Tibaldo
7 # 7 #
8 # This program is free software: you can redistribute it and/or modify 8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by 9 # it under the terms of the GNU General Public License as published by
@@ -55,8 +55,9 @@ class csphagen(ctools.csobservation): @@ -55,8 +55,9 @@ class csphagen(ctools.csobservation):
55 # Return 55 # Return
56 return 56 return
57 57
  58 +
58 # Private methods 59 # Private methods
59 - def __query_src_direction(self): 60 + def _query_src_direction(self):
60 """ 61 """
61 Set up the source direction parameter. 62 Set up the source direction parameter.
62 Query relevant parameters. 63 Query relevant parameters.
@@ -72,101 +73,137 @@ class csphagen(ctools.csobservation): @@ -72,101 +73,137 @@ class csphagen(ctools.csobservation):
72 glat = self['glat'].real() 73 glat = self['glat'].real()
73 self._src_dir.lb_deg(glon, glat) 74 self._src_dir.lb_deg(glon, glat)
74 75
75 - def _get_parameters(self): 76 + def _get_parameters_bkgmethod_reflected(self):
76 """ 77 """
77 - Get parameters from parfile and setup observations  
78 -  
79 - Raises  
80 - ------  
81 - RuntimeError  
82 - Multiple On-Regions in on region file or missing Off-Regions files. 78 + Get parameters for REFLECTED background method
83 """ 79 """
84 - # Setup observations (require response and allow event list, don't  
85 - # allow counts cube)  
86 - self._setup_observations(self.obs(), True, True, False)  
87 -  
88 - # Set energy bounds  
89 - self._ebounds = self._create_ebounds()  
90 -  
91 - # Initialize empty src regions container  
92 - self._src_reg = gammalib.GSkyRegions() 80 + # Get source shape
  81 + self._srcshape = self['srcshape'].string()
93 82
94 - # Query background estimation method and parameters  
95 - bkgmethod = self['bkgmethod'].string()  
96 - if bkgmethod == 'REFLECTED': 83 + # Set source region (so far only CIRCLE is supported)
  84 + if self._srcshape == 'CIRCLE':
97 85
98 - # Always query src direction  
99 - self.__query_src_direction()  
100 -  
101 - # Query region parameters  
102 - self._srcshape = self['srcshape'].string()  
103 - if self._srcshape == 'CIRCLE':  
104 - self._rad = self['rad'].real()  
105 - self._src_reg.append(gammalib.GSkyRegionCircle(self._src_dir, self._rad)) 86 + # Query source direction
  87 + self._query_src_direction()
106 88
  89 + # Query minimum number of background regions
107 self['bkgregmin'].integer() 90 self['bkgregmin'].integer()
108 91
109 - elif bkgmethod == 'CUSTOM': 92 + # Set circular source region
  93 + self._rad = self['rad'].real()
  94 + self._src_reg.append(gammalib.GSkyRegionCircle(self._src_dir, self._rad))
110 95
111 - # Set up src region. Only 1 region is allowed.  
112 - src_reg_file = self['srcreg'].filename()  
113 - self._src_reg = gammalib.GSkyRegions(src_reg_file) 96 + # Return
  97 + return
114 98
115 - if len(self._src_reg) != 1:  
116 - raise RuntimeError('Only 1 ON region is allowed.') 99 + def _get_parameters_bkgmethod_custom(self):
  100 + """
  101 + Get parameters for CUSTOM background method
117 102
118 - # Set up src direction. Query if neccessary.  
119 - if isinstance(self._src_reg[0], gammalib.GSkyRegionCircle):  
120 - self._src_dir = self._src_reg[0].centre()  
121 - self._rad = self._src_reg[0].radius() 103 + Raises
  104 + ------
  105 + RuntimeError
  106 + Multiple On-Regions in on region file or missing Off-Regions files.
  107 + """
  108 + # Set up source region
  109 + src_reg_file = self['srcregfile'].filename()
  110 + self._src_reg = gammalib.GSkyRegions(src_reg_file)
  111 +
  112 + # Raise an exception if there is more than one source region
  113 + if len(self._src_reg) != 1:
  114 + raise RuntimeError('Only 1 On region is allowed.')
  115 +
  116 + # Set up source direction. Query parameters if neccessary.
  117 + if isinstance(self._src_reg[0], gammalib.GSkyRegionCircle):
  118 + self._src_dir = self._src_reg[0].centre()
  119 + self._rad = self._src_reg[0].radius()
  120 + else:
  121 + self._query_src_direction()
  122 +
  123 + # Try opening file as XML file. If this files we have probably a FITS
  124 + # events file on input, hence we query later one background region
  125 + # file
  126 + try:
  127 + # Open observation definition XML file
  128 + obs_file = self['inobs'].filename()
  129 + xml = gammalib.GXml(obs_file)
  130 +
  131 + # Go through elements in <observationlist>
  132 + for elem in xml[0]:
  133 +
  134 + # Get observation id from <observation> header
  135 + obs_id = elem.attribute('id')
  136 +
  137 + # Get region file path from <observation> body
  138 + off_regions_file = ''
  139 + for entry in elem:
  140 +
  141 + # <parameter name="OffRegions" file=".."/> contains region file
  142 + if entry.attribute('name') == 'OffRegions':
  143 + off_regions_file = entry.attribute('file')
  144 + break
  145 +
  146 + # Store file paths
  147 + self._bkg_reg_files[obs_id] = gammalib.GFilename(off_regions_file)
  148 +
  149 + # Not existing background region files are set to None (for every obs)
  150 + if not self._bkg_reg_files[obs_id].exists():
  151 + self._bkg_reg_files[obs_id] = None
  152 +
  153 + # XML file opening failed
  154 + except:
  155 + self._bkg_reg_files = {0: None}
  156 +
  157 + # Query missing background region file
  158 + if len([True for x in self._bkg_reg_files if self._bkg_reg_files[x] is None]) > 0:
  159 + if len(self._bkg_reg_files) > 1:
  160 + # Querying of multiple regions not supported
  161 + raise RuntimeError('There are missing bkg region files in the '
  162 + 'observation definition XML file. Please '
  163 + 'specify all background region files.')
122 else: 164 else:
123 - self.__query_src_direction()  
124 -  
125 - # Set up bkg regions  
126 - obs_file = self['inobs'].filename() 165 + # Query bkg region file for single observation
  166 + self._bkg_reg_files[self._bkg_reg_files.keys()[0]] = \
  167 + self['bkgregfile'].filename()
127 168
128 - # obs def XML: look for region files  
129 - if obs_file.file()[-3:] == 'xml':  
130 - # open and load XML obs definition file  
131 - xml = gammalib.GXml()  
132 - xml.load(obs_file) 169 + # Return
  170 + return
133 171
134 - # Go through elements in <observationlist>  
135 - for elem in xml[0]: 172 + def _get_parameters_bkgmethod(self):
  173 + """
  174 + Get background method parameters
  175 + """
  176 + # Get background method
  177 + bkgmethod = self['bkgmethod'].string()
136 178
137 - # Get observation id from <observation> header  
138 - obs_id = elem.attribute('id') 179 + # Get background method dependent parameters
  180 + if bkgmethod == 'REFLECTED':
  181 + self._get_parameters_bkgmethod_reflected()
  182 + elif bkgmethod == 'CUSTOM':
  183 + self._get_parameters_bkgmethod_custom()
139 184
140 - # Get region file path from <observation> body  
141 - off_regions_file = ''  
142 - for entry in elem: 185 + # Query parameters that are needed for all background methods
  186 + self['maxoffset'].real()
143 187
144 - # <parameter name="OffRegions" file=".."/> contains region file  
145 - if entry.attribute('name') == 'OffRegions':  
146 - off_regions_file = entry.attribute('file') 188 + # Return
  189 + return
147 190
148 - # Store file paths  
149 - self._bkg_reg_files[obs_id] = gammalib.GFilename(off_regions_file) 191 + def _get_parameters(self):
  192 + """
  193 + Get parameters from parfile and setup observations
  194 + """
  195 + # Setup observations (require response and allow event list, don't
  196 + # allow counts cube)
  197 + self._setup_observations(self.obs(), True, True, False)
150 198
151 - # Not existing bkg region files are set to None (for every obs)  
152 - if not self._bkg_reg_files[obs_id].exists():  
153 - self._bkg_reg_files[obs_id] = None 199 + # Set energy bounds
  200 + self._ebounds = self._create_ebounds()
154 201
155 - else:  
156 - # event FITS files: query later 1 bkg region file  
157 - self._bkg_reg_files = {0:None}  
158 -  
159 - # Query missing bkg region file  
160 - if len([True for x in self._bkg_reg_files if self._bkg_reg_files[x] is None]) > 0:  
161 - if len(self._bkg_reg_files) > 1:  
162 - # Querying of multiple regions not supported  
163 - raise RuntimeError('There are missing bkg region files in the obs definition'  
164 - +' XML. Please specify all bkg region files!')  
165 - else:  
166 - # Query bkg region file for single observation  
167 - self._bkg_reg_files[self._bkg_reg_files.keys()[0]] = self['bkgreg'].filename() 202 + # Initialize empty src regions container
  203 + self._src_reg = gammalib.GSkyRegions()
168 204
169 - self['maxoffset'].real() 205 + # Get background method parameters
  206 + self._get_parameters_bkgmethod()
170 207
171 # Exclusion map 208 # Exclusion map
172 if self['inexclusion'].filename().is_fits(): 209 if self['inexclusion'].filename().is_fits():
@@ -260,7 +297,9 @@ class csphagen(ctools.csobservation): @@ -260,7 +297,9 @@ class csphagen(ctools.csobservation):
260 297
261 def _regions_from_file(self, obs, file_path): 298 def _regions_from_file(self, obs, file_path):
262 """ 299 """
263 - Read list of reflected regions for a single observation (pointing) from file. 300 + Read list of reflected regions for a single observation (pointing)
  301 + from file.
  302 +
264 Perform basic tests for circle shaped regions. 303 Perform basic tests for circle shaped regions.
265 304
266 Parameters 305 Parameters
@@ -278,12 +317,13 @@ class csphagen(ctools.csobservation): @@ -278,12 +317,13 @@ class csphagen(ctools.csobservation):
278 # Load regions from ds9 file of FITS WCS map 317 # Load regions from ds9 file of FITS WCS map
279 regions = gammalib.GSkyRegions( file_path ) 318 regions = gammalib.GSkyRegions( file_path )
280 319
281 - # Do region tests only for circle shaped on-region. Else simply return list. 320 + # Do region tests only for circle shaped on-region, simply return list
  321 + # for other shapes.
282 on_region = self._src_reg[0] 322 on_region = self._src_reg[0]
283 if isinstance(on_region, gammalib.GSkyRegionCircle): 323 if isinstance(on_region, gammalib.GSkyRegionCircle):
284 324
285 # Prepare parameters for comparison 325 # Prepare parameters for comparison
286 - pnt_dir = obs.pointing().dir() 326 + pnt_dir = obs.pointing().dir()
287 offset_on = pnt_dir.dist_deg(self._src_dir) 327 offset_on = pnt_dir.dist_deg(self._src_dir)
288 radius_on = on_region.radius() 328 radius_on = on_region.radius()
289 329
@@ -297,27 +337,31 @@ class csphagen(ctools.csobservation): @@ -297,27 +337,31 @@ class csphagen(ctools.csobservation):
297 offset_off = pnt_dir.dist_deg(region.centre()) 337 offset_off = pnt_dir.dist_deg(region.centre())
298 radius_off = region.radius() 338 radius_off = region.radius()
299 339
300 - # Warn: different radius 340 + # Warning: different radius
301 if radius_off != radius_on: 341 if radius_off != radius_on:
302 - self._log_string(gammalib.EXPLICIT, 'Off region radius differs from on'  
303 - 'region radius: %.2f vs %.2f' % ((radius_off, radius_on))) 342 + self._log_string(gammalib.EXPLICIT, 'Off region radius '
  343 + 'differs from On region radius: %.2f '
  344 + 'vs %.2f' % ((radius_off, radius_on)))
304 345
305 - # Warn: offset is too small or too large 346 + # Warning: offset is too small or too large
306 if offset_off <= radius_on or offset_off >= self['maxoffset'].real(): 347 if offset_off <= radius_on or offset_off >= self['maxoffset'].real():
307 - self._log_string(gammalib.EXPLICIT, 'Region offset invalid for observation '  
308 - '%s (%.3f deg) ' % ((obs.id(), offset_off))) 348 + self._log_string(gammalib.EXPLICIT, 'Region offset '
  349 + 'invalid for observation %s '
  350 + '(%.3f deg) ' % ((obs.id(), offset_off)))
309 351
310 - # Warn: offset of off and on region differ 352 + # Warning: offset of off and on region differ
311 if offset_off != offset_on: 353 if offset_off != offset_on:
312 - self._log_string(gammalib.EXPLICIT, 'Off region offset differs '  
313 - '%.3f deg from on region offset' % (offset_off-offset_on)) 354 + self._log_string(gammalib.EXPLICIT, 'Off region offset '
  355 + 'differs %.3f deg from On region '
  356 + 'offset' % (offset_off-offset_on))
314 357
315 # end: off-regions test for circle shaped regions 358 # end: off-regions test for circle shaped regions
316 # end: for loop iterating over off regions 359 # end: for loop iterating over off regions
317 # end: do region tests only if on-region is circle shaped 360 # end: do region tests only if on-region is circle shaped
318 361
319 # Inform user how many regions were loaded 362 # Inform user how many regions were loaded
320 - self._log_string(gammalib.NORMAL, 'Read %i regions from file %s.' % (regions.size(), file_path.url())) 363 + self._log_string(gammalib.NORMAL, 'Read %i regions from file %s' % \
  364 + (regions.size(), file_path.url()))
321 365
322 # return list of regions 366 # return list of regions
323 return regions 367 return regions
@@ -390,6 +434,45 @@ class csphagen(ctools.csobservation): @@ -390,6 +434,45 @@ class csphagen(ctools.csobservation):
390 # Return energy boundaries 434 # Return energy boundaries
391 return ebounds 435 return ebounds
392 436
  437 + def _set_background_regions(self, obs):
  438 + """
  439 + Set background regions for an observation
  440 +
  441 + Parameters
  442 + ----------
  443 + obs : `~gammalib.GCTAObservation()`
  444 + CTA observation
  445 +
  446 + Returns
  447 + -------
  448 + regions : `~gammalib.GSkyRegions()`
  449 + Background regions
  450 + """
  451 + # Initialise empty background regions for this observation
  452 + bkg_reg = gammalib.GSkyRegions()
  453 +
  454 + # If reflected background is requested then created reflected
  455 + # background regions
  456 + if self['bkgmethod'].string() == 'REFLECTED':
  457 + bkg_reg = self._reflected_regions(obs)
  458 +
  459 + # ... otherwise if custom background is requested the get the background
  460 + # regions from a region file
  461 + elif self['bkgmethod'].string() == 'CUSTOM':
  462 +
  463 + # Get file path of background region file from dictionary
  464 + if len(self._bkg_reg_files) > 1:
  465 + bkg_reg_file = self._bkg_reg_files[obs.id()]
  466 + else:
  467 + # for inobs==event list no obs id is set.
  468 + bkg_reg_file = self._bkg_reg_files[self._bkg_reg_files.keys()[0]]
  469 +
  470 + # Load background regions from region file for current observation
  471 + bkg_reg = self._regions_from_file(obs, bkg_reg_file)
  472 +
  473 + # Return background regions
  474 + return bkg_reg
  475 +
393 476
394 # Public methods 477 # Public methods
395 def run(self): 478 def run(self):
@@ -432,26 +515,10 @@ class csphagen(ctools.csobservation): @@ -432,26 +515,10 @@ class csphagen(ctools.csobservation):
432 # Log current observation 515 # Log current observation
433 self._log_string(gammalib.NORMAL, 'Process Observation %s' % (obs.id())) 516 self._log_string(gammalib.NORMAL, 'Process Observation %s' % (obs.id()))
434 517
435 - # Initialise background regions for this observation  
436 - bkg_reg = gammalib.GSkyRegions()  
437 -  
438 - # If reflected background is requested then created reflected  
439 - # background regions  
440 - if self['bkgmethod'].string() == 'REFLECTED':  
441 - bkg_reg = self._reflected_regions(obs)  
442 - elif self['bkgmethod'].string() == 'CUSTOM':  
443 - # Get file path of bkg region file from dictionary  
444 - if len(self._bkg_reg_files) > 1:  
445 - bkg_reg_file = self._bkg_reg_files[obs.id()]  
446 - else:  
447 - # for inobs==event list no obs id is set.  
448 - bkg_reg_file = self._bkg_reg_files[self._bkg_reg_files.keys()[0]]  
449 -  
450 - # Load off regions from region file for current observation  
451 - bkg_reg = self._regions_from_file(obs, bkg_reg_file)  
452 - 518 + # Set background regions for this observation
  519 + bkg_reg = self._set_background_regions(obs)
453 520
454 - # If there are reflected regions then create On/Off observation 521 + # If there are background regions then create On/Off observation
455 # and append it to the output container 522 # and append it to the output container
456 if bkg_reg.size() >= self['bkgregmin'].integer(): 523 if bkg_reg.size() >= self['bkgregmin'].integer():
457 onoff = gammalib.GCTAOnOffObservation(obs, self._src_dir, 524 onoff = gammalib.GCTAOnOffObservation(obs, self._src_dir,
cscripts/obsutils.py
1 # ========================================================================== 1 # ==========================================================================
2 # Utility functions for observation handling 2 # Utility functions for observation handling
3 # 3 #
4 -# Copyright (C) 2011-2017 Juergen Knoedlseder 4 +# Copyright (C) 2011-2018 Juergen Knoedlseder
5 # 5 #
6 # This program is free software: you can redistribute it and/or modify 6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by 7 # it under the terms of the GNU General Public License as published by
@@ -130,6 +130,7 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, @@ -130,6 +130,7 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0,
130 phagen['rad'] = onrad 130 phagen['rad'] = onrad
131 phagen['stack'] = False 131 phagen['stack'] = False
132 phagen['inexclusion'] = 'NONE' 132 phagen['inexclusion'] = 'NONE'
  133 + phagen['bkgmethod'] = 'REFLECTED'
133 134
134 # Optionally open the log file 135 # Optionally open the log file
135 if log: 136 if log:
doc/source/admin/release_history/1.5.rst
@@ -24,6 +24,8 @@ Bug fixes @@ -24,6 +24,8 @@ Bug fixes
24 Improvements 24 Improvements
25 ------------ 25 ------------
26 26
  27 +* [`2284 <https://cta-redmine.irap.omp.eu/issues/2284>`_] -
  28 + Add ``CUSTOM`` background method to :ref:`csphagen` script
27 * [`2273 <https://cta-redmine.irap.omp.eu/issues/2273>`_] - 29 * [`2273 <https://cta-redmine.irap.omp.eu/issues/2273>`_] -
28 Support On/Off analysis in :ref:`cslightcrv` and :ref:`csphasecrv` 30 Support On/Off analysis in :ref:`cslightcrv` and :ref:`csphasecrv`
29 * [`2267 <https://cta-redmine.irap.omp.eu/issues/2267>`_] - 31 * [`2267 <https://cta-redmine.irap.omp.eu/issues/2267>`_] -
doc/source/users/reference_manual/csphagen.rst
@@ -31,50 +31,48 @@ General parameters @@ -31,50 +31,48 @@ General parameters
31 ------------------ 31 ------------------
32 32
33 ``inobs [file]`` 33 ``inobs [file]``
34 - Input event list or observation definition XML file. 34 + Input event list or observation definition XML file
35 35
36 ``caldb [string]`` 36 ``caldb [string]``
37 - Calibration database. 37 + Calibration database
38 38
39 ``irf [string]`` 39 ``irf [string]``
40 - Instrument response function. 40 + Instrument response function
41 41
42 ``(inexclusion = NONE) [file]`` 42 ``(inexclusion = NONE) [file]``
43 Optional FITS file containing a WCS map in the first hdu that defines sky 43 Optional FITS file containing a WCS map in the first hdu that defines sky
44 - regions not to be used for background estimation (where map value != 0). 44 + regions not to be used for background estimation (where map value != 0)
45 45
46 ``outobs [string]`` 46 ``outobs [string]``
47 - Output observation definition XML file. 47 + Output observation definition XML file
48 48
49 ``(prefix = onoff) [string]`` 49 ``(prefix = onoff) [string]``
50 - Prefix of the file name for output PHA, ARF, RMF, XML, and DS9 region files. 50 + Prefix of the file name for output PHA, ARF, RMF, XML, and DS9 region files
51 51
52 ``emin [real]`` 52 ``emin [real]``
53 - Lower energy limit (TeV) if ``LIN`` or ``LOG`` binning algorithms are used. 53 + Lower energy limit (TeV) if ``LIN`` or ``LOG`` binning algorithms are used
54 54
55 ``emax [real]`` 55 ``emax [real]``
56 - Upper energy limit (TeV) if ``LIN`` or ``LOG`` binning algorithms are used. 56 + Upper energy limit (TeV) if ``LIN`` or ``LOG`` binning algorithms are used
57 57
58 ``enumbins [integer]`` 58 ``enumbins [integer]``
59 Number of energy bins. At least 30 bins per decade are recommended for 59 Number of energy bins. At least 30 bins per decade are recommended for
60 proper evaluation of the instrument response. 60 proper evaluation of the instrument response.
61 61
62 -``ebinalg [string]``  
63 - Energy binning algorithm:  
64 - ``LOG`` : logarithmically spaced energy bins;  
65 - ``LIN`` : linearly spaced energy bins;  
66 - ``FILE``: energy bounds retrieved from file. 62 +``ebinalg <FILE|LIN|LOG> [string]``
  63 + Algorithm for defining energy bins (``FILE``: energy bounds retrieved from
  64 + file, see ``ebinfile`` parameter; ``LIN``: linearly spaced energy bins;
  65 + ``LOG``: logarithmically spaced energy bins)
67 66
68 ``ebinfile [file]`` 67 ``ebinfile [file]``
69 Name of the file containing the energy bin definition if ``FILE`` algorithm 68 Name of the file containing the energy bin definition if ``FILE`` algorithm
70 - is used. 69 + is used
71 70
72 -``(srcshape = CIRCLE) [string]``  
73 - Shape of the source region.  
74 - ``CIRCLE``: circular region around given position. 71 +``(srcshape = CIRCLE) <CIRCLE> [string]``
  72 + Shape of the source region (``CIRCLE``: circular region around given position)
75 73
76 -``coordsys [string]``  
77 - Coordinate system (``CEL`` - celestial, ``GAL`` - galactic) 74 +``coordsys <CEL|GAL> [string]``
  75 + Coordinate system (``CEL``: celestial; ``GAL``: galactic)
78 76
79 ``ra [real]`` 77 ``ra [real]``
80 Right Ascension of source region centre (deg) 78 Right Ascension of source region centre (deg)
@@ -91,17 +89,25 @@ General parameters @@ -91,17 +89,25 @@ General parameters
91 ``rad [real]`` 89 ``rad [real]``
92 Radius of source region circle (deg) 90 Radius of source region circle (deg)
93 91
94 -``(bkgmethod = REFLECTED) [string]``  
95 - Method for background estimation.  
96 - ``REFLECTED:`` background evaluated in regions with the same shape as  
97 - source region reflected w.r.t. pointing direction for each observation.  
98 - ``CUSTOM:`` background evaluated in regions specified by user.  
99 - For event list or single obs in an obs definition XML: region files can  
100 - be queried.  
101 - For multiple observations: those have to be specified in the obs def XML.  
102 - Here use parameter name="OffRegions" (per observation) with appropriate  
103 - <file> entry. Files can be ds9 regions or FITS WCS maps. The on region  
104 - will always be queried. 92 +``srcregfile [file]``
  93 + Source region file (ds9 or FITS WCS map)
  94 +
  95 +``bkgmethod <REFLECTED|CUSTOM> [string]``
  96 + Method for background estimation:
  97 +
  98 + - ``REFLECTED``: background is evaluated in regions with the same shape as
  99 + the source region reflected w.r.t. pointing direction for each observation
  100 +
  101 + - ``CUSTOM``: background is evaluated in regions specified by user. For an
  102 + event list or a single observation in the observation definition XML file
  103 + a region file will be queried (see ``bkgregfile`` parameter). For multiple
  104 + observations specified in the observation definition XML file the name of
  105 + the region file will be extracted from the ``OffRegions`` parameter that
  106 + needs to be specified for each observation in the observation definition
  107 + XML file. Off region files can be either ds9 region files or FITS WCS maps.
  108 +
  109 +``bkgregfile [file]``
  110 + Background regions file (ds9 or FITS WCS map)
105 111
106 ``(bkgregmin = 2) [integer]`` 112 ``(bkgregmin = 2) [integer]``
107 Minimum number of background regions that are required for an observation. 113 Minimum number of background regions that are required for an observation.
@@ -110,26 +116,20 @@ General parameters @@ -110,26 +116,20 @@ General parameters
110 116
111 ``(maxoffset = 4.0) [real]`` 117 ``(maxoffset = 4.0) [real]``
112 Maximum offset in degrees of source from camera center to accept the 118 Maximum offset in degrees of source from camera center to accept the
113 - observation. 119 + observation
114 120
115 ``stack [boolean]`` 121 ``stack [boolean]``
116 Specifies whether multiple observations should be stacked (``yes``) or 122 Specifies whether multiple observations should be stacked (``yes``) or
117 - whether run-wise PHA, ARF and RMF files should be produced (``no``). 123 + whether run-wise PHA, ARF and RMF files should be produced (``no``)
118 124
119 ``(etruemin = 0.01) [real]`` 125 ``(etruemin = 0.01) [real]``
120 - Minimum true energy (TeV). 126 + Minimum true energy (TeV)
121 127
122 ``(etruemax = 0.01) [real]`` 128 ``(etruemax = 0.01) [real]``
123 - Maximum true energy (TeV). 129 + Maximum true energy (TeV)
124 130
125 ``(etruebins = 30) [integer]`` 131 ``(etruebins = 30) [integer]``
126 - Number of bins per decade for true energy bins.  
127 -  
128 -``(bkgreg = bkg.reg) [file]``  
129 - Background regions file (ds9 or FITS WCS map).  
130 -  
131 -``(srcreg = on.reg) [file]``  
132 - Source region file (ds9 or FITS WCS map). 132 + Number of bins per decade for true energy bins
133 133
134 134
135 Standard parameters 135 Standard parameters
test/test_csphagen.py
@@ -92,7 +92,8 @@ class Test(test): @@ -92,7 +92,8 @@ class Test(test):
92 ' coordsys="CEL" ra=83.633 dec=22.0145' + \ 92 ' coordsys="CEL" ra=83.633 dec=22.0145' + \
93 ' rad=0.2 stack="no" inexclusion="' + \ 93 ' rad=0.2 stack="no" inexclusion="' + \
94 self._exclusion + \ 94 self._exclusion + \
95 - '" outobs="csphagen_cmd1.xml" prefix="csphagen_cmd1" ' + \ 95 + '" bkgmethod="REFLECTED" '+ \
  96 + 'outobs="csphagen_cmd1.xml" prefix="csphagen_cmd1" ' + \
96 'logfile="csphagen_cmd1.log" chatter=2' 97 'logfile="csphagen_cmd1.log" chatter=2'
97 98
98 # Check if execution of wrong command fails 99 # Check if execution of wrong command fails
@@ -119,7 +120,8 @@ class Test(test): @@ -119,7 +120,8 @@ class Test(test):
119 ' coordsys="CEL" ra=83.633 dec=22.0145' + \ 120 ' coordsys="CEL" ra=83.633 dec=22.0145' + \
120 ' rad=0.2 stack="no" inexclusion="' + \ 121 ' rad=0.2 stack="no" inexclusion="' + \
121 self._exclusion + \ 122 self._exclusion + \
122 - '" outobs="csphagen_cmd2.xml" prefix="csphagen_cmd2" ' + \ 123 + '" bkgmethod="REFLECTED" '+ \
  124 + 'outobs="csphagen_cmd2.xml" prefix="csphagen_cmd2" ' + \
123 'logfile="csphagen_cmd2.log" debug=yes chatter=1' 125 'logfile="csphagen_cmd2.log" debug=yes chatter=1'
124 126
125 # Check if execution failed 127 # Check if execution failed
@@ -151,6 +153,7 @@ class Test(test): @@ -151,6 +153,7 @@ class Test(test):
151 phagen['rad'] = 0.2 153 phagen['rad'] = 0.2
152 phagen['stack'] = False 154 phagen['stack'] = False
153 phagen['inexclusion'] = self._exclusion 155 phagen['inexclusion'] = self._exclusion
  156 + phagen['bkgmethod'] = 'REFLECTED'
154 phagen['etruemin'] = 0.05 157 phagen['etruemin'] = 0.05
155 phagen['etruemax'] = 150.0 158 phagen['etruemax'] = 150.0
156 phagen['etruebins'] = 5 159 phagen['etruebins'] = 5
@@ -180,6 +183,7 @@ class Test(test): @@ -180,6 +183,7 @@ class Test(test):
180 phagen['dec'] = 22.0145 183 phagen['dec'] = 22.0145
181 phagen['rad'] = 0.2 184 phagen['rad'] = 0.2
182 phagen['stack'] = False 185 phagen['stack'] = False
  186 + phagen['bkgmethod'] = 'REFLECTED'
183 phagen['etruemin'] = 0.05 187 phagen['etruemin'] = 0.05
184 phagen['etruemax'] = 150.0 188 phagen['etruemax'] = 150.0
185 phagen['etruebins'] = 5 189 phagen['etruebins'] = 5
@@ -216,6 +220,7 @@ class Test(test): @@ -216,6 +220,7 @@ class Test(test):
216 phagen['rad'] = 0.2 220 phagen['rad'] = 0.2
217 phagen['stack'] = False 221 phagen['stack'] = False
218 phagen['inexclusion'] = self._exclusion 222 phagen['inexclusion'] = self._exclusion
  223 + phagen['bkgmethod'] = 'REFLECTED'
219 phagen['etruemin'] = 0.05 224 phagen['etruemin'] = 0.05
220 phagen['etruemax'] = 150.0 225 phagen['etruemax'] = 150.0
221 phagen['etruebins'] = 5 226 phagen['etruebins'] = 5
@@ -246,6 +251,7 @@ class Test(test): @@ -246,6 +251,7 @@ class Test(test):
246 phagen['rad'] = 0.2 251 phagen['rad'] = 0.2
247 phagen['stack'] = True 252 phagen['stack'] = True
248 phagen['inexclusion'] = self._exclusion 253 phagen['inexclusion'] = self._exclusion
  254 + phagen['bkgmethod'] = 'REFLECTED'
249 phagen['etruemin'] = 0.05 255 phagen['etruemin'] = 0.05
250 phagen['etruemax'] = 150.0 256 phagen['etruemax'] = 150.0
251 phagen['etruebins'] = 5 257 phagen['etruebins'] = 5
@@ -293,9 +299,10 @@ class Test(test): @@ -293,9 +299,10 @@ class Test(test):
293 'inexclusion="' + self._exclusion + '" ' + \ 299 'inexclusion="' + self._exclusion + '" ' + \
294 'bkgmethod="CUSTOM" ' + \ 300 'bkgmethod="CUSTOM" ' + \
295 'rad=0.2 ' + \ 301 'rad=0.2 ' + \
296 - 'srcreg="' + self._regfile_src + '" ' + \  
297 - 'bkgreg="' + self._regfile_bkg + '" ' + \  
298 - 'outobs="csphagen_regfiles_cmd1.xml" prefix="csphagen_regfiles_cmd1" ' + \ 302 + 'srcregfile="' + self._regfile_src + '" ' + \
  303 + 'bkgregfile="' + self._regfile_bkg + '" ' + \
  304 + 'outobs="csphagen_regfiles_cmd1.xml" ' + \
  305 + 'prefix="csphagen_regfiles_cmd1" ' + \
299 'logfile="csphagen_regfiles_cmd1.log" chatter=2 ' + \ 306 'logfile="csphagen_regfiles_cmd1.log" chatter=2 ' + \
300 'coordsys="CEL" ra=83.633 dec=22.0145' 307 'coordsys="CEL" ra=83.633 dec=22.0145'
301 308