show_model_mc.py

Knödlseder Jürgen, 11/22/2018 11:04 AM

Download (10.1 KB)

 
1
#! /usr/bin/env python
2
# ==========================================================================
3
# Show simulation - model for a given model
4
#
5
# Copyright (C) 2018 Juergen Knoedlseder
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
#
20
# ==========================================================================
21
import os
22
import math
23
import gammalib
24
import ctools
25
import cscripts
26
from cscripts import obsutils
27
import matplotlib.pyplot as plt
28

    
29

    
30
# ====================== #
31
# Plot residual spectrum #
32
# ====================== #
33
def plot_resspec(frame, energies, resspec, errspec, emin=0.1, emax=100.0):
34
    """
35
    Plot residual spectrum
36

37
    Parameters
38
    ----------
39
    frame : pyplot
40
        Frame for spectrum
41
    """
42
    # Set axes scales and limit
43
    frame.set_xscale('log')
44
    frame.set_xlim([emin, emax])
45

    
46
    # Counts and model
47
    frame.errorbar(energies, resspec, yerr=errspec,
48
                   fmt='ko', capsize=0, linewidth=2, zorder=2, label='Data')
49
    frame.plot(frame.get_xlim(),[0,0], 'r-')
50
    frame.set_xlabel('Energy (TeV)')
51
    frame.set_ylabel('Simulation - Model')
52

    
53
    # Return
54
    return
55

    
56

    
57
# ================= #
58
# Plot residual map #
59
# ================= #
60
def plot_resmap(plt1, plt2, map, error, steps=1):
61
    """
62
    Plot pull histogram
63

64
    Parameters
65
    ----------
66
    plt1 : pyplot
67
        Frame for first map
68
    plt2 : pyplot
69
        Frame for second map
70
    map : `~gammalib.GSkyMap()`
71
        Sky map
72
    error : `~gammalib.GSkyMap()`
73
        Sky map
74
    steps : int
75
        Number of steps for rebinning
76
    """
77
    # Create longitude array from skymap
78
    x_lon = []
79
    y_lon = []
80
    e_lon = []
81
    for ix in range(0, map.nx(), steps):
82
        value = 0.0
83
        err   = 0.0
84
        for istep in range(steps):
85
            if istep+ix < map.nx():
86
                for iy in range(map.ny()):
87
                    index  = istep+ix+iy*map.nx()
88
                    value += map[index]
89
                    err   += error[index]*error[index]
90
        x_lon.append(ix)
91
        y_lon.append(value)
92
        e_lon.append(math.sqrt(err))
93

    
94
    # Create latitude array from skymap
95
    x_lat = []
96
    y_lat = []
97
    e_lat = []
98
    for iy in range(0, map.ny(), steps):
99
        value = 0.0
100
        err   = 0.0
101
        for istep in range(steps):
102
            if istep+iy < map.ny():
103
                for ix in range(map.nx()):
104
                    index  = ix+(istep+iy)*map.nx()
105
                    value += map[index]
106
                    err   += error[index]*error[index]
107
        x_lat.append(iy)
108
        y_lat.append(value)
109
        e_lat.append(math.sqrt(err))
110

    
111
    # Plot longitude distribution
112
    plt1.errorbar(x_lon, y_lon, yerr=e_lon,
113
                  fmt='ko', capsize=0, linewidth=2, zorder=2)
114
    plt1.axhline(0, color='r', linestyle='--')
115
    plt1.set_xlabel('Right Ascension (pixels)')
116
    plt1.set_ylabel('Simulation - Model')
117
    plt1.grid(True)
118

    
119
    # Plot latitude distribution
120
    plt2.errorbar(x_lat, y_lat, yerr=e_lat,
121
                  fmt='ko', capsize=0, linewidth=2, zorder=2)
122
    plt2.axhline(0, color='r', linestyle='--')
123
    plt2.set_xlabel('Declination (pixels)')
124
    plt2.set_ylabel('Simulation - Model')
125
    plt2.grid(True)
126

    
127
    # Return
128
    return
