robert 1.2.0__tar.gz → 1.2.1__tar.gz
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.
- {robert-1.2.0 → robert-1.2.1}/PKG-INFO +2 -2
- {robert-1.2.0 → robert-1.2.1}/README.md +18 -9
- {robert-1.2.0 → robert-1.2.1}/robert/__main__.py +1 -1
- {robert-1.2.0 → robert-1.2.1}/robert/aqme.py +13 -11
- {robert-1.2.0 → robert-1.2.1}/robert/argument_parser.py +2 -1
- {robert-1.2.0 → robert-1.2.1}/robert/curate.py +2 -2
- {robert-1.2.0 → robert-1.2.1}/robert/predict_utils.py +6 -6
- {robert-1.2.0 → robert-1.2.1}/robert/report.py +25 -6
- {robert-1.2.0 → robert-1.2.1}/robert/report_utils.py +1 -0
- {robert-1.2.0 → robert-1.2.1}/robert/robert.py +2 -2
- {robert-1.2.0 → robert-1.2.1}/robert/utils.py +20 -6
- {robert-1.2.0 → robert-1.2.1}/robert.egg-info/PKG-INFO +2 -2
- {robert-1.2.0 → robert-1.2.1}/setup.py +1 -1
- {robert-1.2.0 → robert-1.2.1}/tests/test_1curate.py +6 -6
- {robert-1.2.0 → robert-1.2.1}/tests/test_2generate.py +7 -7
- {robert-1.2.0 → robert-1.2.1}/tests/test_4predict.py +1 -1
- {robert-1.2.0 → robert-1.2.1}/tests/test_5aqme_n_full.py +31 -31
- {robert-1.2.0 → robert-1.2.1}/tests/test_6evaluate.py +2 -2
- {robert-1.2.0 → robert-1.2.1}/LICENSE +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/__init__.py +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/evaluate.py +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/generate.py +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/generate_utils.py +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/model_params/ADAB_params.yaml +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/model_params/GB_params.yaml +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/model_params/GP_params.yaml +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/model_params/MVL_params.yaml +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/model_params/NN_params.yaml +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/model_params/RF_params.yaml +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/model_params/VR_params.yaml +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/predict.py +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/GENERATE.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/Robert_icon.ico +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/Robert_logo.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/Robert_logo1.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/abbrev.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/adv_anal.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/features.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/outliers.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/pred.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/repro.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_0.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_1.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_10.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_2.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_3.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_4.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_5.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_6.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_7.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_8.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_9.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_1_0.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_1_1.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_2_0.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_2_1.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_2_2.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_3_0.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_3_1.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_3_2.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/score_w_3_3.jpg +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/transpa.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/report/y_distrib.png +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert/verify.py +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert.egg-info/SOURCES.txt +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert.egg-info/dependency_links.txt +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert.egg-info/requires.txt +0 -0
- {robert-1.2.0 → robert-1.2.1}/robert.egg-info/top_level.txt +0 -0
- {robert-1.2.0 → robert-1.2.1}/setup.cfg +0 -0
- {robert-1.2.0 → robert-1.2.1}/tests/test_3verify.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robert
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Refiner and Optimizer of a Bunch of Existing Regression Tools
|
|
5
5
|
Home-page: https://github.com/jvalegre/robert
|
|
6
|
-
Download-URL: https://github.com/jvalegre/robert/archive/refs/tags/1.2.
|
|
6
|
+
Download-URL: https://github.com/jvalegre/robert/archive/refs/tags/1.2.1.tar.gz
|
|
7
7
|
Author: Juan V. Alegre Requena, David Dalmau
|
|
8
8
|
Author-email: jv.alegre@csic.es
|
|
9
9
|
License: MIT
|
|
@@ -7,15 +7,22 @@
|
|
|
7
7
|
[](https://codecov.io/gh/jvalegre/robert)
|
|
8
8
|
[](https://www.pepy.tech/projects/robert)
|
|
9
9
|
[](https://robert.readthedocs.io/)
|
|
10
|
-
|
|
11
|
-
ROBERT is an ensemble of automated machine learning protocols that can be run sequentially
|
|
12
|
-
through a single command line or a graphical user interface. The program works for **regression and classification problems**.
|
|
13
|
-
Comprehensive workflows have been designed to meet state-of-the-art standards for cheminformatics studies, including:
|
|
10
|
+
[](https://pypi.org/project/robert/)
|
|
14
11
|
|
|
15
12
|
## Documentation
|
|
16
13
|
Full documentation with installation instructions, technical details and examples can be found in [Read the Docs](https://robert.readthedocs.io).
|
|
17
14
|
|
|
18
|
-
Don't miss out the latest hands-on tutorials from our [YouTube channel](https://www.youtube.com/channel/UCHRqI8N61bYxWV9BjbUI4Xw)!
|
|
15
|
+
Don't miss out the latest hands-on tutorials from our [YouTube channel](https://www.youtube.com/channel/UCHRqI8N61bYxWV9BjbUI4Xw)!
|
|
16
|
+
|
|
17
|
+
## Recommended installation
|
|
18
|
+
1. (Only once) Create new conda environment: `conda create -n robert python=3.10`
|
|
19
|
+
2. Activate conda environment: `conda activate robert`
|
|
20
|
+
3. Install ROBERT using pip: `pip install robert`
|
|
21
|
+
4. Install libraries for the PDF report `conda install -y -c conda-forge glib gtk3 pango mscorefonts`
|
|
22
|
+
5. (Only for compatible devices) Install Intelex accelerator: `pip install scikit-learn-intelex`
|
|
23
|
+
* Inexperienced users should visit the *Users with no Python experience* section in [Read the Docs](https://robert.readthedocs.io).
|
|
24
|
+
## Update the program
|
|
25
|
+
1. Update to the latest version: `pip install robert --upgrade`
|
|
19
26
|
|
|
20
27
|
## Developers and help desk
|
|
21
28
|
List of main developers and contact emails:
|
|
@@ -32,6 +39,8 @@ J.V.A.R. - The acronym ROBERT is dedicated to **ROBERT Paton**, who was a mentor
|
|
|
32
39
|
|
|
33
40
|
D.D.G. - The style of the ROBERT_report.pdf file was created with the help of **Oliver Lee** (2023, Zysman-Colman group at University of St Andrews).
|
|
34
41
|
|
|
42
|
+
J.V.A.R. and D.D.G. - The improvements from v1.0 to v1.2 are largely the result of insightful discussions with **Matthew Sigman** and his students, **Jamie Cadge** and **Simone Gallarati** (2024, University of Utah).
|
|
43
|
+
|
|
35
44
|
We really THANK all the testers for their feedback and for participating in the reproducibility tests, including:
|
|
36
45
|
|
|
37
46
|
* **David Valiente** (2022-2023, Universidad Miguel Hernández)
|
|
@@ -44,11 +53,11 @@ We really THANK all the testers for their feedback and for participating in the
|
|
|
44
53
|
|
|
45
54
|
## How to cite ROBERT
|
|
46
55
|
If you use any of the ROBERT modules, please include this citation:
|
|
47
|
-
* Dalmau, D.; Alegre Requena, J. V.
|
|
56
|
+
* Dalmau, D.; Alegre Requena, J. V. ROBERT: Bridging the Gap between Machine Learning and Chemistry. *Wiley Interdiscip. Rev. Comput. Mol. Sci.* **2024**, *accepted*. DOI: 10.1002/WCMS.1733.
|
|
48
57
|
|
|
49
58
|
If you use the AQME module, please include this citation:
|
|
50
|
-
* Alegre-Requena et al., AQME: Automated Quantum Mechanical Environments for Researchers and Educators. Wiley Interdiscip. Rev. Comput. Mol. Sci
|
|
59
|
+
* Alegre-Requena et al., AQME: Automated Quantum Mechanical Environments for Researchers and Educators. *Wiley Interdiscip. Rev. Comput. Mol. Sci.* **2023**, *13*, e1663.
|
|
51
60
|
|
|
52
61
|
Additionally, please include the corresponding reference for Scikit-learn and SHAP:
|
|
53
|
-
* Pedregosa et al., Scikit-learn: Machine Learning in Python
|
|
54
|
-
* Lundberg et al., From local explanations to global understanding with explainable AI for trees
|
|
62
|
+
* Pedregosa et al., Scikit-learn: Machine Learning in Python. *J. Mach. Learn. Res.* **2011**, *12*, 2825-2830.
|
|
63
|
+
* Lundberg et al., From local explanations to global understanding with explainable AI for trees. *Nat. Mach. Intell.* **2020**, *2*, 56–67.
|
|
@@ -13,7 +13,7 @@ from robert import robert
|
|
|
13
13
|
# This allows the usage python pip-*.whl/pip install pip-*.whl
|
|
14
14
|
|
|
15
15
|
if __package__ != 'robert':
|
|
16
|
-
print('ROBERT is not installed! Use: pip install robert or conda install -c conda-forge robert.')
|
|
16
|
+
print('ROBERT is not installed! Use: pip install robert or conda install -y -c conda-forge robert.')
|
|
17
17
|
|
|
18
18
|
if __name__ == '__main__':
|
|
19
19
|
robert.main()
|
|
@@ -15,6 +15,8 @@ Parameters
|
|
|
15
15
|
csearch_keywords : str, default='--sample 50'
|
|
16
16
|
Add extra keywords to the AQME-CSEARCH run (i.e. csearch_keywords='--sample 10'). CREST can be
|
|
17
17
|
used instead of RDKit by adding "--program crest".
|
|
18
|
+
descp_lvl : str, default='interpret'
|
|
19
|
+
Type of descriptor to be used in the AQME-ROBERT workflow. Options are 'interpret', 'denovo' or 'full'.
|
|
18
20
|
|
|
19
21
|
"""
|
|
20
22
|
#####################################################.
|
|
@@ -95,7 +97,7 @@ class aqme:
|
|
|
95
97
|
os.remove(new_sdf)
|
|
96
98
|
shutil.move(sdf_file, new_sdf)
|
|
97
99
|
|
|
98
|
-
#Load database
|
|
100
|
+
# Load database
|
|
99
101
|
csv_df = load_database(self,csv_target,job_type)
|
|
100
102
|
|
|
101
103
|
# find if there is more than one SMILES column in the CSV file
|
|
@@ -137,29 +139,29 @@ class aqme:
|
|
|
137
139
|
if smi_suffix is not None:
|
|
138
140
|
# Change column names by adding suffix
|
|
139
141
|
try:
|
|
140
|
-
df_temp = pd.read_csv(f'AQME-ROBERT_{aqme_indv_name}.csv', encoding='utf-8')
|
|
142
|
+
df_temp = pd.read_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', encoding='utf-8')
|
|
141
143
|
except FileNotFoundError:
|
|
142
144
|
self.args.log.write("x WARNING! ROBERT stopped due to a problem with the AQME job. Please, check the previous AQME warnings.")
|
|
143
145
|
sys.exit()
|
|
144
146
|
df_temp.columns = [f'{col}_{smi_suffix}' if col not in ['code_name','SMILES'] and col not in aqme_args else col for col in df_temp.columns]
|
|
145
|
-
df_temp.to_csv(f'AQME-ROBERT_{aqme_indv_name}.csv', index=False)
|
|
147
|
+
df_temp.to_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', index=False)
|
|
146
148
|
|
|
147
149
|
# Check if there are missing rows in the AQME-ROBERT_{aqme_indv_name}.csv
|
|
148
150
|
if len(df_temp) < len(csv_temp):
|
|
149
151
|
missing_rows = csv_temp.loc[~csv_temp['code_name'].isin(df_temp['code_name'])]
|
|
150
|
-
missing_rows[['code_name', 'SMILES']].to_csv(f'AQME-ROBERT_{aqme_indv_name}.csv', mode='a', header=False, index=False)
|
|
152
|
+
missing_rows[['code_name', 'SMILES']].to_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', mode='a', header=False, index=False)
|
|
151
153
|
|
|
152
154
|
# Get the order of code_name in aqme_indv_name
|
|
153
155
|
order = csv_temp['code_name'].tolist()
|
|
154
156
|
|
|
155
157
|
# Sort the rows in 'AQME-ROBERT_{aqme_indv_name}.csv' based on the order
|
|
156
|
-
df_temp = pd.read_csv(f'AQME-ROBERT_{aqme_indv_name}.csv', encoding='utf-8')
|
|
158
|
+
df_temp = pd.read_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', encoding='utf-8')
|
|
157
159
|
df_temp = df_temp.sort_values(by='code_name', key=lambda x: x.map({v: i for i, v in enumerate(order)}))
|
|
158
160
|
|
|
159
161
|
# Fill missing values with corresponding SMILES row
|
|
160
162
|
df_temp = df_temp.fillna(df_temp.groupby('SMILES').transform('first'))
|
|
161
163
|
|
|
162
|
-
df_temp.to_csv(f'AQME-ROBERT_{aqme_indv_name}.csv', index=False)
|
|
164
|
+
df_temp.to_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', index=False)
|
|
163
165
|
|
|
164
166
|
# return SDF files after csv_test
|
|
165
167
|
if aqme_test:
|
|
@@ -169,23 +171,23 @@ class aqme:
|
|
|
169
171
|
shutil.rmtree(path_sdf)
|
|
170
172
|
|
|
171
173
|
# if AQME-ROBERT_AQME_indiv_n.csv >0 in folder:
|
|
172
|
-
if len(glob.glob('AQME-
|
|
174
|
+
if len(glob.glob(f'AQME-ROBERT_{self.args.descp_lvl}_AQME_indiv*.csv')) > 0:
|
|
173
175
|
|
|
174
176
|
df_concat = pd.DataFrame()
|
|
175
177
|
|
|
176
178
|
# Read and concatenate CSV files
|
|
177
|
-
for file in sorted(glob.glob('AQME-
|
|
179
|
+
for file in sorted(glob.glob(f'AQME-ROBERT_{self.args.descp_lvl}_AQME_indiv*.csv'), key=os.path.getmtime,reverse=True):
|
|
178
180
|
columns_to_drop = ['code_name', 'SMILES'] + aqme_args
|
|
179
181
|
df_temp = pd.read_csv(file, encoding='utf-8')
|
|
180
182
|
columns_to_drop = [col for col in columns_to_drop if col in df_temp.columns]
|
|
181
183
|
df_temp = df_temp.drop(columns=columns_to_drop)
|
|
182
184
|
df_concat = pd.concat([df_temp, df_concat], axis=1)
|
|
183
185
|
df_concat = pd.concat([csv_df, df_concat], axis=1)
|
|
184
|
-
df_concat.to_csv(f'AQME-ROBERT_{csv_target}', index=False)
|
|
186
|
+
df_concat.to_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{csv_target}', index=False)
|
|
185
187
|
|
|
186
188
|
|
|
187
189
|
# if no qdesc_atom is set, only keep molecular properties and discard atomic properties
|
|
188
|
-
aqme_db = f'AQME-ROBERT_{csv_target}'
|
|
190
|
+
aqme_db = f'AQME-ROBERT_{self.args.descp_lvl}_{csv_target}'
|
|
189
191
|
|
|
190
192
|
# ensure that the AQME database was successfully created
|
|
191
193
|
if not os.path.exists(aqme_db):
|
|
@@ -226,7 +228,7 @@ class aqme:
|
|
|
226
228
|
try:
|
|
227
229
|
from aqme.qprep import qprep
|
|
228
230
|
except ModuleNotFoundError:
|
|
229
|
-
self.args.log.write("x AQME is not installed (required for the --aqme option)!
|
|
231
|
+
self.args.log.write("x AQME is not installed (required for the --aqme option)! The program is typically installed within 2-5 minutes (https://aqme.readthedocs.io, see the Installation section)")
|
|
230
232
|
sys.exit()
|
|
231
233
|
|
|
232
234
|
|
|
@@ -30,7 +30,7 @@ var_dict = {
|
|
|
30
30
|
"corr_filter" : True,
|
|
31
31
|
"desc_thres" : 25,
|
|
32
32
|
"thres_y" : 0.001,
|
|
33
|
-
"thres_x" : 0.
|
|
33
|
+
"thres_x" : 0.7,
|
|
34
34
|
"test_set" : 0.1,
|
|
35
35
|
"auto_test" : True,
|
|
36
36
|
"train" : [60,70,80,90],
|
|
@@ -58,6 +58,7 @@ var_dict = {
|
|
|
58
58
|
"pfi_show" : 10,
|
|
59
59
|
"names" : '',
|
|
60
60
|
"qdescp_keywords" : '',
|
|
61
|
+
"descp_lvl": "interpret",
|
|
61
62
|
"csearch_keywords": '--sample 10',
|
|
62
63
|
"report_modules" : ['AQME','CURATE','GENERATE','VERIFY','PREDICT'],
|
|
63
64
|
"debug_report": False
|
|
@@ -32,9 +32,9 @@ Parameters
|
|
|
32
32
|
desc_thres : float, default=25
|
|
33
33
|
Threshold for the descriptor-to-datapoints ratio to loose the correlation filter. By default,
|
|
34
34
|
the correlation filter is loosen if there are 25 times more datapoints than descriptors.
|
|
35
|
-
thres_x : float, default=0.
|
|
35
|
+
thres_x : float, default=0.7
|
|
36
36
|
Thresolhold to discard descriptors based on high R**2 correlation with other descriptors (i.e.
|
|
37
|
-
if thres_x=0.
|
|
37
|
+
if thres_x=0.7, variables that show R**2 > 0.7 will be discarded).
|
|
38
38
|
thres_y : float, default=0.001
|
|
39
39
|
Thresolhold to discard descriptors with poor correlation with the y values based on R**2 (i.e.
|
|
40
40
|
if thres_y=0.001, variables that show R**2 < 0.001 will be discarded).
|
|
@@ -503,15 +503,15 @@ def print_predict(self,Xy_data,params_dict,path_n_suffix,loaded_model):
|
|
|
503
503
|
if 'y_pred_csv_test' in Xy_data and not Xy_data['y_csv_test'].isnull().values.any() and len(Xy_data['y_csv_test']) > 0:
|
|
504
504
|
print_results += f"\n - csv_test : R2 = {Xy_data['r2_csv_test']:.2}, MAE = {Xy_data['mae_csv_test']:.2}, RMSE = {Xy_data['rmse_csv_test']:.2}"
|
|
505
505
|
# add equation for linear models
|
|
506
|
-
if params_dict['model'].upper() == 'MVL':
|
|
506
|
+
if params_dict['model'].upper() == 'MVL' or self.args.evaluate == 'True':
|
|
507
507
|
desc_mvl = ast.literal_eval(params_dict['X_descriptors'])
|
|
508
508
|
print_results += f"\n\n o Linear model equation, with coefficients obtained using standardized data (coefficient values/importances can be compared):"
|
|
509
509
|
print_results += f"\n - {params_dict['y']} = {loaded_model.intercept_:.2} "
|
|
510
|
-
for i,coeff in enumerate(loaded_model.coef_):
|
|
510
|
+
for i, coeff in enumerate(loaded_model.coef_):
|
|
511
511
|
if float(coeff) >= 0:
|
|
512
|
-
print_results += f"+ {coeff:.2}
|
|
512
|
+
print_results += f"+ ({coeff:.2} * {desc_mvl[i]}) "
|
|
513
513
|
else:
|
|
514
|
-
print_results += f"- {np.abs(coeff):.2}
|
|
514
|
+
print_results += f"- ({np.abs(coeff):.2} * {desc_mvl[i]}) "
|
|
515
515
|
|
|
516
516
|
elif params_dict['type'].lower() == 'clas':
|
|
517
517
|
print_results += f"\n - Train : Accuracy = {Xy_data['acc_train']:.2}, F1 score = {Xy_data['f1_train']:.2}, MCC = {Xy_data['mcc_train']:.2}"
|
|
@@ -1040,9 +1040,9 @@ def pearson_map_predict(self,Xy_data,params_dir):
|
|
|
1040
1040
|
max_r = corr_dict['r'][abs_r_list.index(abs_max_r)]
|
|
1041
1041
|
max_descp_1 = corr_dict['descp_1'][abs_r_list.index(abs_max_r)]
|
|
1042
1042
|
max_descp_2 = corr_dict['descp_2'][abs_r_list.index(abs_max_r)]
|
|
1043
|
-
if abs_max_r > 0.
|
|
1043
|
+
if abs_max_r > 0.84:
|
|
1044
1044
|
print_corr += f"\n x WARNING! High correlations observed (up to r = {round(max_r,2)} or R2 = {round(max_r*max_r,2)}, for {max_descp_1} and {max_descp_2})"
|
|
1045
|
-
elif abs_max_r > 0.
|
|
1045
|
+
elif abs_max_r > 0.71:
|
|
1046
1046
|
print_corr += f"\n x WARNING! Noticeable correlations observed (up to r = {round(max_r,2)} or R2 = {round(max_r*max_r,2)}, for {max_descp_1} and {max_descp_2})"
|
|
1047
1047
|
|
|
1048
1048
|
self.args.log.write(print_corr)
|
|
@@ -68,7 +68,7 @@ class report:
|
|
|
68
68
|
try:
|
|
69
69
|
from weasyprint import HTML
|
|
70
70
|
except (OSError, ModuleNotFoundError):
|
|
71
|
-
print(f"\n x The REPORT module requires weasyprint but this module is missing, the PDF with the summary of the results has not been created. Try installing ROBERT with 'conda install -c conda-forge robert'")
|
|
71
|
+
print(f"\n x The REPORT module requires weasyprint but this module is missing, the PDF with the summary of the results has not been created. Try installing ROBERT with 'conda install -y -c conda-forge robert'")
|
|
72
72
|
sys.exit()
|
|
73
73
|
|
|
74
74
|
# load default and user-specified variables
|
|
@@ -676,8 +676,27 @@ class report:
|
|
|
676
676
|
|
|
677
677
|
# starts with the icon of feature importances
|
|
678
678
|
feature_dat = ''
|
|
679
|
-
feature_dat = self.module_lines('features',feature_dat)
|
|
679
|
+
feature_dat = self.module_lines('features',feature_dat)
|
|
680
680
|
|
|
681
|
+
# Add linear model equations
|
|
682
|
+
spacing = get_spacing_col('PFI',spacing_PFI)
|
|
683
|
+
with open(f'{os.getcwd()}/PREDICT/PREDICT_data.dat', 'r') as file:
|
|
684
|
+
lines = file.readlines()
|
|
685
|
+
linear_model_eqs = [lines[i + 1].strip().lstrip('- ') for i, line in enumerate(lines) if 'o Linear model equation' in line]
|
|
686
|
+
|
|
687
|
+
if linear_model_eqs:
|
|
688
|
+
feature_dat += "<p style='margin-top:-5px; margin-bottom:-6px'><span style='font-weight:bold;'>Linear model equation_No_PFI</span></p>"
|
|
689
|
+
if len(linear_model_eqs) == 1:
|
|
690
|
+
feature_dat += f"<p style='margin-top:10px; margin-bottom:35px'>{linear_model_eqs[0]}</p>"
|
|
691
|
+
else:
|
|
692
|
+
columns_eq = []
|
|
693
|
+
for i, eq in enumerate(linear_model_eqs):
|
|
694
|
+
if i == 0:
|
|
695
|
+
columns_eq.append(f"<p style='margin-top:10px; margin-bottom:35px'>{eq}</p>")
|
|
696
|
+
else:
|
|
697
|
+
columns_eq.append(f"<p style='margin-top:-5px; margin-bottom:-6px'><span style='font-weight:bold;'>{spacing*3}Linear model equation_PFI</span></p><p style='margin-top:10px; margin-bottom:35px'>{spacing*3}{eq}</p>")
|
|
698
|
+
feature_dat += combine_cols(columns_eq)
|
|
699
|
+
|
|
681
700
|
# add corresponding images
|
|
682
701
|
module_path = Path(f'{os.getcwd()}/PREDICT')
|
|
683
702
|
|
|
@@ -855,7 +874,7 @@ class report:
|
|
|
855
874
|
repro_dat += f"""<p style="text-align: justify; margin-top: -44px;"><br><strong>2. Install and adjust the versions of the following Python modules:</strong></p>"""
|
|
856
875
|
else:
|
|
857
876
|
repro_dat += f"""{first_line}<br><strong>2. Install and adjust the versions of the following Python modules:</strong></p>"""
|
|
858
|
-
repro_dat += f"""{reduced_line}{space}- Install ROBERT and its dependencies: conda install -c conda-forge robert</p>"""
|
|
877
|
+
repro_dat += f"""{reduced_line}{space}- Install ROBERT and its dependencies: conda install -y -c conda-forge robert</p>"""
|
|
859
878
|
repro_dat += f"""{reduced_line}{space}- Adjust ROBERT version: pip install robert=={robert_version}</p>"""
|
|
860
879
|
|
|
861
880
|
if intelex_version != 'not installed':
|
|
@@ -868,7 +887,7 @@ class report:
|
|
|
868
887
|
if aqme_workflow:
|
|
869
888
|
if not find_aqme:
|
|
870
889
|
repro_dat += f"""{reduced_line}{space}- AQME is required, but no version was found:</p>"""
|
|
871
|
-
repro_dat += f"""{reduced_line}{space}- Install AQME and its dependencies: conda install -c conda-forge aqme</p>"""
|
|
890
|
+
repro_dat += f"""{reduced_line}{space}- Install AQME and its dependencies: conda install -y -c conda-forge aqme</p>"""
|
|
872
891
|
if find_aqme:
|
|
873
892
|
repro_dat += f"""{reduced_line}{space}- Adjust AQME version: pip install aqme=={aqme_version}</p>"""
|
|
874
893
|
|
|
@@ -884,9 +903,9 @@ class report:
|
|
|
884
903
|
find_xtb = False
|
|
885
904
|
if not find_xtb:
|
|
886
905
|
repro_dat += f"""{reduced_line}{space}- xTB is required, but no version was found:</p>"""
|
|
887
|
-
repro_dat += f"""{reduced_line}{space}- Install xTB: conda install -c conda-forge xtb</p>"""
|
|
906
|
+
repro_dat += f"""{reduced_line}{space}- Install xTB: conda install -y -c conda-forge xtb</p>"""
|
|
888
907
|
if find_xtb:
|
|
889
|
-
repro_dat += f"""{reduced_line}{space}- Adjust xTB version (if possible): conda install -c conda-forge xtb={xtb_version}</p>"""
|
|
908
|
+
repro_dat += f"""{reduced_line}{space}- Adjust xTB version (if possible): conda install -y -c conda-forge xtb={xtb_version}</p>"""
|
|
890
909
|
|
|
891
910
|
if crest_workflow:
|
|
892
911
|
try:
|
|
@@ -434,6 +434,7 @@ def get_col_score(score_info,data_score,suffix,spacing,eval_only):
|
|
|
434
434
|
column = f"""<p style="margin-top:-18px;"><span style="font-weight:bold;">{title_line}</span></p>
|
|
435
435
|
{ML_line_format}Model = {data_score['ML_model']} · {partitions_ratio}</p>
|
|
436
436
|
{part_line_format}Points(train+valid.):descriptors = {data_score[f'points_descp_ratio_{suffix}']}</p>
|
|
437
|
+
{part_line_format}Score = {data_score[f'robert_score_{suffix}']} / 10</p>
|
|
437
438
|
<p style="margin-top: 4px;">{score_info}
|
|
438
439
|
<p style="margin-bottom: 18px;"></p>
|
|
439
440
|
"""
|
|
@@ -73,9 +73,9 @@ def main(exe_type='command',sys_args=None):
|
|
|
73
73
|
if args.aqme:
|
|
74
74
|
aqme(**vars(args))
|
|
75
75
|
# set the path to the database created by AQME to continue in the full_workflow
|
|
76
|
-
args.csv_name = Path(os.path.dirname(args.csv_name)).joinpath(f'AQME-ROBERT_{os.path.basename(args.csv_name)}')
|
|
76
|
+
args.csv_name = Path(os.path.dirname(args.csv_name)).joinpath(f'AQME-ROBERT_{args.descp_lvl}_{os.path.basename(args.csv_name)}')
|
|
77
77
|
if args.csv_test != '':
|
|
78
|
-
args.csv_test = Path(os.path.dirname(args.csv_test)).joinpath(f'AQME-ROBERT_{os.path.basename(args.csv_test)}')
|
|
78
|
+
args.csv_test = Path(os.path.dirname(args.csv_test)).joinpath(f'AQME-ROBERT_{args.descp_lvl}_{os.path.basename(args.csv_test)}')
|
|
79
79
|
|
|
80
80
|
# CURATE
|
|
81
81
|
if args.curate or full_workflow:
|
|
@@ -39,14 +39,15 @@ from sklearn.ensemble import (
|
|
|
39
39
|
from sklearn.gaussian_process import GaussianProcessRegressor, GaussianProcessClassifier
|
|
40
40
|
from sklearn.neural_network import MLPRegressor, MLPClassifier
|
|
41
41
|
from sklearn.linear_model import LinearRegression
|
|
42
|
+
from sklearn.impute import KNNImputer
|
|
42
43
|
from mapie.regression import MapieRegressor
|
|
43
44
|
from mapie.conformity_scores import AbsoluteConformityScore
|
|
44
45
|
import warnings # this avoids warnings from sklearn
|
|
45
46
|
warnings.filterwarnings("ignore")
|
|
46
47
|
|
|
47
|
-
robert_version = "1.2.
|
|
48
|
+
robert_version = "1.2.1"
|
|
48
49
|
time_run = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())
|
|
49
|
-
robert_ref = "Dalmau, D.; Alegre Requena, J. V.
|
|
50
|
+
robert_ref = "Dalmau, D.; Alegre Requena, J. V. WIREs Comput Mol Sci. 2024, DOI: 10.1002/WCMS.1733"
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
# load paramters from yaml file
|
|
@@ -128,7 +129,7 @@ def command_line_args(exe_type,sys_args):
|
|
|
128
129
|
"aqme",
|
|
129
130
|
"report",
|
|
130
131
|
"cheers",
|
|
131
|
-
"evaluate"
|
|
132
|
+
"evaluate",
|
|
132
133
|
]
|
|
133
134
|
list_args = [
|
|
134
135
|
"discard",
|
|
@@ -136,7 +137,7 @@ def command_line_args(exe_type,sys_args):
|
|
|
136
137
|
"train",
|
|
137
138
|
"model",
|
|
138
139
|
"report_modules",
|
|
139
|
-
"seed"
|
|
140
|
+
"seed",
|
|
140
141
|
]
|
|
141
142
|
int_args = [
|
|
142
143
|
'pfi_epochs',
|
|
@@ -229,6 +230,7 @@ o Other common options:
|
|
|
229
230
|
* Affecting SMILES workflows, AQME:
|
|
230
231
|
--qdescp_keywords STR (default="") : extra keywords in QDESCP (i.e. "--qdescp_atoms [Ir] --alpb h2o")
|
|
231
232
|
--csearch_keywords STR (default="--sample 50") : extra keywords in CSEARCH
|
|
233
|
+
--descp_lvl (default="interpret") "interpret", "denovo" or "full" : type of descriptor calculation
|
|
232
234
|
|
|
233
235
|
|
|
234
236
|
o How to cite ROBERT:
|
|
@@ -304,6 +306,10 @@ def load_variables(kwargs, robert_module):
|
|
|
304
306
|
if not os.path.exists(f"{self.csv_name}") and os.path.exists(f'{self.csv_name}.csv'):
|
|
305
307
|
self.csv_name = f'{self.csv_name}.csv'
|
|
306
308
|
|
|
309
|
+
# check if user used .csv in csv_test
|
|
310
|
+
if self.csv_test and not os.path.exists(f"{self.csv_test}") and os.path.exists(f'{self.csv_test}.csv'):
|
|
311
|
+
self.csv_test = f'{self.csv_test}.csv'
|
|
312
|
+
|
|
307
313
|
if robert_module != "command":
|
|
308
314
|
self.initial_dir = Path(os.getcwd())
|
|
309
315
|
|
|
@@ -789,8 +795,14 @@ def load_database(self,csv_load,module):
|
|
|
789
795
|
txt_load += f'\nx WARNING! The original database was not a valid CSV (i.e., formatting issues from Microsoft Excel?). A new database using commas as separators was created and used instead, and the original database was stored as {new_csv_name}. To prevent this issue from happening again, you should use commas as separators: https://support.edapp.com/change-csv-separator.\n\n'
|
|
790
796
|
|
|
791
797
|
csv_df = pd.read_csv(csv_load, encoding='utf-8')
|
|
792
|
-
# Fill missing values
|
|
793
|
-
csv_df = csv_df.
|
|
798
|
+
# Fill missing values using KNN imputer
|
|
799
|
+
csv_df = csv_df.dropna(axis=1, thresh=int(0.7 * len(csv_df))) # Remove columns with less than 70% of the data
|
|
800
|
+
int_columns = csv_df.select_dtypes(include=['int']).columns
|
|
801
|
+
numeric_columns = csv_df.select_dtypes(include=['float']).columns
|
|
802
|
+
imputer = KNNImputer(n_neighbors=5)
|
|
803
|
+
if csv_df[numeric_columns].isna().any().any():
|
|
804
|
+
csv_df[numeric_columns] = pd.DataFrame(imputer.fit_transform(csv_df[numeric_columns]), columns=numeric_columns)
|
|
805
|
+
csv_df[int_columns] = csv_df[int_columns]
|
|
794
806
|
|
|
795
807
|
if module.lower() not in ['verify','no_print','evaluate']:
|
|
796
808
|
sanity_checks(self.args,'csv_db',module,csv_df.columns)
|
|
@@ -901,6 +913,7 @@ def load_model_reg(params):
|
|
|
901
913
|
params = correct_hidden_layers(params)
|
|
902
914
|
|
|
903
915
|
loaded_model = MLPRegressor(batch_size=params['batch_size'],
|
|
916
|
+
solver='lbfgs',
|
|
904
917
|
hidden_layer_sizes=params['hidden_layer_sizes'],
|
|
905
918
|
learning_rate_init=params['learning_rate_init'],
|
|
906
919
|
max_iter=params['max_iter'],
|
|
@@ -980,6 +993,7 @@ def load_model_clas(params):
|
|
|
980
993
|
params = correct_hidden_layers(params)
|
|
981
994
|
|
|
982
995
|
loaded_model = MLPClassifier(batch_size=params['batch_size'],
|
|
996
|
+
solver='lbfgs',
|
|
983
997
|
hidden_layer_sizes=params['hidden_layer_sizes'],
|
|
984
998
|
learning_rate_init=params['learning_rate_init'],
|
|
985
999
|
max_iter=params['max_iter'],
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robert
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Refiner and Optimizer of a Bunch of Existing Regression Tools
|
|
5
5
|
Home-page: https://github.com/jvalegre/robert
|
|
6
|
-
Download-URL: https://github.com/jvalegre/robert/archive/refs/tags/1.2.
|
|
6
|
+
Download-URL: https://github.com/jvalegre/robert/archive/refs/tags/1.2.1.tar.gz
|
|
7
7
|
Author: Juan V. Alegre Requena, David Dalmau
|
|
8
8
|
Author-email: jv.alegre@csic.es
|
|
9
9
|
License: MIT
|
|
@@ -86,7 +86,7 @@ def test_CURATE(test_job):
|
|
|
86
86
|
# 1. Duplicate entries are removed
|
|
87
87
|
assert len(db_final['Name']) == 37
|
|
88
88
|
# 2. Correlated variables with X and noise (low R2 with y) are removed
|
|
89
|
-
discard_vars = ['x1','x3','ynoise']
|
|
89
|
+
discard_vars = ['x1','x3','x5', 'x6','ynoise']
|
|
90
90
|
for var in discard_vars:
|
|
91
91
|
assert var not in db_final.columns
|
|
92
92
|
# 3. Ignored variables and y are kept
|
|
@@ -95,12 +95,12 @@ def test_CURATE(test_job):
|
|
|
95
95
|
# 4. Discarded variables are removed
|
|
96
96
|
assert 'xtest' not in db_final.columns
|
|
97
97
|
# 5. The rest of the variables are kept
|
|
98
|
-
final_vars = ['x2','
|
|
98
|
+
final_vars = ['x2','x7','x8','x9','x10','x11']
|
|
99
99
|
for var in final_vars:
|
|
100
100
|
assert var in db_final.columns
|
|
101
101
|
|
|
102
102
|
# check that categorical variables are converted with one-hot encoding
|
|
103
|
-
categ_vars = ['Csub-H','Csub-Csub','H-O'
|
|
103
|
+
categ_vars = ['Csub-H','Csub-Csub','H-O']
|
|
104
104
|
for var in categ_vars:
|
|
105
105
|
assert var in db_final.columns
|
|
106
106
|
assert 'x4' not in db_final.columns
|
|
@@ -144,11 +144,11 @@ def test_CURATE(test_job):
|
|
|
144
144
|
]
|
|
145
145
|
subprocess.run(cmd_robert)
|
|
146
146
|
|
|
147
|
-
# check that all the missing values were filled
|
|
147
|
+
# check that all the missing values were filled
|
|
148
148
|
db_final = pd.read_csv(f"{path_curate}/Robert_example_NaNs_CURATE.csv")
|
|
149
149
|
# 1. Duplicate entries are removed
|
|
150
|
-
assert db_final['
|
|
151
|
-
assert db_final['
|
|
150
|
+
assert isinstance(db_final['x2'][4], (int, float))
|
|
151
|
+
assert isinstance(db_final['x2'][0], (int, float))
|
|
152
152
|
|
|
153
153
|
elif test_job == 'corr_filter':
|
|
154
154
|
cmd_robert = [
|
|
@@ -143,7 +143,7 @@ def test_GENERATE(test_job):
|
|
|
143
143
|
assert "ROBERT v" in outlines[0]
|
|
144
144
|
assert "- 37 datapoints" in outlines[9]
|
|
145
145
|
if test_job != 'reduced_clas':
|
|
146
|
-
assert "-
|
|
146
|
+
assert "- 9 accepted descriptors" in outlines[10]
|
|
147
147
|
else:
|
|
148
148
|
assert "- 9 accepted descriptors" in outlines[10]
|
|
149
149
|
assert "- 1 ignored descriptors" in outlines[11]
|
|
@@ -185,26 +185,26 @@ def test_GENERATE(test_job):
|
|
|
185
185
|
if test_job in ['reduced','reduced_PFImax','reduced_rnd']:
|
|
186
186
|
if folder == 'No_PFI':
|
|
187
187
|
if test_job != 'reduced_clas':
|
|
188
|
-
desc_list = ['x2', '
|
|
188
|
+
desc_list = ['x2', 'x7', 'x8', 'x9', 'x10', 'x11', 'Csub-Csub', 'Csub-H', 'H-O']
|
|
189
189
|
else:
|
|
190
190
|
desc_list = ['x1', 'x2', 'x3', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10']
|
|
191
191
|
elif folder == 'PFI':
|
|
192
192
|
if test_job == 'reduced':
|
|
193
|
-
desc_list = ['
|
|
193
|
+
desc_list = ['x7', 'x9', 'x10']
|
|
194
194
|
elif test_job == 'reduced_rnd':
|
|
195
|
-
desc_list = ['
|
|
195
|
+
desc_list = ['x7', 'x9', 'x10']
|
|
196
196
|
elif test_job =='reduced_PFImax':
|
|
197
|
-
desc_list = ['
|
|
197
|
+
desc_list = ['x7', 'x9']
|
|
198
198
|
|
|
199
199
|
if test_job in ['reduced','reduced_rnd']:
|
|
200
200
|
sum_split = 0
|
|
201
201
|
if db_best['Set'][0] == 'Training':
|
|
202
202
|
sum_split += 1
|
|
203
|
-
if db_best['Set'][1] == '
|
|
203
|
+
if db_best['Set'][1] == 'Validation':
|
|
204
204
|
sum_split += 1
|
|
205
205
|
if db_best['Set'][2] == 'Training':
|
|
206
206
|
sum_split += 1
|
|
207
|
-
if db_best['Set'][3] == '
|
|
207
|
+
if db_best['Set'][3] == 'Training':
|
|
208
208
|
sum_split += 1
|
|
209
209
|
if test_job == 'reduced':
|
|
210
210
|
assert sum_split == 4
|
|
@@ -106,7 +106,7 @@ def test_PREDICT(test_job):
|
|
|
106
106
|
if 'x WARNING! High correlations observed (up to r = 1.0 or R2 = 1.0, for x1 and x3)' in line:
|
|
107
107
|
pearson_found = True
|
|
108
108
|
else:
|
|
109
|
-
if '
|
|
109
|
+
if 'o Correlations between variables are acceptable' in line:
|
|
110
110
|
pearson_found = True
|
|
111
111
|
if test_job == "clas":
|
|
112
112
|
if 'o Your data seems quite uniform' in line:
|
|
@@ -80,7 +80,7 @@ def test_AQME(test_job):
|
|
|
80
80
|
"--epochs", "5",
|
|
81
81
|
"--seed", "[0]",
|
|
82
82
|
"--model", "['RF']",
|
|
83
|
-
"--train", "[
|
|
83
|
+
"--train", "[70]",
|
|
84
84
|
"--pfi_epochs", "1",
|
|
85
85
|
"--debug_report", "True"
|
|
86
86
|
]
|
|
@@ -150,9 +150,9 @@ def test_AQME(test_job):
|
|
|
150
150
|
assert len(glob.glob(f'{path_main}/PREDICT/*.csv')) == 4
|
|
151
151
|
|
|
152
152
|
if test_job == 'aqme':
|
|
153
|
-
assert os.path.exists(f'{path_main}/AQME-
|
|
154
|
-
db_aqme = pd.read_csv(f'{path_main}/AQME-
|
|
155
|
-
descps = ['code_name','solub','
|
|
153
|
+
assert os.path.exists(f'{path_main}/AQME-ROBERT_interpret_solubility.csv')
|
|
154
|
+
db_aqme = pd.read_csv(f'{path_main}/AQME-ROBERT_interpret_solubility.csv')
|
|
155
|
+
descps = ['code_name','solub','HOMO','Total charge']
|
|
156
156
|
for descp in descps:
|
|
157
157
|
assert descp in db_aqme.columns
|
|
158
158
|
assert 'smiles' in db_aqme.columns
|
|
@@ -164,12 +164,12 @@ def test_AQME(test_job):
|
|
|
164
164
|
assert "ROBERT v" in outlines[0]
|
|
165
165
|
assert os.path.exists(f'{path_aqme}/CSEARCH')
|
|
166
166
|
assert os.path.exists(f'{path_aqme}/QDESCP')
|
|
167
|
-
assert len(glob.glob(f'{path_aqme}/*.csv')) ==
|
|
167
|
+
assert len(glob.glob(f'{path_aqme}/*.csv')) == 0
|
|
168
168
|
assert len(glob.glob(f'{path_aqme}/*.dat')) == 3
|
|
169
169
|
|
|
170
170
|
if test_job == '2smiles_columns':
|
|
171
|
-
assert os.path.exists(f'{path_main}/AQME-
|
|
172
|
-
db_aqme = pd.read_csv(f'{path_main}/AQME-
|
|
171
|
+
assert os.path.exists(f'{path_main}/AQME-ROBERT_interpret_solubility_solvent.csv')
|
|
172
|
+
db_aqme = pd.read_csv(f'{path_main}/AQME-ROBERT_interpret_solubility_solvent.csv')
|
|
173
173
|
assert 'smiles_sub' and 'smiles_solvent' in db_aqme.columns
|
|
174
174
|
|
|
175
175
|
# find important parts in ROBERT_report
|
|
@@ -185,19 +185,19 @@ def test_AQME(test_job):
|
|
|
185
185
|
for line in outlines:
|
|
186
186
|
if 'Heatmap_ML_models_No_PFI.png' in line:
|
|
187
187
|
find_heatmap += 1
|
|
188
|
-
if '
|
|
188
|
+
if 'VERIFY_tests_RF_70_PFI.png' in line:
|
|
189
189
|
find_verify += 1
|
|
190
|
-
if '
|
|
190
|
+
if 'SHAP_RF_70_PFI.png' in line:
|
|
191
191
|
find_shap += 1
|
|
192
|
-
if '
|
|
192
|
+
if 'PFI_RF_70_PFI.png' in line:
|
|
193
193
|
find_pfi += 1
|
|
194
|
-
if '
|
|
194
|
+
if 'Outliers_RF_70_No_PFI.png' in line:
|
|
195
195
|
find_outliers += 1
|
|
196
|
-
if '
|
|
196
|
+
if 'Results_RF_70_No_PFI.png' in line:
|
|
197
197
|
find_results_reg += 1
|
|
198
|
-
if '
|
|
198
|
+
if 'Results_RF_70_No_PFI_valid.png' in line:
|
|
199
199
|
find_results_valid_clas += 1
|
|
200
|
-
if '
|
|
200
|
+
if 'Results_RF_70_No_PFI_csv_test.png' in line:
|
|
201
201
|
find_results_test_clas += 1
|
|
202
202
|
if 'csv_test :' in line:
|
|
203
203
|
find_test += 1
|
|
@@ -210,7 +210,7 @@ def test_AQME(test_job):
|
|
|
210
210
|
predict_graphs,flawed_image,cv_r2_image,cv_sd_image = False,False,False,False
|
|
211
211
|
y_distrib_image,pearson_pred_image = False,False
|
|
212
212
|
find_severe_red,find_severe_blue = False,False
|
|
213
|
-
find_moder_pred,find_moder_y_dist,
|
|
213
|
+
find_moder_pred,find_moder_y_dist,unclear_test = False,False,False
|
|
214
214
|
find_assess_yellow,find_assess_red = False,False
|
|
215
215
|
|
|
216
216
|
for i,line in enumerate(outlines):
|
|
@@ -218,31 +218,31 @@ def test_AQME(test_job):
|
|
|
218
218
|
robert_score.append(line.split('robert/report/score_')[1][0])
|
|
219
219
|
if 'Model = RF' in line:
|
|
220
220
|
ml_model_count += 1
|
|
221
|
-
if 'Train:Validation =
|
|
221
|
+
if 'Train:Validation = 68:32' in line:
|
|
222
222
|
partition_count += 1
|
|
223
223
|
if 'Points(train+valid.):descriptors = ' in line:
|
|
224
224
|
points_desc.append(line.split('Points(train+valid.):descriptors = ')[1].split('</p>')[0])
|
|
225
|
-
if '
|
|
225
|
+
if 'Results_RF_70_No_PFI.png' in line:
|
|
226
226
|
predict_graphs = True
|
|
227
227
|
if 'Train : R<sup>2</sup> = ' in line:
|
|
228
228
|
metrics_count += 1
|
|
229
229
|
if '1. Model vs "flawed" models' in line:
|
|
230
230
|
flawed_models.append(line)
|
|
231
|
-
if 'VERIFY/
|
|
231
|
+
if 'VERIFY/VERIFY_tests_RF_70_No_PFI.png' in line:
|
|
232
232
|
flawed_image = True
|
|
233
233
|
if '2. Predictive ability of the model' in line:
|
|
234
234
|
pred_ability.append(line)
|
|
235
235
|
if '3a. CV predictions train + valid.' in line:
|
|
236
236
|
cv_r2_models.append(line)
|
|
237
|
-
if 'VERIFY/
|
|
237
|
+
if 'VERIFY/CV_train_valid_predict_RF_70_No_PFI.png' in line:
|
|
238
238
|
cv_r2_image = True
|
|
239
239
|
if '3b. Avg. standard deviation (SD)' in line:
|
|
240
240
|
cv_sd_models.append(line)
|
|
241
|
-
if 'PREDICT/
|
|
241
|
+
if 'PREDICT/CV_variability_RF_70_No_PFI.png' in line:
|
|
242
242
|
cv_sd_image = True
|
|
243
243
|
if '4. Points(train+valid.):descriptors' in line:
|
|
244
244
|
points_descp.append(line)
|
|
245
|
-
if '
|
|
245
|
+
if 'y_distribution_RF_70_No_PFI.png' in line:
|
|
246
246
|
y_distrib_image = True
|
|
247
247
|
if 'Pearson_heatmap_No_PFI.png' in line:
|
|
248
248
|
pearson_pred_image = True
|
|
@@ -254,8 +254,8 @@ def test_AQME(test_job):
|
|
|
254
254
|
find_moder_pred = True
|
|
255
255
|
if 'Slightly uneven y distribution (Section C)' in line and 'color: #c5c57d' in outlines[i-1]:
|
|
256
256
|
find_moder_y_dist = True
|
|
257
|
-
if '
|
|
258
|
-
|
|
257
|
+
if 'Some tests are unclear (Section B.1)' in line and 'color: #c5c57d' in outlines[i-1]:
|
|
258
|
+
unclear_test = True
|
|
259
259
|
if 'Decent model, but it has limitations' in line and 'color: #c5c57d' in outlines[i-1]:
|
|
260
260
|
find_assess_yellow = True
|
|
261
261
|
if 'The model is unreliable' in line and 'color: #c56666' in outlines[i-1]:
|
|
@@ -264,23 +264,23 @@ def test_AQME(test_job):
|
|
|
264
264
|
break
|
|
265
265
|
|
|
266
266
|
# model summary, robert score, predict graphs and model metrics
|
|
267
|
-
assert robert_score[0] == '
|
|
268
|
-
assert robert_score[1] == '
|
|
267
|
+
assert robert_score[0] == '4'
|
|
268
|
+
assert robert_score[1] == '7'
|
|
269
269
|
assert ml_model_count == 2
|
|
270
270
|
assert partition_count == 2
|
|
271
|
-
assert points_desc[0] == '37:
|
|
271
|
+
assert points_desc[0] == '37:9'
|
|
272
272
|
assert points_desc[1] == '37:3'
|
|
273
273
|
assert predict_graphs
|
|
274
274
|
assert metrics_count == 2
|
|
275
275
|
# advanced analysis, flawed models section 1
|
|
276
276
|
assert '1 / 3' in flawed_models[0]
|
|
277
277
|
assert 'robert/report/score_w_3_1.jpg' in flawed_models[0]
|
|
278
|
-
assert '
|
|
279
|
-
assert 'robert/report/
|
|
278
|
+
assert '2 / 3' in flawed_models[1]
|
|
279
|
+
assert 'robert/report/score_w_3_2.jpg' in flawed_models[1]
|
|
280
280
|
assert flawed_image
|
|
281
281
|
# advanced analysis, predictive ability section 2
|
|
282
|
-
assert '
|
|
283
|
-
assert 'robert/report/
|
|
282
|
+
assert '2 / 2' in pred_ability[0]
|
|
283
|
+
assert 'robert/report/score_w_2_2.jpg' in pred_ability[0]
|
|
284
284
|
assert '2 / 2' in pred_ability[1]
|
|
285
285
|
assert 'robert/report/score_w_2_2.jpg' in pred_ability[1]
|
|
286
286
|
# advanced analysis, CV predictive ability section 3a
|
|
@@ -308,7 +308,7 @@ def test_AQME(test_job):
|
|
|
308
308
|
assert find_severe_blue
|
|
309
309
|
assert find_moder_pred
|
|
310
310
|
assert find_moder_y_dist
|
|
311
|
-
assert
|
|
311
|
+
assert unclear_test
|
|
312
312
|
assert find_assess_yellow
|
|
313
313
|
assert find_assess_red
|
|
314
314
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
|
|
3
3
|
######################################################.
|
|
4
|
-
# Testing
|
|
4
|
+
# Testing EVALUATE with pytest #
|
|
5
5
|
######################################################.
|
|
6
6
|
|
|
7
7
|
import os
|
|
@@ -32,7 +32,7 @@ path_tests = os.getcwd() + "/tests"
|
|
|
32
32
|
), # test that if the --csv_train or --csv_valid options are empty, a prompt pops up and asks for them
|
|
33
33
|
],
|
|
34
34
|
)
|
|
35
|
-
def
|
|
35
|
+
def test_EVALUATE(test_job):
|
|
36
36
|
|
|
37
37
|
# reset the folders (to avoid interferences with previous failed tests)
|
|
38
38
|
folders = ['CURATE','GENERATE','GENERATE_reg','GENERATE_clas','PREDICT','VERIFY','AQME','EVALUATE']
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|