Merge lp:~maddm/maddm/no_numpy_scipy into lp:maddm
- no_numpy_scipy
- Merge into release
Proposed by
Olivier Mattelaer
Status: | Superseded |
---|---|
Proposed branch: | lp:~maddm/maddm/no_numpy_scipy |
Merge into: | lp:maddm |
Diff against target: |
255 lines (+87/-24) 3 files modified
__init__.py (+1/-1) maddm_interface.py (+5/-0) maddm_run_interface.py (+81/-23) |
To merge this branch: | bzr merge lp:~maddm/maddm/no_numpy_scipy |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Federico Ambrogi | Pending | ||
Review via email: mp+345140@code.launchpad.net |
Commit message
Avoid direct crash if numpy/scipy are not present on the system.
-> forbids indirect detection but allows relic density computation and direct detection.
This allows to have maddm v2 options still working in version 3 even if numpy/scipy are not available.
Description of the change
To post a comment you must log in.
lp:~maddm/maddm/no_numpy_scipy
updated
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '__init__.py' | |||
2 | --- __init__.py 2018-03-30 22:19:49 +0000 | |||
3 | +++ __init__.py 2018-05-06 15:24:43 +0000 | |||
4 | @@ -16,6 +16,6 @@ | |||
5 | 16 | new_reweight = {'indirect': MGoutput.Indirect_Reweight} | 16 | new_reweight = {'indirect': MGoutput.Indirect_Reweight} |
6 | 17 | 17 | ||
7 | 18 | ## The test/code have been validated up to this version | 18 | ## The test/code have been validated up to this version |
9 | 19 | latest_validated_version = (2,6,2) | 19 | latest_validated_version = (2,6,3) |
10 | 20 | minimal_mg5amcnlo_version = (2,6,2) | 20 | minimal_mg5amcnlo_version = (2,6,2) |
11 | 21 | maximal_mg5amcnlo_version = (1000,1000,1000) | 21 | maximal_mg5amcnlo_version = (1000,1000,1000) |
12 | 22 | 22 | ||
13 | === modified file 'maddm_interface.py' | |||
14 | --- maddm_interface.py 2018-04-29 20:55:19 +0000 | |||
15 | +++ maddm_interface.py 2018-05-06 15:24:43 +0000 | |||
16 | @@ -115,6 +115,11 @@ | |||
17 | 115 | def post_install_PPPC4DMID(self): | 115 | def post_install_PPPC4DMID(self): |
18 | 116 | if os.path.exists(pjoin(MG5DIR, 'PPPC4DMID')): | 116 | if os.path.exists(pjoin(MG5DIR, 'PPPC4DMID')): |
19 | 117 | self.options['pppc4dmid_path'] = pjoin(MG5DIR, 'PPPC4DMID') | 117 | self.options['pppc4dmid_path'] = pjoin(MG5DIR, 'PPPC4DMID') |
20 | 118 | |||
21 | 119 | if not maddm_run_interface.HAS_SCIPY: | ||
22 | 120 | logger.critical("PPC4DMID module requires scipy to be working. Please install those python module. (they are not present)") | ||
23 | 121 | logger.info("you can try to use \"pip install scipy\"") | ||
24 | 122 | |||
25 | 118 | return | 123 | return |
26 | 119 | 124 | ||
27 | 120 | def set_configuration(self, config_path=None, final=True, **opts): | 125 | def set_configuration(self, config_path=None, final=True, **opts): |
28 | 121 | 126 | ||
29 | === modified file 'maddm_run_interface.py' | |||
30 | --- maddm_run_interface.py 2018-04-29 20:53:38 +0000 | |||
31 | +++ maddm_run_interface.py 2018-05-06 15:24:43 +0000 | |||
32 | @@ -10,12 +10,7 @@ | |||
33 | 10 | import stat | 10 | import stat |
34 | 11 | import shutil | 11 | import shutil |
35 | 12 | 12 | ||
42 | 13 | from scipy.interpolate import interp1d | 13 | |
37 | 14 | from scipy.integrate import quad | ||
38 | 15 | from scipy.optimize import minimize_scalar | ||
39 | 16 | from scipy.optimize import brute | ||
40 | 17 | from scipy.optimize import fmin | ||
41 | 18 | from scipy.special import gammainc | ||
43 | 19 | 14 | ||
44 | 20 | import MGoutput | 15 | import MGoutput |
45 | 21 | from madgraph import MadGraph5Error | 16 | from madgraph import MadGraph5Error |
46 | @@ -34,18 +29,36 @@ | |||
47 | 34 | 29 | ||
48 | 35 | #import darkmatter as darkmatter | 30 | #import darkmatter as darkmatter |
49 | 36 | 31 | ||
51 | 37 | import numpy as np | 32 | logger = logging.getLogger('madgraph.plugin.maddm') |
52 | 38 | 33 | ||
53 | 39 | try: | 34 | try: |
54 | 40 | import pymultinest | 35 | import pymultinest |
60 | 41 | except: | 36 | except ImportError: |
61 | 42 | print('WARNING: Multinest module not found! All multinest parameter scanning features will be disabled.') | 37 | pass |
62 | 43 | 38 | ||
63 | 44 | 39 | try: | |
64 | 45 | #import types | 40 | from scipy.interpolate import interp1d |
65 | 41 | from scipy.integrate import quad | ||
66 | 42 | from scipy.special import gammainc | ||
67 | 43 | except ImportError, error: | ||
68 | 44 | print error | ||
69 | 45 | logger.warning('scipy module not found! Some Indirect detection features will be disabled.') | ||
70 | 46 | HAS_SCIPY = False | ||
71 | 47 | else: | ||
72 | 48 | HAS_SCIPY = True | ||
73 | 49 | |||
74 | 50 | try: | ||
75 | 51 | import numpy as np | ||
76 | 52 | except ImportError: | ||
77 | 53 | logger.warning('numpy module not found! Indirect detection features will be disabled.') | ||
78 | 54 | HAS_NUMPY = False | ||
79 | 55 | else: | ||
80 | 56 | HAS_NUMPY = True | ||
81 | 57 | |||
82 | 58 | class ModuleMissing(Exception): pass | ||
83 | 46 | 59 | ||
84 | 47 | pjoin = os.path.join | 60 | pjoin = os.path.join |
86 | 48 | logger = logging.getLogger('madgraph.plugin.maddm') | 61 | |
87 | 49 | logger_tuto = logging.getLogger('tutorial_plugin') | 62 | logger_tuto = logging.getLogger('tutorial_plugin') |
88 | 50 | #logger.setLevel(10) #level 20 = INFO | 63 | #logger.setLevel(10) #level 20 = INFO |
89 | 51 | 64 | ||
90 | @@ -111,14 +124,18 @@ | |||
91 | 111 | self._sigma_ID[item] = -1.0 | 124 | self._sigma_ID[item] = -1.0 |
92 | 112 | self._sigma_ID_width[item] = -1.0 | 125 | self._sigma_ID_width[item] = -1.0 |
93 | 113 | 126 | ||
95 | 114 | self.load_constraints() | 127 | if HAS_NUMPY: |
96 | 128 | self.load_constraints() | ||
97 | 129 | |||
98 | 115 | 130 | ||
99 | 116 | logger.info('Loaded experimental constraints. To change, use the set command') | 131 | logger.info('Loaded experimental constraints. To change, use the set command') |
100 | 117 | logger.info('Omega h^2 = %.4e +- %.4e' %(self._oh2_planck, self._oh2_planck_width)) | 132 | logger.info('Omega h^2 = %.4e +- %.4e' %(self._oh2_planck, self._oh2_planck_width)) |
105 | 118 | logger.info('Spin Independent cross section: %s' % self._dd_si_limit_file) | 133 | if HAS_NUMPY: |
106 | 119 | logger.info('Spin Dependent cross section (p): %s' % self._dd_sd_proton_limit_file) | 134 | logger.info('Spin Independent cross section: %s' % self._dd_si_limit_file) |
107 | 120 | logger.info('Spin Dependent cross section (n): %s' % self._dd_sd_neutron_limit_file) | 135 | logger.info('Spin Dependent cross section (p): %s' % self._dd_sd_proton_limit_file) |
108 | 121 | 136 | logger.info('Spin Dependent cross section (n): %s' % self._dd_sd_neutron_limit_file) | |
109 | 137 | else: | ||
110 | 138 | logger.info('Spin (in)dependent not available due to the missing python module: numpy') | ||
111 | 122 | # for chan in self._allowed_final_states: | 139 | # for chan in self._allowed_final_states: |
112 | 123 | # logger.info('Indirect Detection cross section for final state %s at velocity %.2e: %s'\ | 140 | # logger.info('Indirect Detection cross section for final state %s at velocity %.2e: %s'\ |
113 | 124 | # % (chan, self._id_limit_vel[chan] ,self._id_limit_file[chan])) | 141 | # % (chan, self._id_limit_vel[chan] ,self._id_limit_file[chan])) |
114 | @@ -146,6 +163,10 @@ | |||
115 | 146 | 163 | ||
116 | 147 | #Returns a value in cm^2 | 164 | #Returns a value in cm^2 |
117 | 148 | def SI_max(self, mdm): | 165 | def SI_max(self, mdm): |
118 | 166 | if not HAS_NUMPY: | ||
119 | 167 | logger.warning("missing numpy module for SI limit") | ||
120 | 168 | return __infty__ | ||
121 | 169 | |||
122 | 149 | if (mdm < np.min(self._dd_si_limit_mDM) or mdm > np.max(self._dd_si_limit_mDM)): | 170 | if (mdm < np.min(self._dd_si_limit_mDM) or mdm > np.max(self._dd_si_limit_mDM)): |
123 | 150 | logger.warning('Dark matter mass value '+str(mdm)+' is outside the range of SI limit') | 171 | logger.warning('Dark matter mass value '+str(mdm)+' is outside the range of SI limit') |
124 | 151 | return __infty__ | 172 | return __infty__ |
125 | @@ -154,6 +175,10 @@ | |||
126 | 154 | 175 | ||
127 | 155 | #Returns a value in cm^2 | 176 | #Returns a value in cm^2 |
128 | 156 | def SD_max(self,mdm, nucleon): | 177 | def SD_max(self,mdm, nucleon): |
129 | 178 | if not HAS_NUMPY: | ||
130 | 179 | logger.warning("missing numpy module for SD limit") | ||
131 | 180 | return __infty__ | ||
132 | 181 | |||
133 | 157 | if nucleon not in ['n','p']: | 182 | if nucleon not in ['n','p']: |
134 | 158 | logger.error('nucleon can only be p or n') | 183 | logger.error('nucleon can only be p or n') |
135 | 159 | return __infty__ | 184 | return __infty__ |
136 | @@ -173,6 +198,9 @@ | |||
137 | 173 | 198 | ||
138 | 174 | #Returns a value in cm^3/s | 199 | #Returns a value in cm^3/s |
139 | 175 | def ID_max(self,mdm, channel): | 200 | def ID_max(self,mdm, channel): |
140 | 201 | if not HAS_NUMPY: | ||
141 | 202 | logger.warning("missing numpy module for ID limit") | ||
142 | 203 | return __infty__ | ||
143 | 176 | if (mdm < np.min(self._id_limit_mdm[channel]) or mdm > np.max(self._id_limit_mdm[channel])): | 204 | if (mdm < np.min(self._id_limit_mdm[channel]) or mdm > np.max(self._id_limit_mdm[channel])): |
144 | 177 | logger.warning('Dark matter mass value %.2e for channel %s is outside the range of ID limit' % (mdm, channel)) | 205 | logger.warning('Dark matter mass value %.2e for channel %s is outside the range of ID limit' % (mdm, channel)) |
145 | 178 | return __infty__ | 206 | return __infty__ |
146 | @@ -267,6 +295,10 @@ | |||
147 | 267 | # this function extracts the values of the spectra interpolated linearly between two values mdm_1 and mdm_2 | 295 | # this function extracts the values of the spectra interpolated linearly between two values mdm_1 and mdm_2 |
148 | 268 | # mdm is the DM candidate mass, spectrum is gammas, positron etc, channel is the SM annihilation e.g. bbar, hh etc. | 296 | # mdm is the DM candidate mass, spectrum is gammas, positron etc, channel is the SM annihilation e.g. bbar, hh etc. |
149 | 269 | def interpolate_spectra(self, sp_dic, mdm = '', spectrum = '' , channel = '' , earth = False , prof = 'Ein' , prop = 'MED' , halo_func = 'MF1'): | 297 | def interpolate_spectra(self, sp_dic, mdm = '', spectrum = '' , channel = '' , earth = False , prof = 'Ein' , prop = 'MED' , halo_func = 'MF1'): |
150 | 298 | |||
151 | 299 | if not HAS_SCIPY: | ||
152 | 300 | raise ModuleMissing('scipy module is required for this functionality.') | ||
153 | 301 | |||
154 | 270 | M = sp_dic['Masses'] | 302 | M = sp_dic['Masses'] |
155 | 271 | dm_min = max([m for m in M if m <= mdm]) # extracting lower mass limit to interpolate from | 303 | dm_min = max([m for m in M if m <= mdm]) # extracting lower mass limit to interpolate from |
156 | 272 | dm_max = min([m for m in M if m >= mdm]) # extracting upper mass limit to interpolate from | 304 | dm_max = min([m for m in M if m >= mdm]) # extracting upper mass limit to interpolate from |
157 | @@ -306,7 +338,8 @@ | |||
158 | 306 | self.dSph_ll_files_path = pjoin(MDMDIR, 'Fermi_Data', 'likelihoods') | 338 | self.dSph_ll_files_path = pjoin(MDMDIR, 'Fermi_Data', 'likelihoods') |
159 | 307 | self.dwarves_list = ['coma_berenices', 'draco', 'segue_1', 'ursa_major_II', 'ursa_minor', 'reticulum_II' ] # dSphs with the 6 highest Jfactors | 339 | self.dwarves_list = ['coma_berenices', 'draco', 'segue_1', 'ursa_major_II', 'ursa_minor', 'reticulum_II' ] # dSphs with the 6 highest Jfactors |
160 | 308 | self.dwarveslist_all = self.extract_dwarveslist() | 340 | self.dwarveslist_all = self.extract_dwarveslist() |
162 | 309 | self.dw_in = self.dw_dic() | 341 | if HAS_NUMPY: |
163 | 342 | self.dw_in = self.dw_dic() | ||
164 | 310 | self.ll_tot = '' | 343 | self.ll_tot = '' |
165 | 311 | 344 | ||
166 | 312 | # This function reads the list of dwarves from the Jfactor.dat file | 345 | # This function reads the list of dwarves from the Jfactor.dat file |
167 | @@ -363,6 +396,10 @@ | |||
168 | 363 | def eflux(self,spectrum, emin=1e2, emax=1e5, quiet=False): | 396 | def eflux(self,spectrum, emin=1e2, emax=1e5, quiet=False): |
169 | 364 | """ Integrate a generic spectrum, multiplied by E, to get the energy flux. | 397 | """ Integrate a generic spectrum, multiplied by E, to get the energy flux. |
170 | 365 | """ | 398 | """ |
171 | 399 | |||
172 | 400 | if not HAS_SCIPY: | ||
173 | 401 | raise ModuleMissing('scipy module is required for this functionality.') | ||
174 | 402 | |||
175 | 366 | espectrum = lambda e: spectrum(e)*e | 403 | espectrum = lambda e: spectrum(e)*e |
176 | 367 | tol = min(espectrum(emin),espectrum(emax))*1e-10 | 404 | tol = min(espectrum(emin),espectrum(emax))*1e-10 |
177 | 368 | try: | 405 | try: |
178 | @@ -373,6 +410,9 @@ | |||
179 | 373 | 410 | ||
180 | 374 | def marg_like_dw(self,dw_in_i,pred,marginalize): | 411 | def marg_like_dw(self,dw_in_i,pred,marginalize): |
181 | 375 | 412 | ||
182 | 413 | if not HAS_SCIPY: | ||
183 | 414 | raise ModuleMissing('scipy module is required for this functionality.') | ||
184 | 415 | |||
185 | 376 | j0, nBin = self.j0 , self.nBin | 416 | j0, nBin = self.j0 , self.nBin |
186 | 377 | 417 | ||
187 | 378 | j,jerr,like_inter = dw_in_i['Jfac'], dw_in_i['Jfac_err'], dw_in_i['likelihood'] | 418 | j,jerr,like_inter = dw_in_i['Jfac'], dw_in_i['Jfac_err'], dw_in_i['likelihood'] |
188 | @@ -403,6 +443,9 @@ | |||
189 | 403 | 443 | ||
190 | 404 | def res_tot_dw(self,pred,marginalize): | 444 | def res_tot_dw(self,pred,marginalize): |
191 | 405 | 445 | ||
192 | 446 | if not HAS_SCIPY: | ||
193 | 447 | raise ModuleMissing('scipy module is required for this functionality.') | ||
194 | 448 | |||
195 | 406 | dw_in = self.dw_in | 449 | dw_in = self.dw_in |
196 | 407 | ll_tot = 0.0 | 450 | ll_tot = 0.0 |
197 | 408 | ll_null = 0.0 | 451 | ll_null = 0.0 |
198 | @@ -437,6 +480,13 @@ | |||
199 | 437 | def Fermi_sigmav_lim(self, mDM, x = '' , dndlogx = '' , marginalize = True, sigmav_th = False , maj_dirac='', \ | 480 | def Fermi_sigmav_lim(self, mDM, x = '' , dndlogx = '' , marginalize = True, sigmav_th = False , maj_dirac='', \ |
200 | 438 | sigmavmin=1e-35, sigmavmax=1e-15, step_size_scaling=1.0, cl_val = 0.95): | 481 | sigmavmin=1e-35, sigmavmax=1e-15, step_size_scaling=1.0, cl_val = 0.95): |
201 | 439 | 482 | ||
202 | 483 | if not HAS_NUMPY: | ||
203 | 484 | logger.warning("Fermi limit ignored due to missing numpy module") | ||
204 | 485 | return -1 | ||
205 | 486 | if not HAS_SCIPY: | ||
206 | 487 | logger.warning("Fermi limit ignored due to missing scipy module") | ||
207 | 488 | return -1 | ||
208 | 489 | |||
209 | 440 | np.seterr(divide='ignore', invalid='ignore') # Keep numpy from complaining about dN/dE = 0... | 490 | np.seterr(divide='ignore', invalid='ignore') # Keep numpy from complaining about dN/dE = 0... |
210 | 441 | j0 , nBin = self.j0 , self.nBin | 491 | j0 , nBin = self.j0 , self.nBin |
211 | 442 | 492 | ||
212 | @@ -1226,8 +1276,8 @@ | |||
213 | 1226 | sp_name = sp + '_spectrum_pythia8.dat' | 1276 | sp_name = sp + '_spectrum_pythia8.dat' |
214 | 1227 | out_dir = pjoin(self.dir_path,'Indirect', 'Events', run_name, sp_name ) | 1277 | out_dir = pjoin(self.dir_path,'Indirect', 'Events', run_name, sp_name ) |
215 | 1228 | if sp == 'gammas': # x values are the same for all the spectra | 1278 | if sp == 'gammas': # x values are the same for all the spectra |
218 | 1229 | x = np.loadtxt(out_dir , unpack = True )[0] | 1279 | x = np.loadtxt(out_dir , unpack = True )[0] |
219 | 1230 | self.Spectra.spectra['x'] = [ np.power(10,num) for num in x] # from log[10,x] to x | 1280 | self.Spectra.spectra['x'] = [ np.power(10,num) for num in x] # from log[10,x] to x |
220 | 1231 | self.Spectra.spectra[sp] = np.loadtxt(out_dir , unpack = True )[1].tolist() | 1281 | self.Spectra.spectra[sp] = np.loadtxt(out_dir , unpack = True )[1].tolist() |
221 | 1232 | 1282 | ||
222 | 1233 | 1283 | ||
223 | @@ -1239,6 +1289,10 @@ | |||
224 | 1239 | logger.error('PPPC4DMID not installed. Please install by typing "install PPPC4DMID".') | 1289 | logger.error('PPPC4DMID not installed. Please install by typing "install PPPC4DMID".') |
225 | 1240 | return | 1290 | return |
226 | 1241 | 1291 | ||
227 | 1292 | if not HAS_SCIPY: | ||
228 | 1293 | logger.error('using PPPC4DMID requires scipy module. Please install it (for example with "pip install scipy")') | ||
229 | 1294 | return | ||
230 | 1295 | |||
231 | 1242 | if 'PPPC4DMID' in self.maddm_card['indirect_flux_source_method'] or 'inclusive' in self.maddm_card['sigmav_method']: | 1296 | if 'PPPC4DMID' in self.maddm_card['indirect_flux_source_method'] or 'inclusive' in self.maddm_card['sigmav_method']: |
232 | 1243 | if self.Spectra.check_mass(mdm): | 1297 | if self.Spectra.check_mass(mdm): |
233 | 1244 | if '_ew' in self.maddm_card['indirect_flux_source_method']: | 1298 | if '_ew' in self.maddm_card['indirect_flux_source_method']: |
234 | @@ -2356,7 +2410,9 @@ | |||
235 | 2356 | def set_default_indirect(self): | 2410 | def set_default_indirect(self): |
236 | 2357 | """set the default value for relic=""" | 2411 | """set the default value for relic=""" |
237 | 2358 | 2412 | ||
239 | 2359 | if self.availmode['has_indirect_detection']: | 2413 | if not HAS_NUMPY: |
240 | 2414 | self.switch['indirect'] = 'Not Avail. (numpy missing)' | ||
241 | 2415 | elif self.availmode['has_indirect_detection']: | ||
242 | 2360 | self.switch['indirect'] = 'sigmav' | 2416 | self.switch['indirect'] = 'sigmav' |
243 | 2361 | else: | 2417 | else: |
244 | 2362 | self.switch['indirect'] = 'Not Avail.' | 2418 | self.switch['indirect'] = 'Not Avail.' |
245 | @@ -2368,7 +2424,9 @@ | |||
246 | 2368 | if hasattr(self, 'allowed_indirect'): | 2424 | if hasattr(self, 'allowed_indirect'): |
247 | 2369 | return getattr(self, 'allowed_indirect') | 2425 | return getattr(self, 'allowed_indirect') |
248 | 2370 | 2426 | ||
250 | 2371 | if self.availmode['has_indirect_detection']: | 2427 | if not HAS_NUMPY: |
251 | 2428 | self.allowed_indirect = ['OFF'] | ||
252 | 2429 | elif self.availmode['has_indirect_detection']: | ||
253 | 2372 | self.allowed_indirect = ['OFF', 'sigmav', 'flux_source', 'flux_earth'] | 2430 | self.allowed_indirect = ['OFF', 'sigmav', 'flux_source', 'flux_earth'] |
254 | 2373 | else: | 2431 | else: |
255 | 2374 | return [] | 2432 | return [] |