-
Notifications
You must be signed in to change notification settings - Fork 1
/
mod.py
217 lines (211 loc) · 7.18 KB
/
mod.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
from __future__ import print_function, absolute_import, division, unicode_literals
from mordred import Calculator, descriptors
from rdkit import Chem
from rdkit.Chem import AllChem, Draw
from sklearn import datasets, svm
from datetime import datetime
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, cohen_kappa_score, matthews_corrcoef
from sklearn.impute import SimpleImputer
# TensorFlow and tf.keras
#import tensorflow as tf
#from tensorflow import keras
#print(tf.__version__)
import joblib, sys, os.path, getopt, json
sys.path.append('functions')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import functions as fct
import build_model as bm
import inout as io
# Default values
#
verb=False
# Create date string for file saving
date=datetime.now()
date_string = date.strftime("%d.%m.%Y_%H.%M")
# Read Mordred descriptors
mordred_desc = '/home/gallo/Documents/articles/codes/mordred_supp_info/mordred_descriptor_list.csv'
desc_list = pd.read_csv(mordred_desc) # Mordred descriptor list
# Definition of the calc variable, which evaluates the descriptors
calc = Calculator(descriptors, ignore_3D=True)
# Save the name and dimension
d_name=desc_list['name']
dscpts_dim=desc_list['dimension']
dscpts_name=[]
dscpts_idx=[]
#
# Number of descriptors to calculate
# If ndesc = list, calculate this list of descriptors
# If ndesc = integer, calculate descriptors from 0 to ndesc
# If ndesc = -1, calculate all descriptors
# By default, all descriptors are calculated
ndescs=len(calc)-1
maxnum=len(d_name)
#
try:
opts, args = getopt.getopt(sys.argv[1:],"vp:hm:c:nr:ew:",["create-model"])
except getopt.GetoptError as err:
print('Error!',err)
sys.exit(2)
for opt, arg in opts:
# The argument of -m is the filename with activity info
if opt == '-h':
io.print_help()
# Verbose output
elif opt == '-v':
verb=True
print('Verbose output')
elif opt in ("-r"):
# If input is int, the integer number of descriptors is calculated
ndescs=int(arg)
maxnum=ndescs
"""
# Calculate list of descriptors is not yet implemented
# If input is list, the list of descriptors is calculated
elif isinstance(arg, list):
ndescs=ndesc
dscpts_name=[len(ndescs)]
maxnum=len(ndescs)
for i in len(ndescs):
if dscpts_dim[i]=='2D':
dscpts_name.append(d_name[i])
print('is list',ndescs)
sys.exit()
"""
# <dscpts_name> conatains the names of the descriptors that are being
# calculated. That is saved to a file '*_descnames' further down to be read
# when NaN values have to be removed
for i in range(1,maxnum):
if dscpts_dim[i] !='3D':
dscpts_name.append(d_name[i])
dscpts_idx.append(i)
elif len(dscpts_name) > maxnum:
break
# dscs contains all the descriptors that are being calculated, with their
# respective index trough which they can be called to Calculator
dscs=np.stack((dscpts_idx, dscpts_name))
#
if args:
# Argument (no -option), is taken as the path for the descriptors file, is saved in dumb
dumb=args[0]
# Path (without filename) is stored in 'path'
path=dumb.rsplit("/",1)[0]
# Filename is stored in 'inp'
inp=dumb.split("/")[len(dumb.split("/"))-1]
else:
print('Please, provide a input filename')
sys.exit(2)
#
d=''
nproc=2
for opt, arg in opts:
# Number of processors to be used
if opt in ("-p"):
nproc=int(arg)
# Create model from descriptors file
elif opt in ("-m","--create-model"):
# The argument of -m 'arg' is the filename with activity info
print('\n TASK')
print('Load descriptors, build and evaluate chosen model(s)')
if not os.path.exists(path+'/'+arg):
print('\n',arg,'does not exist in',path)
sys.exit()
# Descriptors (from <input>) and activity values (from <filename>) are loaded
x,y=bm.load_desc(path,inp,arg)
# FUNCTION: build model from descriptors and activity file. The user
# defines which models wants to calculate.
# Explanation and function in build_model.py file
bm.build_model(x,y,verb,path,nproc)
sys.exit()
elif opt in ("-n"):
# Asks to detect number of NaN values per descriptor, assuming all 2D
# descriptors have been calculated
print('\n TASK')
print('Check and remove number of NaN values in the descriptors file\n')
io.detect_nan(path,inp,verb)
sys.exit()
elif opt in ("-w"):
# .csv file with the target chemicals (ID, Compound name, SMILES, CAS)
csv_file=pd.read_csv(path+'/'+inp)
# Calculate descriptors and remove/replace to make them agree with those
# used to build the model, store them in <clean> and save them in
# <desc_file>
clean=fct.calculate_pred(calc,csv_file,path,inp,date_string,verb)
desc_file=path+'/'+inp+'_prediction_descriptor_list.txt'
with open(desc_file,'w+') as f:
np.savetxt(f,clean,fmt='%.6f')
# Call model and calculate
if '.pkl' in arg:
arg=[arg]
predict=bm.predict(arg,path,inp,clean,csv_file)
# User wants to use more than one model
else:
with open(path+'/'+arg,'r') as f:
arg=f.read().splitlines()
if clean.shape[0] == 1:
predict=bm.predict(arg,path,inp,clean,csv_file)
elif clean.shape[0] > 1:
predict=bm.predict_set(arg,path,inp,clean,csv_file)
sys.exit()
with open(path+'/prediction.json', "w") as f:
for i in predict:
json.dump(int(i), f)
sys.exit()
elif opt in ("-c"):
# Load descriptors and evaluate the model
# Descriptors are assumed to be sanitized in comparison with the
# descriptors used to build the model, as contained in the file *_clean.txt
print('\n TASK')
print(' Load descriptors of the prediction data and model and predict')
bm.predict(arg,path,inp,arg,dscs)
sys.exit()
elif opt in ("-e"):
print('\n TASK')
print(' Extract descriptors from the .desc files and save them as an array\n')
# Extract descriptors from .desc files and create np matrix with their
# values
fct.col_to_row(path,ndescs,date_string)
sys.exit()
#
print('\n TASK')
print(' Load database and calculate descriptors')
# Read the data
# Database must have 5 fields (columns) and must start with the following line:
# ID,Compound name, SMILES, CAS, Activity
if ".csv" in inp:
csv_file=pd.read_csv(path+'/'+inp)
else:
print('Ups! If you really are using a .csv file, tell me!')
sys.exit()
# Calculate descriptors
print('\n-> Calculating descriptors (3D disregarded)\n')
x,y=fct.calculate_desc(calc,csv_file,path,inp,date_string,verb)
desc_file=path+'/'+inp+'_descriptor_list.txt'
print('saved to:\n',desc_file)
# Save descriptores to 'f' as numpy array. Each file is a molecule with
# descriptors in rows
with open(desc_file,'w+') as f:
np.savetxt(f,x,fmt='%.6f')
with open(path+'/activity.txt','w+') as f:
np.savetxt(f,y,fmt='%1i')
# Deal with NaN values
print('-> Dealing with NaN values')
x=io.detect_nan(path,inp+'_descriptor_list.txt',verb)
# Build model
print('-> Building model')
bm.build_model(x,y,verb,path,nproc)
"""
# Generate a .png from a molecule
from rdkit.Chem import Draw
for i in range(0,2):
# The file is given the name of the molecule
name = dat.loc[i,'Compound name']+'.png'
# The SMILES in Panda variable 'dat' is used to draw the molecule
print_mol = Chem.MolFromSmiles(dat.loc[i,'SMILES'])
Draw.MolToFile(print_mol,name)
"""