def hash_template(self, template): """ Hashes the reaction template. Parameters: template (str): template SMIRKS pattern Returns: hashed_template (str): sha224 hash of the template SMIRKS pattern """ template = rdChemReactions.ReactionFromSmarts(template) rdChemReactions.RemoveMappingNumbersFromReactions(template) template = rdChemReactions.ReactionToSmiles(template) self.hashed_template = hashlib.sha224( template.encode('utf8')).hexdigest() return self.hashed_template
def _rd_normalize_molecule(molecule: "Molecule", reaction_smarts: List[str], max_iterations=10000) -> "Molecule": from openff.toolkit.topology import Molecule from rdkit import Chem from rdkit.Chem import rdChemReactions rd_molecule: Chem.Mol = molecule.to_rdkit() for atom in rd_molecule.GetAtoms(): atom.SetAtomMapNum(atom.GetIdx() + 1) original_smiles = Chem.MolToSmiles(rd_molecule) old_smiles = original_smiles new_smiles = old_smiles for pattern in reaction_smarts: reaction = rdChemReactions.ReactionFromSmarts(pattern) n_iterations = 0 while True: products = reaction.RunReactants((rd_molecule, ), maxProducts=1) if len(products) == 0: break ((rd_molecule, ), ) = products for atom in rd_molecule.GetAtoms(): atom.SetAtomMapNum(atom.GetIntProp("react_atom_idx") + 1) new_smiles = Chem.MolToSmiles(Chem.AddHs(rd_molecule)) has_changed = old_smiles != new_smiles old_smiles = new_smiles if not has_changed: break n_iterations += 1 assert (n_iterations <= max_iterations), f"could not normalize {original_smiles}" return Molecule.from_mapped_smiles(new_smiles, allow_undefined_stereo=True)
def validate_retro_template(self, template): """Checks whether the template is valid in RDKit. Parameters: template (str): Retro-reaction template SMIRKS pattern Returns: None: If the template cannot be validated in RDKit True (bool): If the template can be validated in RDKit """ template = rdChemReactions.ReactionFromSmarts(template) if template.Validate()[1] != 0: print('Could not validate template - Invalid') return None else: return True
def test17bAddRecursiveQueriesToReaction(self): from rdkit.Chem import FilterCatalog rxn = rdChemReactions.ReactionFromSmarts("[C:1][O:2].[N:3]>>[C:1][N:2]") self.assertTrue(rxn) rxn.Initialize() rxn.GetReactantTemplate(0).GetAtomWithIdx(0).SetProp('query', 'carboxylicacid') querydefs = {k.lower(): v for k, v in FilterCatalog.GetFlattenedFunctionalGroupHierarchy().items()} self.assertTrue('CarboxylicAcid' in FilterCatalog.GetFlattenedFunctionalGroupHierarchy()) rxn.AddRecursiveQueriesToReaction(querydefs, 'query') q = rxn.GetReactantTemplate(0) m = Chem.MolFromSmiles('C(=O)[O-].N') self.assertTrue(m.HasSubstructMatch(q)) m = Chem.MolFromSmiles('C.N') self.assertFalse(m.HasSubstructMatch(q))
def testProperties(self): smirks_thiourea = "[N;$(N-[#6]):3]=[C;$(C=S):1].[N;$(N[#6]);!$(N=*);!$([N-]);!$(N#*);!$([ND3]);!$([ND4]);!$(N[O,N]);!$(N[C,S]=[S,O,N]):2]>>[N:3]-[C:1]-[N+0:2]" rxn = rdChemReactions.ReactionFromSmarts(smirks_thiourea) self.assertFalse(rxn.HasProp("fooprop")) rxn.SetProp("fooprop", "bar", computed=True) rxn.SetIntProp("intprop", 3) self.assertTrue(rxn.HasProp("fooprop")) self.assertTrue(rxn.HasProp("intprop")) self.assertEquals(rxn.GetIntProp("intprop"), 3) nrxn = rdChemReactions.ChemicalReaction(rxn.ToBinary()) self.assertFalse(nrxn.HasProp("fooprop")) nrxn = rdChemReactions.ChemicalReaction(rxn.ToBinary(Chem.PropertyPickleOptions.AllProps)) self.assertTrue(nrxn.HasProp("fooprop")) nrxn.ClearComputedProps() self.assertFalse(nrxn.HasProp("fooprop")) self.assertTrue(nrxn.HasProp("intprop")) self.assertEquals(nrxn.GetIntProp("intprop"), 3)
def test_github_4162(self): rxn = rdChemReactions.ReactionFromSmarts( "[C:1](=[O:2])-[OD1].[N!H0:3]>>[C:1](=[O:2])[N:3]") rxn_copy = rdChemReactions.ChemicalReaction(rxn) rdChemReactions.SanitizeRxn(rxn) rdChemReactions.SanitizeRxn(rxn_copy) pkl = rxn.ToBinary() rxn_from_pickle = rdChemReactions.ChemicalReaction(pkl) rdChemReactions.SanitizeRxn(rxn_from_pickle) pkl = pickle.dumps(rxn) rxn_from_pickle = pickle.loads(pkl) rdChemReactions.SanitizeRxn(rxn_from_pickle) pkl = rxn_from_pickle.ToBinary() rxn_from_pickle = rdChemReactions.ChemicalReaction(pkl) rdChemReactions.SanitizeRxn(rxn_from_pickle) pkl = pickle.dumps(rxn_from_pickle) rxn_from_pickle = pickle.loads(pkl) rdChemReactions.SanitizeRxn(rxn_from_pickle)
def picture2(rsmile): """To draw the reaction""" image2={} image2big={} for i in rsmile: r = rdChemReactions.ReactionFromSmarts(rsmile[i], useSmiles=True) m = ReactionToImage(r,useSVG=True) image=m.split("?>\n")[1] root = etree.fromstring(image, parser=etree.XMLParser()) #resizing html header=root.attrib width=header['width'][:-2] header['width']='385px' header['height']='100px' header['viewbox']='0 0 '+width+' 200' imagemod=etree.tostring(root) image2[i]=imagemod.decode("utf-8") image2big[i]=image return(image2,image2big)
def _neutralise_sulphoxide(mol): smirks = '[S+1:1][O-1:2]>>[S+0:1]=[O-0:2]' rxn = rdChemReactions.ReactionFromSmarts(smirks) frags = rdmolops.GetMolFrags(mol, asMols=True) n_frags = list( filter(lambda x: x is not None, [_apply_rxn(frag, rxn) for frag in frags])) if len(n_frags) == 1: n_mol = n_frags[0] elif len(n_frags) == 2: n_mol = CombineMols(*n_frags) SanitizeMol(n_mol) else: n_mol = CombineMols(n_frags[0], n_frags[1]) for i in range(2, len(n_frags)): n_mol = CombineMols(n_mol, n_frags[i]) SanitizeMol(n_mol) return n_mol
def main(name, argv): if len(argv) != 4: print_usage(name) return with open(argv[0], 'r') as f: reactions = [line.split() for line in f.readlines()] rxns = [[rdChemReactions.ReactionFromSmarts(r[0]), Chem.MolFromSmarts(r[1]), r[2]] for r in reactions] #read molport building blocks with open(argv[1], 'r') as f: lines_1 = [line.split() for line in f.readlines()] with open(argv[2], 'r') as f: lines_2 = [line.split() for line in f.readlines()] #creating RDKit Mol objects molecules_1 = list(map(lambda line: [Chem.MolFromSmiles(line[0]), line[1]], lines_1)) molecules_1 = [m for m in molecules_1 if m[0] is not None] molecules_2 = list(map(lambda line: [Chem.MolFromSmiles(line[0]), line[1]], lines_2)) molecules_2 = [m for m in molecules_2 if m[0] is not None] f = open(argv[3], 'w') # calculate reactions for i, rxn in enumerate(rxns): #find all valid molecules for a specific reaction reactents_smarts = rxn[0].GetReactants() has_patt_1 = list(map(lambda m: m[0].HasSubstructMatch(reactents_smarts[0]), molecules_1)) reactent_option_1 = [m for i,m in enumerate(molecules_1) if has_patt_1[i]] print len(reactent_option_1) has_patt_2 = list(map(lambda m: m[0].HasSubstructMatch(reactents_smarts[1]) and not m[0].HasSubstructMatch(rxn[1]), molecules_2)) reactent_option_2 = [m for i,m in enumerate(molecules_2) if has_patt_2[i]] print len(reactent_option_2) for mol1 in reactent_option_1: for mol2 in reactent_option_2: #calculate the product for the reaction for these two compounds products = rxn[0].RunReactants((mol1[0], mol2[0])) # write to file if len(products) > 1: continue for i, pro in enumerate(products): f.write('%s\t%s_%s_%s_%s\n' % (Chem.MolToSmiles(pro[0]), mol1[1], mol2[1], rxn[2], str(i+1))) f.close()
def reaction_fps(rx_smi: str, fp_method: str, n_bits: int, fp_type: str, include_agents: bool, agent_weight: int, non_agent_weight: int, bit_ratio_agents: float) -> np.array: # === Parameters section params = rdChemReactions.ReactionFingerprintParams() # number of bits of the fingerprint params.fpSize = n_bits # include the agents of a reaction for fingerprint generation params.includeAgents = include_agents # kind of fingerprint used, e.g AtompairFP.Be aware that only AtompairFP, TopologicalTorsion and MorganFP # were supported in the difference fingerprint. params.fpType = FP_TYPES[fp_type] # === rxn = rdChemReactions.ReactionFromSmarts(rx_smi, useSmiles=True) arr = np.zeros((1, )) if fp_method == "difference": # if agents are included, agents could be weighted compared to reactants and products in difference fingerprints params.agentWeight = agent_weight # in difference fingerprints weight factor for reactants and products compared to agents params.nonAgentWeight = non_agent_weight # NOTE: difference fingerprints are not binary fps = rdChemReactions.CreateDifferenceFingerprintForReaction( rxn, params) elif fp_method == "structural": # in structural fingerprints it determines the ratio of bits of the agents in the fingerprint params.bitRatioAgents = bit_ratio_agents # NOTE: structural fingerprints are binary fps = rdChemReactions.CreateStructuralFingerprintForReaction( rxn, params) else: raise ValueError( "Invalid fp_method. Allowed are 'difference' and 'structural'") ConvertToNumpyArray(fps, arr) return arr
def testRemovingBadMatches(self): log("testRemoveBadMatches") smirks_thiourea = "[N;$(N-[#6]):3]=[C;$(C=S):1].[N;$(N[#6]);!$(N=*);!$([N-]);!$(N#*);!$([ND3]);!$([ND4]);!$(N[O,N]);!$(N[C,S]=[S,O,N]):2]>>[N:3]-[C:1]-[N+0:2]" rxn = rdChemReactions.ReactionFromSmarts(smirks_thiourea) # invert matches so nothing matches reagents = [ [Chem.MolFromSmiles('NCc1ncc(Cl)cc1Br'), Chem.MolFromSmiles('NCCc1ncc(Cl)cc1Br'), Chem.MolFromSmiles('NCCCc1ncc(Cl)cc1Br'), ], [Chem.MolFromSmiles('C=CCN=C=S'), Chem.MolFromSmiles('CC=CCN=C=S'), Chem.MolFromSmiles('CCC'), Chem.MolFromSmiles('CCCCC'), ], ] enumerator = rdChemReactions.EnumerateLibrary(rxn, reagents) self.assertEquals([], list(enumerator))
def validate_reaction_smiles(reaction_smiles): """Validates reaction SMILES. Args: reaction_smiles: Text reaction SMILES. Returns: Updated reaction SMILES. Raises: ValueError: If the reaction contains errors. """ try: reaction = rdChemReactions.ReactionFromSmarts(reaction_smiles, useSmiles=True) rdChemReactions.SanitizeRxn(reaction) except ValueError as error: raise ValueError( f'reaction contains errors: {reaction_smiles}') from error _, num_errors = reaction.Validate() if num_errors: raise ValueError(f'reaction contains errors: {reaction_smiles}') return rdChemReactions.ReactionToSmiles(reaction)
def run_reaction_(self): reaction = self.reaction r_smarts = reaction.smarts r_smarts = r_smarts.replace("\\", "-").replace("/", "-") rx = rdChemReactions.ReactionFromSmarts(r_smarts) products_rdkit = [] if self.reactants.count() == 1: reactant = self.format_reactant(self.reactants.all()[0].mol_rdkit) products_rdkit = list(rx.RunReactant(reactant, 0)) elif self.reactants.count() == 2: reactants = [ self.format_reactant(m.mol_rdkit) for m in self.reactants.all() ] for i in range(2): products_rdkit = products_rdkit + list( rx.RunReactants((reactants[i], reactants[1 - i])) ) res = {Molecule.load_from_rdkit(m) for m in list(chain(*products_rdkit))} - { False } self.status_code = ReactProcess.status.DONE self.save() return res
def MappedReactionToHightlightImage(rxnsmiles, highlightByReactant=True): ## Available to use after upgrading to RDkit 2019 import cairosvg from rdkit.Chem.Draw.rdMolDraw2D import MolDraw2DSVG print(rxnsmiles) rxn_mol = rdChemReactions.ReactionFromSmarts(rxnsmiles, useSmiles=True) # set the drawing image size drawer = MolDraw2DSVG(750, 250) colors = [(255 / 255, 200 / 255, 153 / 255), (204 / 255, 255 / 255, 153 / 255), (153 / 255, 179 / 255, 255 / 255), (255 / 255, 153 / 255, 230 / 255), (204 / 255, 0 / 255, 204 / 255), (192 / 255, 192 / 255, 192 / 255), (204 / 255, 153 / 255, 255 / 255)] drawer.DrawReaction(rxn_mol, highlightByReactant=highlightByReactant, highlightColorsReactants=colors) drawer.FinishDrawing() svg = drawer.GetDrawingText() img = Image.open(io.BytesIO(cairosvg.svg2png(svg.replace('svg:', '')))) img = TrimImgByWhite(img, padding=5) print(type(img)) return StitchPILsHorizontally([img])