make_gps.py

Knödlseder Jürgen, 01/11/2016 08:45 PM

Download (11.7 KB)

 
1
#! /usr/bin/env python
2
# ==========================================================================
3
#
4
# Copyright (C) 2015-2016 Juergen Knoedlseder
5
#
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
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
#
19
# ==========================================================================
20
# This script simulates the CTA Galactic Plane Scan KSP. It requires on
21
# input the following files:
22
#
23
#   gps.xml                    Observation definition file for GPS KSP
24
#   model/
25
#         map_ics.fits         Inverse Compton scattering diffuse map
26
#         map_pi0.fits         Pion decay diffuse map
27
#         map_RXJ1713.fits     RXJ1713 supernova remnant (X-ray template)
28
#         map_VelaJunior.fits  Vela Junior supernova remnant
29
#         model_bkg.xml        Background model definition
30
#         model_cygnus.xml     Cygnus region model definition
31
#         model_ics.xml        Inverse Compton scattering model definition
32
#         model_pi0.xml        Pion decay model definition
33
#         model_pwne.xml       PWNe population model definition (-TevCAT)
34
#         model_snrs.xml       SNRs population model definition
35
#         model_tevcat.xml     TeVCat model definition (thanks, Deidre)
36
#
37
# It will produce a file named gps_residual_1-10TeV.fits that contains the
38
# residual counts above background.
39
#
40
# Usage:
41
# ./make_gps.py
42
#
43
# ==========================================================================
44
import gammalib
45
import ctools
46

    
47

    
48
# ===================== #
49
# Create response files #
50
# ===================== #
51
def create_response(obsname, model, \
52
                    emin=0.1, emax=1.0, enumbins=1, \
53
                    debug=True, force=False, \
54
                    expcube="expcube.fits", psfcube="psfcube.fits", \
55
                    bkgcube="bkgcube.fits", bkgmod="model_bkg.xml"):
56
    """
57
    Create response files for stacked analysis.
58

59
    Parameters:
60
     obsname  - Filename of observation definition XML file
61
     model    - Filename of model XML file
62

63
    Keywords:
64
     emin     - Minimum energy of cube [TeV] (default: 0.1)
65
     emax     - Maximum energy of cube [TeV] (default: 100.0)
66
     enumbins - Number of energy bins in cube (default: 20)
67
     debug    - Enable debugging (default: True)
68
     force    - Force computation (default: False)
69
     expcube  - Exposure cube file name
70
     psfcube  - PSF cube file name
71
     bkgcube  - Background cube file name
72
     bkgmod   - Model file name
73
    """
74
    # Create exposure cube
75
    if force or not gammalib.file_exists(expcube):
76
        ctexpcube = ctools.ctexpcube()
77
        ctexpcube["inobs"]    = obsname
78
        ctexpcube["incube"]   = "NONE"
79
        ctexpcube["outcube"]  = expcube
80
        ctexpcube["debug"]    = debug
81
        ctexpcube["ebinalg"]  = "LOG"
82
        ctexpcube["emin"]     = emin
83
        ctexpcube["emax"]     = emax
84
        ctexpcube["enumbins"] = enumbins
85
        ctexpcube["nxpix"]    = 3600
86
        ctexpcube["nypix"]    = 200
87
        ctexpcube["binsz"]    = 0.1
88
        ctexpcube["coordsys"] = "GAL"
89
        ctexpcube["proj"]     = "CAR"
90
        ctexpcube["xref"]     = 0.0
91
        ctexpcube["yref"]     = 0.0
92
        ctexpcube.execute()
93

    
94
    # Create Psf cube
95
    if force or not gammalib.file_exists(psfcube):
96
        ctpsfcube = ctools.ctpsfcube()
97
        ctpsfcube["inobs"]    = obsname
98
        ctpsfcube["incube"]   = "NONE"
99
        ctpsfcube["outcube"]  = psfcube
100
        ctpsfcube["ebinalg"]  = "LOG"
101
        ctpsfcube["emin"]     = emin
102
        ctpsfcube["emax"]     = emax
103
        ctpsfcube["enumbins"] = enumbins
104
        ctpsfcube["nxpix"]    = 360
105
        ctpsfcube["nypix"]    = 20
106
        ctpsfcube["binsz"]    = 1.0
107
        ctpsfcube["coordsys"] = "GAL"
108
        ctpsfcube["proj"]     = "CAR"
109
        ctpsfcube["xref"]     = 0.0
110
        ctpsfcube["yref"]     = 0.0
111
        ctpsfcube["debug"]    = debug
112
        ctpsfcube.execute()
113

    
114
    # Create Background cube
115
    if force or not gammalib.file_exists(bkgcube):
