omniopt2 8366__py3-none-any.whl → 9061__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.
Potentially problematic release.
This version of omniopt2 might be problematic. Click here for more details.
- .gitignore +2 -0
- .helpers.py +0 -9
- .omniopt.py +1369 -1011
- .pareto.py +134 -0
- .shellscript_functions +2 -2
- .tests/pylint.rc +0 -4
- .tpe.py +4 -3
- omniopt +56 -27
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.helpers.py +0 -9
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt.py +1369 -1011
- omniopt2-9061.data/data/bin/.pareto.py +134 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.shellscript_functions +2 -2
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.tpe.py +4 -3
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt +56 -27
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/pylint.rc +0 -4
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/requirements.txt +1 -2
- {omniopt2-8366.dist-info → omniopt2-9061.dist-info}/METADATA +2 -3
- omniopt2-9061.dist-info/RECORD +73 -0
- omniopt2.egg-info/PKG-INFO +2 -3
- omniopt2.egg-info/SOURCES.txt +1 -0
- omniopt2.egg-info/requires.txt +1 -2
- pyproject.toml +1 -1
- requirements.txt +1 -2
- omniopt2-8366.dist-info/RECORD +0 -71
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.colorfunctions.sh +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.general.sh +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_cpu_ram_usage.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_general.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_gpu_usage.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_kde.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_scatter.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_scatter_generation_method.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_scatter_hex.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_time_and_exit_code.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_trial_index_result.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_worker.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.random_generator.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/LICENSE +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/apt-dependencies.txt +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt_docker +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt_evaluate +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt_plot +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt_share +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/setup.py +0 -0
- {omniopt2-8366.data → omniopt2-9061.data}/data/bin/test_requirements.txt +0 -0
- {omniopt2-8366.dist-info → omniopt2-9061.dist-info}/WHEEL +0 -0
- {omniopt2-8366.dist-info → omniopt2-9061.dist-info}/licenses/LICENSE +0 -0
- {omniopt2-8366.dist-info → omniopt2-9061.dist-info}/top_level.txt +0 -0
.pareto.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import importlib.util
|
|
3
|
+
from typing import Tuple, List, Dict, Any
|
|
4
|
+
from rich.table import Table
|
|
5
|
+
from rich.text import Text
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# ----------------- Helpers import -----------------
|
|
10
|
+
script_dir = os.path.dirname(os.path.realpath(__file__))
|
|
11
|
+
helpers_file: str = f"{script_dir}/.helpers.py"
|
|
12
|
+
spec = importlib.util.spec_from_file_location(
|
|
13
|
+
name="helpers",
|
|
14
|
+
location=helpers_file,
|
|
15
|
+
)
|
|
16
|
+
if spec is not None and spec.loader is not None:
|
|
17
|
+
helpers = importlib.util.module_from_spec(spec)
|
|
18
|
+
spec.loader.exec_module(helpers)
|
|
19
|
+
else:
|
|
20
|
+
raise ImportError(f"Could not load module from {helpers_file}")
|
|
21
|
+
|
|
22
|
+
# ----------------- Table utilities -----------------
|
|
23
|
+
def pareto_front_table_filter_rows(rows: List[Dict[str, str]], idxs: List[int]) -> List[Dict[str, str]]:
|
|
24
|
+
result = []
|
|
25
|
+
for row in rows:
|
|
26
|
+
try:
|
|
27
|
+
trial_index = int(row["trial_index"])
|
|
28
|
+
except (KeyError, ValueError):
|
|
29
|
+
continue
|
|
30
|
+
|
|
31
|
+
if row.get("trial_status", "").strip().upper() == "COMPLETED" and trial_index in idxs:
|
|
32
|
+
result.append(row)
|
|
33
|
+
return result
|
|
34
|
+
|
|
35
|
+
def pareto_front_table_add_headers(table: Table, param_cols: List[str], result_cols: List[str]) -> None:
|
|
36
|
+
for col in param_cols:
|
|
37
|
+
table.add_column(col, justify="center")
|
|
38
|
+
for col in result_cols:
|
|
39
|
+
table.add_column(Text(f"{col}", style="cyan"), justify="center")
|
|
40
|
+
|
|
41
|
+
def pareto_front_table_add_rows(table: Table, rows: List[Dict[str, str]], param_cols: List[str], result_cols: List[str]) -> None:
|
|
42
|
+
for row in rows:
|
|
43
|
+
values = [str(helpers.to_int_when_possible(row[col])) for col in param_cols]
|
|
44
|
+
result_values = [Text(str(helpers.to_int_when_possible(row[col])), style="cyan") for col in result_cols]
|
|
45
|
+
table.add_row(*values, *result_values, style="bold green")
|
|
46
|
+
|
|
47
|
+
# ----------------- Pareto internal utilities -----------------
|
|
48
|
+
def _validate_xy(x: np.ndarray, y: np.ndarray) -> None:
|
|
49
|
+
if x.shape != y.shape:
|
|
50
|
+
raise ValueError("Input arrays x and y must have the same shape.")
|
|
51
|
+
if x.size == 0:
|
|
52
|
+
raise ValueError("Input arrays must not be empty.")
|
|
53
|
+
if not np.isfinite(x).all() or not np.isfinite(y).all():
|
|
54
|
+
raise ValueError("Input arrays must contain only finite numbers (no NaN/Inf).")
|
|
55
|
+
|
|
56
|
+
def _point_dominates(xi: float, yi: float, xj: float, yj: float, x_minimize: bool, y_minimize: bool) -> bool:
|
|
57
|
+
"""Return True if j dominates i (standard weak Pareto: >= in all, > in at least one)."""
|
|
58
|
+
if x_minimize:
|
|
59
|
+
x_better_eq = xj <= xi
|
|
60
|
+
x_strict = xj < xi
|
|
61
|
+
else:
|
|
62
|
+
x_better_eq = xj >= xi
|
|
63
|
+
x_strict = xj > xi
|
|
64
|
+
|
|
65
|
+
if y_minimize:
|
|
66
|
+
y_better_eq = yj <= yi
|
|
67
|
+
y_strict = yj < yi
|
|
68
|
+
else:
|
|
69
|
+
y_better_eq = yj >= yi
|
|
70
|
+
y_strict = yj > yi
|
|
71
|
+
|
|
72
|
+
return x_better_eq and y_better_eq and (x_strict or y_strict)
|
|
73
|
+
|
|
74
|
+
def _find_dominated(x: np.ndarray, y: np.ndarray, x_minimize: bool, y_minimize: bool) -> np.ndarray:
|
|
75
|
+
n = len(x)
|
|
76
|
+
is_dominated = np.zeros(n, dtype=bool)
|
|
77
|
+
for i in range(n):
|
|
78
|
+
if is_dominated[i]:
|
|
79
|
+
continue
|
|
80
|
+
xi, yi = x[i], y[i]
|
|
81
|
+
for j in range(n):
|
|
82
|
+
if i == j:
|
|
83
|
+
continue
|
|
84
|
+
xj, yj = x[j], y[j]
|
|
85
|
+
if _point_dominates(xi, yi, xj, yj, x_minimize, y_minimize):
|
|
86
|
+
is_dominated[i] = True
|
|
87
|
+
break
|
|
88
|
+
return is_dominated
|
|
89
|
+
|
|
90
|
+
# ----------------- Public Pareto functions -----------------
|
|
91
|
+
def pareto_front_general(
|
|
92
|
+
x: np.ndarray,
|
|
93
|
+
y: np.ndarray,
|
|
94
|
+
x_minimize: bool = True,
|
|
95
|
+
y_minimize: bool = True
|
|
96
|
+
) -> np.ndarray:
|
|
97
|
+
try:
|
|
98
|
+
xa = np.asarray(x, dtype=float).ravel()
|
|
99
|
+
ya = np.asarray(y, dtype=float).ravel()
|
|
100
|
+
_validate_xy(xa, ya)
|
|
101
|
+
is_dominated = _find_dominated(xa, ya, x_minimize, y_minimize)
|
|
102
|
+
return np.where(~is_dominated)[0]
|
|
103
|
+
except Exception as e:
|
|
104
|
+
print("Error in pareto_front_general:", str(e))
|
|
105
|
+
return np.array([], dtype=int)
|
|
106
|
+
|
|
107
|
+
def pareto_front_filter_complete_points(
|
|
108
|
+
path_to_calculate: str,
|
|
109
|
+
records: Dict[Tuple[int, str], Dict[str, Dict[str, float]]],
|
|
110
|
+
primary_name: str,
|
|
111
|
+
secondary_name: str
|
|
112
|
+
) -> List[Tuple[Tuple[int, str], float, float]]:
|
|
113
|
+
points = []
|
|
114
|
+
for key, metrics in records.items():
|
|
115
|
+
means = metrics['means']
|
|
116
|
+
if primary_name in means and secondary_name in means:
|
|
117
|
+
points.append((key, means[primary_name], means[secondary_name]))
|
|
118
|
+
if len(points) == 0:
|
|
119
|
+
raise ValueError(f"No full data points with both objectives found in {path_to_calculate}.")
|
|
120
|
+
return points
|
|
121
|
+
|
|
122
|
+
def pareto_front_select_pareto_points(
|
|
123
|
+
x: np.ndarray,
|
|
124
|
+
y: np.ndarray,
|
|
125
|
+
x_minimize: bool,
|
|
126
|
+
y_minimize: bool,
|
|
127
|
+
points: List[Tuple[Any, float, float]],
|
|
128
|
+
num_points: int
|
|
129
|
+
) -> List[Tuple[Any, float, float]]:
|
|
130
|
+
indices = pareto_front_general(x, y, x_minimize, y_minimize)
|
|
131
|
+
# Sort by x ascending
|
|
132
|
+
sorted_indices = indices[np.argsort(x[indices])]
|
|
133
|
+
selected_points = [points[i] for i in sorted_indices[:num_points]]
|
|
134
|
+
return selected_points
|
.shellscript_functions
CHANGED
|
@@ -266,7 +266,7 @@
|
|
|
266
266
|
|
|
267
267
|
if [[ -z $DEBUG ]]; then
|
|
268
268
|
pip3 --disable-pip-version-check install -q $MODULE >&2 2>> $INSTALL_ERRORS_FILE || pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || {
|
|
269
|
-
red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE"
|
|
269
|
+
red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE\n"
|
|
270
270
|
|
|
271
271
|
if [[ -n $CI ]] || { [[ -f /proc/self/cgroup ]] && grep -qE '/docker|/lxc' /proc/self/cgroup; }; then
|
|
272
272
|
cat "$INSTALL_ERRORS_FILE"
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
}
|
|
277
277
|
else
|
|
278
278
|
pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || {
|
|
279
|
-
red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE"
|
|
279
|
+
red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE\n"
|
|
280
280
|
|
|
281
281
|
if [[ -n $CI ]] || { [[ -f /proc/self/cgroup ]] && grep -qE '/docker|/lxc' /proc/self/cgroup; }; then
|
|
282
282
|
cat "$INSTALL_ERRORS_FILE"
|
.tests/pylint.rc
CHANGED
|
@@ -103,10 +103,6 @@ recursive=no
|
|
|
103
103
|
# source root.
|
|
104
104
|
source-roots=
|
|
105
105
|
|
|
106
|
-
# When enabled, pylint would attempt to guess common misconfiguration and emit
|
|
107
|
-
# user-friendly hints instead of false-positive error messages.
|
|
108
|
-
suggestion-mode=yes
|
|
109
|
-
|
|
110
106
|
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
|
111
107
|
# active Python interpreter and may run arbitrary code.
|
|
112
108
|
unsafe-load-any-extension=no
|
.tpe.py
CHANGED
|
@@ -2,7 +2,8 @@ import sys
|
|
|
2
2
|
import os
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
|
-
from typing import Optional
|
|
5
|
+
from typing import Optional, Any
|
|
6
|
+
|
|
6
7
|
try:
|
|
7
8
|
import optuna
|
|
8
9
|
from optuna.trial import create_trial
|
|
@@ -52,7 +53,7 @@ def tpe_suggest_point(trial: optuna.Trial, parameters: dict) -> dict:
|
|
|
52
53
|
if pvaltype == 'INT':
|
|
53
54
|
point[param_name] = trial.suggest_int(param_name, rmin, rmax)
|
|
54
55
|
elif pvaltype == 'FLOAT':
|
|
55
|
-
point[param_name] = trial.suggest_float(param_name, rmin, rmax)
|
|
56
|
+
point[param_name] = trial.suggest_float(param_name, rmin, rmax) # type: ignore[assignment]
|
|
56
57
|
else:
|
|
57
58
|
raise ValueError(f"Unsupported type {pvaltype} for RANGE")
|
|
58
59
|
|
|
@@ -162,7 +163,7 @@ def add_existing_trial_to_study(study: optuna.study.study.Study, trial_entry: li
|
|
|
162
163
|
)
|
|
163
164
|
|
|
164
165
|
@beartype
|
|
165
|
-
def get_best_or_new_point(study:
|
|
166
|
+
def get_best_or_new_point(study: Any, parameters: dict, direction: str) -> dict:
|
|
166
167
|
best_trial_value = study.best_trial.value
|
|
167
168
|
if best_trial_value is not None:
|
|
168
169
|
if (direction == "minimize" and best_trial_value < 1e6) or \
|
omniopt
CHANGED
|
@@ -346,10 +346,35 @@
|
|
|
346
346
|
send_anonymized_usage_stats=0
|
|
347
347
|
already_shown_oo_base_url_msg=0
|
|
348
348
|
|
|
349
|
+
function run_live_share {
|
|
350
|
+
if [[ $RUN_UUID != "" ]]; then
|
|
351
|
+
full_log_file="$ORIGINAL_PWD/logs/$RUN_UUID"
|
|
352
|
+
if [[ -e "$full_log_file" ]]; then
|
|
353
|
+
set +e
|
|
354
|
+
run_folder=$(cat "$full_log_file" | grep "Run-folder:" | sed -e 's#Run-folder: ##')
|
|
355
|
+
if [[ -z $run_folder ]]; then
|
|
356
|
+
true
|
|
357
|
+
else
|
|
358
|
+
bash "$SCRIPT_DIR/omniopt_share" --username="$USER" "$run_folder" 2>/dev/null >/dev/null
|
|
359
|
+
fi
|
|
360
|
+
set -e
|
|
361
|
+
else
|
|
362
|
+
red_text "--live_share enabled, but $full_log_file could not be found. Cannot share once again in finalization.\n"
|
|
363
|
+
fi
|
|
364
|
+
fi
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function start_periodidic_live_share {
|
|
368
|
+
while true; do
|
|
369
|
+
run_live_share 2>/dev/null >/dev/null
|
|
370
|
+
sleep 10
|
|
371
|
+
done
|
|
372
|
+
}
|
|
373
|
+
|
|
349
374
|
function myexit {
|
|
350
375
|
CODE=$1
|
|
351
376
|
|
|
352
|
-
end_all_bg_processes
|
|
377
|
+
end_all_bg_processes 2>/dev/null
|
|
353
378
|
|
|
354
379
|
if [[ $follow -eq 1 ]]; then
|
|
355
380
|
if [[ -z $CODE ]] || ! [[ $CODE =~ $int_re ]]; then
|
|
@@ -382,21 +407,7 @@
|
|
|
382
407
|
|
|
383
408
|
if [[ $follow -eq 1 ]] || ! command -v sbatch 2>/dev/null >/dev/null || [[ $force_local_execution -eq 1 ]]; then
|
|
384
409
|
if [[ $live_share -eq 1 ]]; then
|
|
385
|
-
|
|
386
|
-
full_log_file="$ORIGINAL_PWD/logs/$RUN_UUID"
|
|
387
|
-
if [[ -e "$full_log_file" ]]; then
|
|
388
|
-
set +e
|
|
389
|
-
run_folder=$(cat "$full_log_file" | grep "Run-folder:" | sed -e 's#Run-folder: ##')
|
|
390
|
-
if [[ -z $run_folder ]]; then
|
|
391
|
-
true
|
|
392
|
-
else
|
|
393
|
-
bash "$SCRIPT_DIR/omniopt_share" --username="$USER" "$run_folder" 2>/dev/null >/dev/null
|
|
394
|
-
fi
|
|
395
|
-
set -e
|
|
396
|
-
else
|
|
397
|
-
red_text "--live_share enabled, but $full_log_file could not be found. Cannot share once again in finalization.\n"
|
|
398
|
-
fi
|
|
399
|
-
fi
|
|
410
|
+
run_live_share
|
|
400
411
|
fi
|
|
401
412
|
fi
|
|
402
413
|
|
|
@@ -1005,6 +1016,10 @@ $complex_options_str
|
|
|
1005
1016
|
args_string+=" --help "
|
|
1006
1017
|
;;
|
|
1007
1018
|
|
|
1019
|
+
--memray)
|
|
1020
|
+
export RUN_WITH_MEMRAY=1
|
|
1021
|
+
;;
|
|
1022
|
+
|
|
1008
1023
|
--flame_graph)
|
|
1009
1024
|
export RUN_WITH_PYSPY=1
|
|
1010
1025
|
;;
|
|
@@ -1620,15 +1635,30 @@ EOF
|
|
|
1620
1635
|
set +e
|
|
1621
1636
|
trap - ERR
|
|
1622
1637
|
|
|
1638
|
+
live_share_pid=""
|
|
1639
|
+
|
|
1640
|
+
if [[ $live_share -eq 1 ]]; then
|
|
1641
|
+
start_periodidic_live_share &
|
|
1642
|
+
live_share_pid=$!
|
|
1643
|
+
fi
|
|
1644
|
+
|
|
1623
1645
|
if [[ -z $RUN_WITH_COVERAGE ]]; then
|
|
1624
|
-
if [[ -
|
|
1625
|
-
stdbuf -e 0 -o 0 python3 "$SCRIPT_DIR/.omniopt.py" $args_string
|
|
1626
|
-
EXIT_CODE=$?
|
|
1627
|
-
else
|
|
1646
|
+
if [[ -n $RUN_WITH_PYSPY ]]; then
|
|
1628
1647
|
echo "Starting OmniOpt with Py-Spy"
|
|
1629
1648
|
pip install py-spy
|
|
1630
1649
|
stdbuf -e 0 -o 0 py-spy record --rate 10 --subprocesses --native --output "$RUN_UUID.svg" python3 -- "$SCRIPT_DIR/.omniopt.py" $args_string
|
|
1631
1650
|
EXIT_CODE=$?
|
|
1651
|
+
elif [[ -n $RUN_WITH_MEMRAY ]]; then
|
|
1652
|
+
echo "Starting OmniOpt with MemRay."
|
|
1653
|
+
echo "Check later on with 'memray flamegraph $RUN_UUID.bin'"
|
|
1654
|
+
export PYTORCH_NO_CUDA_MEMORY_CACHING=1
|
|
1655
|
+
export PYTHONFAULTHANDLER=1
|
|
1656
|
+
pip install memray
|
|
1657
|
+
stdbuf -e 0 -o 0 memray run -o "$RUN_UUID.bin" -- "$SCRIPT_DIR/.omniopt.py" $args_string
|
|
1658
|
+
EXIT_CODE=$?
|
|
1659
|
+
else
|
|
1660
|
+
stdbuf -e 0 -o 0 python3 "$SCRIPT_DIR/.omniopt.py" $args_string
|
|
1661
|
+
EXIT_CODE=$?
|
|
1632
1662
|
fi
|
|
1633
1663
|
else
|
|
1634
1664
|
echo "Using coverage run -p because \$RUN_WITH_COVERAGE is set"
|
|
@@ -1636,6 +1666,10 @@ EOF
|
|
|
1636
1666
|
EXIT_CODE=$?
|
|
1637
1667
|
fi
|
|
1638
1668
|
|
|
1669
|
+
if [[ $live_share -eq 1 ]] && [[ -n $live_share_pid ]]; then
|
|
1670
|
+
kill -9 $live_share_pid >/dev/null 2>/dev/null
|
|
1671
|
+
fi
|
|
1672
|
+
|
|
1639
1673
|
set -e
|
|
1640
1674
|
trap 'calltracer' ERR
|
|
1641
1675
|
|
|
@@ -1843,7 +1877,7 @@ EOF
|
|
|
1843
1877
|
kill_tail_when_squeue_job_empty "$started_job_nr" &
|
|
1844
1878
|
|
|
1845
1879
|
tail_log_file() {
|
|
1846
|
-
trap 'ask_cancel' SIGINT
|
|
1880
|
+
#trap 'ask_cancel' SIGINT
|
|
1847
1881
|
# weird exec stuff for disabling the "Terminated" message coming from kill
|
|
1848
1882
|
exec 3>&2 # 3 is now a copy of 2
|
|
1849
1883
|
exec 2> /dev/null # 2 now points to /dev/null
|
|
@@ -1890,34 +1924,29 @@ EOF
|
|
|
1890
1924
|
exit_code_lines=$(grep -i "exit-code:*" "$LOG_PATH" 2>/dev/null)
|
|
1891
1925
|
exit_code_lines_lines=$?
|
|
1892
1926
|
if [ $exit_code_lines_lines -ne 0 ] || [ -z "$exit_code_lines" ]; then
|
|
1893
|
-
echo "WARN: grep failed or no exit-code line found."
|
|
1894
1927
|
exit_code_lines=""
|
|
1895
1928
|
fi
|
|
1896
1929
|
|
|
1897
1930
|
exit_code_sed=$(echo "$exit_code_lines" | sed -e 's#Exit-Code:*[[:space:]]*##i' -e 's#,.*##')
|
|
1898
1931
|
exit_code_sed_sed=$?
|
|
1899
1932
|
if [ $exit_code_sed_sed -ne 0 ] || [ -z "$exit_code_sed" ]; then
|
|
1900
|
-
echo "WARN: sed failed or no data after sed."
|
|
1901
1933
|
exit_code_sed=""
|
|
1902
1934
|
fi
|
|
1903
1935
|
|
|
1904
1936
|
exit_code_tail=$(echo "$exit_code_sed" | tail -n1)
|
|
1905
1937
|
exit_code_tail_tail=$?
|
|
1906
1938
|
if [ $exit_code_tail_tail -ne 0 ] || [ -z "$exit_code_tail" ]; then
|
|
1907
|
-
echo "WARN: tail failed or no data after tail."
|
|
1908
1939
|
exit_code_tail=""
|
|
1909
1940
|
fi
|
|
1910
1941
|
|
|
1911
|
-
exit_code_only_digits=$(echo "$exit_code_tail" | grep -o '[0-9]\+')
|
|
1942
|
+
exit_code_only_digits=$(echo "$exit_code_tail" | grep -o '[0-9]\+' | tail -n1)
|
|
1912
1943
|
if [ -z "$exit_code_only_digits" ]; then
|
|
1913
|
-
echo "WARN: No valid exit code found, setting it to 3"
|
|
1914
1944
|
exit_code_only_digits=3
|
|
1915
1945
|
fi
|
|
1916
1946
|
|
|
1917
1947
|
exit_code="$exit_code_only_digits"
|
|
1918
1948
|
|
|
1919
1949
|
if ! [[ "$exit_code" =~ ^[0-9]+$ ]]; then
|
|
1920
|
-
echo "WARN: exit_code invalid ('$exit_code'), setting to 3"
|
|
1921
1950
|
exit_code=3
|
|
1922
1951
|
fi
|
|
1923
1952
|
|
|
@@ -10,7 +10,6 @@ try:
|
|
|
10
10
|
import difflib
|
|
11
11
|
import logging
|
|
12
12
|
import os
|
|
13
|
-
import platform
|
|
14
13
|
import re
|
|
15
14
|
import traceback
|
|
16
15
|
import numpy as np
|
|
@@ -227,12 +226,6 @@ def print_color(color: str, text: str) -> None:
|
|
|
227
226
|
print(f"Error: {e}")
|
|
228
227
|
print(text)
|
|
229
228
|
|
|
230
|
-
def check_python_version() -> None:
|
|
231
|
-
python_version = platform.python_version()
|
|
232
|
-
supported_versions = ["3.8.10", "3.8.20", "3.9.21", "3.10.4", "3.10.12", "3.11.2", "3.11.9", "3.9.2", "3.11.3", "3.12.3", "3.12.4", "3.12.5", "3.12.6", "3.12.7", "3.12.7+", "3.12.8", "3.13.1", "3.13.2", "3.13.3", "3.13.5"]
|
|
233
|
-
if python_version not in supported_versions:
|
|
234
|
-
print_color("yellow", f"Warning: Supported python versions are {', '.join(supported_versions)}, but you are running {python_version}. This may or may not cause problems. Just is just a warning.")
|
|
235
|
-
|
|
236
229
|
def create_widgets(_data: Any) -> Any:
|
|
237
230
|
_plt, button, MAXIMUM_TEXTBOX, MINIMUM_TEXTBOX, _args, TEXTBOX_MINIMUM, TEXTBOX_MAXIMUM, update_graph = _data
|
|
238
231
|
|
|
@@ -882,5 +875,3 @@ def die_if_cannot_be_plotted(run_dir: Optional[str]) -> None:
|
|
|
882
875
|
if not can_be_plotted(run_dir):
|
|
883
876
|
log_error(f"{run_dir} contains multiple RESULTS and thus can only be plotted by parallel plot")
|
|
884
877
|
sys.exit(2)
|
|
885
|
-
|
|
886
|
-
check_python_version()
|