Commit f8c119e28148efb29d91812af4d1abee2f351b90

Authored by Jürgen Knödlseder
2 parents e86c3204 cba4f988

Merge branch 'integration' into devel

... ... @@ -15,5 +15,6 @@ 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 +Andreas Specovius (andreas.specovius@fau.de)
18 19 Luigi Tibaldo (luigi.tibaldo@irap.omp.eu)
19 20 Alexander Ziegler (alexander.ziegler@fau.de)
... ...
ChangeLog
1   -2018-01-09
  1 +2018-01-12
2 2  
3 3 * Version 1.5.0 released
4 4 ========================
5 5  
  6 + Add CUSTOM background method to csphagen script (#2284)
6 7 Add csresspec script (#2289)
7 8 Add ctools::time_reference constant and remove ctools::time_reference() method (#2295)
8 9 Correctly strip .gz suffix from output filenames (#2287)
... ...
1   -New Features and Important Changes in ctools 1.5.0
2   -
3   -9 January 2018
  1 +12 January 2018
4 2  
5 3  
6 4 Introduction
... ... @@ -228,6 +226,11 @@ None
228 226  
229 227 csphagen - Generate On/Off observations
230 228 ---------------------------------------
  229 +The CUSTOM background method was added to allow specifying On and Off regions
  230 +from a region file or FITS WCS map. For multiple observations, a custom Off
  231 +region per observation can be specified in the observation definition XML file
  232 +using the OffRegions parameter (#2284).
  233 +
231 234 The script was added to allow the generation of PHA, ARF and RMF datasets for classical On/Off IACT analysis (#2208).
232 235  
233 236  
... ...
cscripts/Makefile.am
1 1 #############################################################################
2 2 # Makefile for cscripts scripts #
3 3 # ------------------------------------------------------------------------- #
4   -# Copyright (C) 2016-2017 Juergen Knoedlseder #
  4 +# Copyright (C) 2016-2018 Juergen Knoedlseder #
5 5 # ------------------------------------------------------------------------- #
6 6 # #
7 7 # This program is free software: you can redistribute it and/or modify #
... ... @@ -172,6 +172,8 @@ testdata = $(top_srcdir)/test/data/crab.xml \
172 172 $(top_srcdir)/test/data/crab_offaxis1.fits.gz \
173 173 $(top_srcdir)/test/data/crab_offaxis2.fits.gz \
174 174 $(top_srcdir)/test/data/crab_exclusion.fits.gz \
  175 + $(top_srcdir)/test/data/crab_src_reg.reg \
  176 + $(top_srcdir)/test/data/crab_bkg_reg.reg \
175 177 $(top_srcdir)/test/data/tsmap_0.fits \
176 178 $(top_srcdir)/test/data/tsmap_1.fits \
177 179 $(top_srcdir)/test/data/exclusion.reg \
... ...
cscripts/csphagen.par
... ... @@ -26,25 +26,27 @@ prefix, s, h, onoff,,, "Prefix for output files"
26 26 #
27 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,, "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"
  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"
48 50  
49 51 #
50 52 # 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-2018 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
... ... @@ -54,21 +54,14 @@ class csphagen(ctools.csobservation):
54 54 # Return
55 55 return
56 56  
  57 +
57 58 # Private methods
58   - def _get_parameters(self):
  59 + def _query_src_direction(self):
59 60 """
60   - Get parameters from parfile and setup observations
  61 + Set up the source direction parameter.
  62 + Query relevant parameters.
61 63 """
62   - # Setup observations (require response and allow event list, don't
63   - # allow counts cube)
64   - self._setup_observations(self.obs(), True, True, False)
65   -
66   - # Set energy bounds
67   - self._ebounds = self._create_ebounds()
68   -
69   - # Initialise source position/region querying relevant parameters
70 64 self._src_dir = gammalib.GSkyDir()
71   - self._src_reg = gammalib.GSkyRegions()
72 65 coordsys = self['coordsys'].string()
73 66 if coordsys == 'CEL':
74 67 ra = self['ra'].real()
... ... @@ -78,17 +71,100 @@ class csphagen(ctools.csobservation):
78 71 glon = self['glon'].real()
79 72 glat = self['glat'].real()
80 73 self._src_dir.lb_deg(glon, glat)
  74 +
  75 + def _get_parameters_bkgmethod_reflected(self):
  76 + """
  77 + Get parameters for REFLECTED background method
  78 + """
  79 + # Get source shape
81 80 self._srcshape = self['srcshape'].string()
  81 +
  82 + # Set source region (so far only CIRCLE is supported)
82 83 if self._srcshape == 'CIRCLE':
  84 +
  85 + # Query source direction
  86 + self._query_src_direction()
  87 +
  88 + # Query minimum number of background regions
  89 + self['bkgregmin'].integer()
  90 +
  91 + # Set circular source region
83 92 self._rad = self['rad'].real()
84 93 self._src_reg.append(gammalib.GSkyRegionCircle(self._src_dir, self._rad))
85 94  
86   - # Query background estimation method and parameters
  95 + # Return
  96 + return
  97 +
  98 + def _get_parameters_bkgmethod_custom(self):
  99 + """
  100 + Get parameters for CUSTOM background method
  101 +
  102 + Raises
  103 + ------
  104 + RuntimeError
  105 + Only one On region is allowed
  106 + """
  107 + # Set up source region
  108 + filename = self['srcregfile'].filename()
  109 + self._src_reg = gammalib.GSkyRegions(filename)
  110 +
  111 + # Raise an exception if there is more than one source region
  112 + if len(self._src_reg) != 1:
  113 + raise RuntimeError('Only one On region is allowed')
  114 +
  115 + # Set up source direction. Query parameters if neccessary.
  116 + if isinstance(self._src_reg[0], gammalib.GSkyRegionCircle):
  117 + self._src_dir = self._src_reg[0].centre()
  118 + self._rad = self._src_reg[0].radius()
  119 + else:
  120 + self._query_src_direction()
  121 +
  122 + # Make sure that all CTA observations have an Off region by loading the
  123 + # Off region region the parameter 'bkgregfile' for all CTA observations
  124 + # without Off region
  125 + for obs in self.obs():
  126 + if obs.instrument() == 'CTA':
  127 + if obs.off_regions().is_empty():
  128 + filename = self['bkgregfile'].filename()
  129 + regions = gammalib.GSkyRegions(filename)
  130 + obs.off_regions(regions)
  131 +
  132 + # Return
  133 + return
  134 +
  135 + def _get_parameters_bkgmethod(self):
  136 + """
  137 + Get background method parameters
  138 + """
  139 + # Get background method
87 140 bkgmethod = self['bkgmethod'].string()
  141 +
  142 + # Get background method dependent parameters
88 143 if bkgmethod == 'REFLECTED':
89   - self['bkgregmin'].integer()
  144 + self._get_parameters_bkgmethod_reflected()
  145 + elif bkgmethod == 'CUSTOM':
  146 + self._get_parameters_bkgmethod_custom()
  147 +
  148 + # Query parameters that are needed for all background methods
90 149 self['maxoffset'].real()
91 150  
  151 + # Return
  152 + return
  153 +
  154 + def _get_parameters(self):
  155 + """
  156 + Get parameters from parfile and setup observations
  157 + """
  158 + # Setup observations (require response and allow event list, don't
  159 + # allow counts cube)
  160 + self._setup_observations(self.obs(), True, True, False)
  161 +
  162 + # Set energy bounds
  163 + self._ebounds = self._create_ebounds()
  164 +
  165 + # Initialize empty src regions container
  166 + self._src_reg = gammalib.GSkyRegions()
  167 +
92 168 # Exclusion map
93 169 if self['inexclusion'].filename().is_fits():
94 170 self._excl_reg = gammalib.GSkyRegionMap(self['inexclusion'].filename())
... ... @@ -109,6 +185,10 @@ class csphagen(ctools.csobservation):
109 185 if self.obs().is_empty():
110 186 self.obs(self._get_observations(False))
111 187  
  188 + # Get background method parameters (have to come after setting up of
  189 + # observations)
  190 + self._get_parameters_bkgmethod()
  191 +
112 192 # Write input parameters into logger
113 193 self._log_parameters(gammalib.TERSE)
114 194  
... ... @@ -247,6 +327,38 @@ class csphagen(ctools.csobservation):
247 327 # Return energy boundaries
248 328 return ebounds
249 329  
  330 + def _set_background_regions(self, obs):
  331 + """
  332 + Set background regions for an observation
  333 +
  334 + Parameters
  335 + ----------
  336 + obs : `~gammalib.GCTAObservation()`
  337 + CTA observation
  338 +
  339 + Returns
  340 + -------
  341 + regions : `~gammalib.GSkyRegions()`
  342 + Background regions
  343 + """
  344 + # Initialise empty background regions for this observation
  345 + bkg_reg = gammalib.GSkyRegions()
  346 +
  347 + # If reflected background is requested then created reflected
  348 + # background regions
  349 + if self['bkgmethod'].string() == 'REFLECTED':
  350 + bkg_reg = self._reflected_regions(obs)
  351 +
  352 + # ... otherwise if custom background is requested then get the
  353 + # background regions from the observation. We use a copy here since
  354 + # otherwise the background regions go out of scope once the observations
  355 + # are replaced by the On/Off observations.
  356 + elif self['bkgmethod'].string() == 'CUSTOM':
  357 + bkg_reg = obs.off_regions().copy()
  358 +
  359 + # Return background regions
  360 + return bkg_reg
  361 +
250 362  
251 363 # Public methods
252 364 def run(self):
... ... @@ -286,15 +398,20 @@ class csphagen(ctools.csobservation):
286 398 # Loop through observations and generate pha, arf, rmf files
287 399 for obs in self.obs():
288 400  
289   - # Initialise background regions for this observation
290   - bkg_reg = gammalib.GSkyRegions()
  401 + # Skip non CTA observations
  402 + if obs.instrument() != 'CTA':
  403 + self._log_string(gammalib.NORMAL, 'Skip %s observation "%s"' % \
  404 + (obs.instrument(), obs.id()))
  405 + continue
  406 +
  407 + # Log current observation
  408 + self._log_string(gammalib.NORMAL, 'Process observation "%s"' % \
  409 + (obs.id()))
291 410  
292   - # If reflected background is requested then created reflected
293   - # background regions
294   - if self['bkgmethod'].string() == 'REFLECTED':
295   - bkg_reg = self._reflected_regions(obs)
  411 + # Set background regions for this observation
  412 + bkg_reg = self._set_background_regions(obs)
296 413  
297   - # If there are reflected regions then create On/Off observation
  414 + # If there are background regions then create On/Off observation
298 415 # and append it to the output container
299 416 if bkg_reg.size() >= self['bkgregmin'].integer():
300 417 onoff = gammalib.GCTAOnOffObservation(obs, self._src_dir,
... ...
cscripts/obsutils.py
... ... @@ -130,6 +130,7 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0,
130 130 phagen['rad'] = onrad
131 131 phagen['stack'] = False
132 132 phagen['inexclusion'] = 'NONE'
  133 + phagen['bkgmethod'] = 'REFLECTED'
133 134  
134 135 # Optionally open the log file
135 136 if log:
... ...
doc/source/admin/release_history/1.5.rst
... ... @@ -29,6 +29,8 @@ Improvements
29 29 * [`2295 <https://cta-redmine.irap.omp.eu/issues/2295>`_] -
30 30 Add ``ctools::time_reference`` constant and remove ``ctools::time_reference()``
31 31 method
  32 +* [`2284 <https://cta-redmine.irap.omp.eu/issues/2284>`_] -
  33 + Add ``CUSTOM`` background method to :ref:`csphagen` script
32 34 * [`2273 <https://cta-redmine.irap.omp.eu/issues/2273>`_] -
33 35 Support On/Off analysis in :ref:`cslightcrv` and :ref:`csphasecrv`
34 36 * [`2267 <https://cta-redmine.irap.omp.eu/issues/2267>`_] -
... ...
doc/source/users/reference_manual/csphagen.rst
... ... @@ -13,8 +13,9 @@ Synopsis
13 13 This script can be used to derive from an observation or a set of observations
14 14 the count spectra in a source region and in background regions, as well as the
15 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).
  16 +used to perform a classical 1D spectral analysis. Regions can be placed
  17 +automatically or by hand. The output files are saved in the OGIP format normally
  18 +used in X-ray astronomy (PHA, ARF, RMF).
18 19 `See here <https://heasarc.gsfc.nasa.gov/docs/heasarc/ofwg/docs/spectra/ogip_92_007/node5.html>`__.
19 20  
20 21 The outputs are:
... ... @@ -30,50 +31,48 @@ General parameters
30 31 ------------------
31 32  
32 33 ``inobs [file]``
33   - Input event list or observation definition XML file.
  34 + Input event list or observation definition XML file
34 35  
35 36 ``caldb [string]``
36   - Calibration database.
  37 + Calibration database
37 38  
38 39 ``irf [string]``
39   - Instrument response function.
  40 + Instrument response function
40 41  
41 42 ``(inexclusion = NONE) [file]``
42 43 Optional FITS file containing a WCS map in the first hdu that defines sky
43   - 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)
44 45  
45 46 ``outobs [string]``
46   - Output observation definition XML file.
  47 + Output observation definition XML file
47 48  
48 49 ``(prefix = onoff) [string]``
49   - 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
50 51  
51 52 ``emin [real]``
52   - 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
53 54  
54 55 ``emax [real]``
55   - 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
56 57  
57 58 ``enumbins [integer]``
58 59 Number of energy bins. At least 30 bins per decade are recommended for
59 60 proper evaluation of the instrument response.
60 61  
61   -``ebinalg [string]``
62   - Energy binning algorithm:
63   - ``LOG`` : logarithmically spaced energy bins;
64   - ``LIN`` : linearly spaced energy bins;
65   - ``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)
66 66  
67 67 ``ebinfile [file]``
68 68 Name of the file containing the energy bin definition if ``FILE`` algorithm
69   - is used.
  69 + is used
70 70  
71   -``(srcshape = CIRCLE) [string]``
72   - Shape of the source region.
73   - ``CIRCLE``: circular region around given position.
  71 +``(srcshape = CIRCLE) <CIRCLE> [string]``
  72 + Shape of the source region (``CIRCLE``: circular region around given position)
74 73  
75   -``coordsys [string]``
76   - Coordinate system (``CEL`` - celestial, ``GAL`` - galactic)
  74 +``coordsys <CEL|GAL> [string]``
  75 + Coordinate system (``CEL``: celestial; ``GAL``: galactic)
77 76  
78 77 ``ra [real]``
79 78 Right Ascension of source region centre (deg)
... ... @@ -90,10 +89,25 @@ General parameters
90 89 ``rad [real]``
91 90 Radius of source region circle (deg)
92 91  
93   -``(bkgmethod = REFLECTED) [string]``
94   - Method for background estimation.
95   - ``REFLECTED:`` background evaluated in regions with the same shape as
96   - source region reflected w.r.t. pointing direction for each observation.
  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)
97 111  
98 112 ``(bkgregmin = 2) [integer]``
99 113 Minimum number of background regions that are required for an observation.
... ... @@ -102,20 +116,20 @@ General parameters
102 116  
103 117 ``(maxoffset = 4.0) [real]``
104 118 Maximum offset in degrees of source from camera center to accept the
105   - observation.
  119 + observation
106 120  
107 121 ``stack [boolean]``
108 122 Specifies whether multiple observations should be stacked (``yes``) or
109   - 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``)
110 124  
111 125 ``(etruemin = 0.01) [real]``
112   - Minimum true energy (TeV).
  126 + Minimum true energy (TeV)
113 127  
114 128 ``(etruemax = 0.01) [real]``
115   - Maximum true energy (TeV).
  129 + Maximum true energy (TeV)
116 130  
117 131 ``(etruebins = 30) [integer]``
118   - Number of bins per decade for true energy bins.
  132 + Number of bins per decade for true energy bins
119 133  
120 134  
121 135 Standard parameters
... ...
test/data/crab_bkg_reg.reg 0 → 100644
  1 +# Region file format: DS9 version 4.1
  2 +global color=green dashlist=8 3 width=1
  3 +fk5;circle(82.2412081162728,22.7975361111674,0.2)
  4 +fk5;circle(82.5360705305998,23.1293202741537,0.2)
  5 +fk5;circle(82.980058098929,23.260640435668,0.2)
  6 +fk5;circle(83.4304728956696,23.1492236356079,0.2)
  7 +fk5;circle(83.7424610541293,22.8309432073396,0.2)
... ...
test/data/crab_src_reg.reg 0 → 100644
  1 +# Region file format: DS9 version 4.1
  2 +global color=green dashlist=8 3 width=1
  3 +fk5;circle(83.633,22.0145,0.2)
... ...
test/test_csphagen.py
... ... @@ -2,7 +2,7 @@
2 2 # ==========================================================================
3 3 # This scripts performs unit tests for the csphagen script.
4 4 #
5   -# Copyright (C) 2017 Luigi Tibaldo
  5 +# Copyright (C) 2017-2018 Luigi Tibaldo
6 6 #
7 7 # This program is free software: you can redistribute it and/or modify
8 8 # it under the terms of the GNU General Public License as published by
... ... @@ -48,10 +48,11 @@ class Test(test):
48 48 self._exclusion = self._datadir + '/crab_exclusion.fits'
49 49 self._nreg_with_excl = 5
50 50 self._nreg_wo_excl = 8
  51 + self._nreg_bkg_reg = 5
51 52 self._nreg_mul = [self._nreg_with_excl, 6]
52 53 self._nbins = 10
53   - # number of expected background regions with/wo exclusion,
54   - # and for two different runs
  54 + self._regfile_src = self._datadir + '/crab_src_reg.reg'
  55 + self._regfile_bkg = self._datadir + '/crab_bkg_reg.reg'
55 56  
56 57 # Return
57 58 return
... ... @@ -88,7 +89,8 @@ class Test(test):
88 89 ' coordsys="CEL" ra=83.633 dec=22.0145' + \
89 90 ' rad=0.2 stack="no" inexclusion="' + \
90 91 self._exclusion + \
91   - '" outobs="csphagen_cmd1.xml" prefix="csphagen_cmd1" ' + \
  92 + '" bkgmethod="REFLECTED" '+ \
  93 + 'outobs="csphagen_cmd1.xml" prefix="csphagen_cmd1" ' + \
92 94 'logfile="csphagen_cmd1.log" chatter=2'
93 95  
94 96 # Check if execution of wrong command fails
... ... @@ -112,7 +114,8 @@ class Test(test):
112 114 ' coordsys="CEL" ra=83.633 dec=22.0145' + \
113 115 ' rad=0.2 stack="no" inexclusion="' + \
114 116 self._exclusion + \
115   - '" outobs="csphagen_cmd2.xml" prefix="csphagen_cmd2" ' + \
  117 + '" bkgmethod="REFLECTED" '+ \
  118 + 'outobs="csphagen_cmd2.xml" prefix="csphagen_cmd2" ' + \
116 119 'logfile="csphagen_cmd2.log" debug=yes chatter=1'
117 120  
118 121 # Check if execution failed
... ... @@ -144,6 +147,7 @@ class Test(test):
144 147 phagen['rad'] = 0.2
145 148 phagen['stack'] = False
146 149 phagen['inexclusion'] = self._exclusion
  150 + phagen['bkgmethod'] = 'REFLECTED'
147 151 phagen['etruemin'] = 0.05
148 152 phagen['etruemax'] = 150.0
149 153 phagen['etruebins'] = 5
... ... @@ -152,7 +156,7 @@ class Test(test):
152 156 phagen['logfile'] = 'csphagen_py1.log'
153 157 phagen['chatter'] = 1
154 158  
155   - # Run script
  159 + # Execute script
156 160 phagen.execute()
157 161  
158 162 # Check output
... ... @@ -173,6 +177,7 @@ class Test(test):
173 177 phagen['dec'] = 22.0145
174 178 phagen['rad'] = 0.2
175 179 phagen['stack'] = False
  180 + phagen['bkgmethod'] = 'REFLECTED'
176 181 phagen['etruemin'] = 0.05
177 182 phagen['etruemax'] = 150.0
178 183 phagen['etruebins'] = 5
... ... @@ -181,7 +186,7 @@ class Test(test):
181 186 phagen['logfile'] = 'csphagen_py2.log'
182 187 phagen['chatter'] = 2
183 188  
184   - # Run script
  189 + # Execute script
185 190 phagen.execute()
186 191  
187 192 # Check output
... ... @@ -209,6 +214,7 @@ class Test(test):
209 214 phagen['rad'] = 0.2
210 215 phagen['stack'] = False
211 216 phagen['inexclusion'] = self._exclusion
  217 + phagen['bkgmethod'] = 'REFLECTED'
212 218 phagen['etruemin'] = 0.05
213 219 phagen['etruemax'] = 150.0
214 220 phagen['etruebins'] = 5
... ... @@ -226,8 +232,7 @@ class Test(test):
226 232 self._nreg_mul[s])
227 233 self._check_outobs('csphagen_py3', 2)
228 234  
229   - # Setup csphagen for test with multiple input observations and
230   - # stacking
  235 + # Setup csphagen for test with multiple input observations and stacking
231 236 phagen = cscripts.csphagen(obs)
232 237 phagen['ebinalg'] = 'LOG'
233 238 phagen['emin'] = 0.1
... ... @@ -239,6 +244,7 @@ class Test(test):
239 244 phagen['rad'] = 0.2
240 245 phagen['stack'] = True
241 246 phagen['inexclusion'] = self._exclusion
  247 + phagen['bkgmethod'] = 'REFLECTED'
242 248 phagen['etruemin'] = 0.05
243 249 phagen['etruemax'] = 150.0
244 250 phagen['etruebins'] = 5
... ... @@ -247,7 +253,7 @@ class Test(test):
247 253 phagen['logfile'] = 'csphagen_py4.log'
248 254 phagen['chatter'] = 4
249 255  
250   - # Run script
  256 + # Execute script
251 257 phagen.execute()
252 258  
253 259 # Check output
... ... @@ -256,6 +262,66 @@ class Test(test):
256 262 0, check_regions=False)
257 263 self._check_outobs('csphagen_py4', 1)
258 264  
  265 + # Setup csphagen for test with custom On and Off regions provided
  266 + phagen = cscripts.csphagen()
  267 + phagen['inobs'] = self._myevents1
  268 + phagen['caldb'] = self._caldb
  269 + phagen['irf'] = self._irf
  270 + phagen['ebinalg'] = 'LOG'
  271 + phagen['emin'] = 0.1
  272 + phagen['emax'] = 100.0
  273 + phagen['enumbins'] = self._nbins
  274 + phagen['bkgmethod'] = 'CUSTOM'
  275 + phagen['srcregfile'] = self._regfile_src
  276 + phagen['bkgregfile'] = self._regfile_bkg
  277 + phagen['etruemin'] = 0.05
  278 + phagen['etruemax'] = 150.0
  279 + phagen['etruebins'] = 5
  280 + phagen['stack'] = False
  281 + phagen['outobs'] = 'csphagen_py5.xml'
  282 + phagen['prefix'] = 'csphagen_py5'
  283 + phagen['logfile'] = 'csphagen_py5.log'
  284 + phagen['chatter'] = 2
  285 +
  286 + # Execute script
  287 + phagen.execute()
  288 +
  289 + # Check output
  290 + self._check_output('csphagen_py5', self._nbins, self._nreg_bkg_reg)
  291 + self._check_outobs('csphagen_py5', 1)
  292 +
  293 + # Append off regions to observation container
  294 + for run in obs:
  295 + run.off_regions(gammalib.GSkyRegions(self._regfile_bkg))
  296 +
  297 + # Setup csphagen for test with multiple input observations and stacking
  298 + phagen = cscripts.csphagen(obs)
  299 + phagen['ebinalg'] = 'LOG'
  300 + phagen['emin'] = 0.1
  301 + phagen['emax'] = 100.0
  302 + phagen['enumbins'] = self._nbins
  303 + phagen['coordsys'] = 'CEL'
  304 + phagen['stack'] = True
  305 + phagen['inexclusion'] = self._exclusion
  306 + phagen['bkgmethod'] = 'CUSTOM'
  307 + phagen['srcregfile'] = self._regfile_src
  308 + phagen['etruemin'] = 0.05
  309 + phagen['etruemax'] = 150.0
  310 + phagen['etruebins'] = 5
  311 + phagen['outobs'] = 'csphagen_py6.xml'
  312 + phagen['prefix'] = 'csphagen_py6'
  313 + phagen['logfile'] = 'csphagen_py6.log'
  314 + phagen['chatter'] = 4
  315 +
  316 + # Execute script
  317 + phagen.execute()
  318 +
  319 + # Check output
  320 + for s in range(2):
  321 + self._check_output('csphagen_py6_stacked', self._nbins,
  322 + 0, check_regions=False)
  323 + self._check_outobs('csphagen_py6', 1)
  324 +
259 325 # Return
260 326 return
261 327  
... ... @@ -309,7 +375,7 @@ class Test(test):
309 375 self.test_assert(table.contains(col),
310 376 'FITS file contains "' + col + '" column')
311 377  
312   - # Check SPECTRUM table
  378 + # Check EBOUNDS table
313 379 table = fits['EBOUNDS']
314 380 self._check_ebounds(table, bins)
315 381  
... ... @@ -433,3 +499,26 @@ class Test(test):
433 499  
434 500 # Return
435 501 return
  502 +
  503 + def _read_pha_counts(self, filename):
  504 + """
  505 + Read and integrate the counts in a pha file.
  506 + Pha file structure already tested in _check_pha()
  507 + """
  508 + # Open FITS file
  509 + fits = gammalib.GFits(filename)
  510 +
  511 + # Get SPECTRUM table
  512 + table = fits['SPECTRUM']
  513 +
  514 + # Integrate counts
  515 + counts_col = table['COUNTS']
  516 + counts = 0
  517 + for channel in range( counts_col.nrows() ):
  518 + counts += counts_col[channel]
  519 +
  520 + # Close FITS file
  521 + fits.close()
  522 +
  523 + # Return
  524 + return counts
... ...