D4CMPP2 0.4.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.
- D4CMPP2/_Data/AGENTS.md +24 -0
- D4CMPP2/_Data/Aqsoldb.csv +9291 -0
- D4CMPP2/_Data/BradleyMP.csv +3042 -0
- D4CMPP2/_Data/Lipophilicity.csv +1131 -0
- D4CMPP2/_Data/README.md +8 -0
- D4CMPP2/_Data/__init__.py +26 -0
- D4CMPP2/_Data/optical.csv +20237 -0
- D4CMPP2/_Data/test.csv +190 -0
- D4CMPP2/__init__.py +16 -0
- D4CMPP2/__main__.py +5 -0
- D4CMPP2/_main.py +500 -0
- D4CMPP2/cli.py +7 -0
- D4CMPP2/exceptions.py +53 -0
- D4CMPP2/grid_search.py +259 -0
- D4CMPP2/network_refer.yaml +160 -0
- D4CMPP2/networks/AFP_model.py +72 -0
- D4CMPP2/networks/AFPwithSolv_model.py +72 -0
- D4CMPP2/networks/DMPNN_model.py +90 -0
- D4CMPP2/networks/DMPNNwithSolv_model.py +89 -0
- D4CMPP2/networks/GAT_model.py +48 -0
- D4CMPP2/networks/GATwithSolv_model.py +63 -0
- D4CMPP2/networks/GCN_model.py +113 -0
- D4CMPP2/networks/GCNwithSolv_model.py +103 -0
- D4CMPP2/networks/GC_model.py +122 -0
- D4CMPP2/networks/ISATPM_model.py +14 -0
- D4CMPP2/networks/ISATPN_model.py +199 -0
- D4CMPP2/networks/ISAT_model.py +90 -0
- D4CMPP2/networks/MPNN_model.py +56 -0
- D4CMPP2/networks/MPNNwithSolv_model.py +72 -0
- D4CMPP2/networks/__init__.py +25 -0
- D4CMPP2/networks/base.py +250 -0
- D4CMPP2/networks/registry.py +187 -0
- D4CMPP2/networks/src/AFP.py +118 -0
- D4CMPP2/networks/src/BiDropout.py +29 -0
- D4CMPP2/networks/src/DMPNN.py +35 -0
- D4CMPP2/networks/src/GAT.py +69 -0
- D4CMPP2/networks/src/GC.py +85 -0
- D4CMPP2/networks/src/GCN.py +71 -0
- D4CMPP2/networks/src/ISAT.py +153 -0
- D4CMPP2/networks/src/Linear.py +49 -0
- D4CMPP2/networks/src/MPNN.py +56 -0
- D4CMPP2/networks/src/SolventLayer.py +62 -0
- D4CMPP2/networks/src/__init__.py +0 -0
- D4CMPP2/networks/src/distGCN.py +21 -0
- D4CMPP2/networks/src/pyg_hetero.py +24 -0
- D4CMPP2/optimize.py +472 -0
- D4CMPP2/src/Analyzer/ISAAnalyzer.py +458 -0
- D4CMPP2/src/Analyzer/ISAPNAnalyzer.py +366 -0
- D4CMPP2/src/Analyzer/ISAwSAnalyzer.py +117 -0
- D4CMPP2/src/Analyzer/MolAnalyzer.py +319 -0
- D4CMPP2/src/Analyzer/__init__.py +54 -0
- D4CMPP2/src/Analyzer/core.py +480 -0
- D4CMPP2/src/Analyzer/factory.py +166 -0
- D4CMPP2/src/Analyzer/interpretation.py +232 -0
- D4CMPP2/src/Analyzer/results.py +101 -0
- D4CMPP2/src/DataManager/Dataset/GraphDataset.py +314 -0
- D4CMPP2/src/DataManager/Dataset/ISAGraphDataset.py +384 -0
- D4CMPP2/src/DataManager/Dataset/__init__.py +0 -0
- D4CMPP2/src/DataManager/GraphGenerator/ISAGraphGenerator.py +223 -0
- D4CMPP2/src/DataManager/GraphGenerator/MolGraphGenerator.py +73 -0
- D4CMPP2/src/DataManager/GraphGenerator/__init__.py +14 -0
- D4CMPP2/src/DataManager/ISADataManager.py +67 -0
- D4CMPP2/src/DataManager/MolDataManager.py +735 -0
- D4CMPP2/src/DataManager/__init__.py +14 -0
- D4CMPP2/src/DataManager/contracts.py +179 -0
- D4CMPP2/src/NetworkManager/ISANetworkManager.py +12 -0
- D4CMPP2/src/NetworkManager/NetworkManager.py +520 -0
- D4CMPP2/src/NetworkManager/__init__.py +14 -0
- D4CMPP2/src/PostProcessor.py +160 -0
- D4CMPP2/src/TrainManager/ISATrainManager.py +26 -0
- D4CMPP2/src/TrainManager/TrainManager.py +254 -0
- D4CMPP2/src/TrainManager/__init__.py +14 -0
- D4CMPP2/src/TrainManager/callbacks.py +119 -0
- D4CMPP2/src/__init__.py +0 -0
- D4CMPP2/src/utils/PATH.py +246 -0
- D4CMPP2/src/utils/__init__.py +0 -0
- D4CMPP2/src/utils/argparser.py +56 -0
- D4CMPP2/src/utils/checkpointing.py +90 -0
- D4CMPP2/src/utils/config_resolution.py +123 -0
- D4CMPP2/src/utils/config_validation.py +370 -0
- D4CMPP2/src/utils/csv_validation.py +105 -0
- D4CMPP2/src/utils/data_quality.py +181 -0
- D4CMPP2/src/utils/featureizer.py +202 -0
- D4CMPP2/src/utils/functional_group.csv +169 -0
- D4CMPP2/src/utils/graph_cache.py +213 -0
- D4CMPP2/src/utils/leaderboard.py +212 -0
- D4CMPP2/src/utils/metrics.py +31 -0
- D4CMPP2/src/utils/module_loader.py +147 -0
- D4CMPP2/src/utils/output.py +80 -0
- D4CMPP2/src/utils/reproducibility.py +70 -0
- D4CMPP2/src/utils/run_manifest.py +175 -0
- D4CMPP2/src/utils/scaler.py +40 -0
- D4CMPP2/src/utils/sculptor.py +713 -0
- D4CMPP2/src/utils/splitting.py +250 -0
- D4CMPP2/src/utils/supportfile_saver.py +94 -0
- D4CMPP2/src/utils/tools.py +156 -0
- D4CMPP2/src/utils/transfer_learning.py +111 -0
- d4cmpp2-0.4.0.dist-info/METADATA +420 -0
- d4cmpp2-0.4.0.dist-info/RECORD +103 -0
- d4cmpp2-0.4.0.dist-info/WHEEL +5 -0
- d4cmpp2-0.4.0.dist-info/entry_points.txt +2 -0
- d4cmpp2-0.4.0.dist-info/licenses/LICENSE +21 -0
- d4cmpp2-0.4.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"""Compatibility Analyzer classes backed by the row-preserving inference core."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import pickle
|
|
8
|
+
import warnings
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
import pandas as pd
|
|
13
|
+
from rdkit import Chem
|
|
14
|
+
|
|
15
|
+
from .core import InferenceCore
|
|
16
|
+
from .results import PredictionResult, UncertaintyResult
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MolAnalyzer:
|
|
20
|
+
"""Load a saved model and predict molecular properties.
|
|
21
|
+
|
|
22
|
+
This class preserves the legacy ``predict(smiles, solvent_list=None)`` result
|
|
23
|
+
mapping. New code should use :meth:`predict_rows` when duplicate or invalid
|
|
24
|
+
input rows must be retained.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
model_path,
|
|
30
|
+
save_result=False,
|
|
31
|
+
*,
|
|
32
|
+
device=None,
|
|
33
|
+
batch_size=None,
|
|
34
|
+
model_dir=None,
|
|
35
|
+
):
|
|
36
|
+
self._core = InferenceCore(
|
|
37
|
+
model_path,
|
|
38
|
+
device=device,
|
|
39
|
+
batch_size=batch_size,
|
|
40
|
+
model_dir=model_dir,
|
|
41
|
+
)
|
|
42
|
+
self.model_path = str(self._core.artifacts.root)
|
|
43
|
+
self.data_path = str(self._core.artifacts.root / "data")
|
|
44
|
+
self.save_result = bool(save_result)
|
|
45
|
+
self.config = self._core.config
|
|
46
|
+
self.dm = self._core.dm
|
|
47
|
+
self.nm = self._core.nm
|
|
48
|
+
self.tm = self._core.tm
|
|
49
|
+
self.scaler = self._core.scaler
|
|
50
|
+
self.molecule_columns = list(self._core.molecule_columns)
|
|
51
|
+
self.numeric_input_columns = list(self._core.numeric_input_columns)
|
|
52
|
+
self.data_keys = ["prediction"]
|
|
53
|
+
self.for_pickle = []
|
|
54
|
+
if self.save_result:
|
|
55
|
+
Path(self.data_path).mkdir(parents=True, exist_ok=True)
|
|
56
|
+
|
|
57
|
+
def predict_rows(self, *args, **kwargs) -> PredictionResult:
|
|
58
|
+
"""Predict while retaining every original row and its validation status."""
|
|
59
|
+
|
|
60
|
+
result = self._core.predict(*args, **kwargs)
|
|
61
|
+
self._save_prediction_rows(result)
|
|
62
|
+
return result
|
|
63
|
+
|
|
64
|
+
def prepare_temp_data(self, *args, **kwargs):
|
|
65
|
+
"""Compatibility bridge for ISA helpers that operate on prepared loaders."""
|
|
66
|
+
|
|
67
|
+
normalized = self._core.normalize_inputs(args, kwargs)
|
|
68
|
+
self.dm.init_temp_data(**{key: list(value) for key, value in normalized.items()})
|
|
69
|
+
return self.dm.get_Dataloaders(temp=True), {
|
|
70
|
+
**self.dm.valid_smiles,
|
|
71
|
+
**self.dm.numeric_inputs,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
def predict(self, smiles_list, solvent_list=None, dropout=False):
|
|
75
|
+
"""Return the historical SMILES-keyed prediction mapping."""
|
|
76
|
+
|
|
77
|
+
if dropout:
|
|
78
|
+
warnings.warn(
|
|
79
|
+
"dropout=True returns one stochastic draw and is deprecated. "
|
|
80
|
+
"Use predict_uncertainty(samples=..., seed=...) for reproducible MC dropout.",
|
|
81
|
+
DeprecationWarning,
|
|
82
|
+
stacklevel=2,
|
|
83
|
+
)
|
|
84
|
+
inputs = self._legacy_inputs(smiles_list, solvent_list)
|
|
85
|
+
uncertainty = self._core.predict_uncertainty(**inputs, samples=2)
|
|
86
|
+
structured = uncertainty.samples[0]
|
|
87
|
+
else:
|
|
88
|
+
structured = self.predict_rows(**self._legacy_inputs(smiles_list, solvent_list))
|
|
89
|
+
|
|
90
|
+
result = {}
|
|
91
|
+
for row in structured.valid_rows:
|
|
92
|
+
smiles = row.inputs[self.molecule_columns[0]]
|
|
93
|
+
if solvent_list is None:
|
|
94
|
+
result[smiles] = row.prediction
|
|
95
|
+
else:
|
|
96
|
+
solvent_column = self.molecule_columns[1]
|
|
97
|
+
result[(smiles, row.inputs[solvent_column])] = row.prediction
|
|
98
|
+
return result
|
|
99
|
+
|
|
100
|
+
def _legacy_inputs(self, smiles_list, solvent_list):
|
|
101
|
+
inputs = {self.molecule_columns[0]: smiles_list}
|
|
102
|
+
if solvent_list is not None:
|
|
103
|
+
if len(self.molecule_columns) < 2:
|
|
104
|
+
raise ValueError(
|
|
105
|
+
f"Model {self.model_path!r} does not define a solvent molecule column. "
|
|
106
|
+
f"Expected columns: {self.molecule_columns}."
|
|
107
|
+
)
|
|
108
|
+
inputs[self.molecule_columns[1]] = solvent_list
|
|
109
|
+
for column in self.numeric_input_columns:
|
|
110
|
+
if column not in inputs:
|
|
111
|
+
raise ValueError(
|
|
112
|
+
f"Legacy MolAnalyzer.predict cannot infer required numeric input {column!r}. "
|
|
113
|
+
"Use MolAnalyzer_v2.predict with named inputs."
|
|
114
|
+
)
|
|
115
|
+
return inputs
|
|
116
|
+
|
|
117
|
+
def predict_uncertainty(self, *args, samples=30, seed=None, **kwargs) -> UncertaintyResult:
|
|
118
|
+
"""Estimate MC-dropout mean/std without changing the default predict output."""
|
|
119
|
+
|
|
120
|
+
return self._core.predict_uncertainty(*args, samples=samples, seed=seed, **kwargs)
|
|
121
|
+
|
|
122
|
+
def predict_csv(
|
|
123
|
+
self,
|
|
124
|
+
input_path,
|
|
125
|
+
output_path=None,
|
|
126
|
+
*,
|
|
127
|
+
index_col=None,
|
|
128
|
+
uncertainty_samples=None,
|
|
129
|
+
uncertainty_seed=None,
|
|
130
|
+
**read_csv_kwargs,
|
|
131
|
+
):
|
|
132
|
+
"""Predict a CSV while preserving every source row and invalid-row error."""
|
|
133
|
+
|
|
134
|
+
source = Path(input_path).expanduser().resolve()
|
|
135
|
+
if not source.is_file():
|
|
136
|
+
raise FileNotFoundError(
|
|
137
|
+
f"Inference CSV {str(source)!r} does not exist. Provide an existing CSV path."
|
|
138
|
+
)
|
|
139
|
+
try:
|
|
140
|
+
frame = pd.read_csv(source, **read_csv_kwargs)
|
|
141
|
+
except (pd.errors.ParserError, pd.errors.EmptyDataError, UnicodeDecodeError) as exc:
|
|
142
|
+
raise ValueError(
|
|
143
|
+
f"Could not read inference CSV {str(source)!r}. "
|
|
144
|
+
"Check its encoding, delimiter, header, and row structure."
|
|
145
|
+
) from exc
|
|
146
|
+
missing = [column for column in self._core.input_columns if column not in frame.columns]
|
|
147
|
+
if missing:
|
|
148
|
+
raise ValueError(
|
|
149
|
+
f"Inference CSV {str(source)!r} is missing required columns {missing}. "
|
|
150
|
+
f"Available columns: {list(frame.columns)}."
|
|
151
|
+
)
|
|
152
|
+
if index_col is not None and index_col not in frame.columns:
|
|
153
|
+
raise ValueError(
|
|
154
|
+
f"Inference CSV {str(source)!r} does not contain index_col "
|
|
155
|
+
f"{index_col!r}. Available columns: {list(frame.columns)}."
|
|
156
|
+
)
|
|
157
|
+
source_indices = (
|
|
158
|
+
frame[index_col].tolist()
|
|
159
|
+
if index_col is not None
|
|
160
|
+
else frame.index.tolist()
|
|
161
|
+
)
|
|
162
|
+
inputs = {column: frame[column].tolist() for column in self._core.input_columns}
|
|
163
|
+
uncertainty = None
|
|
164
|
+
if uncertainty_samples is None:
|
|
165
|
+
result = self.predict_rows(**inputs)
|
|
166
|
+
else:
|
|
167
|
+
uncertainty = self.predict_uncertainty(
|
|
168
|
+
**inputs,
|
|
169
|
+
samples=uncertainty_samples,
|
|
170
|
+
seed=uncertainty_seed,
|
|
171
|
+
)
|
|
172
|
+
result = uncertainty.mean
|
|
173
|
+
output = result.to_dataframe()
|
|
174
|
+
if uncertainty is not None:
|
|
175
|
+
std_frame = uncertainty.std.to_dataframe()
|
|
176
|
+
for target in self._core.targets:
|
|
177
|
+
output[f"{target}_pred_std"] = std_frame[f"{target}_pred"]
|
|
178
|
+
output["uncertainty_samples"] = uncertainty_samples
|
|
179
|
+
output["row_index"] = source_indices
|
|
180
|
+
destination = (
|
|
181
|
+
Path(output_path).expanduser().resolve()
|
|
182
|
+
if output_path is not None
|
|
183
|
+
else source.with_name(source.stem + "_prediction.csv")
|
|
184
|
+
)
|
|
185
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
186
|
+
temporary = destination.with_name(destination.name + ".tmp")
|
|
187
|
+
output.to_csv(temporary, index=False)
|
|
188
|
+
temporary.replace(destination)
|
|
189
|
+
return str(destination)
|
|
190
|
+
|
|
191
|
+
def _save_prediction_rows(self, result):
|
|
192
|
+
if not self.save_result:
|
|
193
|
+
return
|
|
194
|
+
for row in result.valid_rows:
|
|
195
|
+
if not self.numeric_input_columns and len(self.molecule_columns) == 1:
|
|
196
|
+
identity = row.inputs[self.molecule_columns[0]]
|
|
197
|
+
elif not self.numeric_input_columns and len(self.molecule_columns) == 2:
|
|
198
|
+
identity = (
|
|
199
|
+
f"{row.inputs[self.molecule_columns[0]]}_"
|
|
200
|
+
f"{row.inputs[self.molecule_columns[1]]}"
|
|
201
|
+
)
|
|
202
|
+
else:
|
|
203
|
+
identity = json.dumps(dict(row.inputs), sort_keys=True, default=str)
|
|
204
|
+
self.save_data(identity, {"prediction": row.prediction})
|
|
205
|
+
|
|
206
|
+
def save_data(self, identity, data):
|
|
207
|
+
"""Save compatible per-input Analyzer cache entries."""
|
|
208
|
+
|
|
209
|
+
if not self.save_result:
|
|
210
|
+
return
|
|
211
|
+
for key, value in data.items():
|
|
212
|
+
if key not in self.data_keys:
|
|
213
|
+
raise ValueError(f"Analyzer cache key must be one of {self.data_keys}, got {key!r}.")
|
|
214
|
+
path = Path(self.data_path) / self.get_file_name(identity, key)
|
|
215
|
+
if key in self.for_pickle:
|
|
216
|
+
with path.open("wb") as file:
|
|
217
|
+
pickle.dump(value, file)
|
|
218
|
+
else:
|
|
219
|
+
with path.open("wb") as file:
|
|
220
|
+
np.save(file, np.asarray(value))
|
|
221
|
+
|
|
222
|
+
def load_data(self, identity, key):
|
|
223
|
+
if not self.save_result:
|
|
224
|
+
return None
|
|
225
|
+
path = Path(self.data_path) / self.get_file_name(identity, key)
|
|
226
|
+
if not path.is_file():
|
|
227
|
+
return None
|
|
228
|
+
try:
|
|
229
|
+
with path.open("rb") as file:
|
|
230
|
+
return pickle.load(file) if key in self.for_pickle else np.load(file)
|
|
231
|
+
except (OSError, ValueError, EOFError, pickle.PickleError) as exc:
|
|
232
|
+
warnings.warn(
|
|
233
|
+
f"Ignoring unreadable Analyzer cache file {str(path)!r}: {exc}. "
|
|
234
|
+
"The value will be recalculated.",
|
|
235
|
+
RuntimeWarning,
|
|
236
|
+
stacklevel=2,
|
|
237
|
+
)
|
|
238
|
+
return None
|
|
239
|
+
|
|
240
|
+
def get_file_name(self, identity, key):
|
|
241
|
+
if key not in self.data_keys:
|
|
242
|
+
raise ValueError(f"Analyzer cache key must be one of {self.data_keys}, got {key!r}.")
|
|
243
|
+
digest = hashlib.sha256(str(identity).encode("utf-8")).hexdigest()
|
|
244
|
+
extension = "pickle" if key in self.for_pickle else "np"
|
|
245
|
+
return f"{digest}_{self.data_keys.index(key)}.{extension}"
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class MolAnalyzer_v2(MolAnalyzer):
|
|
249
|
+
"""Generalized Analyzer for named molecule and numeric input columns."""
|
|
250
|
+
|
|
251
|
+
def __init__(self, model_path, save_result=True, **kwargs):
|
|
252
|
+
super().__init__(model_path, save_result=save_result, **kwargs)
|
|
253
|
+
try:
|
|
254
|
+
version = tuple(int(part) for part in str(self.config.get("version", "1.0")).split("."))
|
|
255
|
+
except ValueError as exc:
|
|
256
|
+
raise ValueError(
|
|
257
|
+
f"Saved model version {self.config.get('version')!r} is not a dotted numeric version."
|
|
258
|
+
) from exc
|
|
259
|
+
if version < (1, 3):
|
|
260
|
+
raise ValueError(
|
|
261
|
+
"MolAnalyzer_v2 requires config version 2.0 or the compatible "
|
|
262
|
+
"historical version 1.3. Use MolAnalyzer for a version 1.0 model."
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
def predict(self, *args, dropout=False, **kwargs):
|
|
266
|
+
if dropout:
|
|
267
|
+
warnings.warn(
|
|
268
|
+
"dropout=True returns one stochastic draw and is deprecated. "
|
|
269
|
+
"Use predict_uncertainty(samples=..., seed=...) instead.",
|
|
270
|
+
DeprecationWarning,
|
|
271
|
+
stacklevel=2,
|
|
272
|
+
)
|
|
273
|
+
structured = self._core.predict_uncertainty(
|
|
274
|
+
*args, samples=2, **kwargs
|
|
275
|
+
).samples[0]
|
|
276
|
+
else:
|
|
277
|
+
structured = self.predict_rows(*args, **kwargs)
|
|
278
|
+
return structured.legacy_dict(self._core.input_columns)
|
|
279
|
+
|
|
280
|
+
def handle_positional_args(self, args, kwargs):
|
|
281
|
+
"""Compatibility parser used by ISA plotting methods.
|
|
282
|
+
|
|
283
|
+
Analyzer input keys are normalized separately from plotting options, and
|
|
284
|
+
neither the caller's mapping nor its sequence values are mutated.
|
|
285
|
+
"""
|
|
286
|
+
|
|
287
|
+
input_kwargs = {}
|
|
288
|
+
other_kwargs = {}
|
|
289
|
+
for key, value in dict(kwargs).items():
|
|
290
|
+
if key in self._core.input_columns:
|
|
291
|
+
input_kwargs[key] = value
|
|
292
|
+
else:
|
|
293
|
+
other_kwargs[key] = value
|
|
294
|
+
normalized = self._core.normalize_inputs(args, input_kwargs)
|
|
295
|
+
return normalized, other_kwargs
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
class MolAnalyzer_v1p3(MolAnalyzer_v2):
|
|
299
|
+
"""Deprecated compatibility name for :class:`MolAnalyzer_v2`."""
|
|
300
|
+
|
|
301
|
+
def __init__(self, *args, **kwargs):
|
|
302
|
+
warnings.warn(
|
|
303
|
+
"MolAnalyzer_v1p3 is deprecated; use MolAnalyzer_v2 or Analyzer(...) instead.",
|
|
304
|
+
FutureWarning,
|
|
305
|
+
stacklevel=2,
|
|
306
|
+
)
|
|
307
|
+
super().__init__(*args, **kwargs)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def mol_with_atom_index(mol):
|
|
311
|
+
"""Return an RDKit molecule labelled with its zero-based atom indices."""
|
|
312
|
+
|
|
313
|
+
if isinstance(mol, str):
|
|
314
|
+
mol = Chem.MolFromSmiles(mol)
|
|
315
|
+
if mol is None:
|
|
316
|
+
raise ValueError("Could not parse molecule for atom-index display.")
|
|
317
|
+
for index in range(mol.GetNumAtoms()):
|
|
318
|
+
mol.GetAtomWithIdx(index).SetProp("molAtomMapNumber", str(index))
|
|
319
|
+
return mol
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Public Analyzer API.
|
|
2
|
+
|
|
3
|
+
Exports are explicit so adding an internal helper cannot silently change the public API.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .ISAAnalyzer import (
|
|
7
|
+
ISAAnalyzer,
|
|
8
|
+
ISAAnalyzer_v2,
|
|
9
|
+
ISAAnalyzer_v1p3,
|
|
10
|
+
mol_with_atom_index,
|
|
11
|
+
showAtomHighlight,
|
|
12
|
+
)
|
|
13
|
+
from .ISAPNAnalyzer import (
|
|
14
|
+
ISAPNAnalyzer,
|
|
15
|
+
ISAPNAnalyzer_v2,
|
|
16
|
+
ISAPNAnalyzer_v1p3,
|
|
17
|
+
ISATPNAnalyzer,
|
|
18
|
+
ISATPNAnalyzer_v2,
|
|
19
|
+
)
|
|
20
|
+
from .ISAwSAnalyzer import ISAwSAnalyzer
|
|
21
|
+
from .MolAnalyzer import MolAnalyzer, MolAnalyzer_v2, MolAnalyzer_v1p3
|
|
22
|
+
from .core import InferenceCore, ModelArtifacts, predict_ensemble, resolve_model_artifacts
|
|
23
|
+
from .factory import Analyzer, create_analyzer, select_analyzer_class
|
|
24
|
+
from .interpretation import ISAAnalysisResult, ISAAnalysisRow
|
|
25
|
+
from .results import PredictionResult, PredictionRow, UncertaintyResult
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"Analyzer",
|
|
29
|
+
"InferenceCore",
|
|
30
|
+
"ISAAnalyzer",
|
|
31
|
+
"ISAAnalyzer_v2",
|
|
32
|
+
"ISAAnalyzer_v1p3",
|
|
33
|
+
"ISAAnalysisResult",
|
|
34
|
+
"ISAAnalysisRow",
|
|
35
|
+
"ISAPNAnalyzer",
|
|
36
|
+
"ISAPNAnalyzer_v2",
|
|
37
|
+
"ISAPNAnalyzer_v1p3",
|
|
38
|
+
"ISATPNAnalyzer",
|
|
39
|
+
"ISATPNAnalyzer_v2",
|
|
40
|
+
"ISAwSAnalyzer",
|
|
41
|
+
"ModelArtifacts",
|
|
42
|
+
"MolAnalyzer",
|
|
43
|
+
"MolAnalyzer_v2",
|
|
44
|
+
"MolAnalyzer_v1p3",
|
|
45
|
+
"PredictionResult",
|
|
46
|
+
"PredictionRow",
|
|
47
|
+
"UncertaintyResult",
|
|
48
|
+
"create_analyzer",
|
|
49
|
+
"mol_with_atom_index",
|
|
50
|
+
"predict_ensemble",
|
|
51
|
+
"resolve_model_artifacts",
|
|
52
|
+
"select_analyzer_class",
|
|
53
|
+
"showAtomHighlight",
|
|
54
|
+
]
|