TransitionListener 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- transitionlistener/__init__.py +21 -0
- transitionlistener/bubbledynamics.py +2250 -0
- transitionlistener/bubbledynamics_fixedstep.py +2929 -0
- transitionlistener/check_installation.py +309 -0
- transitionlistener/ckm.py +91 -0
- transitionlistener/colors.py +288 -0
- transitionlistener/config.py +185 -0
- transitionlistener/constants.py +64 -0
- transitionlistener/counterterms/__init__.py +230 -0
- transitionlistener/counterterms/cw.py +298 -0
- transitionlistener/counterterms/tensors.py +343 -0
- transitionlistener/counterterms/twohdm.py +520 -0
- transitionlistener/counterterms/twohdm_solver.py +374 -0
- transitionlistener/errors.py +315 -0
- transitionlistener/examples/bp_et.yaml +64 -0
- transitionlistener/examples/bp_lisa.yaml +70 -0
- transitionlistener/examples/bp_muares.yaml +69 -0
- transitionlistener/examples/bp_pta.yaml +64 -0
- transitionlistener/examples/example_dark_photon.yaml +73 -0
- transitionlistener/examples/example_grid.yaml +55 -0
- transitionlistener/examples/example_line.yaml +51 -0
- transitionlistener/examples/example_point.yaml +73 -0
- transitionlistener/examples/example_random_conformal.yaml +42 -0
- transitionlistener/examples/example_ultranest.yaml +39 -0
- transitionlistener/finiteT.py +468 -0
- transitionlistener/generic_potential.py +1521 -0
- transitionlistener/gridplots.py +592 -0
- transitionlistener/gwfopt.py +604 -0
- transitionlistener/helper_functions.py +843 -0
- transitionlistener/hydrodynamics.py +647 -0
- transitionlistener/interface/__init__.py +95 -0
- transitionlistener/interface/check.py +51 -0
- transitionlistener/interface/cli.py +211 -0
- transitionlistener/interface/config_loader.py +264 -0
- transitionlistener/interface/logging_utils.py +30 -0
- transitionlistener/interface/output_schema.py +296 -0
- transitionlistener/interface/pipeline.py +300 -0
- transitionlistener/interface/samplers.py +565 -0
- transitionlistener/interface/scans.py +468 -0
- transitionlistener/interface/single_point.py +581 -0
- transitionlistener/interface/state.py +61 -0
- transitionlistener/lineplots.py +597 -0
- transitionlistener/logo/TL-logo_large.png +0 -0
- transitionlistener/logo/TL-logo_small.png +0 -0
- transitionlistener/models/TL_2HDM.py +512 -0
- transitionlistener/models/TL_conformal_dark_u1.py +202 -0
- transitionlistener/models/TL_dark_U1.py +198 -0
- transitionlistener/models/TL_dark_U1_g_parameterization.py +198 -0
- transitionlistener/models/TL_dark_flipflop.py +274 -0
- transitionlistener/models/templatePotential.py +260 -0
- transitionlistener/nucleation.py +412 -0
- transitionlistener/observability.py +790 -0
- transitionlistener/particles.py +436 -0
- transitionlistener/pathDeformation.py +1462 -0
- transitionlistener/percolation_adaptive_gridbuilders.py +1385 -0
- transitionlistener/percolation_adaptive_rate.py +1049 -0
- transitionlistener/percolation_adaptivestepsize.py +1632 -0
- transitionlistener/percolation_fixedstepsize.py +618 -0
- transitionlistener/phases.py +1499 -0
- transitionlistener/plot_settings.py +121 -0
- transitionlistener/plots.py +1781 -0
- transitionlistener/runtime_options.py +278 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/bandwidths.npy +0 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/density.npy +0 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/freqs.npy +0 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log.txt +16 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log10rhogrid.npy +0 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log10rholabels.txt +30 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/pulsar_list.txt +1 -0
- transitionlistener/tab_data/HLV-O2-PLI.csv +82 -0
- transitionlistener/tab_data/HLV-O2-noise.csv +83 -0
- transitionlistener/tab_data/HLVK-design-PLI.csv +61 -0
- transitionlistener/tab_data/HLVK-design-noise.csv +83 -0
- transitionlistener/tab_data/NG15_PLI_hc.csv +31 -0
- transitionlistener/tab_data/NG15_noise_hc.csv +56 -0
- transitionlistener/tab_data/PLI-dataset.csv +327 -0
- transitionlistener/tab_data/energydensities.dat +1001 -0
- transitionlistener/tab_data/finiteT_b.dat.txt +1999 -0
- transitionlistener/tab_data/finiteT_f.dat.txt +1000 -0
- transitionlistener/tab_data/geff_SM.dat +10009 -0
- transitionlistener/tab_data/muAres_f_Hz_PLI_h2OmegaGW.csv +131 -0
- transitionlistener/tab_data/muAres_f_Hz_h2Omega_noise.csv +99 -0
- transitionlistener/tab_data/noise-dataset.csv +327 -0
- transitionlistener/tab_data/numberdensities.dat +1001 -0
- transitionlistener/tab_data/pressures.dat +1001 -0
- transitionlistener/thermodynamics.py +686 -0
- transitionlistener/transitionObservables.py +1199 -0
- transitionlistener/transitionObservables_fixedstep.py +976 -0
- transitionlistener/transitions.py +1000 -0
- transitionlistener/tunneling1D.py +910 -0
- transitionlistener-2.0.0.dist-info/METADATA +817 -0
- transitionlistener-2.0.0.dist-info/RECORD +95 -0
- transitionlistener-2.0.0.dist-info/WHEEL +4 -0
- transitionlistener-2.0.0.dist-info/entry_points.txt +2 -0
- transitionlistener-2.0.0.dist-info/licenses/LICENSE.txt +674 -0
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
"""Sampler integrations and helpers for TransitionListener.
|
|
2
|
+
|
|
3
|
+
Part of TransitionListener v2.0
|
|
4
|
+
Documentation: https://tasillo.de/TransitionListener/
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Jonas Matuszak <jonas.matuszak@kit.edu>
|
|
8
|
+
Carlo Tasillo <carlo.tasillo@ific.uv.es>
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import glob
|
|
14
|
+
import os
|
|
15
|
+
import shutil
|
|
16
|
+
from typing import Dict
|
|
17
|
+
import numpy as np
|
|
18
|
+
import pandas as pd
|
|
19
|
+
|
|
20
|
+
from ultranest import ReactiveNestedSampler
|
|
21
|
+
|
|
22
|
+
from transitionlistener.observability import PTA_LIKELIHOOD_SETTINGS
|
|
23
|
+
from transitionlistener.helper_functions import import_file, load_potential
|
|
24
|
+
|
|
25
|
+
from . import state
|
|
26
|
+
from .logging_utils import Logger
|
|
27
|
+
from .output_schema import OutputSchema, OutputRandomscan
|
|
28
|
+
from .pipeline import run_TL
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
PTA_LABELS = tuple(PTA_LIKELIHOOD_SETTINGS.keys())
|
|
32
|
+
MPI_RANK_ENV_VARS = (
|
|
33
|
+
"OMPI_COMM_WORLD_RANK",
|
|
34
|
+
"PMI_RANK",
|
|
35
|
+
"PMIX_RANK",
|
|
36
|
+
"SLURM_PROCID",
|
|
37
|
+
"RANK",
|
|
38
|
+
"I_MPI_RANK",
|
|
39
|
+
"MPI_LOCALRANKID",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def scanfunc(input, verbose: bool = False) -> dict:
|
|
44
|
+
"""Wrapper used by worker processes to execute a single scan point."""
|
|
45
|
+
inputparams_dict, modelfile, potential_name, outpath, timeout = input
|
|
46
|
+
potential = load_potential(modelfile, potential_name)
|
|
47
|
+
errorlogger = Logger(outpath + "error.log")
|
|
48
|
+
resultlogger = Logger(outpath + "result.log")
|
|
49
|
+
return run_TL(
|
|
50
|
+
inputparams_dict,
|
|
51
|
+
potential,
|
|
52
|
+
errorlogger,
|
|
53
|
+
resultlogger,
|
|
54
|
+
timeout,
|
|
55
|
+
verbose=verbose,
|
|
56
|
+
call_from_sampler=False,
|
|
57
|
+
include_smbhb=False,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def sample_and_export_to_csv(args):
|
|
62
|
+
"""Evaluate a single parameter point and append the
|
|
63
|
+
outcome to ``output_table.csv``."""
|
|
64
|
+
inputparams_dict, modelfile, potential_name, output_path, derived_params, timeout = args
|
|
65
|
+
|
|
66
|
+
potential = load_potential(modelfile, potential_name)
|
|
67
|
+
errorlogger = Logger(output_path + "error.log")
|
|
68
|
+
resultlogger = Logger(output_path + "result.log")
|
|
69
|
+
|
|
70
|
+
res = call_by_sampler(potential, inputparams_dict, errorlogger,
|
|
71
|
+
resultlogger, timeout, verbose=False, include_smbhb=False)
|
|
72
|
+
res_params = extract_parameters(res, derived_params)
|
|
73
|
+
|
|
74
|
+
schema = OutputSchema(potential, derived_params.keys())
|
|
75
|
+
output_file = _ranked_output_file(output_path + "output_table.csv")
|
|
76
|
+
schema.append_row(output_file, inputparams_dict, res_params)
|
|
77
|
+
|
|
78
|
+
# Return only the PTArcade log-likelihood value for sampler use
|
|
79
|
+
lnL_value = res_params.get("PTArcade_lnL", np.nan)
|
|
80
|
+
return pd.Series([lnL_value], name="lnL")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def rand_listener(q, output_path, derived_params) -> None:
|
|
84
|
+
"""Listener which appends the output to a file.
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
q : multiprocessing.Manager.Queue
|
|
90
|
+
output_path : str
|
|
91
|
+
Path to the output. The output file is ouput_path + output_table.csv
|
|
92
|
+
derived_params : dict
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
None."""
|
|
97
|
+
output_file = output_path + "output_table.csv"
|
|
98
|
+
outputter = OutputRandomscan(output_file)
|
|
99
|
+
while True:
|
|
100
|
+
message = q.get()
|
|
101
|
+
if message == 'kill':
|
|
102
|
+
outputter.stop()
|
|
103
|
+
break
|
|
104
|
+
try:
|
|
105
|
+
inputparams_dict, res_params = message
|
|
106
|
+
outputter.write_row(inputparams_dict, res_params)
|
|
107
|
+
except Exception as e:
|
|
108
|
+
print(e)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def rand_worker(inp_params, q):
|
|
112
|
+
"""Worker for the random scan.
|
|
113
|
+
|
|
114
|
+
Puts the results in the queue.
|
|
115
|
+
|
|
116
|
+
Parameters
|
|
117
|
+
----------
|
|
118
|
+
inp_params : tuple
|
|
119
|
+
Tuple with all the input parameters
|
|
120
|
+
q : multiprocessing.Manager.Queue
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
None."""
|
|
125
|
+
inputparams_dict, modelfile, potential_name, output_path, derived_params, timeout = inp_params
|
|
126
|
+
|
|
127
|
+
potential = load_potential(modelfile, potential_name)
|
|
128
|
+
errorlogger = Logger(output_path + "error.log")
|
|
129
|
+
resultlogger = Logger(output_path + "result.log")
|
|
130
|
+
|
|
131
|
+
res = call_by_sampler(potential, inputparams_dict, errorlogger,
|
|
132
|
+
resultlogger, timeout, verbose=False, include_smbhb=False)
|
|
133
|
+
|
|
134
|
+
# this is a bad temporary fix.
|
|
135
|
+
# However I think generalising this would require a lot of refactoring
|
|
136
|
+
# Dont return the masses, that makes everything complicated. They can
|
|
137
|
+
# be computed easily after the scans.
|
|
138
|
+
if res["error"] != 0:
|
|
139
|
+
errcode = res["error"]
|
|
140
|
+
errms = res["errormsg"]
|
|
141
|
+
res_params = get_empty_result()
|
|
142
|
+
res_params["error"] = errcode
|
|
143
|
+
res_params["errormsg"] = ""
|
|
144
|
+
else:
|
|
145
|
+
res_params = extract_parameters(res, derived_params)
|
|
146
|
+
|
|
147
|
+
res = (inputparams_dict, res_params)
|
|
148
|
+
q.put(res)
|
|
149
|
+
return res
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def call_by_sampler(potential: object, inputparams_dict: dict,
|
|
153
|
+
errorlogger: Logger, resultlogger: Logger,
|
|
154
|
+
timeout: float, verbose: bool = False, include_smbhb: bool = False):
|
|
155
|
+
"""Evaluate TransitionListener for external samplers and return the result dictionary."""
|
|
156
|
+
res = {'error': 0}
|
|
157
|
+
res['errormsg'] = ""
|
|
158
|
+
state.TIMEOUT = int(timeout)
|
|
159
|
+
|
|
160
|
+
if state.DEBUGMODE:
|
|
161
|
+
run_TL(
|
|
162
|
+
inputparams_dict,
|
|
163
|
+
potential,
|
|
164
|
+
errorlogger,
|
|
165
|
+
resultlogger,
|
|
166
|
+
timeout,
|
|
167
|
+
verbose=verbose,
|
|
168
|
+
call_from_sampler=True,
|
|
169
|
+
include_smbhb=include_smbhb,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
try:
|
|
173
|
+
all_params_dict = run_TL(
|
|
174
|
+
inputparams_dict,
|
|
175
|
+
potential,
|
|
176
|
+
errorlogger,
|
|
177
|
+
resultlogger,
|
|
178
|
+
timeout,
|
|
179
|
+
verbose=verbose,
|
|
180
|
+
call_from_sampler=True,
|
|
181
|
+
include_smbhb=include_smbhb,
|
|
182
|
+
)
|
|
183
|
+
res["all_params_dict"] = all_params_dict
|
|
184
|
+
|
|
185
|
+
except Exception as err:
|
|
186
|
+
if hasattr(err, 'errorcode') and err.errorcode is not None:
|
|
187
|
+
line = (
|
|
188
|
+
"ERROR in TransitionListener of type "
|
|
189
|
+
+ str(err.errorcode)
|
|
190
|
+
+ " for input parameters "
|
|
191
|
+
+ str(inputparams_dict)
|
|
192
|
+
+ ": "
|
|
193
|
+
+ getattr(err, 'message', str(err))
|
|
194
|
+
)
|
|
195
|
+
res['errormsg'] = line
|
|
196
|
+
res['error'] = err.errorcode
|
|
197
|
+
else:
|
|
198
|
+
line = (
|
|
199
|
+
"ERROR in TransitionListener of type -1 for input parameters "
|
|
200
|
+
+ str(inputparams_dict)
|
|
201
|
+
+ ": "
|
|
202
|
+
+ getattr(err, 'message', str(err))
|
|
203
|
+
)
|
|
204
|
+
res['errormsg'] = line
|
|
205
|
+
res['error'] = -1
|
|
206
|
+
return res
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def extract_parameters(res: dict, derived_params: dict, mainPTA: str = "NG15_14bins") -> Dict[str, float]:
|
|
210
|
+
"""Extract the parameters from the result dictionary."""
|
|
211
|
+
|
|
212
|
+
def _to_primitive(value):
|
|
213
|
+
"""Convert numpy scalars and arrays to Python primitives for CSV output."""
|
|
214
|
+
if isinstance(value, (np.bool_, bool)):
|
|
215
|
+
return bool(value)
|
|
216
|
+
if isinstance(value, (np.integer,)):
|
|
217
|
+
return int(value)
|
|
218
|
+
if isinstance(value, (np.floating,)):
|
|
219
|
+
return float(value)
|
|
220
|
+
if isinstance(value, (float, int, bool, str)):
|
|
221
|
+
return value
|
|
222
|
+
if isinstance(value, np.ndarray):
|
|
223
|
+
if value.size == 1:
|
|
224
|
+
return _to_primitive(value.flatten()[0])
|
|
225
|
+
return np.nan
|
|
226
|
+
if value is None:
|
|
227
|
+
return np.nan
|
|
228
|
+
return value
|
|
229
|
+
|
|
230
|
+
params: Dict[str, float] = {}
|
|
231
|
+
|
|
232
|
+
error_value = res.get("error", np.nan)
|
|
233
|
+
if isinstance(error_value, np.ndarray):
|
|
234
|
+
error_value = error_value.flatten()[0] if error_value.size else np.nan
|
|
235
|
+
params["error"] = _to_primitive(error_value)
|
|
236
|
+
params["errormsg"] = str(res.get("errormsg", ""))
|
|
237
|
+
params["PTArcade_lnL"] = -np.inf
|
|
238
|
+
params["smoothened_lnL"] = -np.inf
|
|
239
|
+
params["mock_lnL"] = -np.inf
|
|
240
|
+
params["lnL"] = -np.inf
|
|
241
|
+
|
|
242
|
+
if params["error"] == 0:
|
|
243
|
+
all_params_dict = res.get("all_params_dict", {})
|
|
244
|
+
strongest = all_params_dict.get("strongestTransitionObservables", {})
|
|
245
|
+
observability = all_params_dict.get("observability", {})
|
|
246
|
+
|
|
247
|
+
for name in derived_params.keys():
|
|
248
|
+
if name in strongest:
|
|
249
|
+
params[name] = _to_primitive(strongest[name])
|
|
250
|
+
elif name in observability:
|
|
251
|
+
params[name] = _to_primitive(observability[name])
|
|
252
|
+
else:
|
|
253
|
+
params[name] = np.nan
|
|
254
|
+
|
|
255
|
+
main_pta_key = f"lnL_PTArcade_{mainPTA}"
|
|
256
|
+
params["PTArcade_lnL"] = _to_primitive(
|
|
257
|
+
observability.get(
|
|
258
|
+
main_pta_key,
|
|
259
|
+
observability.get(f"lnL_{mainPTA}", -np.inf),
|
|
260
|
+
)
|
|
261
|
+
)
|
|
262
|
+
smooth_key = f"lnL_smooth_{mainPTA}"
|
|
263
|
+
params["smoothened_lnL"] = _to_primitive(
|
|
264
|
+
observability.get(smooth_key, -np.inf)
|
|
265
|
+
)
|
|
266
|
+
mock_key = f"lnL_mock_{mainPTA}"
|
|
267
|
+
params["mock_lnL"] = _to_primitive(
|
|
268
|
+
observability.get(mock_key, -np.inf)
|
|
269
|
+
)
|
|
270
|
+
params["lnL"] = params["PTArcade_lnL"]
|
|
271
|
+
|
|
272
|
+
for label in PTA_LABELS:
|
|
273
|
+
smooth_src = f"lnL_smooth_{label}"
|
|
274
|
+
if smooth_src in observability:
|
|
275
|
+
params[f"lnL_smoothened_{label}"] = _to_primitive(observability[smooth_src])
|
|
276
|
+
|
|
277
|
+
ptarcade_src = f"lnL_PTArcade_{label}"
|
|
278
|
+
if ptarcade_src in observability:
|
|
279
|
+
params[f"lnL_PTArcade_{label}"] = _to_primitive(observability[ptarcade_src])
|
|
280
|
+
|
|
281
|
+
mock_src = f"lnL_mock_{label}"
|
|
282
|
+
if mock_src in observability:
|
|
283
|
+
params[f"lnL_mock_{label}"] = _to_primitive(observability[mock_src])
|
|
284
|
+
|
|
285
|
+
lin_renames = {
|
|
286
|
+
"f_peak_Hz_lin": "f_peak_Hz",
|
|
287
|
+
"h2OmegaGW_peak_lin": "h2OmegaGW_peak",
|
|
288
|
+
"f_pivot_Hz_lin": "f_pivot_Hz",
|
|
289
|
+
"h2OmegaGW_at_pivot_lin": "h2OmegaGW_at_pivot",
|
|
290
|
+
}
|
|
291
|
+
skip_exact = {
|
|
292
|
+
"DNeff_GW_lin",
|
|
293
|
+
"DNeff_GW_log10",
|
|
294
|
+
"DNeff_GW_latex",
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
for key, value in observability.items():
|
|
298
|
+
if key in params:
|
|
299
|
+
continue
|
|
300
|
+
|
|
301
|
+
if key in lin_renames:
|
|
302
|
+
params[lin_renames[key]] = _to_primitive(value)
|
|
303
|
+
continue
|
|
304
|
+
|
|
305
|
+
if key in skip_exact:
|
|
306
|
+
continue
|
|
307
|
+
if key.endswith("_detectable"):
|
|
308
|
+
continue
|
|
309
|
+
if key.endswith("_latex") or key.endswith("_log10"):
|
|
310
|
+
continue
|
|
311
|
+
if key.startswith("lnL_") and not key.startswith("lnL_PTArcade_"):
|
|
312
|
+
continue
|
|
313
|
+
if key.startswith("delta_lnL_") or key.startswith("sigma_") or key.startswith("within_3sigma_"):
|
|
314
|
+
continue
|
|
315
|
+
|
|
316
|
+
params[key] = _to_primitive(value)
|
|
317
|
+
return params
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def log_likelihood(args):
|
|
321
|
+
"""Evaluate the nested-sampling log-likelihood for a given parameter vector."""
|
|
322
|
+
inputparams_dict = {name: val for name, val in zip(state.config.scan_params, args)}
|
|
323
|
+
|
|
324
|
+
transformation_file = getattr(state.config, "transformation_file", None)
|
|
325
|
+
if transformation_file is not None:
|
|
326
|
+
transform_module = import_file(transformation_file)
|
|
327
|
+
transform_scan_params = transform_module.transform_scan_params
|
|
328
|
+
inputparams_dict = transform_scan_params(inputparams_dict)
|
|
329
|
+
|
|
330
|
+
if state.config.other_params is not None:
|
|
331
|
+
inputparams_dict.update(state.config.other_params)
|
|
332
|
+
|
|
333
|
+
res = call_by_sampler(
|
|
334
|
+
state.potential,
|
|
335
|
+
inputparams_dict,
|
|
336
|
+
state.errorlogger,
|
|
337
|
+
state.resultlogger,
|
|
338
|
+
state.TIMEOUT,
|
|
339
|
+
verbose=False,
|
|
340
|
+
include_smbhb=False,
|
|
341
|
+
)
|
|
342
|
+
params = extract_parameters(res, state.config.derived_params)
|
|
343
|
+
|
|
344
|
+
schema = OutputSchema(state.model, state.config.derived_params.keys())
|
|
345
|
+
output_file = _ranked_output_file(state.config.output_path + "output_table.csv")
|
|
346
|
+
schema.append_row(output_file, inputparams_dict, params)
|
|
347
|
+
|
|
348
|
+
if params["error"] != 0:
|
|
349
|
+
return -1e100
|
|
350
|
+
smooth_value = params.get("smoothened_lnL", -np.inf)
|
|
351
|
+
if not np.isfinite(smooth_value):
|
|
352
|
+
return -1e100
|
|
353
|
+
return smooth_value
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def prior_transform(cube):
|
|
357
|
+
"""Transforms the unit cube to the prior space."""
|
|
358
|
+
params = cube.copy()
|
|
359
|
+
for i, name in enumerate(state.config.scan_params.keys()):
|
|
360
|
+
prior = state.config.scan_params[name]["range"]
|
|
361
|
+
|
|
362
|
+
try:
|
|
363
|
+
low = float(prior[0])
|
|
364
|
+
except ValueError:
|
|
365
|
+
low = eval(prior[0])
|
|
366
|
+
|
|
367
|
+
try:
|
|
368
|
+
high = float(prior[1])
|
|
369
|
+
except ValueError:
|
|
370
|
+
high = eval(prior[1])
|
|
371
|
+
|
|
372
|
+
if state.config.scan_params[name]["scale"] == "log":
|
|
373
|
+
params[i] = 10 ** (np.log10(low) + cube[i] * (np.log10(high) - np.log10(low)))
|
|
374
|
+
else:
|
|
375
|
+
params[i] = low + cube[i] * (high - low)
|
|
376
|
+
return params
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def ultranest(conf):
|
|
380
|
+
"""Run the Ultranest sampler."""
|
|
381
|
+
_prepare_ultranest_output_dir(conf)
|
|
382
|
+
state.errorlogger = Logger(conf.output_path + "error.log")
|
|
383
|
+
state.resultlogger = Logger(conf.output_path + "result.log")
|
|
384
|
+
state.TIMEOUT = conf.timeout
|
|
385
|
+
state.config = conf
|
|
386
|
+
points_file = os.path.join(conf.output_path, "results", "points.hdf5")
|
|
387
|
+
try:
|
|
388
|
+
sampler = ReactiveNestedSampler(
|
|
389
|
+
list(conf.scan_params.keys()),
|
|
390
|
+
log_likelihood,
|
|
391
|
+
prior_transform,
|
|
392
|
+
log_dir=conf.output_path,
|
|
393
|
+
resume=conf.resume_mode,
|
|
394
|
+
vectorized=False,
|
|
395
|
+
draw_multiple=False,
|
|
396
|
+
ndraw_min=1,
|
|
397
|
+
ndraw_max=1,
|
|
398
|
+
)
|
|
399
|
+
except OSError as exc:
|
|
400
|
+
if (
|
|
401
|
+
conf.resume_mode in (True, "resume", "resume-similar")
|
|
402
|
+
and os.path.exists(points_file)
|
|
403
|
+
and "truncated file" in str(exc)
|
|
404
|
+
):
|
|
405
|
+
raise ValueError(
|
|
406
|
+
"UltraNest could not resume because the stored point file is corrupted: "
|
|
407
|
+
f"{points_file}. Delete that file or set `resume_mode: overwrite` in the "
|
|
408
|
+
"YAML to start a fresh run."
|
|
409
|
+
) from exc
|
|
410
|
+
raise
|
|
411
|
+
|
|
412
|
+
sampler.run(
|
|
413
|
+
min_num_live_points=200,
|
|
414
|
+
dKL=25.0,
|
|
415
|
+
max_ncalls=300_000,
|
|
416
|
+
min_ess=2000,
|
|
417
|
+
frac_remain=0.01,
|
|
418
|
+
dlogz=5,
|
|
419
|
+
log_interval=1,
|
|
420
|
+
show_status=True,
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _prepare_ultranest_output_dir(conf) -> None:
|
|
425
|
+
"""Clean UltraNest-generated output files when starting a fresh run."""
|
|
426
|
+
if conf.resume_mode != "overwrite":
|
|
427
|
+
return
|
|
428
|
+
|
|
429
|
+
rank = _current_mpi_rank()
|
|
430
|
+
if rank == 0:
|
|
431
|
+
files_to_remove = (
|
|
432
|
+
"debug.log",
|
|
433
|
+
"error.log",
|
|
434
|
+
"result.log",
|
|
435
|
+
"output_table.csv",
|
|
436
|
+
)
|
|
437
|
+
for filename in files_to_remove:
|
|
438
|
+
path = os.path.join(conf.output_path, filename)
|
|
439
|
+
if os.path.exists(path):
|
|
440
|
+
os.remove(path)
|
|
441
|
+
|
|
442
|
+
for path in glob.glob(os.path.join(conf.output_path, "output_table_rank*.csv")):
|
|
443
|
+
if os.path.isfile(path):
|
|
444
|
+
os.remove(path)
|
|
445
|
+
|
|
446
|
+
for dirname in ("results", "chains", "plots"):
|
|
447
|
+
path = os.path.join(conf.output_path, dirname)
|
|
448
|
+
if os.path.isdir(path):
|
|
449
|
+
shutil.rmtree(path)
|
|
450
|
+
|
|
451
|
+
try:
|
|
452
|
+
from mpi4py import MPI
|
|
453
|
+
comm = MPI.COMM_WORLD
|
|
454
|
+
if comm.Get_size() > 1:
|
|
455
|
+
comm.Barrier()
|
|
456
|
+
except Exception:
|
|
457
|
+
pass
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def _current_mpi_rank() -> int:
|
|
461
|
+
"""Best-effort detection of the current MPI rank from environment variables."""
|
|
462
|
+
for env_var in MPI_RANK_ENV_VARS:
|
|
463
|
+
value = os.environ.get(env_var)
|
|
464
|
+
if value is not None:
|
|
465
|
+
try:
|
|
466
|
+
return int(value)
|
|
467
|
+
except ValueError:
|
|
468
|
+
continue
|
|
469
|
+
return 0
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def _ranked_output_file(base_file: str) -> str:
|
|
473
|
+
"""Return a rank-specific filename to avoid concurrent writes."""
|
|
474
|
+
root, ext = os.path.splitext(base_file)
|
|
475
|
+
rank = _current_mpi_rank()
|
|
476
|
+
return f"{root}_rank{rank:03d}{ext}"
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
def get_empty_result() -> dict:
|
|
480
|
+
"""Return an empty result for the random scan.
|
|
481
|
+
This is neccessary when the potential initialisation
|
|
482
|
+
fails
|
|
483
|
+
|
|
484
|
+
Parameters
|
|
485
|
+
----------
|
|
486
|
+
|
|
487
|
+
Returns
|
|
488
|
+
-------
|
|
489
|
+
dict :
|
|
490
|
+
The result with np.nans """
|
|
491
|
+
res = {'error': 0,
|
|
492
|
+
'errormsg': '',
|
|
493
|
+
'PTArcade_lnL': np.nan,
|
|
494
|
+
'smoothened_lnL': np.nan,
|
|
495
|
+
'mock_lnL': np.nan,
|
|
496
|
+
'lnL': np.nan,
|
|
497
|
+
'alpha': np.nan,
|
|
498
|
+
'alpha_theta': np.nan,
|
|
499
|
+
'alpha_thetabar': np.nan,
|
|
500
|
+
'alpha_inf': np.nan,
|
|
501
|
+
'alpha_eq': np.nan,
|
|
502
|
+
'betaH_S3': np.nan,
|
|
503
|
+
'betaH_RH': np.nan,
|
|
504
|
+
'RH': np.nan,
|
|
505
|
+
'Treh_SM_GeV': np.nan,
|
|
506
|
+
'Tperc_SM_GeV': np.nan,
|
|
507
|
+
'g_eff_tot_reh': np.nan,
|
|
508
|
+
'h_eff_tot_reh': np.nan,
|
|
509
|
+
'kappa_phi': np.nan,
|
|
510
|
+
'kappa_sw': np.nan,
|
|
511
|
+
'kappa_turb': np.nan,
|
|
512
|
+
'g0': np.nan,
|
|
513
|
+
'h0': np.nan,
|
|
514
|
+
'v_wall': np.nan,
|
|
515
|
+
'D': np.nan,
|
|
516
|
+
'c_s': np.nan,
|
|
517
|
+
'c_s_sym': np.nan,
|
|
518
|
+
'c_s_bro': np.nan,
|
|
519
|
+
'step': np.nan,
|
|
520
|
+
'total_steps': np.nan,
|
|
521
|
+
'Tnuc_SM_GeV': np.nan,
|
|
522
|
+
'Tcrit_SM_GeV': np.nan,
|
|
523
|
+
'Tf_SM_GeV': np.nan,
|
|
524
|
+
'xi_crit': np.nan,
|
|
525
|
+
'WARNING:too_weak_to_compute_perc': False,
|
|
526
|
+
'WARNING:no_perc_splines': False,
|
|
527
|
+
'WARNING:betaH_small': False,
|
|
528
|
+
'WARNING:betaH_very_small': False,
|
|
529
|
+
'WARNING:betaH_mismatch': False,
|
|
530
|
+
'WARNING:betaH_nonfinite': False,
|
|
531
|
+
'WARNING:nucleationRate_nonexponential': False,
|
|
532
|
+
'WARNING:not_T0_global_min': False,
|
|
533
|
+
'lnL_smoothened_NG15_14bins': np.nan,
|
|
534
|
+
'lnL_PTArcade_NG15_14bins': np.nan,
|
|
535
|
+
'lnL_mock_NG15_14bins': np.nan,
|
|
536
|
+
'lnL_smoothened_NG15_5bins': np.nan,
|
|
537
|
+
'lnL_PTArcade_NG15_5bins': np.nan,
|
|
538
|
+
'lnL_mock_NG15_5bins': np.nan,
|
|
539
|
+
'lnL_smoothened_NG12_5bins': np.nan,
|
|
540
|
+
'lnL_PTArcade_NG12_5bins': np.nan,
|
|
541
|
+
'lnL_mock_NG12_5bins': np.nan,
|
|
542
|
+
'lnL_smoothened_IPTA2_13bins': np.nan,
|
|
543
|
+
'lnL_PTArcade_IPTA2_13bins': np.nan,
|
|
544
|
+
'lnL_mock_IPTA2_13bins': np.nan,
|
|
545
|
+
'SKA_5_yrs_SNR': np.nan,
|
|
546
|
+
'SKA_10_yrs_SNR': np.nan,
|
|
547
|
+
'SKA_20_yrs_SNR': np.nan,
|
|
548
|
+
'EPTA_18_yrs_SNR': np.nan,
|
|
549
|
+
'NANOGrav_11_yrs_SNR': np.nan,
|
|
550
|
+
'NANOGrav_15_yrs_SNR': np.nan,
|
|
551
|
+
'LISA_SNR': np.nan,
|
|
552
|
+
'B-DECIGO_SNR': np.nan,
|
|
553
|
+
'DECIGO_SNR': np.nan,
|
|
554
|
+
'BBO_SNR': np.nan,
|
|
555
|
+
'ET_SNR': np.nan,
|
|
556
|
+
'muAres_SNR': np.nan,
|
|
557
|
+
'HLV_O2_SNR': np.nan,
|
|
558
|
+
'HLVK_design_SNR': np.nan,
|
|
559
|
+
'f_peak_Hz': np.nan,
|
|
560
|
+
'h2OmegaGW_peak': np.nan,
|
|
561
|
+
'f_pivot_Hz': np.nan,
|
|
562
|
+
'h2OmegaGW_at_pivot': np.nan,
|
|
563
|
+
'DNeff_GW': np.nan}
|
|
564
|
+
|
|
565
|
+
return res
|