pythonQEPest 2.0.0a2__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.
- pythonQEPest/.env.example +4 -0
- pythonQEPest/__init__.py +11 -0
- pythonQEPest/cli/__init__.py +7 -0
- pythonQEPest/cli/cli.py +101 -0
- pythonQEPest/config/__init__.py +11 -0
- pythonQEPest/config/config_provider.py +9 -0
- pythonQEPest/config/normalise.py +12 -0
- pythonQEPest/config/qepest_config.py +31 -0
- pythonQEPest/config/qepest_default.py +26 -0
- pythonQEPest/core/__init__.py +7 -0
- pythonQEPest/core/qepest.py +98 -0
- pythonQEPest/core/qepest_meta.py +28 -0
- pythonQEPest/data.txt +2 -0
- pythonQEPest/data.txt.out +2 -0
- pythonQEPest/dto/QEPestData.py +21 -0
- pythonQEPest/dto/QEPestFile.py +34 -0
- pythonQEPest/dto/QEPestInput.py +60 -0
- pythonQEPest/dto/QEPestOutput.py +13 -0
- pythonQEPest/dto/__init__.py +27 -0
- pythonQEPest/dto/coefficients/QEPestCoefficient.py +57 -0
- pythonQEPest/dto/coefficients/QEPestCoefficientList.py +29 -0
- pythonQEPest/dto/coefficients/QEPestCoefficientNumerics.py +44 -0
- pythonQEPest/dto/coefficients/__init__.py +7 -0
- pythonQEPest/dto/normalisation/Normaliser.py +16 -0
- pythonQEPest/dto/normalisation/__init__.py +3 -0
- pythonQEPest/dto/pest_type/PestTypeCoefficient.py +30 -0
- pythonQEPest/dto/pest_type/PestTypeConfig.py +9 -0
- pythonQEPest/dto/pest_type/__init__.py +4 -0
- pythonQEPest/gui/__init__.py +7 -0
- pythonQEPest/gui/actions/__init__.py +9 -0
- pythonQEPest/gui/actions/action_clicks.py +42 -0
- pythonQEPest/gui/actions/actions_crud.py +131 -0
- pythonQEPest/gui/actions/actions_other.py +126 -0
- pythonQEPest/gui/elements/ButtonsFrame.py +50 -0
- pythonQEPest/gui/elements/DataTree.py +23 -0
- pythonQEPest/gui/elements/EditWindow.py +63 -0
- pythonQEPest/gui/elements/Menu.py +12 -0
- pythonQEPest/gui/elements/ResultTree.py +22 -0
- pythonQEPest/gui/elements/SaveButton.py +10 -0
- pythonQEPest/gui/elements/__init__.py +17 -0
- pythonQEPest/gui/gui.py +87 -0
- pythonQEPest/gui/gui_meta.py +17 -0
- pythonQEPest/gui/utility/DataManager.py +76 -0
- pythonQEPest/gui/utility/DataManagerMeta.py +8 -0
- pythonQEPest/gui/utility/__init__.py +6 -0
- pythonQEPest/helpers/__init__.py +17 -0
- pythonQEPest/helpers/check_nan.py +8 -0
- pythonQEPest/helpers/compute_df.py +5 -0
- pythonQEPest/helpers/get_num_of_cols.py +2 -0
- pythonQEPest/helpers/get_values_from_line.py +5 -0
- pythonQEPest/helpers/norm.py +33 -0
- pythonQEPest/helpers/round_to_4digs.py +2 -0
- pythonQEPest/logger.py +58 -0
- pythonQEPest/main.py +4 -0
- pythonQEPest/providers/__init__.py +6 -0
- pythonQEPest/providers/default_provider.py +23 -0
- pythonQEPest/providers/json_provider.py +30 -0
- pythonQEPest/providers/txt_provider.py +46 -0
- pythonQEPest/services/QEPestFileService.py +125 -0
- pythonQEPest/services/__init__.py +3 -0
- pythonqepest-2.0.0a2.dist-info/METADATA +217 -0
- pythonqepest-2.0.0a2.dist-info/RECORD +64 -0
- pythonqepest-2.0.0a2.dist-info/WHEEL +4 -0
- pythonqepest-2.0.0a2.dist-info/entry_points.txt +6 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from pythonQEPest.core.qepest import QEPest
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class QEPestMeta(ABC):
|
|
7
|
+
def __init__(self, root):
|
|
8
|
+
self.root = root
|
|
9
|
+
self.root.title("PythonQEPest")
|
|
10
|
+
|
|
11
|
+
self.qepest = QEPest()
|
|
12
|
+
|
|
13
|
+
self.build_gui()
|
|
14
|
+
|
|
15
|
+
@abstractmethod
|
|
16
|
+
def build_gui(self):
|
|
17
|
+
pass
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from pythonQEPest.gui.utility.DataManagerMeta import DataManagerMeta
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DataManager(metaclass=DataManagerMeta):
|
|
5
|
+
def __init__(self, *args, **kwargs):
|
|
6
|
+
super().__init__(*args, **kwargs)
|
|
7
|
+
self._file_data = []
|
|
8
|
+
self._result_data = []
|
|
9
|
+
|
|
10
|
+
# def __call__(self, *args, **kwargs) -> list:
|
|
11
|
+
# return self.file_data
|
|
12
|
+
|
|
13
|
+
# def __bool__(self):
|
|
14
|
+
# return bool(self.file_data)
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def file_data(self):
|
|
18
|
+
return self._file_data
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def result_data(self):
|
|
22
|
+
return self._result_data
|
|
23
|
+
|
|
24
|
+
def clear(self, lst):
|
|
25
|
+
lst.clear()
|
|
26
|
+
return self
|
|
27
|
+
|
|
28
|
+
def add(self, lst, entry):
|
|
29
|
+
if not entry in lst:
|
|
30
|
+
lst.append(entry)
|
|
31
|
+
return self
|
|
32
|
+
|
|
33
|
+
def update(self, lst, index, new_entry):
|
|
34
|
+
if 0 <= index < len(lst):
|
|
35
|
+
lst[index] = new_entry
|
|
36
|
+
return self
|
|
37
|
+
|
|
38
|
+
def remove_by_id(self, lst, id: str | int):
|
|
39
|
+
return [row for row in lst if row[0] != id]
|
|
40
|
+
|
|
41
|
+
def remove_by_ids(self, lst, ids: list[str, int]):
|
|
42
|
+
return [row for row in lst if row[0] not in ids]
|
|
43
|
+
|
|
44
|
+
def clear_file(self):
|
|
45
|
+
return self.clear(self.file_data)
|
|
46
|
+
|
|
47
|
+
def add_file(self, entry):
|
|
48
|
+
return self.add(self.file_data, entry)
|
|
49
|
+
|
|
50
|
+
def update_file(self, index, new_entry):
|
|
51
|
+
return self.update(self.file_data, index, new_entry)
|
|
52
|
+
|
|
53
|
+
def remove_file_by_id(self, id: str | int):
|
|
54
|
+
self._file_data = self.remove_by_id(self.file_data, id)
|
|
55
|
+
return self
|
|
56
|
+
|
|
57
|
+
def remove_file_by_ids(self, ids: list[str, int]):
|
|
58
|
+
self._file_data = self.remove_by_ids(self.file_data, ids)
|
|
59
|
+
return self
|
|
60
|
+
|
|
61
|
+
def clear_result(self):
|
|
62
|
+
return self.clear(self.result_data)
|
|
63
|
+
|
|
64
|
+
def add_result(self, entry):
|
|
65
|
+
return self.add(self.result_data, entry)
|
|
66
|
+
|
|
67
|
+
def update_result(self, index, new_entry):
|
|
68
|
+
return self.update(self.result_data, index, new_entry)
|
|
69
|
+
|
|
70
|
+
def remove_result_by_id(self, id: str | int):
|
|
71
|
+
self._result_data = self.remove_by_id(self.result_data, id)
|
|
72
|
+
return self
|
|
73
|
+
|
|
74
|
+
def remove_result_by_ids(self, ids: list[str, int]):
|
|
75
|
+
self._result_data = self.remove_by_ids(self.result_data, ids)
|
|
76
|
+
return self
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from pythonQEPest.helpers.check_nan import check_nan
|
|
2
|
+
from pythonQEPest.helpers.compute_df import compute_df
|
|
3
|
+
from pythonQEPest.helpers.get_num_of_cols import get_num_of_cols
|
|
4
|
+
from pythonQEPest.helpers.get_values_from_line import get_values_from_line
|
|
5
|
+
from pythonQEPest.helpers.norm import norm_h, norm_f, norm_i
|
|
6
|
+
from pythonQEPest.helpers.round_to_4digs import round_to_4digs
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"check_nan",
|
|
10
|
+
"compute_df",
|
|
11
|
+
"get_num_of_cols",
|
|
12
|
+
"get_values_from_line",
|
|
13
|
+
"norm_h",
|
|
14
|
+
"norm_f",
|
|
15
|
+
"norm_i",
|
|
16
|
+
"round_to_4digs",
|
|
17
|
+
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def norm(arr: Union[list, tuple], d: Union[int, float], descr: int) -> float:
|
|
5
|
+
if descr > len(arr):
|
|
6
|
+
raise KeyError(f"Out of array. {descr} > {len(arr)}")
|
|
7
|
+
|
|
8
|
+
max_val = arr[int(descr)]
|
|
9
|
+
return d / max_val if max_val != 0 else 0.0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def norm_h(d: Union[int, float], descr: int) -> float:
|
|
13
|
+
return norm(
|
|
14
|
+
(69.5849922, 94.4228257, 120.4572352, 228.1589796, 89.7012502, 276.9634213),
|
|
15
|
+
d,
|
|
16
|
+
descr,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def norm_i(d: Union[int, float], descr: int) -> float:
|
|
21
|
+
return norm(
|
|
22
|
+
(78.2919965, 71.2829691, 133.9224801, 331.170104, 70.5540709, 193.0023343),
|
|
23
|
+
d,
|
|
24
|
+
descr,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def norm_f(d: Union[int, float], descr: int) -> float:
|
|
29
|
+
return norm(
|
|
30
|
+
(53.3719946, 52.773116, 73.7976536, 144.9887053, 41.4385926, 102.3024319),
|
|
31
|
+
d,
|
|
32
|
+
descr,
|
|
33
|
+
)
|
pythonQEPest/logger.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from logging.handlers import RotatingFileHandler
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def init_logger() -> None:
|
|
8
|
+
# If debug mode is enabled, we want to log everything, otherwise we can skip logging
|
|
9
|
+
if os.getenv("APP_DEBUG_ENABLE", "true").lower() == "false":
|
|
10
|
+
return
|
|
11
|
+
|
|
12
|
+
root_logger = logging.getLogger("pythonQEPest")
|
|
13
|
+
|
|
14
|
+
log_file: str = os.getenv("LOG_FILE_LOCATION", "logs/app.log")
|
|
15
|
+
level = os.getenv("LOG_LEVEL", "INFO").upper()
|
|
16
|
+
|
|
17
|
+
match level:
|
|
18
|
+
case "DEBUG":
|
|
19
|
+
level = logging.DEBUG
|
|
20
|
+
case "INFO":
|
|
21
|
+
level = logging.INFO
|
|
22
|
+
case "WARNING":
|
|
23
|
+
level = logging.WARNING
|
|
24
|
+
case "ERROR":
|
|
25
|
+
level = logging.ERROR
|
|
26
|
+
case _:
|
|
27
|
+
level = logging.INFO
|
|
28
|
+
|
|
29
|
+
if root_logger.handlers:
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
log_path = Path(log_file)
|
|
33
|
+
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
|
|
35
|
+
formatter = logging.Formatter(
|
|
36
|
+
fmt="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
37
|
+
datefmt="%Y-%m-%d %H:%M:%S",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
file_handler = RotatingFileHandler(
|
|
41
|
+
log_path,
|
|
42
|
+
maxBytes=1_000_000,
|
|
43
|
+
backupCount=3,
|
|
44
|
+
encoding="utf-8",
|
|
45
|
+
)
|
|
46
|
+
file_handler.setLevel(level)
|
|
47
|
+
file_handler.setFormatter(formatter)
|
|
48
|
+
|
|
49
|
+
console_handler = logging.StreamHandler()
|
|
50
|
+
console_handler.setLevel(level)
|
|
51
|
+
console_handler.setFormatter(formatter)
|
|
52
|
+
|
|
53
|
+
root_logger.setLevel(level)
|
|
54
|
+
root_logger.addHandler(file_handler)
|
|
55
|
+
root_logger.addHandler(console_handler)
|
|
56
|
+
|
|
57
|
+
root_logger.info("Logger started Successfully")
|
|
58
|
+
root_logger.info(f"Level: {level}")
|
pythonQEPest/main.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from pythonQEPest.config.config_provider import ConfigProvider
|
|
2
|
+
from pythonQEPest.config.qepest_config import QEPestConfig, PestTypeConfig
|
|
3
|
+
from pythonQEPest.dto import PestTypeCoefficient
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DefaultConfigProvider(ConfigProvider):
|
|
7
|
+
def load(self) -> QEPestConfig:
|
|
8
|
+
from pythonQEPest.config.qepest_default import qepest_default
|
|
9
|
+
from pythonQEPest.config.normalise import normalise_default
|
|
10
|
+
|
|
11
|
+
pest_types = []
|
|
12
|
+
for pest_name in qepest_default.keys():
|
|
13
|
+
pest_types.append(
|
|
14
|
+
PestTypeConfig(
|
|
15
|
+
name=pest_name,
|
|
16
|
+
coefficients=PestTypeCoefficient.model_validate(
|
|
17
|
+
qepest_default[pest_name]
|
|
18
|
+
),
|
|
19
|
+
normaliser=normalise_default[pest_name],
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
return QEPestConfig(pest_types=pest_types)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from pythonQEPest.config.config_provider import ConfigProvider
|
|
5
|
+
from pythonQEPest.config.qepest_config import QEPestConfig, PestTypeConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class JSONConfigProvider(ConfigProvider):
|
|
9
|
+
def load(self, path: str | Path) -> QEPestConfig:
|
|
10
|
+
path = Path(path)
|
|
11
|
+
|
|
12
|
+
with open(path, encoding="utf-8") as f:
|
|
13
|
+
data = json.load(f)
|
|
14
|
+
|
|
15
|
+
return self.load_raw_json(data)
|
|
16
|
+
|
|
17
|
+
def load_raw_json(self, data):
|
|
18
|
+
pest_types = []
|
|
19
|
+
for pest_name, pest_data in data.items():
|
|
20
|
+
coefficients = [tuple(coef) for coef in pest_data["coefficients"]]
|
|
21
|
+
normaliser = tuple(pest_data["normaliser"])
|
|
22
|
+
pest_types.append(
|
|
23
|
+
PestTypeConfig(
|
|
24
|
+
name=pest_name,
|
|
25
|
+
coefficients=coefficients,
|
|
26
|
+
normaliser=normaliser,
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
return QEPestConfig(pest_types=pest_types)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from pythonQEPest.config.config_provider import ConfigProvider
|
|
4
|
+
from pythonQEPest.config.qepest_config import QEPestConfig, PestTypeConfig
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TXTConfigProvider(ConfigProvider):
|
|
8
|
+
def __init__(self, path: str | Path):
|
|
9
|
+
self.path = Path(path)
|
|
10
|
+
|
|
11
|
+
def load(self) -> QEPestConfig:
|
|
12
|
+
with open(self.path, encoding="utf-8") as f:
|
|
13
|
+
lines = f.readlines()
|
|
14
|
+
|
|
15
|
+
pest_types_dict: dict[str, dict] = {}
|
|
16
|
+
current_pest = None
|
|
17
|
+
|
|
18
|
+
for line in lines:
|
|
19
|
+
line = line.strip()
|
|
20
|
+
if not line or line.startswith("#"):
|
|
21
|
+
continue
|
|
22
|
+
|
|
23
|
+
if line.startswith("[") and line.endswith("]"):
|
|
24
|
+
current_pest = line[1:-1]
|
|
25
|
+
pest_types_dict[current_pest] = {"coefficients": [], "normaliser": []}
|
|
26
|
+
elif current_pest and "=" in line:
|
|
27
|
+
key, value = line.split("=", 1)
|
|
28
|
+
if key.strip() == "coefficients":
|
|
29
|
+
parts = [float(x.strip()) for x in value.strip().split(",")]
|
|
30
|
+
for i in range(0, len(parts), 4):
|
|
31
|
+
pest_types_dict[current_pest]["coefficients"].append(
|
|
32
|
+
tuple(parts[i:i + 4])
|
|
33
|
+
)
|
|
34
|
+
elif key.strip() == "normaliser":
|
|
35
|
+
parts = [float(x.strip()) for x in value.strip().split(",")]
|
|
36
|
+
pest_types_dict[current_pest]["normaliser"] = tuple(parts)
|
|
37
|
+
|
|
38
|
+
pest_types = []
|
|
39
|
+
for pest_name, pest_data in pest_types_dict.items():
|
|
40
|
+
pest_types.append(PestTypeConfig(
|
|
41
|
+
name=pest_name,
|
|
42
|
+
coefficients=pest_data["coefficients"],
|
|
43
|
+
normaliser=tuple(pest_data["normaliser"]),
|
|
44
|
+
))
|
|
45
|
+
|
|
46
|
+
return QEPestConfig(pest_types=pest_types)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
from pythonQEPest.core import QEPestMeta
|
|
5
|
+
from pythonQEPest.dto import QEPestFile, QEPestInput
|
|
6
|
+
from pythonQEPest.dto.QEPestFile import QEPestFormat
|
|
7
|
+
from pythonQEPest.helpers.get_values_from_line import get_values_from_line
|
|
8
|
+
from pythonQEPest.helpers.get_num_of_cols import get_num_of_cols
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class QEPestFileService:
|
|
14
|
+
|
|
15
|
+
def __init__(self, qepest: QEPestMeta, qepest_file: QEPestFile):
|
|
16
|
+
self.qepest = qepest
|
|
17
|
+
self.qepest_file = qepest_file
|
|
18
|
+
self.error = False
|
|
19
|
+
|
|
20
|
+
def _write_txt_line(self, line: str, file) -> None:
|
|
21
|
+
splitted_line = line.split("\t")[0]
|
|
22
|
+
qex_headers = " ".join(self.qepest.qex.model_dump().keys())
|
|
23
|
+
qex_values = " ".join(str(x) for x in self.qepest.qex.model_dump().values())
|
|
24
|
+
|
|
25
|
+
file.write(f"Name {qex_headers.upper()}\n")
|
|
26
|
+
file.write(f"{splitted_line} {qex_values}\n")
|
|
27
|
+
|
|
28
|
+
def _write_json_line(self, line: str, file) -> None:
|
|
29
|
+
splitted_line = line.split("\t")[0]
|
|
30
|
+
data = {"name": splitted_line, **self.qepest.qex.model_dump()}
|
|
31
|
+
file.write(json.dumps(data) + "\n")
|
|
32
|
+
|
|
33
|
+
def _process_smiles_line(self, smiles: str, index: int) -> None:
|
|
34
|
+
qepest_input = QEPestInput.from_smiles(smiles, name=f"mol_{index}")
|
|
35
|
+
if qepest_input.mol_weight == 0.0:
|
|
36
|
+
raise RuntimeError(
|
|
37
|
+
"RDKit is not installed. Install it with: pip install rdkit"
|
|
38
|
+
)
|
|
39
|
+
d_values = get_values_from_line(list(qepest_input.model_dump().values()))
|
|
40
|
+
self.qepest.get_qex_values(d_values)
|
|
41
|
+
|
|
42
|
+
def _write_smiles_txt_line(self, index: int, file) -> None:
|
|
43
|
+
name = f"mol_{index}"
|
|
44
|
+
qex_headers = " ".join(self.qepest.qex.model_dump().keys())
|
|
45
|
+
qex_values = " ".join(str(x) for x in self.qepest.qex.model_dump().values())
|
|
46
|
+
file.write(f"Name {qex_headers.upper()}\n")
|
|
47
|
+
file.write(f"{name} {qex_values}\n")
|
|
48
|
+
|
|
49
|
+
def _write_smiles_json_line(self, index: int, file) -> None:
|
|
50
|
+
name = f"mol_{index}"
|
|
51
|
+
data = {"name": name, **self.qepest.qex.model_dump()}
|
|
52
|
+
file.write(json.dumps(data) + "\n")
|
|
53
|
+
|
|
54
|
+
def read_file_and_compute_params(self) -> None:
|
|
55
|
+
if self.qepest_file.smiles:
|
|
56
|
+
self._read_smiles_file()
|
|
57
|
+
else:
|
|
58
|
+
self._read_descriptor_file()
|
|
59
|
+
|
|
60
|
+
def _read_smiles_file(self) -> None:
|
|
61
|
+
try:
|
|
62
|
+
with open(self.qepest_file.input_file, "r") as f:
|
|
63
|
+
lines = f.readlines()
|
|
64
|
+
|
|
65
|
+
with open(self.qepest_file.output_file, "w") as wr:
|
|
66
|
+
for index, line in enumerate(lines):
|
|
67
|
+
smiles = line.strip()
|
|
68
|
+
if not smiles:
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
self._process_smiles_line(smiles, index)
|
|
73
|
+
except RuntimeError as e:
|
|
74
|
+
logger.error(str(e))
|
|
75
|
+
self.error = True
|
|
76
|
+
break
|
|
77
|
+
|
|
78
|
+
if self.qepest_file.format == QEPestFormat.TXT:
|
|
79
|
+
self._write_smiles_txt_line(index, wr)
|
|
80
|
+
else:
|
|
81
|
+
self._write_smiles_json_line(index, wr)
|
|
82
|
+
|
|
83
|
+
if not self.error:
|
|
84
|
+
logger.info("Computation completed")
|
|
85
|
+
else:
|
|
86
|
+
logger.warning("Finished with errors")
|
|
87
|
+
|
|
88
|
+
except FileNotFoundError:
|
|
89
|
+
self.error = True
|
|
90
|
+
logger.error(f"Error: can't find: {self.qepest_file.input_file}")
|
|
91
|
+
|
|
92
|
+
def _read_descriptor_file(self) -> None:
|
|
93
|
+
try:
|
|
94
|
+
with open(self.qepest_file.input_file, "r") as f:
|
|
95
|
+
lines = f.readlines()
|
|
96
|
+
|
|
97
|
+
with open(self.qepest_file.output_file, "w") as wr:
|
|
98
|
+
for index, line in enumerate(lines):
|
|
99
|
+
if get_num_of_cols(line) != self.qepest.col_number:
|
|
100
|
+
logger.error(
|
|
101
|
+
f"Error: Line {index} does not have the "
|
|
102
|
+
"expected number of columns."
|
|
103
|
+
)
|
|
104
|
+
self.error = True
|
|
105
|
+
break
|
|
106
|
+
|
|
107
|
+
if index == 0:
|
|
108
|
+
continue
|
|
109
|
+
|
|
110
|
+
d_values = get_values_from_line(line.split("\t"))
|
|
111
|
+
self.qepest.get_qex_values(d_values)
|
|
112
|
+
|
|
113
|
+
if self.qepest_file.format == QEPestFormat.TXT:
|
|
114
|
+
self._write_txt_line(line, wr)
|
|
115
|
+
else:
|
|
116
|
+
self._write_json_line(line, wr)
|
|
117
|
+
|
|
118
|
+
if not self.error:
|
|
119
|
+
logger.info("Computation completed")
|
|
120
|
+
else:
|
|
121
|
+
logger.warning("Finished with errors")
|
|
122
|
+
|
|
123
|
+
except FileNotFoundError:
|
|
124
|
+
self.error = True
|
|
125
|
+
logger.error(f"Error: can't find: {self.qepest_file.input_file}")
|