You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

datasets.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. import os.path as osp
  2. import pandas as pd
  3. import torch
  4. from torch_geometric.data import Dataset, Data
  5. import numpy as np
  6. import random
  7. import os
  8. from tqdm import tqdm
  9. from rdkit import Chem
  10. import deepchem as dc
  11. class DDInteractionDataset(Dataset):
  12. def __init__(self, root = "\\drug/data/", transform=None, pre_transform=None, pre_filter=None, gpu_id=None):
  13. self.gpu_id = gpu_id
  14. super(DDInteractionDataset, self).__init__(os.path.dirname(os.path.abspath(os.path.dirname( __file__ ))) + "/drug/data/", transform, pre_transform, pre_filter)
  15. @property
  16. def num_features(self):
  17. return self._num_features
  18. @num_features.setter
  19. def num_features(self, value):
  20. self._num_features = value
  21. @property
  22. def raw_file_names(self):
  23. return ['new_interaction.tsv']
  24. @property
  25. def processed_file_names(self):
  26. return ['ddi_processed.pt']
  27. @property
  28. def raw_dir(self):
  29. dir = osp.join(self.root, 'DDI/DrugBank/raw')
  30. return dir
  31. @property
  32. def processed_dir(self):
  33. name = 'processed'
  34. return osp.join(self.root, 'DDI/DrugBank/' + name)
  35. def download(self):
  36. pass
  37. def find_drugBank_id(self, index):
  38. path = osp.join(self.root, 'DDI/DrugBank/raw/' + 'drug2id.tsv')
  39. drug2id_df = pd.read_csv(path, sep='\t')
  40. drugBankID = drug2id_df['DrugBank_id'][index]
  41. return drugBankID
  42. def generate_rand_fp(self):
  43. number = random.getrandbits(256)
  44. # Convert the number to binary
  45. binary_string = '{0:0256b}'.format(number)
  46. random_fp = [x for x in binary_string]
  47. random_fp = list(map(int, random_fp))
  48. return random_fp
  49. def read_node_features(self, num_nodes):
  50. drug_fp_path = osp.join(self.root, 'RDkit extracted/drug2FP.csv')
  51. drug_fp_df = pd.read_csv(drug_fp_path)
  52. node_features = list()
  53. node_ids = list()
  54. for i in range(num_nodes):
  55. drugbankid = self.find_drugBank_id(i)
  56. fp = drug_fp_df.loc[drug_fp_df['DrugBank_id'] == drugbankid]
  57. if fp.empty:
  58. fp = self.generate_rand_fp()
  59. else:
  60. fp = list(fp.to_numpy()[0,1:])
  61. node_features.append(fp)
  62. node_ids.append(drugbankid)
  63. #add synergy file drugs to end of the graph
  64. drug_fp_synergy_path = osp.join(self.root, 'drug2FP_synergy.csv')
  65. drug_fp_synergy_df = pd.read_csv(drug_fp_synergy_path)
  66. for index, row in drug_fp_synergy_df.iterrows():
  67. node_ids.append(row[0])
  68. node_features.append(list(row.to_numpy()[1:]))
  69. self.num_features = len(node_features[0])
  70. return node_ids, node_features
  71. def process(self):
  72. path = osp.join(self.raw_dir, self.raw_file_names[0])
  73. ddi = pd.read_csv(path , sep='\t')
  74. edge_index = torch.tensor([ddi['drug1_idx'],ddi['drug2_idx']], dtype=torch.long)
  75. num_nodes = ddi['drug1_idx'].max() + 1
  76. node_ids, node_features = self.read_node_features(num_nodes)
  77. node_features = torch.tensor(node_features, dtype=torch.int)
  78. print("node features nrow and ncol: ",len(node_features),len(node_features[0]))
  79. # ---------------------------------------------------------------
  80. data = Data(x = node_features, edge_index = edge_index)
  81. if self.gpu_id is not None:
  82. data = data.cuda(self.gpu_id)
  83. if self.pre_filter is not None and not self.pre_filter(data):
  84. pass
  85. if self.pre_transform is not None:
  86. data = self.pre_transform(data)
  87. torch.save(data, osp.join(self.processed_dir, 'ddi_graph_dataset.pt'))
  88. def len(self):
  89. return len(self.processed_file_names)
  90. def get(self):
  91. data = torch.load(osp.join(self.processed_dir, 'ddi_graph_dataset.pt'))
  92. return data
  93. # run for checking
  94. # ddiDataset = DDInteractionDataset(root = "drug/data/")
  95. # print(ddiDataset.get().edge_index.t())
  96. # print(ddiDataset.get().x)
  97. # print(ddiDataset.num_features)
  98. class MoleculeDataset(Dataset):
  99. def __init__(self, root = "/drug/data/", test=False, transform=None, pre_transform=None):
  100. """
  101. root = Where the dataset should be stored. This folder is split
  102. into raw_dir (downloaded dataset) and processed_dir (processed data).
  103. """
  104. self.test = test
  105. super(MoleculeDataset, self).__init__(root, transform, pre_transform)
  106. # self.atom_indices = self.get_atom_indices()
  107. @property
  108. def raw_file_names(self):
  109. """ If this file exists in raw_dir, the download is not triggered.
  110. """
  111. return ['DrugCombDB_drugs.csv']
  112. @property
  113. def raw_dir(self):
  114. dir = osp.join(self.root, 'Smiles/raw')
  115. return dir
  116. @property
  117. def processed_dir(self):
  118. return osp.join(self.root, 'Smiles/processed')
  119. @property
  120. def processed_file_names(self):
  121. """ If these files are found in raw_dir, processing is skipped"""
  122. #self.data = pd.read_csv(self.raw_paths[0]).reset_index()
  123. self.data = pd.read_csv(osp.join(os.path.dirname(os.path.abspath(__file__)), "data/Smiles/raw/DrugCombDB_drugs.csv")).reset_index()
  124. if self.test:
  125. return [f'data_test_{i}.pt' for i in list(self.data.index)]
  126. else:
  127. return [f'data_{i}.pt' for i in list(self.data.index)]
  128. def download(self):
  129. pass
  130. def _custom_to_pyg_graph(self,graph_data):
  131. from torch_geometric.data import Data
  132. return Data(x=torch.from_numpy(graph_data.node_features).float(),
  133. edge_index=torch.from_numpy(graph_data.edge_index).long(),
  134. edge_attr=torch.from_numpy(graph_data.edge_features).float())
  135. def process(self):
  136. path = osp.join(self.raw_dir, self.raw_file_names[0])
  137. #self.data = pd.read_csv(path).reset_index()
  138. # deepchem ------------------------------
  139. featurizer = dc.feat.MolGraphConvFeaturizer(use_edges=True)
  140. # deep chem end -------------------------
  141. self.data = pd.read_csv(osp.join(os.path.dirname(os.path.abspath(__file__)), "data/Smiles/raw/DrugCombDB_drugs.csv")).reset_index()
  142. for index, mol in tqdm(self.data.iterrows(), total=self.data.shape[0]):
  143. # mol_obj = Chem.MolFromSmiles(mol["smiles"])
  144. # # Get node features
  145. # node_feats = self.get_node_features(mol_obj)
  146. # # Get edge features
  147. # edge_feats = self.get_edge_features(mol_obj)
  148. # # Get adjacency info
  149. # edge_index = self.get_adjacency_info(mol_obj)
  150. # deepchem ----------------------------------
  151. mol_obj = Chem.MolFromSmiles(mol["smiles"])
  152. f = featurizer._featurize(mol_obj)
  153. # data = f.to_pyg_graph()
  154. data = self._custom_to_pyg_graph(f)
  155. data.id = mol['id']
  156. data.smiles = mol["smiles"]
  157. # deepchem end -------------------------------
  158. # Create data object
  159. # data = Data(x=node_feats,
  160. # edge_index=edge_index,
  161. # edge_attr=edge_feats,
  162. # id=mol['drugbank_id'],
  163. # smiles=mol["smiles"]
  164. # )
  165. if self.test:
  166. torch.save(data,
  167. os.path.join(self.processed_dir,
  168. f'data_test_{index}.pt'))
  169. else:
  170. torch.save(data,
  171. os.path.join(self.processed_dir,
  172. f'data_{index}.pt'))
  173. # def get_node_features(self, mol):
  174. # """
  175. # This will return a matrix / 2d array of the shape
  176. # [Number of Nodes, Node Feature size]
  177. # """
  178. # all_node_feats = []
  179. # for atom in mol.GetAtoms():
  180. # node_feats = []
  181. # # Feature 1: Atomic number
  182. # node_feats.append(atom.GetAtomicNum())
  183. # # Feature 2: Atom degree
  184. # node_feats.append(atom.GetDegree())
  185. # # Feature 3: Formal charge
  186. # node_feats.append(atom.GetFormalCharge())
  187. # # Feature 4: Hybridization
  188. # node_feats.append(atom.GetHybridization())
  189. # # Feature 5: Aromaticity
  190. # node_feats.append(atom.GetIsAromatic())
  191. # # Feature 6: Total Num Hs
  192. # node_feats.append(atom.GetTotalNumHs())
  193. # # Feature 7: Radical Electrons
  194. # node_feats.append(atom.GetNumRadicalElectrons())
  195. # # Feature 8: In Ring
  196. # node_feats.append(atom.IsInRing())
  197. # # Feature 9: Chirality
  198. # node_feats.append(atom.GetChiralTag())
  199. # # Append node features to matrix
  200. # all_node_feats.append(node_feats)
  201. # all_node_feats = np.asarray(all_node_feats)
  202. # return torch.tensor(all_node_feats, dtype=torch.float)
  203. # def get_edge_features(self, mol):
  204. # """
  205. # This will return a matrix / 2d array of the shape
  206. # [Number of edges, Edge Feature size]
  207. # """
  208. # all_edge_feats = []
  209. # for bond in mol.GetBonds():
  210. # edge_feats = []
  211. # # Feature 1: Bond type (as double)
  212. # edge_feats.append(bond.GetBondTypeAsDouble())
  213. # # Feature 2: Rings
  214. # edge_feats.append(bond.IsInRing())
  215. # # Append node features to matrix (twice, per direction)
  216. # all_edge_feats += [edge_feats, edge_feats]
  217. # all_edge_feats = np.asarray(all_edge_feats)
  218. # return torch.tensor(all_edge_feats, dtype=torch.float)
  219. # def get_adjacency_info(self, mol):
  220. # """
  221. # We could also use rdmolops.GetAdjacencyMatrix(mol)
  222. # but we want to be sure that the order of the indices
  223. # matches the order of the edge features
  224. # """
  225. # edge_indices = []
  226. # for bond in mol.GetBonds():
  227. # i = bond.GetBeginAtomIdx()
  228. # j = bond.GetEndAtomIdx()
  229. # edge_indices += [[i, j], [j, i]]
  230. # edge_indices = torch.tensor(edge_indices)
  231. # edge_indices = edge_indices.t().to(torch.long).view(2, -1)
  232. # return edge_indices
  233. def len(self):
  234. return self.data.shape[0]
  235. def get_by_idx(self, idx):
  236. if self.test:
  237. data = torch.load(os.path.join(self.processed_dir,
  238. f'data_test_{idx}.pt'))
  239. else:
  240. data = torch.load(os.path.join(self.processed_dir,
  241. f'data_{idx}.pt'))
  242. return data
  243. def get(self, indices):
  244. """ - Equivalent to __getitem__ in pytorch
  245. - Is not needed for PyG's InMemoryDataset
  246. """
  247. if isinstance(indices, int):
  248. idx = indices
  249. return self.get_by_idx(idx)
  250. else:
  251. data_list = []
  252. for idx in indices:
  253. data = self.get_by_idx(idx)
  254. data_list.append(data)
  255. return data_list
  256. def get_atom_indices(self):
  257. atom_indices = {}
  258. counter = 0
  259. for i in range(616):
  260. atom_indices[i] = []
  261. atom_indices[i].append(counter)
  262. counter += len(self.get(i).x)
  263. atom_indices[i].append(counter)
  264. return atom_indices
  265. # run for checking
  266. # moleculeDataset = MoleculeDataset(root = "drug/data/")
  267. # print(moleculeDataset.get(0).edge_index.t())
  268. # print(moleculeDataset.get(0).x)
  269. # print(moleculeDataset.get(0).id)