129

    
130

    
131
# ======== #
132
# Plot map #
133
# ======== #
134
def plot_map(frame, map, smooth=0.0):
135
    """
136
    Plot Aitoff map
137

138
    Parameters
139
    ----------
140
    frame : pyplot
141
        Frame for map
142
    map : `~gammalib.GSkyMap()`
143
        Sky map
144
    smooth : float, optional
145
        Map smoothing parameter (degrees)
146
    """
147
    # Optionally smooth map
148
    if smooth > 0.0:
149
        _map = map.copy()
150
        _map.smooth('DISK', smooth)
151
    else:
152
        _map = map
153
    
154
    # Create array from skymap
155
    array = []
156
    v_max = 0.0
157
    for iy in range(_map.ny()):
158
        row = []
159
        for ix in range(_map.nx()):
160
            index = ix+iy*_map.nx()
161
            value = _map[index]
162
            row.append(value)
163
        array.append(row)
164

    
165
    # Show Aitoff projection
166
    c = frame.imshow(array, aspect=1.0)
167
    cbar = plt.colorbar(c, orientation='vertical', shrink=0.7)
168
    frame.grid(True)
169
    frame.set_xlabel('Right Ascension (pixels)')
170
    frame.set_ylabel('Declination (pixels)')
171

    
172
    # Return
173
    return
174

    
175

    
176
# =========================== #
177
# Determine spatial residuals #
178
# =========================== #
179
def residual_spatial(countscube, modelcube):
180
    """
181
    Determine spatial residuals
182

183
    Parameters
184
    ----------
185
    countscube : `~gammalib.GCTAEventCube`
186
        Simulated counts cube
187
    modelcube : `~gammalib.GCTAEventCube`
188
        Model cube
189

190
    Returns
191
    -------
192
    map, error : `~gammalib.GSkyMap()`
193
        Residual sky map and error
194
    """
195
    # Get model cube maps
196
    map1 = countscube.counts()
197
    map2 = modelcube.counts()
198

    
199
    # Generate residual map
200
    map = map1 - map2
201
    map.stack_maps()
202

    
203
    # Generate residual error bars
204
    error = map2.copy()
205
    error.stack_maps()
206
    error = error.sqrt()
207

    
208
    # Return residual map and error map
209
    return map, error
210

    
211

    
212
# ============================ #
213
# Determine spectral residuals #
214
# ============================ #
215
def residual_spectral(countscube, modelcube):
216
    """
217
    Determine spectral residuals
218

219
    Parameters
220
    ----------
221
    countscube : `~gammalib.GCTAEventCube`
222
        Simulated counts cube
223
    modelcube : `~gammalib.GCTAEventCube`
224
        Model cube
225

226
    Returns
227
    -------
228
    map, error : list
229
        Residual vector
230
    """
231
    # Get model cube maps
232
    map1 = countscube.counts()
233
    map2 = modelcube.counts()
234

    
235
    # Compute spectra
236
    spec1    = []
237
    spec2    = []
238
    residual = []
239
    error    = []
240
    energies = []
241
    for ieng in range(map1.nmaps()):
242
        sum1 = 0.0
243
        sum2 = 0.0
244
        for ipix in range(map1.npix()):
245
            sum1 += map1[ipix, ieng]
246
            sum2 += map2[ipix, ieng]
247
        spec1.append(sum1)
248
        spec2.append(sum2)
249
        residual.append(sum1 - sum2)
250
        error.append(math.sqrt(sum2))
251
        energies.append(modelcube.energy(ieng).TeV())
252

    
253
    # Return residual and error
254
    return energies, residual, error
255

    
256

    
257
# ==================== #
258
# Simulate counts cube #
259
# ==================== #
260
def simulate_counts_cube(obs, ra=83.63, dec=22.01, npix=50, binsz=0.02,
261
                         emin=0.1, emax=100.0, ebins=20, seed=1, edisp=False):
262
    """
263
    Simulate counts cube
264

265
    Parameters
266
    ----------
267
    obs : `~gammalib.GObservations`
268
        Observation container
269
    ebins : int, optional
270
        Number of energy bins for binned or stacked analysis
271
    edisp : boolean, optional
272
        Use energy dispersion
273
    """
274
    # Simulate events
