Spaces:
Paused
Paused
Upload 7 files
Browse files- PDC_2023.h5 +3 -0
- PDC_2024.h5 +3 -0
- PDC_2025.h5 +3 -0
- dataset.py +164 -0
- encoding.py +100 -0
- model.py +240 -0
- utils.py +110 -0
PDC_2023.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e809a36078ca3d39d255aab3edaf2ec5b93e6715442074ec3da43984814e3c7e
|
| 3 |
+
size 30278752
|
PDC_2024.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8295cd6bb8a03b51474e85e419c47d395682ea44e772816f9c3d1781990d938a
|
| 3 |
+
size 30279144
|
PDC_2025.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b6ef69dc4bb3d1e160b86114def079e038e930d0c32423ff0b226ad23d251488
|
| 3 |
+
size 30279144
|
dataset.py
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from os.path import split
|
| 2 |
+
from operator import concat
|
| 3 |
+
import re
|
| 4 |
+
from cProfile import label
|
| 5 |
+
from cgi import test
|
| 6 |
+
from tkinter import Label
|
| 7 |
+
import pandas as pd
|
| 8 |
+
import numpy as np
|
| 9 |
+
import tensorflow as tf
|
| 10 |
+
from utils import smiles2adjoin, molecular_fg
|
| 11 |
+
from rdkit import Chem
|
| 12 |
+
from random import Random
|
| 13 |
+
from collections import defaultdict
|
| 14 |
+
from rdkit.Chem.Scaffolds import MurckoScaffold
|
| 15 |
+
from itertools import compress
|
| 16 |
+
|
| 17 |
+
str2num = {'<pad>':0 ,'H': 1, 'C': 2, 'N': 3, 'O': 4, 'S': 5, 'F': 6, 'Cl': 7, 'Br': 8, 'P': 9,
|
| 18 |
+
'I': 10,'Na': 11,'B':12,'Se':13,'Si':14,'<unk>':15,'<mask>':16,'<global>':17}
|
| 19 |
+
num2str = {i:j for j,i in str2num.items()}
|
| 20 |
+
|
| 21 |
+
class Graph_Classification_Dataset(object):
|
| 22 |
+
def __init__(self,path,smiles_field1='Smiles1',smiles_field2='Smiles2',label_field=label, index_field=label, max_len=500,seed=1,batch_size=16,a=1,addH=True):
|
| 23 |
+
if path.endswith('.txt') or path.endswith('.tsv'):
|
| 24 |
+
self.df = pd.read_csv(path,sep='\t',encoding='latin1')
|
| 25 |
+
elif path.endswith('.xlsx'):
|
| 26 |
+
self.df = pd.read_excel(path)
|
| 27 |
+
else:
|
| 28 |
+
self.df = pd.read_csv(path, encoding='latin1')
|
| 29 |
+
self.smiles_field1 = smiles_field1
|
| 30 |
+
self.smiles_field2 = smiles_field2
|
| 31 |
+
self.label_field = label_field
|
| 32 |
+
self.index_field = index_field
|
| 33 |
+
self.vocab = str2num
|
| 34 |
+
self.devocab = num2str
|
| 35 |
+
self.df = self.df[self.df[smiles_field1].str.len() <= max_len]
|
| 36 |
+
self.df = self.df[[True if Chem.MolFromSmiles(smi) is not None else False for smi in self.df[smiles_field1]]]
|
| 37 |
+
self.seed = seed
|
| 38 |
+
self.batch_size = batch_size
|
| 39 |
+
self.a = a
|
| 40 |
+
self.addH = addH
|
| 41 |
+
|
| 42 |
+
def get_data(self):
|
| 43 |
+
'''Randomized Split Dataset'''
|
| 44 |
+
data = self.df
|
| 45 |
+
data = data.fillna(666)
|
| 46 |
+
train_idx = []
|
| 47 |
+
idx = data.sample(frac=0.8).index
|
| 48 |
+
train_idx.extend(idx)
|
| 49 |
+
train_data = data[data.index.isin(train_idx)]
|
| 50 |
+
data = data[~data.index.isin(train_idx)]
|
| 51 |
+
test_idx = []
|
| 52 |
+
idx = data[~data.index.isin(train_data)].sample(frac=0.5).index
|
| 53 |
+
test_idx.extend(idx)
|
| 54 |
+
test_data = data[data.index.isin(test_idx)]
|
| 55 |
+
val_data = data[~data.index.isin(train_idx+test_idx)]
|
| 56 |
+
df_train_data = pd.DataFrame(train_data)
|
| 57 |
+
df_test_data = pd.DataFrame(test_data)
|
| 58 |
+
df_val_data = pd.DataFrame(val_data)
|
| 59 |
+
|
| 60 |
+
self.dataset1 = tf.data.Dataset.from_tensor_slices(
|
| 61 |
+
(df_train_data[self.smiles_field1], df_train_data[self.label_field], df_train_data[self.smiles_field2], df_train_data[self.index_field]))
|
| 62 |
+
self.dataset1 = self.dataset1.map(self.tf_numerical_smiles).cache().padded_batch(batch_size=self.batch_size, padded_shapes=(
|
| 63 |
+
tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([self.a]),tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([1]))).shuffle(1000).prefetch(50)
|
| 64 |
+
|
| 65 |
+
self.dataset2 = tf.data.Dataset.from_tensor_slices((df_test_data[self.smiles_field1], df_test_data[self.label_field], df_test_data[self.smiles_field2], df_test_data[self.index_field]))
|
| 66 |
+
self.dataset2 = self.dataset2.map(self.tf_numerical_smiles).padded_batch(512, padded_shapes=(
|
| 67 |
+
tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([self.a]),tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([1]))).cache().prefetch(100)
|
| 68 |
+
|
| 69 |
+
self.dataset3 = tf.data.Dataset.from_tensor_slices((df_val_data[self.smiles_field1], df_val_data[self.label_field], df_val_data[self.smiles_field2], df_val_data[self.index_field]))
|
| 70 |
+
self.dataset3 = self.dataset3.map(self.tf_numerical_smiles).padded_batch(512, padded_shapes=(
|
| 71 |
+
tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([self.a]),tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([1]))).cache().prefetch(100)
|
| 72 |
+
|
| 73 |
+
return self.dataset1, self.dataset2, self.dataset3
|
| 74 |
+
|
| 75 |
+
def numerical_smiles(self, smiles, label):
|
| 76 |
+
smiles = smiles.numpy().decode()
|
| 77 |
+
atoms_list, adjoin_matrix = smiles2adjoin(smiles,explicit_hydrogens=self.addH)
|
| 78 |
+
atoms_list = ['<global>'] + atoms_list
|
| 79 |
+
nums_list = [str2num.get(i,str2num['<unk>']) for i in atoms_list]
|
| 80 |
+
temp = np.ones((len(nums_list),len(nums_list)))
|
| 81 |
+
temp[1:, 1:] = adjoin_matrix
|
| 82 |
+
adjoin_matrix = (1-temp)*(-1e9)
|
| 83 |
+
x = np.array(nums_list).astype('int64')
|
| 84 |
+
y = np.array(label).astype('int64')
|
| 85 |
+
return x, adjoin_matrix, y
|
| 86 |
+
|
| 87 |
+
def tf_numerical_smiles(self, smiles1, label, smiles2, index):
|
| 88 |
+
x1,adjoin_matrix1,y= tf.py_function(self.numerical_smiles, [smiles1,label], [tf.int64, tf.float32 ,tf.int64])
|
| 89 |
+
x1.set_shape([None])
|
| 90 |
+
adjoin_matrix1.set_shape([None,None])
|
| 91 |
+
y.set_shape([None])
|
| 92 |
+
x2,adjoin_matrix2,index = tf.py_function(self.numerical_smiles, [smiles2,index], [tf.int64, tf.float32 ,tf.int64])
|
| 93 |
+
x2.set_shape([None])
|
| 94 |
+
adjoin_matrix2.set_shape([None,None])
|
| 95 |
+
index.set_shape([None])
|
| 96 |
+
return x1, adjoin_matrix1, y, x2,adjoin_matrix2, index
|
| 97 |
+
|
| 98 |
+
class Inference_Dataset(object):
|
| 99 |
+
def __init__(self,sml_list,max_len=500,addH=True):
|
| 100 |
+
self.vocab = str2num
|
| 101 |
+
self.devocab = num2str
|
| 102 |
+
self.sml_list = [i for i in sml_list if len(i)<max_len]
|
| 103 |
+
self.addH = addH
|
| 104 |
+
|
| 105 |
+
def get_data(self):
|
| 106 |
+
self.dataset = tf.data.Dataset.from_tensor_slices((self.sml_list,))
|
| 107 |
+
self.dataset = self.dataset.map(self.tf_numerical_smiles).padded_batch(512, padded_shapes=(
|
| 108 |
+
tf.TensorShape([None]), tf.TensorShape([None,None]),tf.TensorShape([1]),tf.TensorShape([None]))).cache().prefetch(20)
|
| 109 |
+
|
| 110 |
+
return self.dataset
|
| 111 |
+
|
| 112 |
+
def numerical_smiles(self, smiles):
|
| 113 |
+
smiles_origin = smiles
|
| 114 |
+
smiles = smiles.numpy().decode()
|
| 115 |
+
atoms_list, adjoin_matrix = smiles2adjoin(smiles,explicit_hydrogens=self.addH)
|
| 116 |
+
atoms_list = ['<global>'] + atoms_list
|
| 117 |
+
nums_list = [str2num.get(i,str2num['<unk>']) for i in atoms_list]
|
| 118 |
+
temp = np.ones((len(nums_list),len(nums_list)))
|
| 119 |
+
temp[1:,1:] = adjoin_matrix
|
| 120 |
+
adjoin_matrix = (1-temp)*(-1e9)
|
| 121 |
+
x = np.array(nums_list).astype('int64')
|
| 122 |
+
return x, adjoin_matrix,[smiles], atoms_list
|
| 123 |
+
|
| 124 |
+
def tf_numerical_smiles(self, smiles):
|
| 125 |
+
x,adjoin_matrix,smiles,atom_list = tf.py_function(self.numerical_smiles, [smiles], [tf.int64, tf.float32,tf.string, tf.string])
|
| 126 |
+
x.set_shape([None])
|
| 127 |
+
adjoin_matrix.set_shape([None,None])
|
| 128 |
+
smiles.set_shape([1])
|
| 129 |
+
atom_list.set_shape([None])
|
| 130 |
+
return x, adjoin_matrix,smiles,atom_list
|
| 131 |
+
|
| 132 |
+
class Inference_Dataset(object):
|
| 133 |
+
def __init__(self,sml_list,max_len=500,addH=True):
|
| 134 |
+
self.vocab = str2num
|
| 135 |
+
self.devocab = num2str
|
| 136 |
+
self.sml_list = [i for i in sml_list if len(i)<max_len]
|
| 137 |
+
self.addH = addH
|
| 138 |
+
|
| 139 |
+
def get_data(self):
|
| 140 |
+
self.dataset = tf.data.Dataset.from_tensor_slices((self.sml_list,))
|
| 141 |
+
self.dataset = self.dataset.map(self.tf_numerical_smiles).padded_batch(512, padded_shapes=(
|
| 142 |
+
tf.TensorShape([None]), tf.TensorShape([None,None]),tf.TensorShape([1]),tf.TensorShape([None]))).cache().prefetch(20)
|
| 143 |
+
|
| 144 |
+
return self.dataset
|
| 145 |
+
|
| 146 |
+
def numerical_smiles(self, smiles):
|
| 147 |
+
smiles_origin = smiles
|
| 148 |
+
smiles = smiles.numpy().decode()
|
| 149 |
+
atoms_list, adjoin_matrix = smiles2adjoin(smiles,explicit_hydrogens=self.addH)
|
| 150 |
+
atoms_list = ['<global>'] + atoms_list
|
| 151 |
+
nums_list = [str2num.get(i,str2num['<unk>']) for i in atoms_list]
|
| 152 |
+
temp = np.ones((len(nums_list),len(nums_list)))
|
| 153 |
+
temp[1:,1:] = adjoin_matrix
|
| 154 |
+
adjoin_matrix = (1-temp)*(-1e9)
|
| 155 |
+
x = np.array(nums_list).astype('int64')
|
| 156 |
+
return x, adjoin_matrix,[smiles], atoms_list
|
| 157 |
+
|
| 158 |
+
def tf_numerical_smiles(self, smiles):
|
| 159 |
+
x,adjoin_matrix,smiles,atom_list = tf.py_function(self.numerical_smiles, [smiles], [tf.int64, tf.float32,tf.string, tf.string])
|
| 160 |
+
x.set_shape([None])
|
| 161 |
+
adjoin_matrix.set_shape([None,None])
|
| 162 |
+
smiles.set_shape([1])
|
| 163 |
+
atom_list.set_shape([None])
|
| 164 |
+
return x, adjoin_matrix,smiles,atom_list
|
encoding.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
def zscale_padding(seq_list, padding):
|
| 4 |
+
zscale = {
|
| 5 |
+
'A': [0.24, -2.32, 0.60, -0.14, 1.30],
|
| 6 |
+
'C': [0.84, -1.67, 3.71, 0.18, -2.65],
|
| 7 |
+
'D': [3.98, 0.93, 1.93, -2.46, 0.75],
|
| 8 |
+
'E': [3.11, 0.26, -0.11, -0.34, -0.25],
|
| 9 |
+
'F': [-4.22, 1.94, 1.06, 0.54, -0.62],
|
| 10 |
+
'G': [2.05, -4.06, 0.36, -0.82, -0.38],
|
| 11 |
+
'H': [2.47, 1.95, 0.26, 3.90, 0.09],
|
| 12 |
+
'I': [-3.89, -1.73, -1.71, -0.84, 0.26],
|
| 13 |
+
'K': [2.29, 0.89, -2.49, 1.49, 0.31],
|
| 14 |
+
'L': [-4.28, -1.30, -1.49, -0.72, 0.84],
|
| 15 |
+
'M': [-2.85, -0.22, 0.47, 1.94, -0.98],
|
| 16 |
+
'N': [3.05, 1.62, 1.04, -1.15, 1.61],
|
| 17 |
+
'P': [-1.66, 0.27, 1.84, 0.70, 2.00],
|
| 18 |
+
'Q': [1.75, 0.50, -1.44, -1.34, 0.66],
|
| 19 |
+
'R': [3.52, 2.50, -3.50, 1.99, -0.17],
|
| 20 |
+
'S': [2.39, -1.07, 1.15, -1.39, 0.67],
|
| 21 |
+
'T': [0.75, -2.18, -1.12, -1.46, -0.40],
|
| 22 |
+
'V': [-2.59, -2.64, -1.54, -0.85, -0.02],
|
| 23 |
+
'W': [-4.36, 3.94, 0.59, 3.44, -1.59],
|
| 24 |
+
'Y': [-2.54, 2.44, 0.43, 0.04, -1.47],
|
| 25 |
+
'-': [0.00, 0.00, 0.00, 0.00, 0.00] # For gaps or unknown amino acids
|
| 26 |
+
}
|
| 27 |
+
feat_list = []
|
| 28 |
+
for seq in seq_list:
|
| 29 |
+
feat = [zscale.get(aa, zscale['-']) for aa in seq]
|
| 30 |
+
feat += [[0] * 5] * (padding - len(seq))
|
| 31 |
+
feat_list.append(feat)
|
| 32 |
+
return np.array(feat_list)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def one_hot_padding(seq_list, padding):
|
| 36 |
+
feat_list = []
|
| 37 |
+
one_hot = {}
|
| 38 |
+
aa = ['A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y']
|
| 39 |
+
for i in range(len(aa)):
|
| 40 |
+
one_hot[aa[i]] = [0] * 20
|
| 41 |
+
one_hot[aa[i]][i] = 1
|
| 42 |
+
for seq in seq_list:
|
| 43 |
+
feat = [one_hot[aa] for aa in seq] + [[0] * 20] * (padding - len(seq))
|
| 44 |
+
feat_list.append(feat)
|
| 45 |
+
return np.array(feat_list)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def position_encoding(padding, d=20, b=1000):
|
| 49 |
+
pos_encoding = np.zeros((padding, d))
|
| 50 |
+
for pos in range(padding):
|
| 51 |
+
for i in range(d // 2):
|
| 52 |
+
pos_encoding[pos, 2 * i] = np.sin(pos / (b ** (2 * i / d)))
|
| 53 |
+
pos_encoding[pos, 2 * i + 1] = np.cos(pos / (b ** (2 * i / d)))
|
| 54 |
+
return pos_encoding
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
blosum62 = {
|
| 58 |
+
'A': [4, -1, -2, -2, 0, -2, -1, 0, -2, -1, -1, -1, -1, -1, -1, 1, 0, 0, -3, -2],
|
| 59 |
+
'C': [-1, 9, -3, -4, -2, -3, -3, -3, -3, -1, -1, -3, -3, -3, -3, -1, -1, -1, -2, -2],
|
| 60 |
+
'D': [-2, -3, 6, 2, -3, 1, -1, -1, -1, -4, -3, 1, 0, -3, -3, 0, -1, -3, -4, -3],
|
| 61 |
+
'E': [-2, -4, 2, 5, -3, 0, -2, -1, 1, -3, -2, 0, 0, -3, -2, 0, -1, -2, -3, -2],
|
| 62 |
+
'F': [0, -2, -3, -3, 6, -3, -1, -3, -1, 0, 0, -3, -4, -3, -3, -2, -2, -3, 1, 3],
|
| 63 |
+
'G': [-2, -3, 1, 0, -3, 6, -2, -4, -2, -4, -3, 0, -2, -3, -2, 0, -2, -3, -2, -3],
|
| 64 |
+
'H': [-1, -3, -1, -2, -1, -2, 8, -3, -1, -3, -2, -1, -2, -1, -2, -2, -2, -2, 2, 2],
|
| 65 |
+
'I': [0, -3, -1, -1, -3, -4, -3, 4, -3, -3, -3, -1, -3, -3, -3, -3, -1, 2, -3, -1],
|
| 66 |
+
'K': [-2, -3, -1, 1, -1, -2, -1, -3, 5, -2, -1, 0, -1, 1, 0, -1, 0, -2, -3, -2],
|
| 67 |
+
'L': [-1, -1, -4, -3, 0, -4, -3, -3, -2, 4, 2, -3, -3, -2, -2, -2, -1, 1, -2, -1],
|
| 68 |
+
'M': [-1, -1, -3, -2, 0, -3, -2, -3, -1, 2, 5, -2, -2, 0, -1, -2, -1, 1, -1, -1],
|
| 69 |
+
'N': [-1, -3, 1, 0, -3, 0, -1, -1, 0, -3, -2, 6, 2, -3, -3, 1, 0, -3, -4, -2],
|
| 70 |
+
'P': [-1, -3, 0, 0, -4, -2, -2, -3, -1, -3, -2, 2, 7, -1, -1, -1, -1, -2, -4, -3],
|
| 71 |
+
'Q': [-1, -3, -3, -3, -3, -3, -1, -3, 1, -2, 0, -3, -1, 5, 2, -1, 0, -2, -2, -1],
|
| 72 |
+
'R': [-1, -3, -3, -2, -3, -2, -2, -3, 0, -2, -1, -3, -1, 2, 5, -1, 0, -2, -3, -2],
|
| 73 |
+
'S': [1, -1, 0, 0, -2, 0, -2, -3, -1, -2, -2, 1, -1, -1, -1, 4, 1, -2, -3, -2],
|
| 74 |
+
'T': [0, -1, -1, -1, -2, -2, -2, -1, 0, -1, -1, 0, -1, 0, 0, 1, 5, 0, -2, -2],
|
| 75 |
+
'V': [0, -1, -3, -2, -3, -3, -2, 2, -2, 1, 1, -3, -2, -2, -2, -2, 0, 4, -3, -1],
|
| 76 |
+
'W': [-3, -2, -4, -3, 1, -2, 2, -3, -3, -2, -1, -4, -4, -2, -3, -3, -2, -3, 11, 2],
|
| 77 |
+
'Y': [-2, -2, -3, -2, 3, -3, 2, -1, -2, -1, -1, -2, -3, -1, -2, -2, -2, -1, 2, 7],
|
| 78 |
+
'X': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # For unknown amino acids
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
def blosum62_padding(seq_list, padding):
|
| 82 |
+
feat_list = []
|
| 83 |
+
for seq in seq_list:
|
| 84 |
+
feat = [blosum62.get(aa, blosum62['X']) for aa in seq] + [[0] * 20] * (padding - len(seq))
|
| 85 |
+
feat_list.append(feat)
|
| 86 |
+
return np.array(feat_list)
|
| 87 |
+
|
| 88 |
+
def combined_encoding(seq_list, padding):
|
| 89 |
+
one_hot_encoded = one_hot_padding(seq_list, padding)
|
| 90 |
+
pos_encoded = position_encoding(padding)
|
| 91 |
+
blosum_encoded = blosum62_padding(seq_list, padding)
|
| 92 |
+
zscale_encoded = zscale_padding(seq_list, padding)
|
| 93 |
+
|
| 94 |
+
pos_encoded_expanded = np.expand_dims(pos_encoded, axis=0).repeat(len(seq_list), axis=0)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
combined_encoding = np.concatenate(
|
| 98 |
+
(one_hot_encoded, pos_encoded_expanded, blosum_encoded, zscale_encoded), axis=2
|
| 99 |
+
)
|
| 100 |
+
return combined_encoding
|
model.py
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
from cProfile import label
|
| 3 |
+
import tensorflow as tf
|
| 4 |
+
from layers import Attention, MultiHeadAttention
|
| 5 |
+
from tf_keras.models import Model
|
| 6 |
+
from tf_keras.layers import Masking, Dense, LSTM, Bidirectional, Input, Dropout
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def gelu(x):
|
| 11 |
+
return 0.5 * x * (1.0 + tf.math.erf(x / tf.sqrt(2.)))
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def scaled_dot_product_attention(q, k, v, mask,adjoin_matrix):
|
| 15 |
+
|
| 16 |
+
matmul_qk = tf.matmul(q, k, transpose_b=True)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
dk = tf.cast(tf.shape(k)[-1], tf.float32)
|
| 20 |
+
scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
if mask is not None:
|
| 24 |
+
scaled_attention_logits += (mask * -1e9)
|
| 25 |
+
if adjoin_matrix is not None:
|
| 26 |
+
scaled_attention_logits += adjoin_matrix
|
| 27 |
+
|
| 28 |
+
attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)
|
| 29 |
+
|
| 30 |
+
output = tf.matmul(attention_weights, v)
|
| 31 |
+
|
| 32 |
+
return output, attention_weights
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class MultiHeadAttention(tf.keras.layers.Layer):
|
| 36 |
+
def __init__(self, d_model, num_heads):
|
| 37 |
+
super(MultiHeadAttention, self).__init__()
|
| 38 |
+
self.num_heads = num_heads
|
| 39 |
+
self.d_model = d_model
|
| 40 |
+
|
| 41 |
+
assert d_model % self.num_heads == 0
|
| 42 |
+
|
| 43 |
+
self.depth = d_model // self.num_heads
|
| 44 |
+
|
| 45 |
+
self.wq = tf.keras.layers.Dense(d_model)
|
| 46 |
+
self.wk = tf.keras.layers.Dense(d_model)
|
| 47 |
+
self.wv = tf.keras.layers.Dense(d_model)
|
| 48 |
+
|
| 49 |
+
self.dense = tf.keras.layers.Dense(d_model)
|
| 50 |
+
|
| 51 |
+
def split_heads(self, x, batch_size):
|
| 52 |
+
"""Split the last dimension into (num_heads, depth).
|
| 53 |
+
Transpose the result such that the shape is (batch_size, num_heads, seq_len, depth)
|
| 54 |
+
"""
|
| 55 |
+
x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))
|
| 56 |
+
return tf.transpose(x, perm=[0, 2, 1, 3])
|
| 57 |
+
|
| 58 |
+
def call(self, v, k, q, mask,adjoin_matrix):
|
| 59 |
+
batch_size = tf.shape(q)[0]
|
| 60 |
+
|
| 61 |
+
q = self.wq(q)
|
| 62 |
+
k = self.wk(k)
|
| 63 |
+
v = self.wv(v)
|
| 64 |
+
|
| 65 |
+
q = self.split_heads(q, batch_size)
|
| 66 |
+
k = self.split_heads(k, batch_size)
|
| 67 |
+
v = self.split_heads(v, batch_size)
|
| 68 |
+
|
| 69 |
+
scaled_attention, attention_weights = scaled_dot_product_attention(
|
| 70 |
+
q, k, v, mask,adjoin_matrix)
|
| 71 |
+
|
| 72 |
+
scaled_attention = tf.transpose(scaled_attention,
|
| 73 |
+
perm=[0, 2, 1, 3])
|
| 74 |
+
|
| 75 |
+
concat_attention = tf.reshape(scaled_attention,
|
| 76 |
+
(batch_size, -1, self.d_model))
|
| 77 |
+
|
| 78 |
+
output = self.dense(concat_attention)
|
| 79 |
+
|
| 80 |
+
return output, attention_weights
|
| 81 |
+
|
| 82 |
+
def point_wise_feed_forward_network(d_model, dff):
|
| 83 |
+
return tf.keras.Sequential([
|
| 84 |
+
tf.keras.layers.Dense(dff, activation=gelu),
|
| 85 |
+
tf.keras.layers.Dense(d_model)
|
| 86 |
+
])
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
class EncoderLayer(tf.keras.layers.Layer):
|
| 90 |
+
def __init__(self, d_model, num_heads, dff, rate=0.1):
|
| 91 |
+
super(EncoderLayer, self).__init__()
|
| 92 |
+
|
| 93 |
+
self.mha = MultiHeadAttention(d_model, num_heads)
|
| 94 |
+
self.ffn = point_wise_feed_forward_network(d_model, dff)
|
| 95 |
+
|
| 96 |
+
self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
|
| 97 |
+
self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
|
| 98 |
+
|
| 99 |
+
self.dropout1 = tf.keras.layers.Dropout(rate)
|
| 100 |
+
self.dropout2 = tf.keras.layers.Dropout(rate)
|
| 101 |
+
|
| 102 |
+
def call(self, x, training, mask,adjoin_matrix):
|
| 103 |
+
attn_output, attention_weights = self.mha(x, x, x, mask,adjoin_matrix)
|
| 104 |
+
attn_output = self.dropout1(attn_output, training=training)
|
| 105 |
+
out1 = self.layernorm1(x + attn_output)
|
| 106 |
+
|
| 107 |
+
ffn_output = self.ffn(out1)
|
| 108 |
+
ffn_output = self.dropout2(ffn_output, training=training)
|
| 109 |
+
out2 = self.layernorm2(out1 + ffn_output)
|
| 110 |
+
|
| 111 |
+
return out2,attention_weights
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
class Encoder(tf.keras.Model):
|
| 116 |
+
def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size,
|
| 117 |
+
maximum_position_encoding, rate=0.1):
|
| 118 |
+
super(Encoder, self).__init__()
|
| 119 |
+
|
| 120 |
+
self.d_model = d_model
|
| 121 |
+
self.num_layers = num_layers
|
| 122 |
+
|
| 123 |
+
self.embedding = tf.keras.layers.Embedding(input_vocab_size, d_model)
|
| 124 |
+
|
| 125 |
+
self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate)
|
| 126 |
+
for _ in range(num_layers)]
|
| 127 |
+
|
| 128 |
+
self.dropout = tf.keras.layers.Dropout(rate)
|
| 129 |
+
|
| 130 |
+
def call(self, x, training, mask,adjoin_matrix):
|
| 131 |
+
seq_len = tf.shape(x)[1]
|
| 132 |
+
adjoin_matrix = adjoin_matrix[:,tf.newaxis,:,:]
|
| 133 |
+
x = self.embedding(x)
|
| 134 |
+
x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
|
| 135 |
+
|
| 136 |
+
x = self.dropout(x, training=training)
|
| 137 |
+
|
| 138 |
+
for i in range(self.num_layers):
|
| 139 |
+
x, attention_weights = self.enc_layers[i](x, training=training, mask=mask, adjoin_matrix=adjoin_matrix)
|
| 140 |
+
return x
|
| 141 |
+
|
| 142 |
+
class Encoder_test(tf.keras.Model):
|
| 143 |
+
def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size,
|
| 144 |
+
maximum_position_encoding, rate=0.1):
|
| 145 |
+
super(Encoder_test, self).__init__()
|
| 146 |
+
|
| 147 |
+
self.d_model = d_model
|
| 148 |
+
self.num_layers = num_layers
|
| 149 |
+
|
| 150 |
+
self.embedding = tf.keras.layers.Embedding(input_vocab_size, d_model)
|
| 151 |
+
|
| 152 |
+
self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate)
|
| 153 |
+
for _ in range(num_layers)]
|
| 154 |
+
|
| 155 |
+
self.dropout = tf.keras.layers.Dropout(rate)
|
| 156 |
+
|
| 157 |
+
def call(self, x, training, mask,adjoin_matrix):
|
| 158 |
+
seq_len = tf.shape(x)[1]
|
| 159 |
+
adjoin_matrix = adjoin_matrix[:,tf.newaxis,:,:]
|
| 160 |
+
x = self.embedding(x)
|
| 161 |
+
x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
|
| 162 |
+
|
| 163 |
+
x = self.dropout(x, training=training)
|
| 164 |
+
attention_weights_list = []
|
| 165 |
+
xs = []
|
| 166 |
+
|
| 167 |
+
for i in range(self.num_layers):
|
| 168 |
+
x,attention_weights = self.enc_layers[i](x, training, mask,adjoin_matrix)
|
| 169 |
+
attention_weights_list.append(attention_weights)
|
| 170 |
+
xs.append(x)
|
| 171 |
+
|
| 172 |
+
return x,attention_weights_list,xs
|
| 173 |
+
|
| 174 |
+
class BertModel_test(tf.keras.Model):
|
| 175 |
+
def __init__(self,num_layers = 6,d_model = 256,dff = 512,num_heads = 8,vocab_size = 18,dropout_rate = 0.1):
|
| 176 |
+
super(BertModel_test, self).__init__()
|
| 177 |
+
self.encoder = Encoder_test(num_layers=num_layers,d_model=d_model,
|
| 178 |
+
num_heads=num_heads,dff=dff,input_vocab_size=vocab_size,maximum_position_encoding=200,rate=dropout_rate)
|
| 179 |
+
self.fc1 = tf.keras.layers.Dense(d_model, activation=gelu)
|
| 180 |
+
self.layernorm = tf.keras.layers.LayerNormalization(-1)
|
| 181 |
+
self.fc2 = tf.keras.layers.Dense(vocab_size)
|
| 182 |
+
def call(self,x,adjoin_matrix,mask,training=False):
|
| 183 |
+
x,att,xs = self.encoder(x,training=training,mask=mask,adjoin_matrix=adjoin_matrix)
|
| 184 |
+
x = self.fc1(x)
|
| 185 |
+
x = self.layernorm(x)
|
| 186 |
+
x = self.fc2(x)
|
| 187 |
+
return x,att,xs
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
class BertModel(tf.keras.Model):
|
| 191 |
+
def __init__(self,num_layers = 6,d_model = 256,dff = 512,num_heads = 8,vocab_size = 18,dropout_rate = 0.1):
|
| 192 |
+
super(BertModel, self).__init__()
|
| 193 |
+
self.encoder = Encoder(num_layers=num_layers,d_model=d_model,
|
| 194 |
+
num_heads=num_heads,dff=dff,input_vocab_size=vocab_size,maximum_position_encoding=200,rate=dropout_rate)
|
| 195 |
+
self.fc1 = tf.keras.layers.Dense(d_model, activation=gelu)
|
| 196 |
+
self.layernorm = tf.keras.layers.LayerNormalization(-1)
|
| 197 |
+
self.fc2 = tf.keras.layers.Dense(vocab_size)
|
| 198 |
+
|
| 199 |
+
def call(self,x,adjoin_matrix,mask,training=False):
|
| 200 |
+
x = self.encoder(x,training=training,mask=mask,adjoin_matrix=adjoin_matrix)
|
| 201 |
+
x = self.fc1(x)
|
| 202 |
+
x = self.layernorm(x)
|
| 203 |
+
x = self.fc2(x)
|
| 204 |
+
return x
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
class PredictModel(tf.keras.Model):
|
| 208 |
+
def __init__(self,num_layers = 6,d_model = 256,dff = 512,num_heads = 8,vocab_size =18, a=2, dropout_rate = 0.1,dense_dropout=0.1):
|
| 209 |
+
super(PredictModel, self).__init__()
|
| 210 |
+
self.encoder = Encoder(num_layers=num_layers,d_model=d_model,
|
| 211 |
+
num_heads=num_heads,dff=dff,input_vocab_size=vocab_size,maximum_position_encoding=200,rate=dropout_rate)
|
| 212 |
+
self.fc1 = tf.keras.layers.Dense(256,activation=tf.keras.layers.LeakyReLU(0.1))
|
| 213 |
+
self.dropout1 = tf.keras.layers.Dropout(dense_dropout)
|
| 214 |
+
self.fc2 = tf.keras.layers.Dense(a)
|
| 215 |
+
self.t2_processing_network = self.build_layer()
|
| 216 |
+
|
| 217 |
+
def build_layer(self, maxlen=71):
|
| 218 |
+
inputs = Input(shape=(maxlen, 65), name='t2_Input')
|
| 219 |
+
masking = Masking(mask_value=0.0, input_shape=(maxlen, 65), name='Masking')(inputs)
|
| 220 |
+
hidden = Bidirectional(LSTM(512, use_bias=True, dropout=0.5, return_sequences=True), name='Bidirectional-LSTM')(
|
| 221 |
+
masking)
|
| 222 |
+
hidden = Dropout(0.2, name='Dropout_1')(hidden)
|
| 223 |
+
hidden = Attention(name='Attention')(hidden)
|
| 224 |
+
hidden = Dense(512, activation='relu')(hidden)
|
| 225 |
+
|
| 226 |
+
model = Model(inputs=inputs, outputs=hidden)
|
| 227 |
+
return model
|
| 228 |
+
|
| 229 |
+
def call(self,x1,adjoin_matrix1,mask1,x2,adjoin_matrix2,mask2,t1,t2, training=False):
|
| 230 |
+
x1 = self.encoder(x1,training=False,mask=mask1,adjoin_matrix=adjoin_matrix1)
|
| 231 |
+
x1 = x1[:,0,:]
|
| 232 |
+
x2 = self.encoder(x2,training=False,mask=mask2,adjoin_matrix=adjoin_matrix2)
|
| 233 |
+
x2 = x2[:,0,:]
|
| 234 |
+
x = tf.concat([x1,x2], axis=1)
|
| 235 |
+
t2 = self.t2_processing_network(t2)
|
| 236 |
+
x = tf.concat([x, t1, t2], axis=1)
|
| 237 |
+
x = self.fc1(x)
|
| 238 |
+
x = self.dropout1(x,training=training)
|
| 239 |
+
x = self.fc2(x)
|
| 240 |
+
return x
|
utils.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from rdkit import Chem
|
| 2 |
+
from rdkit.Chem import rdmolfiles, rdmolops
|
| 3 |
+
import numpy as np
|
| 4 |
+
import openbabel as ob
|
| 5 |
+
import os
|
| 6 |
+
import csv
|
| 7 |
+
from rdkit import RDConfig
|
| 8 |
+
from rdkit.Chem import FragmentCatalog
|
| 9 |
+
|
| 10 |
+
def fg_list(): # 47 FGs list
|
| 11 |
+
fName=os.path.join(RDConfig.RDDataDir,'FunctionalGroups.txt')
|
| 12 |
+
fparams = FragmentCatalog.FragCatParams(1,6,fName)
|
| 13 |
+
fg_list = []
|
| 14 |
+
for i in range(fparams.GetNumFuncGroups()):
|
| 15 |
+
fg_list.append(fparams.GetFuncGroup(i))
|
| 16 |
+
fg_list.pop(27)
|
| 17 |
+
|
| 18 |
+
x = [Chem.MolToSmiles(_) for _ in fg_list]+['*C=C','*F','*Cl','*Br','*I','[Na+]','*P','*P=O','*[Se]','*[Si]']
|
| 19 |
+
y = set(x)
|
| 20 |
+
return list(y)
|
| 21 |
+
|
| 22 |
+
def obsmitosmile(smi):
|
| 23 |
+
conv = ob.OBConversion()
|
| 24 |
+
conv.SetInAndOutFormats("smi", "can")
|
| 25 |
+
conv.SetOptions("K", conv.OUTOPTIONS)
|
| 26 |
+
mol = ob.OBMol()
|
| 27 |
+
conv.ReadString(mol, smi)
|
| 28 |
+
smile = conv.WriteString(mol)
|
| 29 |
+
smile = smile.replace('\t\n', '')
|
| 30 |
+
return smile
|
| 31 |
+
|
| 32 |
+
def molecular_fg(smiles): # Getting functional groups (including rings) in molecules
|
| 33 |
+
|
| 34 |
+
mol = Chem.MolFromSmiles(smiles)
|
| 35 |
+
if mol is None:
|
| 36 |
+
print('error')
|
| 37 |
+
mol = Chem.MolFromSmiles(obsmitosmile(smiles))
|
| 38 |
+
assert mol is not None, smiles + ' is not valid '
|
| 39 |
+
a = fg_list()
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
ssr = Chem.GetSymmSSSR(mol)
|
| 43 |
+
num_ring = len(ssr)
|
| 44 |
+
ring_dict = {}
|
| 45 |
+
for i in range(num_ring):
|
| 46 |
+
ring_dict[i+1] = list(ssr[i])
|
| 47 |
+
|
| 48 |
+
f_g_list = []
|
| 49 |
+
for i in ring_dict.values():
|
| 50 |
+
f_g_list.append(i)
|
| 51 |
+
|
| 52 |
+
for i in a:
|
| 53 |
+
patt = Chem.MolFromSmarts(i)
|
| 54 |
+
flag = mol.HasSubstructMatch(patt)
|
| 55 |
+
if flag:
|
| 56 |
+
atomids = mol.GetSubstructMatches(patt)
|
| 57 |
+
for atomid in atomids:
|
| 58 |
+
f_g_list.append(list(atomid))
|
| 59 |
+
return f_g_list
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def smiles2adjoin(smiles,explicit_hydrogens=True,canonical_atom_order=False): # Converting molecules in SMILES format to atom lists and adjacency matrices
|
| 63 |
+
|
| 64 |
+
mol = Chem.MolFromSmiles(smiles)
|
| 65 |
+
if mol is None:
|
| 66 |
+
print('error')
|
| 67 |
+
mol = Chem.MolFromSmiles(obsmitosmile(smiles))
|
| 68 |
+
assert mol is not None, smiles + ' is not valid '
|
| 69 |
+
|
| 70 |
+
if explicit_hydrogens:
|
| 71 |
+
mol = Chem.AddHs(mol)
|
| 72 |
+
else:
|
| 73 |
+
mol = Chem.RemoveHs(mol)
|
| 74 |
+
|
| 75 |
+
if canonical_atom_order:
|
| 76 |
+
new_order = rdmolfiles.CanonicalRankAtoms(mol)
|
| 77 |
+
mol = rdmolops.RenumberAtoms(mol, new_order)
|
| 78 |
+
num_atoms = mol.GetNumAtoms()
|
| 79 |
+
|
| 80 |
+
atoms_list = []
|
| 81 |
+
for i in range(num_atoms):
|
| 82 |
+
atom = mol.GetAtomWithIdx(i)
|
| 83 |
+
atoms_list.append(atom.GetSymbol())
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
adjoin_matrix = np.eye(num_atoms)
|
| 87 |
+
num_bonds = mol.GetNumBonds()
|
| 88 |
+
|
| 89 |
+
for i in range(num_bonds):
|
| 90 |
+
bond = mol.GetBondWithIdx(i)
|
| 91 |
+
u = bond.GetBeginAtomIdx()
|
| 92 |
+
v = bond.GetEndAtomIdx()
|
| 93 |
+
adjoin_matrix[u,v] = 1.0
|
| 94 |
+
adjoin_matrix[v,u] = 1.0
|
| 95 |
+
|
| 96 |
+
return atoms_list,adjoin_matrix
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def get_header(path):
|
| 100 |
+
with open(path) as f:
|
| 101 |
+
header = next(csv.reader(f))
|
| 102 |
+
|
| 103 |
+
return header
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
def get_task_names(path, use_compound_names=False):
|
| 107 |
+
index = 2 if use_compound_names else 1
|
| 108 |
+
task_names = get_header(path)[index:]
|
| 109 |
+
|
| 110 |
+
return task_names
|