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,468 @@
|
|
|
1
|
+
"""Scan routines for different sampling strategies.
|
|
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 multiprocessing
|
|
14
|
+
from typing import Iterable
|
|
15
|
+
|
|
16
|
+
import h5py
|
|
17
|
+
import numpy as np
|
|
18
|
+
from tqdm import tqdm
|
|
19
|
+
|
|
20
|
+
from transitionlistener.gridplots import plot2dData
|
|
21
|
+
from transitionlistener.lineplots import plot1dData
|
|
22
|
+
from transitionlistener.helper_functions import load_potential
|
|
23
|
+
from transitionlistener import console
|
|
24
|
+
from rich.panel import Panel
|
|
25
|
+
|
|
26
|
+
from .logging_utils import Logger
|
|
27
|
+
from .pipeline import run_TL
|
|
28
|
+
from .samplers import scanfunc, sample_and_export_to_csv, rand_worker, rand_listener
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _to_scalar_or_nan(value) -> float:
|
|
32
|
+
"""Convert value to a scalar float when possible, otherwise NaN."""
|
|
33
|
+
try:
|
|
34
|
+
arr = np.asarray(value)
|
|
35
|
+
except Exception:
|
|
36
|
+
return float("nan")
|
|
37
|
+
if arr.size == 0:
|
|
38
|
+
return float("nan")
|
|
39
|
+
if arr.size == 1:
|
|
40
|
+
try:
|
|
41
|
+
return float(np.squeeze(arr))
|
|
42
|
+
except Exception:
|
|
43
|
+
return float("nan")
|
|
44
|
+
return float("nan")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def create_grid(xminmax: tuple, yminmax: tuple, N: int,
|
|
48
|
+
xscale: str, yscale: str) -> tuple[np.ndarray]:
|
|
49
|
+
"""Create a regular grid of x/y coordinates."""
|
|
50
|
+
if xscale == "lin":
|
|
51
|
+
xrange = np.linspace(*xminmax, num=N)
|
|
52
|
+
elif xscale == "log":
|
|
53
|
+
xrange = np.logspace(*xminmax, num=N)
|
|
54
|
+
else:
|
|
55
|
+
raise ValueError("xscale must be 'lin' or 'log'")
|
|
56
|
+
|
|
57
|
+
if yscale == "lin":
|
|
58
|
+
yrange = np.linspace(*yminmax, num=N)
|
|
59
|
+
elif yscale == "log":
|
|
60
|
+
yrange = np.logspace(*yminmax, num=N)
|
|
61
|
+
else:
|
|
62
|
+
raise ValueError("yscale must be 'lin' or 'log'")
|
|
63
|
+
|
|
64
|
+
return xrange, yrange
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def line_scan(conf, n_jobs: int):
|
|
68
|
+
"""1D scan over only one parameter."""
|
|
69
|
+
outpath = conf.output_path
|
|
70
|
+
|
|
71
|
+
if conf.scale == "lin":
|
|
72
|
+
xrange = np.linspace(*conf.minmax, num=conf.N)
|
|
73
|
+
elif conf.scale == "log":
|
|
74
|
+
xrange = np.logspace(*conf.minmax, num=conf.N)
|
|
75
|
+
else:
|
|
76
|
+
raise ValueError("xscale must be 'lin' or 'log'")
|
|
77
|
+
|
|
78
|
+
input_params_list = []
|
|
79
|
+
for _, x in enumerate(xrange):
|
|
80
|
+
inputparam_dict = {conf.line_param: x}
|
|
81
|
+
for key, val in conf.other_params.items():
|
|
82
|
+
inputparam_dict[key] = val
|
|
83
|
+
input_params_list.append((inputparam_dict, conf.modelfile,
|
|
84
|
+
conf.potential_name, outpath, conf.timeout))
|
|
85
|
+
|
|
86
|
+
if n_jobs != 1:
|
|
87
|
+
n_jobs = n_jobs - 1
|
|
88
|
+
pool = multiprocessing.Pool(processes=n_jobs)
|
|
89
|
+
results = []
|
|
90
|
+
|
|
91
|
+
for result in tqdm(pool.imap(func=scanfunc,
|
|
92
|
+
iterable=input_params_list), total=conf.N):
|
|
93
|
+
results.append(result)
|
|
94
|
+
|
|
95
|
+
save_results_1d(
|
|
96
|
+
results,
|
|
97
|
+
conf.N,
|
|
98
|
+
xrange,
|
|
99
|
+
outpath,
|
|
100
|
+
conf.derived_params,
|
|
101
|
+
conf.format,
|
|
102
|
+
conf.line_param,
|
|
103
|
+
conf.other_params,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
if conf.plots:
|
|
107
|
+
plot_results_1d(results, conf, xrange, outpath)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def grid_scan(conf, n_jobs: int):
|
|
111
|
+
"""2D grid scan."""
|
|
112
|
+
outpath = conf.output_path
|
|
113
|
+
xrange, yrange = create_grid(conf.minmax["x"], conf.minmax["y"],
|
|
114
|
+
conf.N, conf.scales["x"], conf.scales["y"])
|
|
115
|
+
|
|
116
|
+
input_params_list = []
|
|
117
|
+
for _, x in enumerate(xrange):
|
|
118
|
+
for _, y in enumerate(yrange):
|
|
119
|
+
inputparam_dict = {}
|
|
120
|
+
for key, val in conf.grid_names.items():
|
|
121
|
+
if key == "x":
|
|
122
|
+
inputparam_dict[val] = x
|
|
123
|
+
elif key == "y":
|
|
124
|
+
inputparam_dict[val] = y
|
|
125
|
+
for key, val in conf.other_params.items():
|
|
126
|
+
inputparam_dict[key] = val
|
|
127
|
+
input_params_list.append((inputparam_dict, conf.modelfile,
|
|
128
|
+
conf.potential_name, outpath, conf.timeout))
|
|
129
|
+
|
|
130
|
+
if n_jobs != 1:
|
|
131
|
+
n_jobs = n_jobs - 1
|
|
132
|
+
pool = multiprocessing.Pool(processes=n_jobs)
|
|
133
|
+
results = []
|
|
134
|
+
|
|
135
|
+
for result in tqdm(pool.imap(func=scanfunc,
|
|
136
|
+
iterable=input_params_list), total=conf.N**2):
|
|
137
|
+
results.append(result)
|
|
138
|
+
msg = ("Phase transition analysis done. Now, save the "
|
|
139
|
+
"results and check if signal is observable.")
|
|
140
|
+
console.print(Panel.fit(f"[bold green]{msg}[/bold green]", border_style="green"))
|
|
141
|
+
|
|
142
|
+
save_results_2d(
|
|
143
|
+
results,
|
|
144
|
+
conf.N,
|
|
145
|
+
xrange,
|
|
146
|
+
yrange,
|
|
147
|
+
outpath,
|
|
148
|
+
conf.derived_params.copy(),
|
|
149
|
+
conf.format,
|
|
150
|
+
conf.grid_names,
|
|
151
|
+
conf.other_params,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if conf.plots:
|
|
155
|
+
plot_results_2d(results, conf, xrange, yrange, outpath)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def table(conf, n_jobs: int):
|
|
159
|
+
"""Evaluate points specified in a CSV table."""
|
|
160
|
+
try:
|
|
161
|
+
file = np.genfromtxt(conf.table_file, delimiter=',')
|
|
162
|
+
file_transpose = np.transpose(file)
|
|
163
|
+
except Exception as exc:
|
|
164
|
+
raise Exception(f"Error reading table file {conf.table_file}: {exc}")
|
|
165
|
+
|
|
166
|
+
offset = 1 if np.isnan(file_transpose[0][0]) else 0
|
|
167
|
+
|
|
168
|
+
input_params_list = []
|
|
169
|
+
for i in range(conf.N):
|
|
170
|
+
inputparam_dict = {}
|
|
171
|
+
for name in conf.scan_params.keys():
|
|
172
|
+
inputparam_dict[name] = float(file_transpose[conf.scan_params[name]["index"]][i + offset])
|
|
173
|
+
for key, val in conf.other_params.items():
|
|
174
|
+
inputparam_dict[key] = val
|
|
175
|
+
input_params_list.append(
|
|
176
|
+
(
|
|
177
|
+
inputparam_dict,
|
|
178
|
+
conf.modelfile,
|
|
179
|
+
conf.potential_name,
|
|
180
|
+
conf.output_path,
|
|
181
|
+
conf.derived_params,
|
|
182
|
+
conf.timeout,
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
if n_jobs != 1:
|
|
187
|
+
n_jobs = n_jobs - 1
|
|
188
|
+
pool = multiprocessing.Pool(processes=n_jobs)
|
|
189
|
+
results = []
|
|
190
|
+
|
|
191
|
+
for result in tqdm(pool.imap(func=sample_and_export_to_csv,
|
|
192
|
+
iterable=input_params_list), total=conf.N):
|
|
193
|
+
results.append(result)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def random_scan(conf, n_jobs: int):
|
|
197
|
+
"""Random parameter scan."""
|
|
198
|
+
N = conf.N
|
|
199
|
+
|
|
200
|
+
if n_jobs != 1:
|
|
201
|
+
n_jobs = n_jobs - 1
|
|
202
|
+
|
|
203
|
+
manager = multiprocessing.Manager()
|
|
204
|
+
q = manager.Queue()
|
|
205
|
+
pool = multiprocessing.Pool(processes=n_jobs)
|
|
206
|
+
watcher = multiprocessing.Process(target=rand_listener,
|
|
207
|
+
args=(q, conf.output_path,
|
|
208
|
+
conf.derived_params,))
|
|
209
|
+
# Make sure the I/O worker is running
|
|
210
|
+
watcher.start()
|
|
211
|
+
|
|
212
|
+
input_params_list = []
|
|
213
|
+
for _ in range(N):
|
|
214
|
+
inputparam_dict = {}
|
|
215
|
+
cube = np.random.rand(len(conf.scan_params))
|
|
216
|
+
input_params_untransformed = _random_prior_transform(cube, conf)
|
|
217
|
+
for i, name in enumerate(conf.scan_params.keys()):
|
|
218
|
+
inputparam_dict[name] = input_params_untransformed[i]
|
|
219
|
+
for key, val in conf.other_params.items():
|
|
220
|
+
inputparam_dict[key] = val
|
|
221
|
+
input_params_list.append(
|
|
222
|
+
(
|
|
223
|
+
inputparam_dict,
|
|
224
|
+
conf.modelfile,
|
|
225
|
+
conf.potential_name,
|
|
226
|
+
conf.output_path,
|
|
227
|
+
conf.derived_params,
|
|
228
|
+
conf.timeout,
|
|
229
|
+
)
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
jobs = []
|
|
233
|
+
for i in range(N):
|
|
234
|
+
job = pool.apply_async(rand_worker, (input_params_list[i], q))
|
|
235
|
+
jobs.append(job)
|
|
236
|
+
|
|
237
|
+
for job in jobs:
|
|
238
|
+
job.get()
|
|
239
|
+
|
|
240
|
+
q.put('kill')
|
|
241
|
+
pool.close()
|
|
242
|
+
pool.join()
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _random_prior_transform(cube: np.ndarray, conf) -> np.ndarray:
|
|
246
|
+
"""Transforms the unit cube to the prior space defined in the configuration."""
|
|
247
|
+
params = cube.copy()
|
|
248
|
+
for i, name in enumerate(conf.scan_params.keys()):
|
|
249
|
+
prior = conf.scan_params[name]["range"]
|
|
250
|
+
try:
|
|
251
|
+
low = float(prior[0])
|
|
252
|
+
except ValueError:
|
|
253
|
+
low = eval(prior[0])
|
|
254
|
+
try:
|
|
255
|
+
high = float(prior[1])
|
|
256
|
+
except ValueError:
|
|
257
|
+
high = eval(prior[1])
|
|
258
|
+
|
|
259
|
+
if conf.scan_params[name]["scale"] == "log":
|
|
260
|
+
params[i] = 10 ** (np.log10(low) + cube[i] * (np.log10(high) - np.log10(low)))
|
|
261
|
+
else:
|
|
262
|
+
params[i] = low + cube[i] * (high - low)
|
|
263
|
+
return params
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def save_results_2d(res_dict: Iterable[dict], N: int, xrange: np.ndarray,
|
|
267
|
+
yrange: np.ndarray, outpath: str, outnames: dict,
|
|
268
|
+
format: str, grid_names: dict, other_params: dict):
|
|
269
|
+
"""Save the result list to a hdf5 or txt file."""
|
|
270
|
+
outnames.update({"error": "error"})
|
|
271
|
+
h = np.array(res_dict).reshape(N, N)
|
|
272
|
+
res = np.full((N, N, len(outnames)), np.nan)
|
|
273
|
+
|
|
274
|
+
for i in range(N):
|
|
275
|
+
for j in range(N):
|
|
276
|
+
for k, name in enumerate(outnames):
|
|
277
|
+
if "strongestTransitionObservables" in h[i, j]:
|
|
278
|
+
if name in h[i, j]["strongestTransitionObservables"]:
|
|
279
|
+
val = h[i, j]["strongestTransitionObservables"][name]
|
|
280
|
+
res[i, j, k] = _to_scalar_or_nan(val)
|
|
281
|
+
if "error" in h[i, j]:
|
|
282
|
+
res[i, j, k] = _to_scalar_or_nan(h[i, j]["error"])
|
|
283
|
+
|
|
284
|
+
if format == "hdf5":
|
|
285
|
+
with h5py.File(outpath + "data.hdf5", "w") as f:
|
|
286
|
+
f.attrs["xname"] = grid_names["x"]
|
|
287
|
+
f.attrs["yname"] = grid_names["y"]
|
|
288
|
+
f.attrs["xrange"] = xrange
|
|
289
|
+
f.attrs["yrange"] = yrange
|
|
290
|
+
for name, par in zip(other_params.keys(), other_params.values()):
|
|
291
|
+
f.attrs[name] = par
|
|
292
|
+
|
|
293
|
+
d = f.create_group('data')
|
|
294
|
+
for on in outnames:
|
|
295
|
+
d.create_dataset(on, shape=(N, N))
|
|
296
|
+
|
|
297
|
+
for i, x in enumerate(xrange):
|
|
298
|
+
for j, y in enumerate(yrange):
|
|
299
|
+
for k, on in enumerate(outnames):
|
|
300
|
+
d[on][i, j] = res[i, j, k]
|
|
301
|
+
elif format == "txt":
|
|
302
|
+
for k, on in enumerate(outnames):
|
|
303
|
+
data = np.zeros((N, N))
|
|
304
|
+
for i, x in enumerate(xrange):
|
|
305
|
+
for j, y in enumerate(yrange):
|
|
306
|
+
data[i, j] = res[i, j, k]
|
|
307
|
+
np.savetxt(outpath + on + ".txt", data)
|
|
308
|
+
|
|
309
|
+
xname = grid_names["x"]
|
|
310
|
+
yname = grid_names["y"]
|
|
311
|
+
np.savetxt(outpath + "xrange.txt", xrange,
|
|
312
|
+
header=f"X input range for parameter: {xname:}")
|
|
313
|
+
np.savetxt(outpath + "yrange.txt", yrange,
|
|
314
|
+
header=f"Y input range for parameter: {yname:}")
|
|
315
|
+
|
|
316
|
+
with open(outpath + "other_params.txt", "w") as fh:
|
|
317
|
+
fh.write("# " + "\t".join(other_params.keys()) + "\n")
|
|
318
|
+
fh.write("\t".join(str(v) for v in other_params.values()) + "\n")
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def plot_results_2d(results_dict: Iterable[dict], conf, xrange: np.ndarray, yrange: np.ndarray, outpath: str):
|
|
322
|
+
"""Make the grid plots."""
|
|
323
|
+
derived_param_names = [name for name in conf.derived_params.keys()]
|
|
324
|
+
derived_param_plot_names = [name for name in conf.derived_params.values()]
|
|
325
|
+
grid_params_names = [conf.grid_names["x"], conf.grid_names["y"]]
|
|
326
|
+
grid_params_plot_names = [conf.model_params[name]["plotname"] for name in grid_params_names]
|
|
327
|
+
overview_param_plot_names = [
|
|
328
|
+
plot_name for name, plot_name in zip(derived_param_names, derived_param_plot_names)
|
|
329
|
+
if name in conf.overview_param_names
|
|
330
|
+
]
|
|
331
|
+
|
|
332
|
+
scale = conf.scales["x"] + conf.scales["y"]
|
|
333
|
+
all_params = np.array(results_dict).reshape(conf.N, conf.N)
|
|
334
|
+
|
|
335
|
+
grid = plot2dData(
|
|
336
|
+
all_params,
|
|
337
|
+
x=xrange,
|
|
338
|
+
y=yrange,
|
|
339
|
+
scale=scale,
|
|
340
|
+
xy_plot_names=grid_params_plot_names,
|
|
341
|
+
foldername=outpath,
|
|
342
|
+
derived_params_names=derived_param_names,
|
|
343
|
+
derived_params_plot_names=derived_param_plot_names,
|
|
344
|
+
overview_title=conf.plot_description,
|
|
345
|
+
show_scan_points=conf.show_scan_points,
|
|
346
|
+
)
|
|
347
|
+
def _run_plot_step(step_name: str, fn):
|
|
348
|
+
try:
|
|
349
|
+
fn()
|
|
350
|
+
except Exception as exc:
|
|
351
|
+
msg = f"[yellow]Skipping plot step '{step_name}': {exc}[/yellow]"
|
|
352
|
+
console.print(Panel.fit(msg, border_style="yellow"))
|
|
353
|
+
|
|
354
|
+
# Produce the paper-critical four-panel overview first.
|
|
355
|
+
_run_plot_step(
|
|
356
|
+
"overview_plot",
|
|
357
|
+
lambda: grid.plot_overview(
|
|
358
|
+
overview_detector_name=conf.overview_detector_name,
|
|
359
|
+
overview_param_names=conf.overview_param_names,
|
|
360
|
+
overview_param_plot_names=overview_param_plot_names,
|
|
361
|
+
),
|
|
362
|
+
)
|
|
363
|
+
_run_plot_step("log_params", grid.plot_log_params)
|
|
364
|
+
_run_plot_step("lin_params", grid.plot_lin_params)
|
|
365
|
+
_run_plot_step("save_SNRs", grid.save_SNRs)
|
|
366
|
+
_run_plot_step("plot_SNRs", grid.plot_SNRs)
|
|
367
|
+
_run_plot_step("save_logLs", grid.save_logLs)
|
|
368
|
+
_run_plot_step("plot_logLs", grid.plot_logLs)
|
|
369
|
+
_run_plot_step("save_add_infos", grid.save_add_infos)
|
|
370
|
+
_run_plot_step("plot_add_infos", grid.plot_add_infos)
|
|
371
|
+
_run_plot_step("plot_mass_spectrum", grid.plot_mass_spectrum)
|
|
372
|
+
_run_plot_step("plot_errors", grid.plot_errors)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def save_results_1d(res_dict: Iterable[dict], N: int, xrange: np.ndarray, outpath: str,
|
|
376
|
+
outnames: dict, format: str, line_param: str, other_params: dict):
|
|
377
|
+
"""Save the result list to a hdf5 or txt file."""
|
|
378
|
+
outnames.update({"error": "error"})
|
|
379
|
+
h = np.array(res_dict).reshape(N)
|
|
380
|
+
res = np.full((N, len(outnames)), np.nan)
|
|
381
|
+
|
|
382
|
+
for i in range(N):
|
|
383
|
+
for k, name in enumerate(outnames):
|
|
384
|
+
if "strongestTransitionObservables" in h[i]:
|
|
385
|
+
if name in h[i]["strongestTransitionObservables"]:
|
|
386
|
+
val = h[i]["strongestTransitionObservables"][name]
|
|
387
|
+
res[i, k] = _to_scalar_or_nan(val)
|
|
388
|
+
if "error" in h[i]:
|
|
389
|
+
res[i, k] = _to_scalar_or_nan(h[i]["error"])
|
|
390
|
+
|
|
391
|
+
if format == "hdf5":
|
|
392
|
+
with h5py.File(outpath + "data.hdf5", "w") as f:
|
|
393
|
+
f.attrs["xname"] = line_param
|
|
394
|
+
f.attrs["xrange"] = xrange
|
|
395
|
+
for name, par in zip(other_params.keys(), other_params.values()):
|
|
396
|
+
f.attrs[name] = par
|
|
397
|
+
|
|
398
|
+
d = f.create_group('data')
|
|
399
|
+
for on in outnames:
|
|
400
|
+
d.create_dataset(on, shape=(N,))
|
|
401
|
+
|
|
402
|
+
for i, x in enumerate(xrange):
|
|
403
|
+
for k, on in enumerate(outnames):
|
|
404
|
+
d[on][i] = res[i, k]
|
|
405
|
+
elif format == "txt":
|
|
406
|
+
for k, on in enumerate(outnames):
|
|
407
|
+
data = np.zeros((N,))
|
|
408
|
+
for i, x in enumerate(xrange):
|
|
409
|
+
data[i] = res[i, k]
|
|
410
|
+
np.savetxt(outpath + on + ".txt", data)
|
|
411
|
+
|
|
412
|
+
np.savetxt(outpath + "xrange.txt", xrange,
|
|
413
|
+
header=f"X input range for parameter: {line_param:}")
|
|
414
|
+
with open(outpath + "other_params.txt", "w") as fh:
|
|
415
|
+
fh.write("# " + "\t".join(other_params.keys()) + "\n")
|
|
416
|
+
fh.write("\t".join(str(v) for v in other_params.values()) + "\n")
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def plot_results_1d(results_dict: Iterable[dict], conf, xrange: np.ndarray, outpath: str):
|
|
420
|
+
"""Generate line scan plots."""
|
|
421
|
+
derived_param_names = [name for name in conf.derived_params.keys()]
|
|
422
|
+
derived_param_plot_names = [name for name in conf.derived_params.values()]
|
|
423
|
+
x_plot_name = conf.model_params[conf.line_param]["plotname"]
|
|
424
|
+
overview_param_plot_names = [
|
|
425
|
+
plot_name for name, plot_name in zip(derived_param_names, derived_param_plot_names)
|
|
426
|
+
if name in conf.overview_param_names
|
|
427
|
+
]
|
|
428
|
+
|
|
429
|
+
scale = conf.scale
|
|
430
|
+
all_params = np.array(results_dict).reshape(conf.N)
|
|
431
|
+
|
|
432
|
+
grid = plot1dData(
|
|
433
|
+
all_params,
|
|
434
|
+
x=xrange,
|
|
435
|
+
scale=scale,
|
|
436
|
+
x_plot_name=x_plot_name,
|
|
437
|
+
foldername=outpath,
|
|
438
|
+
derived_params_names=derived_param_names,
|
|
439
|
+
derived_params_plot_names=derived_param_plot_names,
|
|
440
|
+
overview_title=conf.plot_description,
|
|
441
|
+
show_scan_points=conf.show_scan_points,
|
|
442
|
+
)
|
|
443
|
+
def _run_plot_step(step_name: str, fn):
|
|
444
|
+
try:
|
|
445
|
+
fn()
|
|
446
|
+
except Exception as exc:
|
|
447
|
+
msg = f"[yellow]Skipping plot step '{step_name}': {exc}[/yellow]"
|
|
448
|
+
console.print(Panel.fit(msg, border_style="yellow"))
|
|
449
|
+
|
|
450
|
+
# Produce the paper-critical four-panel overview first.
|
|
451
|
+
_run_plot_step(
|
|
452
|
+
"overview_plot",
|
|
453
|
+
lambda: grid.plot_overview(
|
|
454
|
+
overview_detector_name=conf.overview_detector_name,
|
|
455
|
+
overview_param_names=conf.overview_param_names,
|
|
456
|
+
overview_param_plot_names=overview_param_plot_names,
|
|
457
|
+
),
|
|
458
|
+
)
|
|
459
|
+
_run_plot_step("plot_log_params", grid.plot_log_params)
|
|
460
|
+
_run_plot_step("plot_lin_params", grid.plot_lin_params)
|
|
461
|
+
_run_plot_step("save_SNRs", grid.save_SNRs)
|
|
462
|
+
_run_plot_step("plot_SNRs", grid.plot_SNRs)
|
|
463
|
+
_run_plot_step("save_logLs", grid.save_logLs)
|
|
464
|
+
_run_plot_step("plot_logLs", grid.plot_logLs)
|
|
465
|
+
_run_plot_step("save_add_infos", grid.save_add_infos)
|
|
466
|
+
_run_plot_step("plot_add_infos", grid.plot_add_infos)
|
|
467
|
+
_run_plot_step("plot_mass_spectrum", grid.plot_mass_spectrum)
|
|
468
|
+
_run_plot_step("plot_errors", grid.plot_errors)
|