xarpes 0.6.4__py3-none-any.whl → 0.6.5__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.
- xarpes/__init__.py +1 -1
- xarpes/functions.py +165 -2
- xarpes/selfenergies.py +111 -131
- {xarpes-0.6.4.dist-info → xarpes-0.6.5.dist-info}/METADATA +1 -1
- {xarpes-0.6.4.dist-info → xarpes-0.6.5.dist-info}/RECORD +8 -8
- {xarpes-0.6.4.dist-info → xarpes-0.6.5.dist-info}/LICENSE +0 -0
- {xarpes-0.6.4.dist-info → xarpes-0.6.5.dist-info}/WHEEL +0 -0
- {xarpes-0.6.4.dist-info → xarpes-0.6.5.dist-info}/entry_points.txt +0 -0
xarpes/__init__.py
CHANGED
xarpes/functions.py
CHANGED
|
@@ -236,7 +236,6 @@ def fit_least_squares(p0, xdata, ydata, function, resolution=None, yerr=None,
|
|
|
236
236
|
return pfit, pcov, success
|
|
237
237
|
|
|
238
238
|
|
|
239
|
-
|
|
240
239
|
def download_examples():
|
|
241
240
|
"""Downloads the examples folder from the main xARPES repository only if it
|
|
242
241
|
does not already exist in the current directory. Prints executed steps and a
|
|
@@ -625,4 +624,168 @@ def chi2kink_logistic(x, a, b, c, d):
|
|
|
625
624
|
expz = np.exp(z[mneg])
|
|
626
625
|
phi[mneg] = a + b * expz / (1.0 + expz)
|
|
627
626
|
|
|
628
|
-
return phi
|
|
627
|
+
return phi
|
|
628
|
+
|
|
629
|
+
def _in_ipython():
|
|
630
|
+
try:
|
|
631
|
+
from IPython import get_ipython
|
|
632
|
+
except Exception:
|
|
633
|
+
return False
|
|
634
|
+
return get_ipython() is not None
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
class _LineBuffer:
|
|
638
|
+
"""Capture text as lines, keeping only head + tail and total count."""
|
|
639
|
+
def __init__(self, head=10, tail=10):
|
|
640
|
+
from collections import deque
|
|
641
|
+
self.head = int(head)
|
|
642
|
+
self.tail = int(tail)
|
|
643
|
+
self._head_lines = []
|
|
644
|
+
self._tail_lines = deque(maxlen=self.tail)
|
|
645
|
+
self._partial = ""
|
|
646
|
+
self._n_lines = 0
|
|
647
|
+
|
|
648
|
+
def feed(self, text):
|
|
649
|
+
if not text:
|
|
650
|
+
return
|
|
651
|
+
|
|
652
|
+
# Normalize carriage returns (progress bars etc.)
|
|
653
|
+
text = str(text).replace("\r", "\n")
|
|
654
|
+
|
|
655
|
+
# Prepend any partial line from previous write.
|
|
656
|
+
text = self._partial + text
|
|
657
|
+
parts = text.split("\n")
|
|
658
|
+
|
|
659
|
+
# If text does not end with '\n', last part is partial.
|
|
660
|
+
self._partial = parts.pop() # may be "" if ended with newline
|
|
661
|
+
|
|
662
|
+
for line in parts:
|
|
663
|
+
# Record completed line
|
|
664
|
+
self._n_lines += 1
|
|
665
|
+
if len(self._head_lines) < self.head:
|
|
666
|
+
self._head_lines.append(line)
|
|
667
|
+
else:
|
|
668
|
+
if self.tail > 0:
|
|
669
|
+
self._tail_lines.append(line)
|
|
670
|
+
|
|
671
|
+
def finalize(self):
|
|
672
|
+
# If there is an unfinished line, treat it as a line.
|
|
673
|
+
if self._partial.strip() != "":
|
|
674
|
+
self.feed("\n") # forces it into completed lines
|
|
675
|
+
self._partial = ""
|
|
676
|
+
|
|
677
|
+
def summary(self):
|
|
678
|
+
self.finalize()
|
|
679
|
+
|
|
680
|
+
n = self._n_lines
|
|
681
|
+
if n == 0:
|
|
682
|
+
return ""
|
|
683
|
+
|
|
684
|
+
# If total small, reconstruct from head + tail if possible
|
|
685
|
+
if n <= self.head + self.tail:
|
|
686
|
+
# We didn't keep all middle lines, but if n <= head+tail we kept all.
|
|
687
|
+
# For n <= head, tail may be empty; for n > head, tail contains rest.
|
|
688
|
+
out = list(self._head_lines)
|
|
689
|
+
if n > len(self._head_lines):
|
|
690
|
+
out.extend(list(self._tail_lines))
|
|
691
|
+
return "\n".join(out)
|
|
692
|
+
|
|
693
|
+
omitted = n - self.head - self.tail
|
|
694
|
+
head_txt = "\n".join(self._head_lines)
|
|
695
|
+
tail_txt = "\n".join(list(self._tail_lines))
|
|
696
|
+
return (
|
|
697
|
+
f"{head_txt}\n"
|
|
698
|
+
f"... ({omitted} lines omitted) ...\n"
|
|
699
|
+
f"{tail_txt}"
|
|
700
|
+
)
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
def trim_notebook_output(print_lines=10, *, enabled=True, clear=True,
|
|
704
|
+
capture_stderr=True, sleep_s=0.05):
|
|
705
|
+
"""Context manager: show live prints, then keep only head/tail in notebooks.
|
|
706
|
+
|
|
707
|
+
In plain scripts (no IPython), this is a no-op.
|
|
708
|
+
"""
|
|
709
|
+
from contextlib import contextmanager
|
|
710
|
+
|
|
711
|
+
@contextmanager
|
|
712
|
+
def _ctx():
|
|
713
|
+
if (not enabled) or (print_lines is None):
|
|
714
|
+
yield
|
|
715
|
+
return
|
|
716
|
+
|
|
717
|
+
n = int(print_lines)
|
|
718
|
+
if n <= 0:
|
|
719
|
+
yield
|
|
720
|
+
return
|
|
721
|
+
|
|
722
|
+
# Only do this in IPython environments; scripts should print normally.
|
|
723
|
+
if not _in_ipython():
|
|
724
|
+
yield
|
|
725
|
+
return
|
|
726
|
+
|
|
727
|
+
import sys
|
|
728
|
+
import time
|
|
729
|
+
|
|
730
|
+
buf = _LineBuffer(head=n, tail=n)
|
|
731
|
+
|
|
732
|
+
stdout_orig = sys.stdout
|
|
733
|
+
stderr_orig = sys.stderr
|
|
734
|
+
|
|
735
|
+
class _TeeStream:
|
|
736
|
+
def __init__(self, real_stream, buffer):
|
|
737
|
+
self._real = real_stream
|
|
738
|
+
self._buf = buffer
|
|
739
|
+
|
|
740
|
+
def write(self, text):
|
|
741
|
+
# Live output
|
|
742
|
+
try:
|
|
743
|
+
self._real.write(text)
|
|
744
|
+
self._real.flush()
|
|
745
|
+
except Exception:
|
|
746
|
+
pass
|
|
747
|
+
# Capture
|
|
748
|
+
self._buf.feed(text)
|
|
749
|
+
|
|
750
|
+
def flush(self):
|
|
751
|
+
try:
|
|
752
|
+
self._real.flush()
|
|
753
|
+
except Exception:
|
|
754
|
+
pass
|
|
755
|
+
|
|
756
|
+
# Some libraries ask for these:
|
|
757
|
+
def isatty(self):
|
|
758
|
+
return False
|
|
759
|
+
|
|
760
|
+
@property
|
|
761
|
+
def encoding(self):
|
|
762
|
+
return getattr(self._real, "encoding", "utf-8")
|
|
763
|
+
|
|
764
|
+
sys.stdout = _TeeStream(stdout_orig, buf)
|
|
765
|
+
if capture_stderr:
|
|
766
|
+
sys.stderr = _TeeStream(stderr_orig, buf)
|
|
767
|
+
|
|
768
|
+
try:
|
|
769
|
+
yield
|
|
770
|
+
finally:
|
|
771
|
+
# Restore streams first.
|
|
772
|
+
sys.stdout = stdout_orig
|
|
773
|
+
sys.stderr = stderr_orig
|
|
774
|
+
|
|
775
|
+
# Let Jupyter finish rendering any queued output.
|
|
776
|
+
if sleep_s:
|
|
777
|
+
time.sleep(float(sleep_s))
|
|
778
|
+
|
|
779
|
+
# Clear cell output and print summary.
|
|
780
|
+
summary = buf.summary()
|
|
781
|
+
if clear:
|
|
782
|
+
try:
|
|
783
|
+
from IPython.display import clear_output
|
|
784
|
+
clear_output(wait=True)
|
|
785
|
+
except Exception:
|
|
786
|
+
pass
|
|
787
|
+
|
|
788
|
+
if summary:
|
|
789
|
+
print(summary)
|
|
790
|
+
|
|
791
|
+
return _ctx()
|
xarpes/selfenergies.py
CHANGED
|
@@ -1175,52 +1175,47 @@ class SelfEnergy:
|
|
|
1175
1175
|
return fig, spectrum, model, omega_range, alpha_select
|
|
1176
1176
|
|
|
1177
1177
|
|
|
1178
|
-
def bayesian_loop(self, *, omega_min, omega_max, omega_num, omega_I,
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1178
|
+
def bayesian_loop(self, *, omega_min, omega_max, omega_num, omega_I,
|
|
1179
|
+
omega_M, fermi_velocity=None,
|
|
1180
|
+
fermi_wavevector=None, bare_mass=None, vary=(),
|
|
1181
|
+
opt_method="Nelder-Mead", opt_options=None,
|
|
1182
|
+
mem=None, loop=None, **mem_kwargs):
|
|
1182
1183
|
r"""
|
|
1183
1184
|
Bayesian outer loop calling `_cost_function()`.
|
|
1184
1185
|
|
|
1186
|
+
If `vary` is non-empty, runs a SciPy optimization over the selected
|
|
1187
|
+
parameters in `vary`.
|
|
1188
|
+
|
|
1189
|
+
Supported entries in `vary` depend on `self._class`:
|
|
1190
|
+
|
|
1191
|
+
- Common: "fermi_wavevector", "impurity_magnitude", "lambda_el", "h_n"
|
|
1192
|
+
- SpectralLinear: additionally "fermi_velocity"
|
|
1193
|
+
- SpectralQuadratic: additionally "bare_mass"
|
|
1194
|
+
|
|
1195
|
+
Notes
|
|
1196
|
+
-----
|
|
1197
|
+
**Convergence behaviour**
|
|
1198
|
+
|
|
1199
|
+
By default, convergence is controlled by a *custom patience criterion*:
|
|
1200
|
+
the optimization terminates when the absolute difference between the
|
|
1201
|
+
current cost and the best cost seen so far is smaller than `tole` for
|
|
1202
|
+
`converge_iters` consecutive iterations.
|
|
1203
|
+
|
|
1204
|
+
To instead rely on SciPy's native convergence criteria (e.g. Nelder–Mead
|
|
1205
|
+
`xatol` / `fatol`), disable the custom criterion by setting
|
|
1206
|
+
`converge_iters=0` or `tole=None`. In that case, SciPy termination options
|
|
1207
|
+
supplied via `opt_options` are used.
|
|
1208
|
+
|
|
1185
1209
|
Parameters
|
|
1186
1210
|
----------
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1211
|
+
opt_options : dict, optional
|
|
1212
|
+
Options passed directly to `scipy.optimize.minimize`. These are only
|
|
1213
|
+
used for convergence if the custom criterion is disabled (see Notes).
|
|
1190
1214
|
"""
|
|
1191
|
-
return self._bayesian_loop_core(
|
|
1192
|
-
omega_min=omega_min,
|
|
1193
|
-
omega_max=omega_max,
|
|
1194
|
-
omega_num=omega_num,
|
|
1195
|
-
omega_I=omega_I,
|
|
1196
|
-
omega_M=omega_M,
|
|
1197
|
-
fermi_velocity=fermi_velocity,
|
|
1198
|
-
fermi_wavevector=fermi_wavevector,
|
|
1199
|
-
bare_mass=bare_mass,
|
|
1200
|
-
vary=vary,
|
|
1201
|
-
opt_method=opt_method,
|
|
1202
|
-
opt_options=opt_options,
|
|
1203
|
-
mem=mem,
|
|
1204
|
-
loop=loop,
|
|
1205
|
-
print_lines=print_lines,
|
|
1206
|
-
**mem_kwargs,
|
|
1207
|
-
)
|
|
1208
|
-
|
|
1209
1215
|
|
|
1210
|
-
def _bayesian_loop_core(self, *, omega_min, omega_max, omega_num, omega_I,
|
|
1211
|
-
omega_M, fermi_velocity=None, fermi_wavevector=None,
|
|
1212
|
-
bare_mass=None, vary=(), opt_method="Nelder-Mead",
|
|
1213
|
-
opt_options=None, mem=None, loop=None,
|
|
1214
|
-
print_lines=None, **mem_kwargs):
|
|
1215
|
-
r"""
|
|
1216
|
-
Core implementation of `bayesian_loop` (prints controlled by print_lines).
|
|
1217
|
-
|
|
1218
|
-
See `bayesian_loop` for API documentation.
|
|
1219
|
-
"""
|
|
1220
1216
|
fermi_velocity, fermi_wavevector, bare_mass = self._prepare_bare(
|
|
1221
|
-
fermi_velocity, fermi_wavevector, bare_mass
|
|
1222
|
-
|
|
1223
|
-
|
|
1217
|
+
fermi_velocity, fermi_wavevector, bare_mass)
|
|
1218
|
+
|
|
1224
1219
|
vary = tuple(vary) if vary is not None else ()
|
|
1225
1220
|
|
|
1226
1221
|
allowed = {"fermi_wavevector", "impurity_magnitude", "lambda_el", "h_n"}
|
|
@@ -1231,17 +1226,16 @@ class SelfEnergy:
|
|
|
1231
1226
|
allowed.add("bare_mass")
|
|
1232
1227
|
else:
|
|
1233
1228
|
raise NotImplementedError(
|
|
1234
|
-
"bayesian_loop does not support spectral class "
|
|
1235
|
-
f"'{self._class}'."
|
|
1229
|
+
f"bayesian_loop does not support spectral class '{self._class}'."
|
|
1236
1230
|
)
|
|
1237
|
-
|
|
1231
|
+
|
|
1238
1232
|
unknown = set(vary).difference(allowed)
|
|
1239
1233
|
if unknown:
|
|
1240
1234
|
raise ValueError(
|
|
1241
1235
|
f"Unsupported entries in vary: {sorted(unknown)}. "
|
|
1242
1236
|
f"Allowed: {sorted(allowed)}."
|
|
1243
1237
|
)
|
|
1244
|
-
|
|
1238
|
+
|
|
1245
1239
|
omega_num = int(omega_num)
|
|
1246
1240
|
if omega_num < 2:
|
|
1247
1241
|
raise ValueError("omega_num must be an integer >= 2.")
|
|
@@ -1307,15 +1301,21 @@ class SelfEnergy:
|
|
|
1307
1301
|
f"Initial h_n ({h_n0:g}) must be >= h_n_min ({h_n_min:g})."
|
|
1308
1302
|
)
|
|
1309
1303
|
if kF0 is None:
|
|
1310
|
-
raise ValueError(
|
|
1304
|
+
raise ValueError(
|
|
1305
|
+
"bayesian_loop requires an initial fermi_wavevector."
|
|
1306
|
+
)
|
|
1311
1307
|
if self._class == "SpectralLinear" and vF0 is None:
|
|
1312
|
-
raise ValueError(
|
|
1308
|
+
raise ValueError(
|
|
1309
|
+
"bayesian_loop requires an initial fermi_velocity."
|
|
1310
|
+
)
|
|
1313
1311
|
if self._class == "SpectralQuadratic" and mb0 is None:
|
|
1314
1312
|
raise ValueError("bayesian_loop requires an initial bare_mass.")
|
|
1315
|
-
|
|
1313
|
+
|
|
1316
1314
|
from scipy.optimize import minimize
|
|
1317
|
-
from collections import deque
|
|
1318
1315
|
from . import create_kernel_function, singular_value_decomposition
|
|
1316
|
+
|
|
1317
|
+
ecut_left = float(mem_cfg["ecut_left"])
|
|
1318
|
+
ecut_right = mem_cfg["ecut_right"]
|
|
1319
1319
|
|
|
1320
1320
|
ecut_left_eV = ecut_left / KILO
|
|
1321
1321
|
if ecut_right is None:
|
|
@@ -1346,14 +1346,10 @@ class SelfEnergy:
|
|
|
1346
1346
|
kernel_used = np.concatenate((np.real(kernel_raw), -np.imag(kernel_raw)))
|
|
1347
1347
|
elif parts == "real":
|
|
1348
1348
|
kernel_used = np.real(kernel_raw)
|
|
1349
|
-
else:
|
|
1349
|
+
else: # parts == "imag"
|
|
1350
1350
|
kernel_used = -np.imag(kernel_raw)
|
|
1351
1351
|
|
|
1352
|
-
|
|
1353
|
-
svd_verbose = (print_lines is None)
|
|
1354
|
-
V_Sigma, U, uvec0 = singular_value_decomposition(
|
|
1355
|
-
kernel_used, sigma_svd
|
|
1356
|
-
)
|
|
1352
|
+
V_Sigma, U, uvec0 = singular_value_decomposition(kernel_used, sigma_svd)
|
|
1357
1353
|
|
|
1358
1354
|
_precomp = {
|
|
1359
1355
|
"omega_range": omega_range,
|
|
@@ -1365,47 +1361,43 @@ class SelfEnergy:
|
|
|
1365
1361
|
"ecut_left": ecut_left,
|
|
1366
1362
|
"ecut_right": ecut_right,
|
|
1367
1363
|
}
|
|
1368
|
-
|
|
1364
|
+
|
|
1369
1365
|
def _reflect_min(xi, p0, p_min, scale):
|
|
1370
1366
|
"""Map R -> [p_min, +inf) using linear reflection around p_min."""
|
|
1371
1367
|
return p_min + np.abs((float(p0) - p_min) + scale * float(xi))
|
|
1372
1368
|
|
|
1373
1369
|
def _unpack_params(x):
|
|
1374
1370
|
params = {}
|
|
1371
|
+
|
|
1375
1372
|
i = 0
|
|
1376
1373
|
for name in vary:
|
|
1377
1374
|
xi = float(x[i])
|
|
1378
1375
|
|
|
1379
1376
|
if name == "fermi_velocity":
|
|
1380
1377
|
if vF0 is None:
|
|
1381
|
-
raise ValueError(
|
|
1382
|
-
|
|
1383
|
-
)
|
|
1378
|
+
raise ValueError("Cannot vary fermi_velocity: no "
|
|
1379
|
+
"initial vF provided.")
|
|
1384
1380
|
params["fermi_velocity"] = vF0 + scale_vF * xi
|
|
1385
1381
|
|
|
1386
1382
|
elif name == "bare_mass":
|
|
1387
1383
|
if mb0 is None:
|
|
1388
|
-
raise ValueError(
|
|
1389
|
-
|
|
1390
|
-
)
|
|
1384
|
+
raise ValueError("Cannot vary bare_mass: no initial "
|
|
1385
|
+
"bare_mass provided.")
|
|
1391
1386
|
params["bare_mass"] = mb0 + scale_mb * xi
|
|
1392
1387
|
|
|
1393
1388
|
elif name == "fermi_wavevector":
|
|
1394
1389
|
if kF0 is None:
|
|
1395
1390
|
raise ValueError(
|
|
1396
|
-
"Cannot vary fermi_wavevector: no initial kF
|
|
1391
|
+
"Cannot vary fermi_wavevector: no initial kF "
|
|
1392
|
+
"provided."
|
|
1397
1393
|
)
|
|
1398
1394
|
params["fermi_wavevector"] = kF0 + scale_kF * xi
|
|
1399
|
-
|
|
1395
|
+
|
|
1400
1396
|
elif name == "impurity_magnitude":
|
|
1401
|
-
params["impurity_magnitude"] = _reflect_min(
|
|
1402
|
-
xi, imp0, 0.0, scale_imp
|
|
1403
|
-
)
|
|
1397
|
+
params["impurity_magnitude"] = _reflect_min(xi, imp0, 0.0, scale_imp)
|
|
1404
1398
|
|
|
1405
1399
|
elif name == "lambda_el":
|
|
1406
|
-
params["lambda_el"] = _reflect_min(
|
|
1407
|
-
xi, lae0, 0.0, scale_lambda_el
|
|
1408
|
-
)
|
|
1400
|
+
params["lambda_el"] = _reflect_min(xi, lae0, 0.0, scale_lambda_el)
|
|
1409
1401
|
|
|
1410
1402
|
elif name == "h_n":
|
|
1411
1403
|
params["h_n"] = _reflect_min(xi, h_n0, h_n_min, scale_hn)
|
|
@@ -1443,14 +1435,14 @@ class SelfEnergy:
|
|
|
1443
1435
|
|
|
1444
1436
|
return self._cost_function(
|
|
1445
1437
|
optimisation_parameters=optimisation_parameters,
|
|
1446
|
-
omega_min=omega_min,
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1438
|
+
omega_min=omega_min, omega_max=omega_max, omega_num=omega_num,
|
|
1439
|
+
omega_I=omega_I, omega_M=omega_M, mem_cfg=mem_cfg,
|
|
1440
|
+
_precomp=_precomp
|
|
1441
|
+
)
|
|
1442
|
+
|
|
1443
|
+
last = {"cost": None, "spectrum": None, "model": None, "alpha": None}
|
|
1444
|
+
|
|
1445
|
+
iter_counter = {"n": 0}
|
|
1454
1446
|
|
|
1455
1447
|
class ConvergenceException(RuntimeError):
|
|
1456
1448
|
"""Raised when optimisation has converged successfully."""
|
|
@@ -1469,6 +1461,7 @@ class SelfEnergy:
|
|
|
1469
1461
|
if converge_iters < 0:
|
|
1470
1462
|
raise ValueError("converge_iters must be >= 0.")
|
|
1471
1463
|
|
|
1464
|
+
# Track best solution seen across all obj calls (not just last).
|
|
1472
1465
|
best_global = {
|
|
1473
1466
|
"x": None,
|
|
1474
1467
|
"params": None,
|
|
@@ -1479,53 +1472,25 @@ class SelfEnergy:
|
|
|
1479
1472
|
}
|
|
1480
1473
|
|
|
1481
1474
|
history = []
|
|
1475
|
+
|
|
1476
|
+
# Cache most recent evaluation so the callback can read a cost without
|
|
1477
|
+
# forcing an extra objective evaluation.
|
|
1478
|
+
last_x = {"x": None}
|
|
1482
1479
|
last_cost = {"cost": None}
|
|
1483
1480
|
initial_cost = {"cost": None}
|
|
1481
|
+
|
|
1484
1482
|
iter_counter = {"n": 0}
|
|
1485
1483
|
|
|
1486
1484
|
def _clean_params(params):
|
|
1487
1485
|
"""Convert NumPy scalar values to plain Python scalars."""
|
|
1488
1486
|
out = {}
|
|
1489
1487
|
for key, val in params.items():
|
|
1490
|
-
|
|
1488
|
+
if isinstance(val, np.generic):
|
|
1489
|
+
out[key] = float(val)
|
|
1490
|
+
else:
|
|
1491
|
+
out[key] = val
|
|
1491
1492
|
return out
|
|
1492
1493
|
|
|
1493
|
-
# --- Deterministic iteration printing (bulletproof) ---
|
|
1494
|
-
if print_lines is None:
|
|
1495
|
-
n_print = None
|
|
1496
|
-
else:
|
|
1497
|
-
n_print = int(print_lines)
|
|
1498
|
-
if n_print < 0:
|
|
1499
|
-
raise ValueError("print_lines must be >= 0 or None.")
|
|
1500
|
-
|
|
1501
|
-
tail_buf = deque(maxlen=0 if n_print is None else n_print)
|
|
1502
|
-
omitted = {"n": 0}
|
|
1503
|
-
|
|
1504
|
-
def _emit_iter_line(line):
|
|
1505
|
-
if n_print is None:
|
|
1506
|
-
print(line)
|
|
1507
|
-
return
|
|
1508
|
-
if n_print == 0:
|
|
1509
|
-
return
|
|
1510
|
-
if iter_counter["n"] <= n_print:
|
|
1511
|
-
print(line)
|
|
1512
|
-
else:
|
|
1513
|
-
tail_buf.append(line)
|
|
1514
|
-
omitted["n"] += 1
|
|
1515
|
-
|
|
1516
|
-
def _flush_tail(clear=True):
|
|
1517
|
-
if n_print is None or n_print == 0:
|
|
1518
|
-
return
|
|
1519
|
-
|
|
1520
|
-
if omitted["n"] > 0:
|
|
1521
|
-
print(f"... ({omitted['n']} lines omitted) ...")
|
|
1522
|
-
for line in tail_buf:
|
|
1523
|
-
print(line)
|
|
1524
|
-
|
|
1525
|
-
if clear:
|
|
1526
|
-
tail_buf.clear()
|
|
1527
|
-
omitted["n"] = 0
|
|
1528
|
-
|
|
1529
1494
|
def obj(x):
|
|
1530
1495
|
import warnings
|
|
1531
1496
|
|
|
@@ -1538,10 +1503,7 @@ class SelfEnergy:
|
|
|
1538
1503
|
try:
|
|
1539
1504
|
cost, spectrum, model, alpha_select = _evaluate_cost(params)
|
|
1540
1505
|
except RuntimeWarning as exc:
|
|
1541
|
-
raise ValueError(
|
|
1542
|
-
f"RuntimeWarning during cost eval: {exc}"
|
|
1543
|
-
) from exc
|
|
1544
|
-
|
|
1506
|
+
raise ValueError(f"RuntimeWarning during cost eval: {exc}") from exc
|
|
1545
1507
|
cost_f = float(cost)
|
|
1546
1508
|
|
|
1547
1509
|
history.append(
|
|
@@ -1555,7 +1517,14 @@ class SelfEnergy:
|
|
|
1555
1517
|
}
|
|
1556
1518
|
)
|
|
1557
1519
|
|
|
1520
|
+
last["cost"] = cost_f
|
|
1521
|
+
last["spectrum"] = spectrum
|
|
1522
|
+
last["model"] = model
|
|
1523
|
+
last["alpha"] = float(alpha_select)
|
|
1524
|
+
|
|
1525
|
+
last_x["x"] = np.array(x, dtype=float, copy=True)
|
|
1558
1526
|
last_cost["cost"] = cost_f
|
|
1527
|
+
|
|
1559
1528
|
if initial_cost["cost"] is None:
|
|
1560
1529
|
initial_cost["cost"] = cost_f
|
|
1561
1530
|
|
|
@@ -1570,15 +1539,18 @@ class SelfEnergy:
|
|
|
1570
1539
|
msg = [f"Iter {iter_counter['n']:4d} | cost = {cost: .4e}"]
|
|
1571
1540
|
for key in sorted(params):
|
|
1572
1541
|
msg.append(f"{key}={params[key]:.8g}")
|
|
1573
|
-
|
|
1542
|
+
print(" | ".join(msg))
|
|
1574
1543
|
|
|
1575
1544
|
return cost_f
|
|
1576
|
-
|
|
1545
|
+
|
|
1577
1546
|
class TerminationCallback:
|
|
1578
|
-
def __init__(self, tole, converge_iters,
|
|
1547
|
+
def __init__(self, tole, converge_iters,
|
|
1548
|
+
min_steps_for_regression):
|
|
1579
1549
|
self.tole = None if tole is None else float(tole)
|
|
1580
1550
|
self.converge_iters = int(converge_iters)
|
|
1581
|
-
self.min_steps_for_regression = int(
|
|
1551
|
+
self.min_steps_for_regression = int(
|
|
1552
|
+
min_steps_for_regression
|
|
1553
|
+
)
|
|
1582
1554
|
self.iter_count = 0
|
|
1583
1555
|
self.call_count = 0
|
|
1584
1556
|
|
|
@@ -1594,7 +1566,7 @@ class SelfEnergy:
|
|
|
1594
1566
|
|
|
1595
1567
|
best_cost = float(best_global["cost"])
|
|
1596
1568
|
if np.isfinite(best_cost):
|
|
1597
|
-
if abs(
|
|
1569
|
+
if abs(current - best_cost) < self.tole:
|
|
1598
1570
|
self.iter_count += 1
|
|
1599
1571
|
else:
|
|
1600
1572
|
self.iter_count = 0
|
|
@@ -1602,10 +1574,11 @@ class SelfEnergy:
|
|
|
1602
1574
|
if self.iter_count >= self.converge_iters:
|
|
1603
1575
|
raise ConvergenceException(
|
|
1604
1576
|
"Converged: |cost-best| < "
|
|
1605
|
-
f"{self.tole:g} for
|
|
1577
|
+
f"{self.tole:g} for "
|
|
1578
|
+
f"{self.converge_iters} iterations."
|
|
1606
1579
|
)
|
|
1607
1580
|
|
|
1608
|
-
if self.call_count < min_steps_for_regression:
|
|
1581
|
+
if self.call_count < self.min_steps_for_regression:
|
|
1609
1582
|
return
|
|
1610
1583
|
|
|
1611
1584
|
init_cost = initial_cost["cost"]
|
|
@@ -1618,7 +1591,10 @@ class SelfEnergy:
|
|
|
1618
1591
|
if not np.isfinite(best_cost):
|
|
1619
1592
|
return
|
|
1620
1593
|
|
|
1621
|
-
if
|
|
1594
|
+
if (
|
|
1595
|
+
abs(current - init_cost) * relative_best
|
|
1596
|
+
< abs(current - best_cost)
|
|
1597
|
+
):
|
|
1622
1598
|
raise RegressionException(
|
|
1623
1599
|
"Regression toward initial guess detected."
|
|
1624
1600
|
)
|
|
@@ -1648,12 +1624,19 @@ class SelfEnergy:
|
|
|
1648
1624
|
res = None
|
|
1649
1625
|
|
|
1650
1626
|
while retry_count <= max_retries:
|
|
1627
|
+
best = {
|
|
1628
|
+
"x": None,
|
|
1629
|
+
"params": None,
|
|
1630
|
+
"cost": np.inf,
|
|
1631
|
+
"spectrum": None,
|
|
1632
|
+
"model": None,
|
|
1633
|
+
"alpha": None,
|
|
1634
|
+
}
|
|
1635
|
+
last_x["x"] = None
|
|
1651
1636
|
last_cost["cost"] = None
|
|
1652
1637
|
initial_cost["cost"] = None
|
|
1653
1638
|
iter_counter["n"] = 0
|
|
1654
1639
|
history.clear()
|
|
1655
|
-
tail_buf.clear()
|
|
1656
|
-
omitted["n"] = 0
|
|
1657
1640
|
|
|
1658
1641
|
callback = TerminationCallback(
|
|
1659
1642
|
tole=tole,
|
|
@@ -1677,7 +1660,6 @@ class SelfEnergy:
|
|
|
1677
1660
|
break
|
|
1678
1661
|
|
|
1679
1662
|
except RegressionException as exc:
|
|
1680
|
-
_flush_tail()
|
|
1681
1663
|
print(f"{exc} Rolling back {rollback_steps} steps.")
|
|
1682
1664
|
retry_count += 1
|
|
1683
1665
|
|
|
@@ -1689,7 +1671,6 @@ class SelfEnergy:
|
|
|
1689
1671
|
continue
|
|
1690
1672
|
|
|
1691
1673
|
except ValueError as exc:
|
|
1692
|
-
_flush_tail()
|
|
1693
1674
|
print(f"ValueError encountered: {exc}. Rolling back.")
|
|
1694
1675
|
retry_count += 1
|
|
1695
1676
|
|
|
@@ -1700,8 +1681,6 @@ class SelfEnergy:
|
|
|
1700
1681
|
x0 = np.array(history[-back]["x"], dtype=float, copy=True)
|
|
1701
1682
|
continue
|
|
1702
1683
|
|
|
1703
|
-
_flush_tail()
|
|
1704
|
-
|
|
1705
1684
|
if retry_count > max_retries:
|
|
1706
1685
|
print("Max retries reached. Parameters may not be optimal.")
|
|
1707
1686
|
|
|
@@ -1723,13 +1702,14 @@ class SelfEnergy:
|
|
|
1723
1702
|
print("Optimised parameters:")
|
|
1724
1703
|
print(args)
|
|
1725
1704
|
|
|
1705
|
+
# store inside class methods
|
|
1726
1706
|
self._a2f_spectrum = spectrum
|
|
1727
1707
|
self._a2f_model = model
|
|
1728
1708
|
self._a2f_omega_range = omega_range
|
|
1729
1709
|
self._a2f_alpha_select = alpha_select
|
|
1730
1710
|
self._a2f_cost = cost
|
|
1731
1711
|
|
|
1732
|
-
return spectrum, model, omega_range, alpha_select, cost, params
|
|
1712
|
+
return spectrum, model, omega_range, alpha_select, cost, params
|
|
1733
1713
|
|
|
1734
1714
|
|
|
1735
1715
|
@staticmethod
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
xarpes/__init__.py,sha256=
|
|
1
|
+
xarpes/__init__.py,sha256=DFt2W5mUNCCXIJt4Q_h3xsCQn0U9nqO_3C1bEguzLnw,756
|
|
2
2
|
xarpes/bandmap.py,sha256=1B5GbRXFdBPqnmeKPJW0mzlz-IUoLD-28rxrThpp4co,34664
|
|
3
3
|
xarpes/constants.py,sha256=XOdgSzyrmHr5xocHZfmcFHHoVAa1G05a305hm3XOTtY,504
|
|
4
4
|
xarpes/distributions.py,sha256=pC8V5MlZDNFdooMonFREEASiN5QodHiyKc2ehnxMKvQ,23498
|
|
5
|
-
xarpes/functions.py,sha256=
|
|
5
|
+
xarpes/functions.py,sha256=oVAdNY0g44h7h6bXI8IYCiNbXfrLvBk7xD79ZQnbhno,25404
|
|
6
6
|
xarpes/mdcs.py,sha256=WRKSfGlRVKBssJp9FIHcAFsINVunPkmW9fBnFjqBHYI,42844
|
|
7
7
|
xarpes/plotting.py,sha256=lGCReHcXhYLQXR5ns3EHFjCQjJ9Sc-HifV7n4BnWby4,5189
|
|
8
|
-
xarpes/selfenergies.py,sha256=
|
|
8
|
+
xarpes/selfenergies.py,sha256=stbKhpDt49F8QTancIpOhgpTrdRvTvCBhvH770p0y-U,84176
|
|
9
9
|
xarpes/settings_parameters.py,sha256=yOYvgEiDeDiLzzLkvysCTiVwqg6fKIkN48B-WSad728,1912
|
|
10
10
|
xarpes/settings_plots.py,sha256=X-qteB2fIbBKOAcLMvMYDfQ8QdlUeA5xYQqF_Nyb4uA,1562
|
|
11
|
-
xarpes-0.6.
|
|
12
|
-
xarpes-0.6.
|
|
13
|
-
xarpes-0.6.
|
|
14
|
-
xarpes-0.6.
|
|
15
|
-
xarpes-0.6.
|
|
11
|
+
xarpes-0.6.5.dist-info/entry_points.txt,sha256=917UR-cqFTMMI_vMqIbk7boYSuFX_zHwQlXKcj9vlCE,79
|
|
12
|
+
xarpes-0.6.5.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
13
|
+
xarpes-0.6.5.dist-info/WHEEL,sha256=jPMR_Dzkc4X4icQtmz81lnNY_kAsfog7ry7qoRvYLXw,81
|
|
14
|
+
xarpes-0.6.5.dist-info/METADATA,sha256=sgr0wwth6Z-sAC4JaIlDXV_PCg9jFX8_F6ZracOhZO4,7154
|
|
15
|
+
xarpes-0.6.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|