robert 1.2.0__tar.gz → 2.0.0__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-2.0.0}/LICENSE +0 -0
- {robert-1.2.0 → robert-2.0.0}/PKG-INFO +35 -36
- {robert-1.2.0 → robert-2.0.0}/README.md +18 -9
- {robert-1.2.0 → robert-2.0.0}/robert/__init__.py +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/__main__.py +1 -1
- {robert-1.2.0 → robert-2.0.0}/robert/aqme.py +23 -29
- {robert-1.2.0 → robert-2.0.0}/robert/argument_parser.py +15 -14
- robert-2.0.0/robert/curate.py +160 -0
- {robert-1.2.0 → robert-2.0.0}/robert/evaluate.py +12 -10
- robert-2.0.0/robert/generate.py +176 -0
- robert-2.0.0/robert/generate_utils.py +223 -0
- {robert-1.2.0 → robert-2.0.0}/robert/model_params/ADAB_params.yaml +1 -4
- {robert-1.2.0 → robert-2.0.0}/robert/model_params/GB_params.yaml +10 -10
- robert-2.0.0/robert/model_params/GP_params.yaml +2 -0
- robert-2.0.0/robert/model_params/MVL_params.yaml +2 -0
- robert-2.0.0/robert/model_params/NN_params.yaml +11 -0
- {robert-1.2.0 → robert-2.0.0}/robert/model_params/RF_params.yaml +8 -8
- robert-2.0.0/robert/model_params/VR_params.yaml +28 -0
- {robert-1.2.0 → robert-2.0.0}/robert/predict.py +20 -30
- robert-2.0.0/robert/predict_utils.py +226 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/Robert_icon.ico +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/Robert_logo.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/Robert_logo1.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/abbrev.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/adv_anal.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/features.png +0 -0
- robert-1.2.0/robert/report/GENERATE.png → robert-2.0.0/robert/report/generate.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/outliers.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/pred.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/repro.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_0.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_1.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_10.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_2.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_3.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_4.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_5.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_6.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_7.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_8.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_9.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_1_0.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_1_1.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_2_0.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_2_1.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_2_2.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_3_0.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_3_1.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_3_2.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/score_w_3_3.jpg +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/transpa.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report/y_distrib.png +0 -0
- {robert-1.2.0 → robert-2.0.0}/robert/report.py +67 -46
- {robert-1.2.0 → robert-2.0.0}/robert/report_utils.py +229 -203
- {robert-1.2.0 → robert-2.0.0}/robert/robert.py +12 -2
- robert-2.0.0/robert/utils.py +2835 -0
- robert-2.0.0/robert/verify.py +271 -0
- {robert-1.2.0 → robert-2.0.0}/robert.egg-info/PKG-INFO +35 -36
- {robert-1.2.0 → robert-2.0.0}/robert.egg-info/SOURCES.txt +2 -2
- {robert-1.2.0 → robert-2.0.0}/robert.egg-info/dependency_links.txt +0 -0
- robert-2.0.0/robert.egg-info/requires.txt +12 -0
- {robert-1.2.0 → robert-2.0.0}/robert.egg-info/top_level.txt +0 -0
- {robert-1.2.0 → robert-2.0.0}/setup.cfg +10 -10
- {robert-1.2.0 → robert-2.0.0}/setup.py +9 -10
- {robert-1.2.0 → robert-2.0.0}/tests/test_1curate.py +54 -13
- {robert-1.2.0 → robert-2.0.0}/tests/test_2generate.py +108 -93
- {robert-1.2.0 → robert-2.0.0}/tests/test_3verify.py +24 -23
- {robert-1.2.0 → robert-2.0.0}/tests/test_4predict.py +21 -14
- {robert-1.2.0 → robert-2.0.0}/tests/test_5aqme_n_full.py +88 -94
- robert-1.2.0/robert/curate.py +0 -311
- robert-1.2.0/robert/generate.py +0 -327
- robert-1.2.0/robert/generate_utils.py +0 -759
- robert-1.2.0/robert/model_params/GP_params.yaml +0 -2
- robert-1.2.0/robert/model_params/MVL_params.yaml +0 -2
- robert-1.2.0/robert/model_params/NN_params.yaml +0 -35
- robert-1.2.0/robert/model_params/VR_params.yaml +0 -28
- robert-1.2.0/robert/predict_utils.py +0 -1048
- robert-1.2.0/robert/utils.py +0 -1376
- robert-1.2.0/robert/verify.py +0 -467
- robert-1.2.0/robert.egg-info/requires.txt +0 -13
- robert-1.2.0/tests/test_6evaluate.py +0 -276
|
File without changes
|
|
@@ -1,36 +1,35 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: robert
|
|
3
|
-
Version:
|
|
4
|
-
Summary: Refiner and Optimizer of a Bunch of Existing Regression Tools
|
|
5
|
-
Home-page: https://github.com/jvalegre/robert
|
|
6
|
-
Download-URL: https://github.com/jvalegre/robert/archive/refs/tags/
|
|
7
|
-
Author: Juan V. Alegre Requena, David Dalmau
|
|
8
|
-
Author-email: jv.alegre@csic.es
|
|
9
|
-
License: MIT
|
|
10
|
-
Keywords: workflows,machine learning,cheminformatics,data curation,prediction,automated
|
|
11
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
-
Classifier: Intended Audience :: Developers
|
|
13
|
-
Classifier: Topic :: Software Development :: Build Tools
|
|
14
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
-
Requires-Python: >=3.10
|
|
20
|
-
Description-Content-Type: text/markdown
|
|
21
|
-
License-File: LICENSE
|
|
22
|
-
Requires-Dist: PyYAML==6.0.
|
|
23
|
-
Requires-Dist: matplotlib==3.
|
|
24
|
-
Requires-Dist: pandas==2.2.
|
|
25
|
-
Requires-Dist: numpy==1.26.4
|
|
26
|
-
Requires-Dist: progress==1.6
|
|
27
|
-
Requires-Dist: seaborn==0.13.2
|
|
28
|
-
Requires-Dist: scipy==1.
|
|
29
|
-
Requires-Dist: scikit-learn==1.
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist: numba==0.60.0
|
|
32
|
-
Requires-Dist: shap==0.
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Documentation in Read The Docs: https://robert.readthedocs.io
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: robert
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Refiner and Optimizer of a Bunch of Existing Regression Tools
|
|
5
|
+
Home-page: https://github.com/jvalegre/robert
|
|
6
|
+
Download-URL: https://github.com/jvalegre/robert/archive/refs/tags/2.0.0.tar.gz
|
|
7
|
+
Author: Juan V. Alegre Requena, David Dalmau
|
|
8
|
+
Author-email: jv.alegre@csic.es
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: workflows,machine learning,cheminformatics,data curation,prediction,automated
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: PyYAML==6.0.2
|
|
23
|
+
Requires-Dist: matplotlib==3.10.0
|
|
24
|
+
Requires-Dist: pandas==2.2.3
|
|
25
|
+
Requires-Dist: numpy==1.26.4
|
|
26
|
+
Requires-Dist: progress==1.6
|
|
27
|
+
Requires-Dist: seaborn==0.13.2
|
|
28
|
+
Requires-Dist: scipy==1.15.0
|
|
29
|
+
Requires-Dist: scikit-learn==1.6.0
|
|
30
|
+
Requires-Dist: bayesian-optimization==3.0.0b1
|
|
31
|
+
Requires-Dist: numba==0.60.0
|
|
32
|
+
Requires-Dist: shap==0.46.0
|
|
33
|
+
Requires-Dist: weasyprint==63.1
|
|
34
|
+
|
|
35
|
+
Documentation in Read The Docs: https://robert.readthedocs.io
|
|
@@ -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==2025.0.1`
|
|
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**, *14*, e1733.
|
|
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.
|
|
File without changes
|
|
@@ -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()
|
|
@@ -12,9 +12,8 @@ Parameters
|
|
|
12
12
|
Name of the column containing the response variable in the input CSV file (i.e. 'solubility').
|
|
13
13
|
qdescp_keywords : str, default=''
|
|
14
14
|
Add extra keywords to the AQME-QDESCP run (i.e. qdescp_keywords="--qdescp_atoms ['Ir']")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
used instead of RDKit by adding "--program crest".
|
|
15
|
+
descp_lvl : str, default='interpret'
|
|
16
|
+
Type of descriptor to be used in the AQME-ROBERT workflow. Options are 'interpret', 'denovo' or 'full'.
|
|
18
17
|
|
|
19
18
|
"""
|
|
20
19
|
#####################################################.
|
|
@@ -95,8 +94,15 @@ class aqme:
|
|
|
95
94
|
os.remove(new_sdf)
|
|
96
95
|
shutil.move(sdf_file, new_sdf)
|
|
97
96
|
|
|
98
|
-
#Load database
|
|
99
|
-
csv_df = load_database(self,csv_target,job_type)
|
|
97
|
+
# Load database
|
|
98
|
+
csv_df,_,_ = load_database(self,csv_target,job_type,print_info=False)
|
|
99
|
+
|
|
100
|
+
# avoid running calcs with special signs (i.e. *)
|
|
101
|
+
for name_csv_indiv in csv_df['code_name']:
|
|
102
|
+
if '*' in f'{name_csv_indiv}':
|
|
103
|
+
self.args.log.write(f"\nx WARNING! The names provided in the CSV contain * (i.e. {name_csv_indiv}). Please, remove all the * characters.")
|
|
104
|
+
self.args.log.finalize()
|
|
105
|
+
sys.exit()
|
|
100
106
|
|
|
101
107
|
# find if there is more than one SMILES column in the CSV file
|
|
102
108
|
for column in csv_df.columns:
|
|
@@ -118,48 +124,36 @@ class aqme:
|
|
|
118
124
|
csv_temp.to_csv(f'AQME_indiv_{smi_suffix}.csv', index=False)
|
|
119
125
|
aqme_indv_name = f'AQME_indiv_{smi_suffix}'
|
|
120
126
|
|
|
121
|
-
# run
|
|
122
|
-
|
|
123
|
-
cmd_csearch = ['python', '-m', 'aqme', '--csearch', '--program', 'rdkit', '--input', f'{aqme_indv_name}.csv', '--nprocs', f'{self.args.nprocs}']
|
|
124
|
-
else:
|
|
125
|
-
self.args.log.write(f"\no CREST detected in the csearch_keywords option, it will be used for conformer sampling")
|
|
126
|
-
cmd_csearch = ['python', '-m', 'aqme', '--csearch', '--input', f'{aqme_indv_name}.csv', '--nprocs', f'{self.args.nprocs}']
|
|
127
|
-
_ = self.run_aqme(cmd_csearch, self.args.csearch_keywords)
|
|
128
|
-
|
|
129
|
-
sdf_files = 'CSEARCH/*.sdf'
|
|
130
|
-
if smi_suffix is not None:
|
|
131
|
-
sdf_files = f'CSEARCH/*_{smi_suffix}_*.sdf'
|
|
132
|
-
|
|
133
|
-
# run QDESCP to generate descriptors
|
|
134
|
-
cmd_qdescp = ['python', '-m', 'aqme', '--qdescp', '--files', sdf_files, '--program', 'xtb', '--csv_name', f'{aqme_indv_name}.csv', '--nprocs', f'{self.args.nprocs}', '--robert']
|
|
127
|
+
# run AQME-QDESCP to generate descriptors
|
|
128
|
+
cmd_qdescp = ['python', '-m', 'aqme', '--qdescp', '--input', f'{aqme_indv_name}.csv', '--program', 'xtb', '--csv_name', f'{aqme_indv_name}.csv', '--nprocs', f'{self.args.nprocs}', '--robert']
|
|
135
129
|
_ = self.run_aqme(cmd_qdescp, self.args.qdescp_keywords)
|
|
136
130
|
|
|
137
131
|
if smi_suffix is not None:
|
|
138
132
|
# Change column names by adding suffix
|
|
139
133
|
try:
|
|
140
|
-
df_temp = pd.read_csv(f'AQME-ROBERT_{aqme_indv_name}.csv', encoding='utf-8')
|
|
134
|
+
df_temp = pd.read_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', encoding='utf-8')
|
|
141
135
|
except FileNotFoundError:
|
|
142
136
|
self.args.log.write("x WARNING! ROBERT stopped due to a problem with the AQME job. Please, check the previous AQME warnings.")
|
|
143
137
|
sys.exit()
|
|
144
138
|
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)
|
|
139
|
+
df_temp.to_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', index=False)
|
|
146
140
|
|
|
147
141
|
# Check if there are missing rows in the AQME-ROBERT_{aqme_indv_name}.csv
|
|
148
142
|
if len(df_temp) < len(csv_temp):
|
|
149
143
|
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)
|
|
144
|
+
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
145
|
|
|
152
146
|
# Get the order of code_name in aqme_indv_name
|
|
153
147
|
order = csv_temp['code_name'].tolist()
|
|
154
148
|
|
|
155
149
|
# 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')
|
|
150
|
+
df_temp = pd.read_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', encoding='utf-8')
|
|
157
151
|
df_temp = df_temp.sort_values(by='code_name', key=lambda x: x.map({v: i for i, v in enumerate(order)}))
|
|
158
152
|
|
|
159
153
|
# Fill missing values with corresponding SMILES row
|
|
160
154
|
df_temp = df_temp.fillna(df_temp.groupby('SMILES').transform('first'))
|
|
161
155
|
|
|
162
|
-
df_temp.to_csv(f'AQME-ROBERT_{aqme_indv_name}.csv', index=False)
|
|
156
|
+
df_temp.to_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{aqme_indv_name}.csv', index=False)
|
|
163
157
|
|
|
164
158
|
# return SDF files after csv_test
|
|
165
159
|
if aqme_test:
|
|
@@ -169,23 +163,23 @@ class aqme:
|
|
|
169
163
|
shutil.rmtree(path_sdf)
|
|
170
164
|
|
|
171
165
|
# if AQME-ROBERT_AQME_indiv_n.csv >0 in folder:
|
|
172
|
-
if len(glob.glob('AQME-
|
|
166
|
+
if len(glob.glob(f'AQME-ROBERT_{self.args.descp_lvl}_AQME_indiv*.csv')) > 0:
|
|
173
167
|
|
|
174
168
|
df_concat = pd.DataFrame()
|
|
175
169
|
|
|
176
170
|
# Read and concatenate CSV files
|
|
177
|
-
for file in sorted(glob.glob('AQME-
|
|
171
|
+
for file in sorted(glob.glob(f'AQME-ROBERT_{self.args.descp_lvl}_AQME_indiv*.csv'), key=os.path.getmtime,reverse=True):
|
|
178
172
|
columns_to_drop = ['code_name', 'SMILES'] + aqme_args
|
|
179
173
|
df_temp = pd.read_csv(file, encoding='utf-8')
|
|
180
174
|
columns_to_drop = [col for col in columns_to_drop if col in df_temp.columns]
|
|
181
175
|
df_temp = df_temp.drop(columns=columns_to_drop)
|
|
182
176
|
df_concat = pd.concat([df_temp, df_concat], axis=1)
|
|
183
177
|
df_concat = pd.concat([csv_df, df_concat], axis=1)
|
|
184
|
-
df_concat.to_csv(f'AQME-ROBERT_{csv_target}', index=False)
|
|
178
|
+
df_concat.to_csv(f'AQME-ROBERT_{self.args.descp_lvl}_{csv_target}', index=False)
|
|
185
179
|
|
|
186
180
|
|
|
187
181
|
# if no qdesc_atom is set, only keep molecular properties and discard atomic properties
|
|
188
|
-
aqme_db = f'AQME-ROBERT_{csv_target}'
|
|
182
|
+
aqme_db = f'AQME-ROBERT_{self.args.descp_lvl}_{csv_target}'
|
|
189
183
|
|
|
190
184
|
# ensure that the AQME database was successfully created
|
|
191
185
|
if not os.path.exists(aqme_db):
|
|
@@ -226,7 +220,7 @@ class aqme:
|
|
|
226
220
|
try:
|
|
227
221
|
from aqme.qprep import qprep
|
|
228
222
|
except ModuleNotFoundError:
|
|
229
|
-
self.args.log.write("x AQME is not installed (required for the --aqme option)!
|
|
223
|
+
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
224
|
sys.exit()
|
|
231
225
|
|
|
232
226
|
|
|
@@ -16,8 +16,7 @@ var_dict = {
|
|
|
16
16
|
"report": False,
|
|
17
17
|
"cheers": False,
|
|
18
18
|
"evaluate": False,
|
|
19
|
-
"seed":
|
|
20
|
-
"generate_acc": 'mid',
|
|
19
|
+
"seed": 0,
|
|
21
20
|
"destination": None,
|
|
22
21
|
"csv_name" : '',
|
|
23
22
|
"csv_train": '',
|
|
@@ -27,29 +26,31 @@ var_dict = {
|
|
|
27
26
|
"discard" : [],
|
|
28
27
|
"ignore" : [],
|
|
29
28
|
"categorical" : "onehot",
|
|
30
|
-
"
|
|
29
|
+
"corr_filter_x" : True,
|
|
30
|
+
"corr_filter_y" : False,
|
|
31
|
+
"std" : True,
|
|
31
32
|
"desc_thres" : 25,
|
|
32
33
|
"thres_y" : 0.001,
|
|
33
|
-
"thres_x" : 0.
|
|
34
|
-
"test_set" : 0.
|
|
34
|
+
"thres_x" : 0.7,
|
|
35
|
+
"test_set" : 0.2,
|
|
35
36
|
"auto_test" : True,
|
|
36
|
-
"train" : [60,70,80,90],
|
|
37
|
-
"auto_kn" : True,
|
|
38
37
|
"auto_type": True,
|
|
39
|
-
"filter_train" : True,
|
|
40
|
-
"split" : "RND",
|
|
41
38
|
"model" : ['RF','GB','NN','MVL'],
|
|
42
39
|
"eval_model" : 'MVL',
|
|
43
40
|
"custom_params" : None,
|
|
44
41
|
"type" : "reg",
|
|
45
|
-
"
|
|
42
|
+
"split" : "even",
|
|
46
43
|
"nprocs": 8,
|
|
47
44
|
"error_type" : "rmse",
|
|
48
45
|
"pfi_epochs" : 5,
|
|
49
|
-
"pfi_threshold" : 0.
|
|
46
|
+
"pfi_threshold" : 0.2,
|
|
50
47
|
"pfi_filter" : True,
|
|
51
48
|
"pfi_max" : 0,
|
|
52
|
-
"
|
|
49
|
+
"init_points" : 10,
|
|
50
|
+
"n_iter" : 10,
|
|
51
|
+
"expect_improv" : 0.05,
|
|
52
|
+
"kfold" : 5,
|
|
53
|
+
"repeat_kfolds" : 10,
|
|
53
54
|
"alpha" : 0.05,
|
|
54
55
|
"params_dir" : '',
|
|
55
56
|
"csv_test" : '',
|
|
@@ -58,7 +59,7 @@ var_dict = {
|
|
|
58
59
|
"pfi_show" : 10,
|
|
59
60
|
"names" : '',
|
|
60
61
|
"qdescp_keywords" : '',
|
|
61
|
-
"
|
|
62
|
+
"descp_lvl": "interpret",
|
|
62
63
|
"report_modules" : ['AQME','CURATE','GENERATE','VERIFY','PREDICT'],
|
|
63
64
|
"debug_report": False
|
|
64
65
|
}
|
|
@@ -83,5 +84,5 @@ def set_options(kwargs):
|
|
|
83
84
|
else:
|
|
84
85
|
print("Warning! Option: [", key,":",kwargs[key],"] provided but no option exists, try the online documentation to see available options for each module.",)
|
|
85
86
|
sys.exit()
|
|
86
|
-
|
|
87
|
+
|
|
87
88
|
return options
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Parameters
|
|
3
|
+
----------
|
|
4
|
+
|
|
5
|
+
csv_name : str, default=''
|
|
6
|
+
Name of the CSV file containing the database. A path can be provided (i.e. 'C:/Users/FOLDER/FILE.csv').
|
|
7
|
+
y : str, default=''
|
|
8
|
+
Name of the column containing the response variable in the input CSV file (i.e. 'solubility').
|
|
9
|
+
discard : list, default=[]
|
|
10
|
+
List containing the columns of the input CSV file that will not be included as descriptors
|
|
11
|
+
in the curated CSV file (i.e. ['name','SMILES']).
|
|
12
|
+
ignore : list, default=[]
|
|
13
|
+
List containing the columns of the input CSV file that will be ignored during the curation process
|
|
14
|
+
(i.e. ['name','SMILES']). The descriptors will be included in the curated CSV file. The y value
|
|
15
|
+
is automatically ignored.
|
|
16
|
+
names : str, default=''
|
|
17
|
+
Column of the names for each datapoint. Names are used to print outliers.
|
|
18
|
+
destination : str, default=None,
|
|
19
|
+
Directory to create the output file(s).
|
|
20
|
+
varfile : str, default=None
|
|
21
|
+
Option to parse the variables using a yaml file (specify the filename, i.e. varfile=FILE.yaml).
|
|
22
|
+
categorical : str, default='onehot'
|
|
23
|
+
Mode to convert data from columns with categorical variables. As an example, a variable containing 4
|
|
24
|
+
types of C atoms (i.e. primary, secondary, tertiary, quaternary) will be converted into categorical
|
|
25
|
+
variables. Options:
|
|
26
|
+
1. 'onehot' (for one-hot encoding, ROBERT will create a descriptor for each type of
|
|
27
|
+
C atom using 0s and 1s to indicate whether the C type is present)
|
|
28
|
+
2. 'numbers' (to describe the C atoms with numbers: 1, 2, 3, 4).
|
|
29
|
+
corr_filter_x : bool, default=True
|
|
30
|
+
Activate the correlation filters of descriptors, based on the correlation
|
|
31
|
+
of the descriptors with other descriptors (x filter).
|
|
32
|
+
corr_filter_y : bool, default=False
|
|
33
|
+
Activate the correlation filters of descriptors, based on the correlation
|
|
34
|
+
of the descriptors with the y values (y filter, for noise). This filter is only
|
|
35
|
+
suggested for MVL.
|
|
36
|
+
desc_thres : float, default=25
|
|
37
|
+
Threshold for the descriptor-to-datapoints ratio to loose the correlation filter. By default,
|
|
38
|
+
the correlation filter is loosen if there are 25 times more datapoints than descriptors.
|
|
39
|
+
thres_x : float, default=0.7
|
|
40
|
+
Thresolhold to discard descriptors based on high R**2 correlation with other descriptors (i.e.
|
|
41
|
+
if thres_x=0.7, variables that show R**2 > 0.7 will be discarded).
|
|
42
|
+
thres_y : float, default=0.001
|
|
43
|
+
Thresolhold to discard descriptors with poor correlation with the y values based on R**2 (i.e.
|
|
44
|
+
if thres_y=0.001, variables that show R**2 < 0.001 will be discarded).
|
|
45
|
+
seed : int, default=0
|
|
46
|
+
Random seed used in RFECV feature selector and other protocols.
|
|
47
|
+
kfold : int, default=5
|
|
48
|
+
Number of random data splits for the cross-validation of the RFECV feature selector.
|
|
49
|
+
repeat_kfolds : int, default=10
|
|
50
|
+
Number of repetitions for the k-fold cross-validation of the RFECV feature selector.
|
|
51
|
+
auto_type : bool, default=True
|
|
52
|
+
If there are only two y values, the program automatically changes the type of problem to classification.
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
#####################################################.
|
|
57
|
+
# This file stores the CURATE class #
|
|
58
|
+
# used in data curation #
|
|
59
|
+
#####################################################.
|
|
60
|
+
|
|
61
|
+
import time
|
|
62
|
+
import os
|
|
63
|
+
import pandas as pd
|
|
64
|
+
from robert.utils import (load_variables, finish_print, load_database, pearson_map,
|
|
65
|
+
check_clas_problem, categorical_transform, correlation_filter)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class curate:
|
|
69
|
+
"""
|
|
70
|
+
Class containing all the functions from the CURATE module.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
kwargs : argument class
|
|
75
|
+
Specify any arguments from the CURATE module (for a complete list of variables, visit the ROBERT documentation)
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def __init__(self, **kwargs):
|
|
79
|
+
|
|
80
|
+
start_time = time.time()
|
|
81
|
+
|
|
82
|
+
# load default and user-specified variables
|
|
83
|
+
self.args = load_variables(kwargs, "curate")
|
|
84
|
+
|
|
85
|
+
# load database, discard user-defined descriptors and perform data checks
|
|
86
|
+
csv_df,_,_ = load_database(self,self.args.csv_name,"curate")
|
|
87
|
+
|
|
88
|
+
# adjust options of classification problems and detects whether the right type of problem was used
|
|
89
|
+
self = check_clas_problem(self,csv_df)
|
|
90
|
+
|
|
91
|
+
if not self.args.evaluate:
|
|
92
|
+
# transform categorical descriptors
|
|
93
|
+
csv_df = categorical_transform(self,csv_df,'curate')
|
|
94
|
+
|
|
95
|
+
# apply duplicate filters (i.e., duplication of datapoints or descriptors)
|
|
96
|
+
csv_df = self.dup_filter(csv_df)
|
|
97
|
+
|
|
98
|
+
# apply the correlation filters and returns the database without correlated descriptors
|
|
99
|
+
if self.args.corr_filter_x or self.args.corr_filter_y:
|
|
100
|
+
csv_df = correlation_filter(self,csv_df)
|
|
101
|
+
|
|
102
|
+
# save the curated CSV
|
|
103
|
+
_ = self.save_curate(csv_df)
|
|
104
|
+
|
|
105
|
+
# create Pearson heatmap
|
|
106
|
+
_ = pearson_map(self,csv_df,'curate')
|
|
107
|
+
|
|
108
|
+
# finish the printing of the CURATE info file
|
|
109
|
+
_ = finish_print(self,start_time,'CURATE')
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def dup_filter(self,csv_df_dup):
|
|
113
|
+
'''
|
|
114
|
+
Removes duplicated datapoints and descriptors
|
|
115
|
+
'''
|
|
116
|
+
|
|
117
|
+
txt_dup = f'\no Duplication filters activated'
|
|
118
|
+
txt_dup += f'\n Excluded datapoints:'
|
|
119
|
+
|
|
120
|
+
# remove duplicated entries
|
|
121
|
+
datapoint_drop = []
|
|
122
|
+
for i,datapoint in enumerate(csv_df_dup.duplicated()):
|
|
123
|
+
if datapoint:
|
|
124
|
+
datapoint_drop.append(i)
|
|
125
|
+
for datapoint in datapoint_drop:
|
|
126
|
+
txt_dup += f'\n - Datapoint number {datapoint}'
|
|
127
|
+
|
|
128
|
+
if len(datapoint_drop) == 0:
|
|
129
|
+
txt_dup += f'\n - No datapoints were removed'
|
|
130
|
+
|
|
131
|
+
csv_df_dup = csv_df_dup.drop(datapoint_drop, axis=0)
|
|
132
|
+
|
|
133
|
+
csv_df_dup.reset_index(drop=True)
|
|
134
|
+
self.args.log.write(txt_dup)
|
|
135
|
+
|
|
136
|
+
return csv_df_dup
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def save_curate(self,csv_df):
|
|
140
|
+
'''
|
|
141
|
+
Saves the curated database and options used in CURATE
|
|
142
|
+
'''
|
|
143
|
+
|
|
144
|
+
# saves curated database
|
|
145
|
+
csv_basename = os.path.basename(f'{self.args.csv_name}').split('.')[0]
|
|
146
|
+
csv_curate_name = f'{csv_basename}_CURATE.csv'
|
|
147
|
+
csv_curate_name = self.args.destination.joinpath(csv_curate_name)
|
|
148
|
+
_ = csv_df.to_csv(f'{csv_curate_name}', index = None, header=True)
|
|
149
|
+
path_reduced = '/'.join(f'{csv_curate_name}'.replace('\\','/').split('/')[-2:])
|
|
150
|
+
self.args.log.write(f'\no The curated database was stored in {path_reduced}.')
|
|
151
|
+
|
|
152
|
+
# saves important options used in CURATE
|
|
153
|
+
options_name = f'CURATE_options.csv'
|
|
154
|
+
options_name = self.args.destination.joinpath(options_name)
|
|
155
|
+
options_df = pd.DataFrame()
|
|
156
|
+
options_df['y'] = [self.args.y]
|
|
157
|
+
options_df['ignore'] = [self.args.ignore]
|
|
158
|
+
options_df['names'] = [self.args.names]
|
|
159
|
+
options_df['csv_name'] = [csv_curate_name]
|
|
160
|
+
_ = options_df.to_csv(f'{options_name}', index = None, header=True)
|
|
@@ -22,6 +22,8 @@ GENERAL
|
|
|
22
22
|
Type of the pedictions. Options:
|
|
23
23
|
1. 'reg' (Regressor)
|
|
24
24
|
2. 'clas' (Classifier)
|
|
25
|
+
seed : int, default=0
|
|
26
|
+
Random seed used in the ML predictor models and other protocols.
|
|
25
27
|
destination : str, default=None,
|
|
26
28
|
Directory to create the output file(s).
|
|
27
29
|
|
|
@@ -58,9 +60,10 @@ Affect PREDICT
|
|
|
58
60
|
Affect VERIFY and PREDICT
|
|
59
61
|
+++++++++++++++++++++++++
|
|
60
62
|
|
|
61
|
-
kfold : int, default=
|
|
62
|
-
Number of
|
|
63
|
-
|
|
63
|
+
kfold : int, default=5
|
|
64
|
+
Number of random data splits for the cross-validation of the models.
|
|
65
|
+
repeat_kfolds : int, default=10
|
|
66
|
+
Number of repetitions for the k-fold cross-validation of the models.
|
|
64
67
|
|
|
65
68
|
"""
|
|
66
69
|
#####################################################.
|
|
@@ -109,12 +112,12 @@ class evaluate:
|
|
|
109
112
|
Load databases, merge them and save CSV (tracking the test types using the Set column)
|
|
110
113
|
'''
|
|
111
114
|
|
|
112
|
-
csv_df_train = load_database(self,self.args.csv_train,"evaluate")
|
|
115
|
+
csv_df_train,_,_ = load_database(self,self.args.csv_train,"evaluate",print_info=False)
|
|
113
116
|
csv_df_train['Set'] = ['Training'] * len(csv_df_train[self.args.y])
|
|
114
|
-
csv_df_valid = load_database(self,self.args.csv_valid,"evaluate")
|
|
117
|
+
csv_df_valid,_,_ = load_database(self,self.args.csv_valid,"evaluate",print_info=False)
|
|
115
118
|
csv_df_valid['Set'] = ['Validation'] * len(csv_df_valid[self.args.y])
|
|
116
119
|
if self.args.csv_test != '':
|
|
117
|
-
csv_df_test = load_database(self,self.args.csv_test,"evaluate")
|
|
120
|
+
csv_df_test,_,_ = load_database(self,self.args.csv_test,"evaluate",print_info=False)
|
|
118
121
|
csv_df_test['Set'] = ['Test'] * len(csv_df_test[self.args.y])
|
|
119
122
|
|
|
120
123
|
self.args.ignore.append('Set')
|
|
@@ -163,12 +166,11 @@ class evaluate:
|
|
|
163
166
|
train_points = len(csv_df_train[self.args.y])
|
|
164
167
|
valid_points = len(csv_df_valid[self.args.y])
|
|
165
168
|
df_params['train'] = [train_proportion]
|
|
166
|
-
df_params['
|
|
169
|
+
df_params['kfold'] = [self.args.kfold]
|
|
170
|
+
df_params['repeat_kfolds'] = [self.args.repeat_kfolds]
|
|
167
171
|
df_params['model'] = [self.args.eval_model]
|
|
168
172
|
df_params['type'] = [self.args.type]
|
|
169
|
-
|
|
170
|
-
self.args.seed = [0]
|
|
171
|
-
df_params['seed'] = [self.args.seed[0]]
|
|
173
|
+
df_params['seed'] = [self.args.seed]
|
|
172
174
|
df_params['y'] = [self.args.y]
|
|
173
175
|
df_params['names'] = [self.args.names]
|
|
174
176
|
df_params['error_type'] = [self.args.error_type]
|