1 | # Licensed under a 3-clause BSD style license - see LICENSE.rst |
||
2 | """Dark matter spectra.""" |
||
3 | from __future__ import absolute_import, division, print_function, unicode_literals |
||
4 | import numpy as np |
||
5 | from astropy.units import Quantity |
||
6 | from astropy.table import Table |
||
7 | from astropy.utils import lazyproperty |
||
8 | from ...utils.scripts import make_path |
||
9 | from ...spectrum.models import TableModel |
||
10 | |||
11 | __all__ = ["PrimaryFlux"] |
||
12 | |||
13 | |||
14 | class PrimaryFlux(object): |
||
0 ignored issues
–
show
Unused Code
introduced
by
Loading history...
|
|||
15 | """DM-annihilation gamma-ray spectra. |
||
16 | |||
17 | Based on the precomputed models by `Cirelli et al. |
||
18 | <http://www.marcocirelli.net/PPPC4DMID.html>`_. All available |
||
19 | annihilation channels can be found there. The dark matter mass will be set |
||
20 | to the nearest available value. The spectra will be available as |
||
21 | `~gammapy.spectrum.models.TableModel` for a chosen dark matter mass and |
||
22 | annihilation channel. |
||
23 | |||
24 | References |
||
25 | ---------- |
||
26 | * `2011JCAP...03..051 <http://adsabs.harvard.edu/abs/2011JCAP...03..051>`_ |
||
27 | """ |
||
28 | |||
29 | channel_registry = { |
||
30 | "eL": "eL", |
||
31 | "eR": "eR", |
||
32 | "e": "e", |
||
33 | "muL": "\\[Mu]L", |
||
34 | "muR": "\\[Mu]R", |
||
35 | "mu": "\\[Mu]", |
||
36 | "tauL": "\\[Tau]L", |
||
37 | "tauR": "\\[Tau]R", |
||
38 | "tau": "\\[Tau]", |
||
39 | "q": "q", |
||
40 | "c": "c", |
||
41 | "b": "b", |
||
42 | "t": "t", |
||
43 | "WL": "WL", |
||
44 | "WT": "WT", |
||
45 | "W": "W", |
||
46 | "ZL": "ZL", |
||
47 | "ZT": "ZT", |
||
48 | "Z": "Z", |
||
49 | "g": "g", |
||
50 | "gamma": "\\[Gamma]", |
||
51 | "h": "h", |
||
52 | "nu_e": "\\[Nu]e", |
||
53 | "nu_mu": "\\[Nu]\\[Mu]", |
||
54 | "nu_tau": "\\[Nu]\\[Tau]", |
||
55 | "V->e": "V->e", |
||
56 | "V->mu": "V->\\[Mu]", |
||
57 | "V->tau": "V->\\[Tau]", |
||
58 | } |
||
59 | |||
60 | def __init__(self, mDM, channel): |
||
61 | self.mDM = mDM |
||
62 | self.channel = channel |
||
63 | |||
64 | @lazyproperty |
||
65 | def table(self): |
||
66 | """Lookup table (`~astropy.table.Table`).""" |
||
67 | filename = "$GAMMAPY_DATA/dark_matter_spectra/AtProduction_gammas.dat" |
||
68 | return Table.read( |
||
69 | str(make_path(filename)), |
||
70 | format="ascii.fast_basic", |
||
71 | guess=False, |
||
72 | delimiter=" ", |
||
73 | ) |
||
74 | |||
75 | @property |
||
76 | def mDM(self): |
||
77 | """Dark matter mass.""" |
||
78 | return self._mDM |
||
79 | |||
80 | @mDM.setter |
||
81 | def mDM(self, mDM): |
||
82 | mDM_vals = self.table["mDM"].data |
||
83 | mDM_ = Quantity(mDM).to_value("GeV") |
||
84 | interp_idx = np.argmin(np.abs(mDM_vals - mDM_)) |
||
85 | self._mDM = Quantity(mDM_vals[interp_idx], "GeV") |
||
0 ignored issues
–
show
|
|||
86 | |||
87 | @property |
||
88 | def allowed_channels(self): |
||
89 | """List of allowed annihilation channels.""" |
||
90 | return list(self.channel_registry.keys()) |
||
91 | |||
92 | @property |
||
93 | def channel(self): |
||
94 | """Annihilation channel (str).""" |
||
95 | return self._channel |
||
96 | |||
97 | @channel.setter |
||
98 | def channel(self, channel): |
||
99 | if channel not in self.allowed_channels: |
||
100 | msg = "Invalid channel {}\n" |
||
101 | msg += "Available: {}\n" |
||
102 | raise ValueError(msg.format(channel, self.allowed_channels)) |
||
103 | else: |
||
104 | self._channel = channel |
||
0 ignored issues
–
show
|
|||
105 | |||
106 | @property |
||
107 | def table_model(self): |
||
108 | """Spectrum as `~gammapy.spectrum.models.TableModel`.""" |
||
109 | subtable = self.table[self.table["mDM"] == self.mDM.value] |
||
110 | energies = (10 ** subtable["Log[10,x]"]) * self.mDM |
||
111 | channel_name = self.channel_registry[self.channel] |
||
112 | dN_dlogx = subtable[channel_name] |
||
113 | dN_dE = dN_dlogx / (energies * np.log(10)) |
||
114 | |||
115 | return TableModel(energy=energies, values=dN_dE, values_scale="lin") |
||
116 |