116
        ctbkgcube = ctools.ctbkgcube()
117
        ctbkgcube["inobs"]    = obsname
118
        ctbkgcube["inmodel"]  = model
119
        ctbkgcube["incube"]   = "NONE"
120
        ctbkgcube["outcube"]  = bkgcube
121
        ctbkgcube["outmodel"] = bkgmod
122
        ctbkgcube["ebinalg"]  = "LOG"
123
        ctbkgcube["emin"]     = emin
124
        ctbkgcube["emax"]     = emax
125
        ctbkgcube["enumbins"] = enumbins
126
        ctbkgcube["nxpix"]    = 7200
127
        ctbkgcube["nypix"]    = 400
128
        ctbkgcube["binsz"]    = 0.05
129
        ctbkgcube["coordsys"] = "GAL"
130
        ctbkgcube["proj"]     = "CAR"
131
        ctbkgcube["xref"]     = 0.0
132
        ctbkgcube["yref"]     = 0.0
133
        ctbkgcube["debug"]    = debug
134
        ctbkgcube.execute()
135

    
136
    # Return
137
    return
138

    
139

    
140
# ============ #
141
# Create model #
142
# ============ #
143
def create_model(expcube, psfcube, bkgcube, model, \
144
                 emin=0.1, emax=1.0, enumbins=1, \
145
                 nxpix=7200, nypix=400, binsz=0.05, \
146
                 modcube="modcube.fits", debug=True, force=False):
147
    """
148
    Create one specific model for stacked analysis.
149

150
    Parameters:
151
     expcube  - Exposure cube file name
152
     psfcube  - PSF cube file name
153
     bkgcube  - Background cube file name
154
     model    - Filename of model XML file
155

156
    Keywords:
157
     emin     - Minimum energy of cube [TeV] (default: 0.1)
158
     emax     - Maximum energy of cube [TeV] (default: 100.0)
159
     enumbins - Number of energy bins in cube (default: 20)
160
     nxpix    - Number of pixels in Galactic longitude (default: 7200)
161
     nypix    - Number of pixels in Galactic latitude (default: 400)
162
     binsz    - Pixel size (default: 0.05 deg)
163
     modcube  - Model cube file name
164
     debug    - Enable debugging (default: True)
165
     force    - Force computation (default: False)
166
    """
167

    
168
    # Create model map
169
    if force or not gammalib.file_exists(modcube):
170
        ctmodel = ctools.ctmodel()
171
        ctmodel["incube"]   = "NONE"
172
        ctmodel["inmodel"]  = model
173
        ctmodel["outcube"]  = modcube
174
        ctmodel["inobs"]    = "NONE"
175
        ctmodel["expcube"]  = expcube
176
        ctmodel["psfcube"]  = psfcube
177
        ctmodel["bkgcube"]  = bkgcube
178
        ctmodel["ebinalg"]  = "LOG"
179
        ctmodel["emin"]     = emin
180
        ctmodel["emax"]     = emax
181
        ctmodel["enumbins"] = enumbins
182
        ctmodel["nxpix"]    = nxpix
183
        ctmodel["nypix"]    = nypix
184
        ctmodel["binsz"]    = binsz
185
        ctmodel["coordsys"] = "GAL"
186
        ctmodel["proj"]     = "CAR"
187
        ctmodel["xref"]     = 0.0
188
        ctmodel["yref"]     = 0.0
189
        ctmodel["debug"]    = debug
190
        ctmodel.execute()
191

    
192
    # Return
193
    return
194

    
195

    
196
# ====================== #
197
# Add and flatten models #
198
# ====================== #
199
def add_and_flatten(models, modmap, name, estr):
200
    """
201
    Add and flatten models.
202

203
    Parameters:
204
     models   - List of models
205
     name     - Name part of file name
206
     estr     - Energy string part of file name
207
     modmap   - Flattened model file name
208
    """
209
    # Initialise first map flag
210
    first = True
211

    
212
    # Loop over all models
213
    for model in models:
214

    
215
        # Build model filename
216
        filename = "%s_%s_%s.fits" % (name, model, estr)
217

    
218
        # Load model
219
        model = gammalib.GCTAEventCube(filename)
220

    
221
        # Get sky map and flatten
222
        map = model.map()
223
        map.stack_maps()
224

    
225
        # If this is the first map then store it
226
        if first:
227
            outmap = map.copy()
228
            first  = False
229
        else:
230
            outmap += map
231

    
232
    # Save map
233
    outmap.save(modmap, True)
234

    
235
    # Return
236
    return
237
    
238

    
239
# =============== #
240
# Simulate events #
241
# =============== #
242
def simulate_events(modmap, evtmap):
243
    """
244
    Simulate events from model map.
245

246
    Parameters:
247
     modmap   - Flattened model file name
248
     evtmap   - Event map file name
249
    """
