show_spectrum_last.py

Diaz-Bahamondes Christian , 12/04/2020 12:07 PM

Download (8.26 KB)

 
1
#! /usr/bin/env python
2
# ==========================================================================
3
# Display spectrum generated by csspec
4
#
5
# Copyright (C) 2015-2020 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 sys
22
try:
23
    import matplotlib.pyplot as plt
24
    plt.figure()
25
    plt.close()
26
except (ImportError, RuntimeError):
27
    print('This script needs the "matplotlib" module')
28
    sys.exit()
29
try:
30
    import numpy as np
31
except ImportError:
32
    print('This script needs the "numpy" module')
33
    sys.exit()
34
import gammalib
35
import cscripts
36

    
37

    
38
# ===================================== #
39
# Extract the spectrum info from a file #
40
# ===================================== #
41
def get_spectrum_file(filename):
42
    """
43
    Extract the spectrum info from a file for plotting
44

45
    Parameters
46
    ----------
47
    filename : str
48
        Name of spectrum FITS file
49

50
    Returns
51
    -------
52
    spec : dict
53
        Python dictionary defining spectral plot parameters
54
    """
55
    # Read spectrum file    
56
    fits = gammalib.GFits(filename)
57

    
58
    # Return dictionary
59
    return get_spectrum_fits(fits)
60

    
61

    
62
# ============================================= #
63
# Extract the spectrum info from a GFits object #
64
# ============================================= #
65
def get_spectrum_fits(fits):
66
    """
67
    Extract the spectrum info from a GFits object
68

69
    Parameters
70
    ----------
71
    fits : `~gammalib.GFits`
72
        Spectral GFits object
73
    
74
    Returns
75
    -------
76
    spec : dict
77
        Python dictionary defining spectral plot parameters
78
    """
79
    # Read spectrum objects
80
    table    = fits.table(1)
81
    c_energy = table['e_ref']
82
    c_ed     = table['e_min']
83
    c_eu     = table['e_max']
84
    c_flux   = table['ref_e2dnde']
85
    c_norm   = table['norm']
86
    c_eflux  = table['norm_err']
87
    c_upper  = table['norm_ul']
88
    c_ts     = table['ts']
89

    
90
    # Initialise arrays to be filled
91
    spec = {
92
        'energies'    : [],
93
        'flux'        : [],
94
        'ed_engs'     : [],
95
        'eu_engs'     : [],
96
        'e_flux'      : [],
97
        'ul_energies' : [],
98
        'ul_ed_engs'  : [],
99
        'ul_eu_engs'  : [],
100
        'ul_flux'     : [],
101
        'yerr'        : [],
102
        'loglike'     : [],
103
        'engs_scan'   : [],
104
        'e2dnde_scan' : [],
105
        'dll_scan'    : []
106
    }
107

    
108
    # Determine if we can load the delta-log-likelihood profiles
109
    has_sedtype = table.has_card('SED_TYPE')
110
    load_dll    = False
111
    if has_sedtype:
112
        seds = table.card('SED_TYPE').string().split(',')
113

    
114
        # Load likelhood columns if present
115
        if seds[0] == 'likelihood':
116
            load_dll    = True
117
            c_loglike   = table['loglike']
118
            c_norm_scan = table['norm_scan']
119
            c_dll_scan  = table['dloglike_scan']
120

    
121
    # Loop over rows of the file
122
    nrows = table.nrows()
123
    for row in range(nrows):
124

    
125
        # Get Test Statistic, flux and flux error
126
        ts    = c_ts.real(row)
127
        norm  = c_norm.real(row)
128
        flx   = norm * c_flux.real(row)
129
        e_flx = flx * c_eflux.real(row)
130

    
131
        # If Test Statistic is larger than 9 and flux error is smaller than
132
        # flux then append flux plots ...
133
        if ts > 9.0 and e_flx < flx:
134
            spec['energies'].append(c_energy.real(row))
135
            spec['flux'].append(flx)
136
            spec['ed_engs'].append(c_ed.real(row))
137
            spec['eu_engs'].append(c_eu.real(row))
138
            spec['e_flux'].append(e_flx)
139

    
140
        # ... otherwise append upper limit
141
        else:
142
            spec['ul_energies'].append(c_energy.real(row))
143
            spec['ul_flux'].append(flx*c_upper.real(row))
144
            spec['ul_ed_engs'].append(c_ed.real(row))
145
            spec['ul_eu_engs'].append(c_eu.real(row))
146

    
147
    # Load the delta log-likelihood values
148
    if load_dll:
149
        spec['e2dnde_scan'] = np.zeros((nrows, c_norm_scan.elements(0)))
150
        spec['dll_scan']    = np.zeros((nrows, c_norm_scan.elements(0)))
151

    
152
        for row in range(nrows):
153
            loglike = c_loglike.real(row)
154
            spec['loglike'].append(loglike)
155
            spec['engs_scan'].append(c_energy.real(row) - c_ed.real(row))
