109 lines
4.0 KiB
Python
109 lines
4.0 KiB
Python
from rdkit import Chem, RDLogger
|
|
import csv
|
|
import requests, time
|
|
import json
|
|
from tqdm import tqdm
|
|
|
|
RDLogger.DisableLog("rdApp.*")
|
|
|
|
def chebi_to_smiles():
|
|
csmiles_dict = {}
|
|
for m in tqdm(Chem.SDMolSupplier("data/chebi_lite.sdf")):
|
|
if m is None:
|
|
continue
|
|
csmiles_dict[m.GetProp("ChEBI ID")] = Chem.MolToSmiles(m)
|
|
|
|
return csmiles_dict
|
|
|
|
|
|
def pdb_to_smiles():
|
|
all_pdb = {}
|
|
with open("data/pdb_smiles.smi", newline="") as f:
|
|
reader = csv.DictReader(f, delimiter="\t")
|
|
|
|
for row in tqdm(reader):
|
|
all_pdb[row['pdb'].upper()] = row['smiles']
|
|
return all_pdb
|
|
|
|
def kegg_to_smiles(kegg_id):
|
|
#time.sleep(0.4) # KEGG asks for modest request rates
|
|
r = requests.get(f"https://rest.kegg.jp/get/{kegg_id}/mol", timeout=30)
|
|
if r.status_code != 200 or not r.text.strip():
|
|
return None
|
|
mol = Chem.MolFromMolBlock(r.text)
|
|
return Chem.MolToSmiles(mol) if mol else None
|
|
|
|
def read_mcsa_csv(csmiles, psmiles):
|
|
all_compounds = {}
|
|
success_count = 0
|
|
total_count = 0
|
|
unsuccessful = []
|
|
with open("data/mcsa-curated_data.csv", newline="") as f:
|
|
reader = csv.DictReader(f) # each row becomes a dict keyed by column name
|
|
|
|
for row in reader:
|
|
total_count+=1
|
|
compound_type = row["residue/reactant/product/cofactor"]
|
|
chain_kegg = row["chain/kegg compound"]
|
|
resid_chebi = row['resid/chebi id']
|
|
pdbcode = row['PDB code'].upper()
|
|
|
|
# assume chebi id
|
|
if resid_chebi and len(resid_chebi)>3 and resid_chebi not in all_compounds:
|
|
if f"CHEBI:{resid_chebi}" in csmiles:
|
|
smiles = csmiles[f"CHEBI:{resid_chebi}"]
|
|
all_compounds[resid_chebi] = {'chebi': resid_chebi, 'type': compound_type, 'smiles': smiles}
|
|
success_count+=1
|
|
print(f"OK:{resid_chebi}")
|
|
continue
|
|
|
|
if pdbcode and pdbcode not in all_compounds:
|
|
if pdbcode in psmiles:
|
|
smiles = psmiles[pdbcode]
|
|
all_compounds[pdbcode] = {'pdb': pdbcode, 'type': compound_type, 'smiles': smiles}
|
|
success_count+=1
|
|
print(f"OK:{pdbcode}")
|
|
continue
|
|
|
|
if chain_kegg and len(chain_kegg)>5 and chain_kegg not in all_compounds:
|
|
smiles = kegg_to_smiles(chain_kegg)
|
|
if smiles:
|
|
all_compounds[chain_kegg] = {'kegg': chain_kegg, 'type': compound_type, 'smiles': smiles}
|
|
success_count+=1
|
|
print(f"OK:{chain_kegg}")
|
|
continue
|
|
|
|
if resid_chebi not in all_compounds and pdbcode not in all_compounds and chain_kegg not in all_compounds:
|
|
print(f"NOT OK:{resid_chebi}-{pdbcode}-{chain_kegg}")
|
|
mcsaid = row['M-CSA ID']
|
|
uniprot = row['Uniprot IDs']
|
|
role = row['role']
|
|
unsuccessful.append({'resid_chebi': resid_chebi, 'pdbcode': pdbcode, \
|
|
'chain_kegg': chain_kegg, 'type': compound_type, \
|
|
'mcsa_id': mcsaid, 'uniprot id': uniprot, 'role': role})
|
|
|
|
return (all_compounds, unsuccessful, success_count, total_count)
|
|
|
|
def main():
|
|
# read in M-CSA csv to get all compounds used
|
|
print("Creating CHEBI lookup table...")
|
|
csmiles = chebi_to_smiles()
|
|
print("Creating PDB lookup table...")
|
|
psmiles = pdb_to_smiles()
|
|
print("Reading M-CSA compounds...")
|
|
(all_compounds, unsuccessful, success_count, total_count) = read_mcsa_csv(csmiles, psmiles)
|
|
|
|
print("Done.\n")
|
|
print("Printing to output/mcsa-smiles.json")
|
|
with open("output/mcsa-smiles.json", "w") as f:
|
|
json.dump(all_compounds, f)
|
|
|
|
print("\nPrinting unsuccessfully parsed compounds...")
|
|
with open("output/unsuccessful.json", 'w') as f:
|
|
json.dump(unsuccessful, f)
|
|
|
|
print(f"{success_count}/{total_count} compound(s) successfully read.")
|
|
|
|
|
|
if __name__=="__main__":
|
|
main() |