From 8f9c8aa8a0d3f9b6ac8ed88fa6157d1f60377a75 Mon Sep 17 00:00:00 2001 From: Stuart McNicholas Date: Thu, 28 Nov 2024 10:15:05 +0000 Subject: [PATCH 1/5] Fix drawing of OEX. --- wrappers/acedrgNew/script/acedrgNew.py | 29 ++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/wrappers/acedrgNew/script/acedrgNew.py b/wrappers/acedrgNew/script/acedrgNew.py index f4438c6b..c8bd1ae2 100644 --- a/wrappers/acedrgNew/script/acedrgNew.py +++ b/wrappers/acedrgNew/script/acedrgNew.py @@ -9,6 +9,7 @@ import math from core import CCP4Modules,CCP4Utils from . import atomMatching, cifToMolBlock, mol2svg +from .setDativeBonds import set_dative_bonds import platform from rdkit.Chem.Draw import rdMolDraw2D from rdkit import Chem @@ -114,8 +115,14 @@ def processInputFiles(self): try: if self.container.inputData.MOL2IN.isSet(): mol = Chem.MolFromMol2File(self.originalMolFilePath) + if not mol: + mol = Chem.MolFromMol2File(self.originalMolFilePath, sanitize=False) + mol = set_dative_bonds(mol) else: mol = Chem.MolFromMolFile(self.originalMolFilePath) + if not mol: + mol = Chem.MolFromMolFile(self.originalMolFilePath, sanitize=False) + mol = set_dative_bonds(mol) for iAtom in range(mol.GetNumAtoms()): atom = mol.GetAtomWithIdx(iAtom) atom.ClearProp('molAtomMapNumber') @@ -307,16 +314,34 @@ def processOutputFiles(self): # chirality information referenceMol = None referenceMolToDraw = None + doSanitize = True if self.container.inputData.MOL2IN.isSet(): referenceMol = Chem.MolFromMol2File(self.originalMolFilePath) referenceMolToDraw = Chem.MolFromMol2File(self.originalMolFilePath) + if not referenceMol: + referenceMol = Chem.MolFromMol2File(self.originalMolFilePath, sanitize=False) + referenceMolToDraw = Chem.MolFromMol2File(self.originalMolFilePath, sanitize=False) + doSanitize = False else: referenceMol = Chem.MolFromMolFile(self.originalMolFilePath) referenceMolToDraw = Chem.MolFromMolFile(self.originalMolFilePath) + if not referenceMol: + referenceMol = Chem.MolFromMolFile(self.originalMolFilePath, sanitize=False) + referenceMolToDraw = Chem.MolFromMolFile(self.originalMolFilePath, sanitize=False) + doSanitize = False + print("########################################") + print("########################################") + print("referenceMolToDraw") + print(referenceMolToDraw) + print("referenceMol") + print(referenceMol) + print("########################################") + print("########################################") try: - Chem.SanitizeMol(referenceMol) - Chem.Kekulize(referenceMol) + if doSanitize: + Chem.SanitizeMol(referenceMol) + Chem.Kekulize(referenceMol) molToWrite = referenceMol # Output a MOL file molBlock = Chem.MolToMolBlock(molToWrite) From c012eec2ff22760f14025d3be22674081687632f Mon Sep 17 00:00:00 2001 From: Stuart McNicholas Date: Thu, 28 Nov 2024 10:16:03 +0000 Subject: [PATCH 2/5] Remove print --- wrappers/acedrgNew/script/acedrgNew.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/wrappers/acedrgNew/script/acedrgNew.py b/wrappers/acedrgNew/script/acedrgNew.py index c8bd1ae2..0715bd76 100644 --- a/wrappers/acedrgNew/script/acedrgNew.py +++ b/wrappers/acedrgNew/script/acedrgNew.py @@ -330,14 +330,6 @@ def processOutputFiles(self): referenceMolToDraw = Chem.MolFromMolFile(self.originalMolFilePath, sanitize=False) doSanitize = False - print("########################################") - print("########################################") - print("referenceMolToDraw") - print(referenceMolToDraw) - print("referenceMol") - print(referenceMol) - print("########################################") - print("########################################") try: if doSanitize: Chem.SanitizeMol(referenceMol) From e7d97abfe02845489604a6ee6db333e05937ceb8 Mon Sep 17 00:00:00 2001 From: Stuart McNicholas Date: Thu, 28 Nov 2024 17:11:11 +0000 Subject: [PATCH 3/5] Fix bond orders of some pictures/smiles in reports. --- wrappers/acedrgNew/script/acedrgNew.py | 12 ++++-- wrappers/acedrgNew/script/cifToMolBlock.py | 46 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/wrappers/acedrgNew/script/acedrgNew.py b/wrappers/acedrgNew/script/acedrgNew.py index 0715bd76..392641fc 100644 --- a/wrappers/acedrgNew/script/acedrgNew.py +++ b/wrappers/acedrgNew/script/acedrgNew.py @@ -93,7 +93,9 @@ def processInputFiles(self): if self.container.inputData.MOLORSMILES.__str__() == 'DICT' or try_mmCIF == True: self.originalMolFilePath = os.path.normpath(os.path.join(self.getWorkDirectory(),'MOLIN.mol')) + print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^") print(self.originalMolFilePath) + print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^") try: if self.container.inputData.DICTIN2.isSet(): molBlock = cifToMolBlock.cifFileToMolBlock(self.container.inputData.DICTIN2.__str__()) @@ -101,8 +103,10 @@ def processInputFiles(self): molBlock = cifToMolBlock.cifFileToMolBlock(self.container.inputData.PDBMMCIFIN.__str__()) else: pass # should not happen + print("**************************************************") print("molBlock:") print(molBlock) + print("**************************************************") with open(self.originalMolFilePath,'w') as molinFile: molinFile.write(molBlock) except: @@ -319,15 +323,15 @@ def processOutputFiles(self): referenceMol = Chem.MolFromMol2File(self.originalMolFilePath) referenceMolToDraw = Chem.MolFromMol2File(self.originalMolFilePath) if not referenceMol: - referenceMol = Chem.MolFromMol2File(self.originalMolFilePath, sanitize=False) - referenceMolToDraw = Chem.MolFromMol2File(self.originalMolFilePath, sanitize=False) + referenceMol = Chem.RemoveHs(Chem.MolFromMol2File(self.originalMolFilePath, sanitize=False), sanitize=False) + referenceMolToDraw = Chem.RemoveHs(Chem.MolFromMol2File(self.originalMolFilePath, sanitize=False), sanitize=False) doSanitize = False else: referenceMol = Chem.MolFromMolFile(self.originalMolFilePath) referenceMolToDraw = Chem.MolFromMolFile(self.originalMolFilePath) if not referenceMol: - referenceMol = Chem.MolFromMolFile(self.originalMolFilePath, sanitize=False) - referenceMolToDraw = Chem.MolFromMolFile(self.originalMolFilePath, sanitize=False) + referenceMol = Chem.RemoveHs(Chem.MolFromMolFile(self.originalMolFilePath, sanitize=False), sanitize=False) + referenceMolToDraw = Chem.RemoveHs(Chem.MolFromMolFile(self.originalMolFilePath, sanitize=False), sanitize=False) doSanitize = False try: diff --git a/wrappers/acedrgNew/script/cifToMolBlock.py b/wrappers/acedrgNew/script/cifToMolBlock.py index bf5ea95c..45caf35e 100644 --- a/wrappers/acedrgNew/script/cifToMolBlock.py +++ b/wrappers/acedrgNew/script/cifToMolBlock.py @@ -14,6 +14,12 @@ def cifFileToMolBlock(input_file): searches_SMILES = ["_pdbx_chem_comp_descriptor.type","_pdbx_chem_comp_descriptor.descriptor"] + bond_searches = ["_chem_comp_atom.comp_id", + "_chem_comp_bond.atom_id_1", + "_chem_comp_bond.atom_id_2", + "_chem_comp_bond.value_order" + ] + searches = ["_chem_comp_atom.comp_id", "_chem_comp_atom.atom_id", "_chem_comp_atom.type_symbol", @@ -27,6 +33,7 @@ def cifFileToMolBlock(input_file): "_chem_comp_atom.model_Cartn_z" ] atom_dict = {} + bond_dict = {} found_molecule = False found_SMILES = False @@ -81,7 +88,7 @@ def cifFileToMolBlock(input_file): try: for block in doc: if found_molecule: - break # We only tke the first molecule. + break # We only take the first molecule. for search in searches: i = 0 for thing in block.find_loop(search): @@ -91,11 +98,19 @@ def cifFileToMolBlock(input_file): atom_dict[i] = {} atom_dict[i][search] = thing i += 1 + for search in bond_searches: + i = 0 + for thing in block.find_loop(search): + if not i in bond_dict: + bond_dict[i] = {} + bond_dict[i][search] = thing + i += 1 except Exception as e: print("Oops. %s" % e) return "" atom_list = list(atom_dict.values()) + bond_list = list(bond_dict.values()) if len(atom_list) > 0: s = gemmi.Structure() @@ -121,6 +136,35 @@ def cifFileToMolBlock(input_file): s.add_model(m) s.write_pdb(output_file) mol = Chem.MolFromPDBFile(output_file) + for b in mol.GetBonds(): + at1 = atom_list[b.GetBeginAtomIdx()]['_chem_comp_atom.atom_id'] + at2 = atom_list[b.GetEndAtomIdx()]['_chem_comp_atom.atom_id'] + for b2 in bond_list: + if '_chem_comp_bond.atom_id_1' in b2 and '_chem_comp_bond.atom_id_2' in b2: + if (b2['_chem_comp_bond.atom_id_1'] == at1 and b2['_chem_comp_bond.atom_id_2'] == at2) or (b2['_chem_comp_bond.atom_id_1'] == at2 and b2['_chem_comp_bond.atom_id_2'] == at1): + if b2["_chem_comp_bond.value_order"].upper()[0:4] == "AROM": + b.SetBondType(Chem.BondType.AROMATIC) + elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "SING": + b.SetBondType(Chem.BondType.SINGLE) + elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "DOUB": + b.SetBondType(Chem.BondType.DOUBLE) + elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "TRIP": + b.SetBondType(Chem.BondType.TRIPLE) + elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "QUAD": + b.SetBondType(Chem.BondType.QUADRUPLE) + elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "QUIN": + b.SetBondType(Chem.BondType.QUINTUPLE) + elif b2["_chem_comp_bond.value_order"].upper()[0:3] == "HEX": + b.SetBondType(Chem.BondType.HEXTUPLE) + elif b2["_chem_comp_bond.value_order"].upper() == "DATIVE": + b.SetBondType(Chem.BondType.DATIVE) + elif b2["_chem_comp_bond.value_order"].upper() == "DATIVEL": + b.SetBondType(Chem.BondType.DATIVEL) + elif b2["_chem_comp_bond.value_order"].upper() == "DATIVER": + b.SetBondType(Chem.BondType.DATIVER) + elif b2["_chem_comp_bond.value_order"].upper() == "DATIVEONE": + b.SetBondType(Chem.BondType.DATIVEONE) + print("Match!",b.GetBondType(),b2["_chem_comp_bond.value_order"]) AllChem.Compute2DCoords(mol) mol.SetProp("_MolFileChiralFlag","1") molBlock = Chem.MolToMolBlock(mol, includeStereo=True, forceV3000=False) From e6234f9ae1ab707716b3bc2519ccad5045d1cac5 Mon Sep 17 00:00:00 2001 From: Stuart McNicholas Date: Fri, 29 Nov 2024 09:48:08 +0000 Subject: [PATCH 4/5] OEX appears to draw OK now as well. --- wrappers/acedrgNew/script/acedrgNew.py | 7 ------- wrappers/acedrgNew/script/cifToMolBlock.py | 11 ++++++----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/wrappers/acedrgNew/script/acedrgNew.py b/wrappers/acedrgNew/script/acedrgNew.py index 392641fc..3f9b6eae 100644 --- a/wrappers/acedrgNew/script/acedrgNew.py +++ b/wrappers/acedrgNew/script/acedrgNew.py @@ -93,9 +93,6 @@ def processInputFiles(self): if self.container.inputData.MOLORSMILES.__str__() == 'DICT' or try_mmCIF == True: self.originalMolFilePath = os.path.normpath(os.path.join(self.getWorkDirectory(),'MOLIN.mol')) - print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^") - print(self.originalMolFilePath) - print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^") try: if self.container.inputData.DICTIN2.isSet(): molBlock = cifToMolBlock.cifFileToMolBlock(self.container.inputData.DICTIN2.__str__()) @@ -103,10 +100,6 @@ def processInputFiles(self): molBlock = cifToMolBlock.cifFileToMolBlock(self.container.inputData.PDBMMCIFIN.__str__()) else: pass # should not happen - print("**************************************************") - print("molBlock:") - print(molBlock) - print("**************************************************") with open(self.originalMolFilePath,'w') as molinFile: molinFile.write(molBlock) except: diff --git a/wrappers/acedrgNew/script/cifToMolBlock.py b/wrappers/acedrgNew/script/cifToMolBlock.py index 45caf35e..e34f2e4a 100644 --- a/wrappers/acedrgNew/script/cifToMolBlock.py +++ b/wrappers/acedrgNew/script/cifToMolBlock.py @@ -64,12 +64,13 @@ def cifFileToMolBlock(input_file): print("Not successful Chem.MolFromSmiles(ss) for ss =", ss) try: mol = Chem.MolFromSmiles(ss, sanitize=False) - mol = set_dative_bonds(mol) + #mol = set_dative_bonds(mol) + print("Success with",ss) except: - print("Not successful try Chem.MolFromSmiles(ss, sanitize=False) or set_dative_bonds(mol) for ss =", ss) + print("Not successful try Chem.MolFromSmiles(ss, sanitize=False) for ss =", ss) continue if not mol: - print("Not successful Chem.MolFromSmiles(ss, sanitize=False) or set_dative_bonds(mol) for ss =", ss) + print("Not successful Chem.MolFromSmiles(ss, sanitize=False) for ss =", ss) continue if mol: try: @@ -78,10 +79,10 @@ def cifFileToMolBlock(input_file): molBlock = Chem.MolToMolBlock(mol, includeStereo=True, forceV3000=False) return molBlock except: - print("Not successful try set_dative_bonds(mol) for ", ss) + print("Not successful for ", ss) continue else: # invalid SMILES - print("Not successful set_dative_bonds(mol) for", ss) + print("Not successful for", ss) continue #If no SMILES string, we hope there is at least one molecule, either in PDB or acedrg chem_comp format. From dcb1ef5ee0c2c2186792b39578b13b30a43589d1 Mon Sep 17 00:00:00 2001 From: Stuart McNicholas Date: Wed, 11 Dec 2024 12:45:06 +0000 Subject: [PATCH 5/5] More flexibility with cif atom/bond tags. --- wrappers/acedrgNew/script/cifToMolBlock.py | 34 +++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/wrappers/acedrgNew/script/cifToMolBlock.py b/wrappers/acedrgNew/script/cifToMolBlock.py index e34f2e4a..c0be61a2 100644 --- a/wrappers/acedrgNew/script/cifToMolBlock.py +++ b/wrappers/acedrgNew/script/cifToMolBlock.py @@ -18,6 +18,7 @@ def cifFileToMolBlock(input_file): "_chem_comp_bond.atom_id_1", "_chem_comp_bond.atom_id_2", "_chem_comp_bond.value_order" + "_chem_comp_bond.type" ] searches = ["_chem_comp_atom.comp_id", @@ -125,7 +126,8 @@ def cifFileToMolBlock(input_file): a = gemmi.Atom() a.name = atom['_chem_comp_atom.atom_id'] a.element = gemmi.Element(atom['_chem_comp_atom.type_symbol']) - a.charge = int(float(atom['_chem_comp_atom.charge'])) + if '_chem_comp_atom.charge' in atom: + a.charge = int(float(atom['_chem_comp_atom.charge'])) if '_chem_comp_atom.x' in atom: pos = gemmi.Position(float(atom['_chem_comp_atom.x']),float(atom['_chem_comp_atom.y']),float(atom['_chem_comp_atom.z'])) elif '_chem_comp_atom.model_Cartn_x' in atom: @@ -143,29 +145,35 @@ def cifFileToMolBlock(input_file): for b2 in bond_list: if '_chem_comp_bond.atom_id_1' in b2 and '_chem_comp_bond.atom_id_2' in b2: if (b2['_chem_comp_bond.atom_id_1'] == at1 and b2['_chem_comp_bond.atom_id_2'] == at2) or (b2['_chem_comp_bond.atom_id_1'] == at2 and b2['_chem_comp_bond.atom_id_2'] == at1): - if b2["_chem_comp_bond.value_order"].upper()[0:4] == "AROM": + if "_chem_comp_bond.value_order" in b2: + orderString = "_chem_comp_bond.value_order" + elif "_chem_comp_bond.type" in b2: + orderString = "_chem_comp_bond.type" + else: + continue + if b2[orderString].upper()[0:4] == "AROM": b.SetBondType(Chem.BondType.AROMATIC) - elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "SING": + elif b2[orderString].upper()[0:4] == "SING": b.SetBondType(Chem.BondType.SINGLE) - elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "DOUB": + elif b2[orderString].upper()[0:4] == "DOUB": b.SetBondType(Chem.BondType.DOUBLE) - elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "TRIP": + elif b2[orderString].upper()[0:4] == "TRIP": b.SetBondType(Chem.BondType.TRIPLE) - elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "QUAD": + elif b2[orderString].upper()[0:4] == "QUAD": b.SetBondType(Chem.BondType.QUADRUPLE) - elif b2["_chem_comp_bond.value_order"].upper()[0:4] == "QUIN": + elif b2[orderString].upper()[0:4] == "QUIN": b.SetBondType(Chem.BondType.QUINTUPLE) - elif b2["_chem_comp_bond.value_order"].upper()[0:3] == "HEX": + elif b2[orderString].upper()[0:3] == "HEX": b.SetBondType(Chem.BondType.HEXTUPLE) - elif b2["_chem_comp_bond.value_order"].upper() == "DATIVE": + elif b2[orderString].upper() == "DATIVE": b.SetBondType(Chem.BondType.DATIVE) - elif b2["_chem_comp_bond.value_order"].upper() == "DATIVEL": + elif b2[orderString].upper() == "DATIVEL": b.SetBondType(Chem.BondType.DATIVEL) - elif b2["_chem_comp_bond.value_order"].upper() == "DATIVER": + elif b2[orderString].upper() == "DATIVER": b.SetBondType(Chem.BondType.DATIVER) - elif b2["_chem_comp_bond.value_order"].upper() == "DATIVEONE": + elif b2[orderString].upper() == "DATIVEONE": b.SetBondType(Chem.BondType.DATIVEONE) - print("Match!",b.GetBondType(),b2["_chem_comp_bond.value_order"]) + print("Match!",b.GetBondType(),b2[orderString]) AllChem.Compute2DCoords(mol) mol.SetProp("_MolFileChiralFlag","1") molBlock = Chem.MolToMolBlock(mol, includeStereo=True, forceV3000=False)