crab.py

Deil Christoph, 12/17/2012 10:52 AM

Download (5.21 KB)

 
1
"""
2
Published Crab nebula reference spectra.
3
========================================
4

5
The Crab is often used as a standard candle in gamma-ray astronomy.
6
Statements like "this source has a flux of 10 % Crab" or
7
"our sensitivity is 2 % Crab" are common.
8

9
Here we provide a reference of what the Crab flux actually is according
10
to several publications.
11

12
Really everyone should be using DEFAULT_REF = 'meyer', but actually
13
e.g. for CTA Konrad uses 'hegra' to state sensitivity in Crab units.
14
'hess_ecpl' is exceptionally bad and doesn't agree with the current
15
result we get for the Crab, the cutoff or curvature is at higher energies. 
16

17
Unless noted otherwise:
18
* diff_flux @ 1 TeV in units cm^-2 s^-1 TeV^-1
19
* int_flux > 1 TeV in units cm^-2 s^-1
20
"""
21
import logging
22
import numpy as np
23

    
24
# HESS publication: 2006A&A...457..899A
25
# Two models are fitted there, a PL and an ECPL
26
hess_pl = {'diff_flux': 3.45e-11,
27
           'index': 2.63,
28
           'int_flux': 2.26e-11}
29
# Note that for ecpl, the diff_flux is not
30
# the differential flux at 1 TeV, that you
31
# get by multiplying with exp(-e / cutoff)
32
hess_ecpl = {'diff_flux': 3.76e-11,
33
             'index': 2.39,
34
             'cutoff': 14.3,
35
             'int_flux': 2.27e-11}
36

    
37
# HEGRA publication : 2004ApJ...614..897A
38
hegra = {'diff_flux': 2.83e-11,
39
         'index': 2.62,
40
         'int_flux': 1.75e-11}
41

    
42
# Meyer et al. publication: 2010arXiv1008.4524M
43
# diff_flux and index were calculated numerically
44
# by hand at 1 TeV as a finite differene
45
meyer = {'diff_flux': 3.3457e-11,
46
         'index': 2.5362,
47
         'int_flux': 2.0744e-11}
48
refs = {'meyer': meyer,
49
        'hegra': hegra,
50
        'hess_pl': hess_pl,
51
        'hess_ecpl': hess_ecpl}
52

    
53
DEFAULT_REF = 'meyer'
54

    
55

    
56
def meyer(energy, energyFlux=False):
57
    """Differential Crab flux at a given energy (TeV).
58

59
    erg cm^-2 s^-1 if energyFlux=True
60
    cm^-1 s^-1 TeV^-1 if energyFlux=False
61

62
    @see: Meyer et al., 2010arXiv1008.4524M, Appendix D"""
63
    p = np.array([-0.00449161, 0, 0.0473174,
64
                  - 0.179475, -0.53616, -10.2708])
65
    log_e = np.log10(np.asarray(energy))
66
    log_f = np.poly1d(p)(log_e)
67
    f = 10 ** log_f
68
    if energyFlux:
69
        return f
70
    else:
71
        erg_to_ev = 624150947960.7719
72
        return 1e-12 * erg_to_ev * f / energy ** 2
73

    
74

    
75
def diff_flux(e=1, ref=DEFAULT_REF):
76
    """Differential Crab flux (cm^-2 s^-1 TeV^-1) at energy e (TeV)
77
    according to some reference publication"""
78
    if ref == 'hegra':
79
        f = hegra['diff_flux']
80
        g = hegra['index']
81
        return f * e ** (-g)
82
    elif ref == 'hess_pl':
83
        f = hess_pl['diff_flux']
84
        g = hess_pl['index']
85
        return f * e ** (-g)
86
    elif ref == 'hess_ecpl':
87
        f = hess_ecpl['diff_flux']
88
        g = hess_ecpl['index']
89
        e_c = hess_ecpl['cutoff']
90
        return f * e ** (-g) * np.exp(-e / e_c)
91
    elif ref == 'meyer':
92
        return meyer(e)
93
    else:
94
        raise ValueError('Unknown ref: %s' % ref)
95

    
96

    
97
def int_flux(e1=1, e2=1e4, ref=DEFAULT_REF):
98
    """Integral Crab flux (cm^-2 s^-1) in energy band e1 to e2 (TeV)
99
    according to some reference publication"""
100
    # @todo there are integration problems with e2=1e6.
101
    # test and use the integrator that works in log space!!!
102
    """
103
    In [36]: spec.crab.int_flux(0.2, 1e4, ref='hess_ecpl')
104
[  2.43196827e-10] [  2.61476507e-18]
105
Out[36]: array([  2.43196827e-10])
106

107
In [37]: spec.crab.int_flux(0.2, 1e5, ref='hess_ecpl')
108
Warning: The algorithm does not converge.  Roundoff error is detected
109
  in the extrapolation table.  It is assumed that the requested tolerance
110
  cannot be achieved, and that the returned result (if full_output = 1) is
111
  the best which can be obtained.
112
[  2.43283459e-10] [  4.37319063e-10]
113
Out[37]: array([  2.43283459e-10])
114

115
In [38]: spec.crab.int_flux(0.2, 1e6, ref='hess_ecpl')
116
[  6.40098358e-48] [  1.27271100e-47]
117
Out[38]: array([  6.40098358e-48])
118
    """
119
    from scipy.integrate import quad
120
    # @todo How does one usually handle 0-dim and 1-dim
121
    # arrays at the same time?
122
    e1, e2 = np.asarray(e1, dtype=float), np.asarray(e2, dtype=float)
123
    npoints = e1.size
124
    e1, e2 = e1.reshape(npoints), e2.reshape(npoints)
125
    I, I_err = np.empty_like(e1), np.empty_like(e2)
126
    for ii in range(npoints):
127
        I[ii], I_err[ii] = quad(diff_flux, e1[ii], e2[ii],
128
                                (ref), epsabs=1e-20)
129
    return I
130

    
131

    
132
def spectral_index(e=1, ref=DEFAULT_REF):
133
    """Spectral index (positive number) at energy e (TeV)"""
134
    # Compute spectral index as slope in log -- log
135
    # as a finite difference
136
    eps = 1 + 1e-3
137
    f1 = diff_flux(e, ref)
138
    f2 = diff_flux(eps * e, ref)
139
    return (np.log10(f1) - np.log10(f2)) / np.log10(eps)
140

    
141

    
142
def to_crab(f, apply_mask=True, min=1e-3, max=300):
143
    """Convert to Crab units"""
144
    f_crab_ref = int_flux(e1=1, ref='meyer')
145
    logging.info('Crab integral flux above 1 TeV according     '
146
                 'to Meyer et al. model ist {0} cm^-2 s^-1'
147
                 ''.format(f_crab_ref))
148
    # The 100 is to get % and the 1e4 is to convert Sensitivity
149
    # to cm^-2, Henning computes it in m^-2
150
    f_crab = 100 * f / 1e4 / f_crab_ref
151
    if apply_mask:
152
        # Get rid of invalid values (negative default and 0) and
153
        # also of very high values
154
        mask = (f_crab < min) | (f_crab > max)
155
        f_crab[mask] = np.nan
156
    return f_crab