156
            for col in range(c_norm_scan.elements(row)):
157
                spec['e2dnde_scan'][row,col] = c_norm_scan.real(row,col) * c_flux.real(row)
158
                spec['dll_scan'][row,col] = c_dll_scan.real(row,col)
159
        spec['engs_scan'].append(c_energy.real(nrows-1)+c_eu.real(nrows-1))
160

    
161
    # Set upper limit errors
162
    spec['yerr'] = [0.6 * x for x in spec['ul_flux']]
163

    
164
    # Return dictionary
165
    return spec
166

    
167

    
168
# ========================= #
169
# Plot delta log-likelihood #
170
# ========================= #
171
def plot_dloglike(spec):
172
    """
173
    Plot delta log-likelihood
174

175
    Parameters
176
    ----------
177
    spec : dict
178
        Python dictionary defining spectral plot parameters
179
    """
180
    # Establish the bounds on the x,y plot
181
    ymin,ymax = plt.gca().get_ylim()
182
    ymin      = np.log10(ymin)
183
    ymax      = np.log10(ymax)
184
    steps     = 1000
185
    ebins     = len(spec['e2dnde_scan'])
186
    y_bounds  = np.linspace(ymin, ymax, steps+1)
187

    
188
    # Compute the logarithmic center of each bin
189
    fluxpnts = 10 ** ((y_bounds[1:]+y_bounds[:-1]) / 2.0)
190
    
191
    # Scale the boundaries on the grid
192
    y_bounds = 10 ** y_bounds
193

    
194
    # Interpolate the dlogLike values
195
    dll_hist = [[]]*ebins
196
    for ebin in range(ebins):
197
        dll_hist[ebin] = np.interp(fluxpnts, spec['e2dnde_scan'][ebin], 
198
                                             spec['dll_scan'][ebin])
199

    
200
    # Transpose the dll_hist array so x=energy, y=dnde
201
    dll_hist = [[row[i] for row in dll_hist] for i in range(steps)]
202

    
203
    # Plot the likelihood profiles
204
    plt.pcolormesh(np.array(spec['engs_scan']), y_bounds,
205
                   np.array(dll_hist), vmin=-10.0, vmax=0.0,
206
                   cmap='Reds', alpha=0.9)
207
    cbar = plt.colorbar()
208
    cbar.set_label(r'$\Delta$ log-likelihood')
209
    plt.grid()
210

    
211
    # Return
212
    return
213

    
214

    
215
# ============= #
216
# Plot spectrum #
217
# ============= #
218
def plot_spectrum(filename, plotfile):
219
    """
220
    Plot spectrum
221

222
    Parameters
223
    ----------
224
    filename : str
225
        Name of spectrum FITS file
226
    plotfile : str
227
        Plot file name
228
    """
229
    # Get spectrum parameters
230
    spec = get_spectrum_file(filename)
231

    
232
    # Create the plot
233
    plt.figure()
234
    plt.loglog()
235
    plt.grid()
236
    plt.xlabel('Energy (TeV)')
237
    plt.ylabel(r'E$^2$ $\times$ dN/dE (erg cm$^{-2}$ s$^{-1}$)')
238

    
239
    # Plot the spectrum
240
    plt.errorbar(spec['energies'], spec['flux'], 
241
                 yerr=spec['e_flux'], xerr=[spec['ed_engs'], spec['eu_engs']],
242
                 fmt='ro')
243

    
244
    # Plot upper limits
245
    if len(spec['ul_energies'])        > 0:
246
        plt.errorbar(spec['ul_energies'], spec['ul_flux'], yerr=spec['yerr'],
247
                     xerr=[spec['ul_ed_engs'], spec['ul_eu_engs']],
248
                     uplims=True, fmt='ro')
249

    
250
    # Plot log-likelihood profiles
251
    if len(spec['dll_scan']) > 0:
252
        plot_dloglike(spec)
253

    
254
    # Show figure
255
    if len(plotfile) > 0:
256
        plt.savefig(plotfile)
257
    else:
258
        plt.show()
259

    
260
    # Return
261
    return
262

    
263

    
264
# ============= #
265
# Show spectrum #
266
# ============= #
267
def show_spectrum():
268
    """
269
    Show spectrum
270
    """
271
    # Set usage string
272
    usage = 'show_spectrum.py [-p plotfile] [file]'
273

    
274
    # Set default options
275
    options = [{'option': '-p', 'value': ''}]
276

    
277
    # Get arguments and options from command line arguments
278
    args, options = cscripts.ioutils.get_args_options(options, usage)
279

    
280
    # Extract script parameters from options
281
    plotfile = options[0]['value']
282

    
283
    # Show spectrum
284
    plot_spectrum(args[0], plotfile)
285

    
286
    # Return
287
    return
288

    
289

    
290
# ======================== #
291
# Main routine entry point #
292
# ======================== #
293
if __name__ == '__main__':
294

    
295
    # Show spectrum
296
    show_spectrum()