275
    ctobssim = ctools.ctobssim(obs)
276
    ctobssim['seed']  = seed
277
    ctobssim['edisp'] = edisp
278
    ctobssim.run()
279
    
280
    # Create counts cube
281
    ctbin = ctools.ctbin(ctobssim.obs())
282
    ctbin['stack']    = True
283
    ctbin['ebinalg']  = 'LOG'
284
    ctbin['emin']     = emin
285
    ctbin['emax']     = emax
286
    ctbin['enumbins'] = ebins
287
    ctbin['coordsys'] = 'CEL'
288
    ctbin['proj']     = 'CAR'
289
    ctbin['xref']     = ra
290
    ctbin['yref']     = dec
291
    ctbin['nxpix']    = npix
292
    ctbin['nypix']    = npix
293
    ctbin['binsz']    = binsz
294
    ctbin.run()
295

    
296
    # Return counts cube
297
    return ctbin.cube().copy()
298

    
299

    
300
# ================= #
301
# Create model cube #
302
# ================= #
303
def create_model_cube(obs, countscube, edisp=False):
304
    """
305
    Create model cube
306

307
    Parameters
308
    ----------
309
    obs : `~gammalib.GObservations`
310
        Observation container
311
    countscube : `~gammalib.GCTAEventCube`
312
        Counts cube for binning
313
    edisp : boolean, optional
314
        Use energy dispersion
315
    """
316
    # Create model cube
317
    ctmodel = ctools.ctmodel(obs)
318
    ctmodel.cube(countscube)
319
    ctmodel['edisp'] = edisp
320
    ctmodel.run()
321

    
322
    # Return model cube
323
    return ctmodel.cube().copy()
324

    
325

    
326
# ================= #
327
# Show model and MC #
328
# ================= #
329
def show_model_mc(modelname, duration=180000.0, caldb='prod2', irf='South_50h',
330
                  ebins=20, edisp=False):
331
    """
332
    """
333
    # Set pointing direction
334
    pntdir = gammalib.GSkyDir()
335
    pntdir.radec_deg(83.63, 22.01)
336
    
337
    # Set single CTA observation
338
    run = obsutils.set_obs(pntdir, duration=duration, caldb=caldb, irf=irf)
339

    
340
    # Set observation container
341
    obs = gammalib.GObservations()
342
    obs.append(run)
343

    
344
    # Load and append model
345
    models = gammalib.GModels(modelname)
346
    obs.models(models)
347

    
348
    # Create simulated counts cube
349
    countscube = simulate_counts_cube(obs, npix=400, binsz=0.002, ebins=ebins,
350
                                      edisp=edisp)
351
    print(countscube)
352

    
353
    # Create model cube
354
    modelcube = create_model_cube(obs, countscube, edisp=edisp)
355
    print(modelcube)
356

    
357
    # Create residual map and spectrum
358
    resmap, errmap             = residual_spatial(countscube, modelcube)
359
    energies, resspec, errspec = residual_spectral(countscube, modelcube)
360

    
361
    # Create figure
362
    fig = plt.figure(figsize=(14,5))
363

    
364
    # Create subplot for residual spectrum
365
    frame1 = fig.add_subplot(131)
366
    plot_resspec(frame1, energies, resspec, errspec, emin=0.05, emax=150.0)
367

    
368
    # Create subplots for residual profiles
369
    frame2 = fig.add_subplot(232)
370
    frame3 = fig.add_subplot(235)
371
    plot_resmap(frame2, frame3, resmap, errmap, steps=5)
372

    
373
    # Create subplot for residual map
374
    frame4 = fig.add_subplot(133)
375
    plot_map(frame4, resmap, smooth=0.02)
376

    
377
    # Show figure
378
    plt.show()
379

    
380
    # Return
381
    return
382

    
383

    
384
# ======================== #
385
# Main routine entry point #
386
# ======================== #
387
if __name__ == '__main__':
388

    
389
    # Set model name
390
    modelname = 'crab.xml'
391

    
392
    # Show model and MC
393
    #show_model_mc(modelname, ebins=50, edisp=False)
394
    show_model_mc(modelname, ebins=50, edisp=True)