250
    # Allocate random number generator
251
    ran = gammalib.GRan()
252

    
253
    # Load model map
254
    map = gammalib.GSkyMap(modmap)
255

    
256
    # Randomize
257
    for i in range(map.npix()):
258
        map[i] = ran.poisson(map[i])
259

    
260
    # Save event map
261
    map.save(evtmap, True)
262

    
263
    # Return
264
    return
265

    
266

    
267
# =================== #
268
# Create residual map #
269
# =================== #
270
def create_residual(evtmap, bkgcomp, resmap):
271
    """
272
    Create residual map.
273

274
    Parameters:
275
     evtmap   - Event map file name
276
     bkgcomp  - Background model file name
277
     resmap   - Residual map file name
278
    """
279
    # Create flat skymap from background component
280
    bkg    = gammalib.GCTAEventCube(bkgcomp)
281
    bkgmap = bkg.map()
282
    bkgmap.stack_maps()
283

    
284
    # Load event map
285
    events = gammalib.GSkyMap(evtmap)
286

    
287
    # Subtract background model
288
    for i in range(events.npix()):
289
        events[i] -= bkgmap[i]
290

    
291
    # Save residual map
292
    events.save(resmap, True)
293

    
294
    # Return
295
    return
296

    
297

    
298
# ======================== #
299
# Main routine entry point #
300
# ======================== #
301
if __name__ == '__main__':
302
    """
303
    """
304
    # Dump header
305
    print("************************************************")
306
    print("*    CTA Galactic Plane Scan KSP simulation    *")
307
    print("************************************************")
308

    
309
    # Set simulation parameters
310
    name     = "gps"
311
    emin     =  1.0
312
    emax     = 10.0
313
    enumbins = 1
314

    
315
    # Set model components that should be processed
316
    components = ["model_pi0", \
317
                  "model_ics", \
318
                  "model_pwne", \
319
                  "model_snrs", \
320
                  "model_tevcat", \
321
                  "model_cygnus"]
322

    
323
    # Set model components that should be co-added
324
    models = []
325
    models.append("model_pi0")
326
    models.append("model_ics")
327
    models.append("model_pwne")
328
    models.append("model_snrs")
329
    models.append("model_tevcat")
330
    models.append("model_cygnus")
331
    models.append("model_bkg")
332

    
333
    # Build names
334
    if emin < 1.0:
335
        estr = "%dGeV-%dTeV" % (emin*1.0e3, emax)
336
    else:
337
        estr = "%d-%dTeV" % (emin, emax)
338
    obsname = "%s.xml" % (name)
339
    expcube = "%s_expcube_%s.fits" % (name, estr)
340
    psfcube = "%s_psfcube_%s.fits" % (name, estr)
341
    bkgcube = "%s_bkgcube_%s.fits" % (name, estr)
342
    bkgmod  = "%s_bkgmodel_%s.xml" % (name, estr)
343
    bkgcomp = "%s_model_bkg_%s.fits" % (name, estr)
344
    evtmap  = "%s_events_%s.fits" % (name, estr)
345
    modmap  = "%s_model_%s.fits" % (name, estr)
346
    resmap  = "%s_residual_%s.fits" % (name, estr)
347
    dmodmap = "%s_diff_model_%s.fits" % (name, estr)
348
    devtmap = "%s_diff_events_%s.fits" % (name, estr)
349
    dresmap = "%s_diff_residual_%s.fits" % (name, estr)
350

    
351
    # Create response components (exposure, psf, background)
352
    create_response(obsname, "models/model_bkg.xml", \
353
                    emin=emin, emax=emax, enumbins=enumbins, \
354
                    expcube=expcube, psfcube=psfcube, \
355
                    bkgcube=bkgcube, bkgmod=bkgmod)
356

    
357
    # Create background model component
358
    create_model(expcube, psfcube, bkgcube, bkgmod, modcube=bkgcomp, \
359
                 emin=emin, emax=emax, enumbins=enumbins)
360

    
361
    # Create source model components
362
    for component in components:
363
        modname = "models/%s.xml" % (component)
364
        modcomp = "%s_%s_%s.fits" % (name, component, estr)
365
        create_model(expcube, psfcube, bkgcube, modname, modcube=modcomp, \
366
                     emin=emin, emax=emax, enumbins=enumbins)
367

    
368
    # Add components and flatten
369
    add_and_flatten(models, modmap, name, estr)
370

    
371
    # Simulate events
372
    simulate_events(modmap, evtmap)
373

    
374
    # Create residual map
375
    create_residual(evtmap, bkgcomp, resmap)