<commit_before># $Id: TemplateExpand.py 1053 2008-07-30 12:03:29Z landrgr1 $
#
#  Created by <NAME>, 2006
#
#
from __future__ import print_function
from rdkit import RDLogger as logging
logger = logging.logger()
logger.setLevel(logging.INFO)
from rdkit import Chem
from rdkit.Chem import Crippen
from rdkit.Chem import AllChem
from rdkit.Chem.ChemUtils.AlignDepict import AlignDepict

import sys
_version="0.8.0"
_greet="This is TemplateExpand version %s"%_version

_usage="""
Usage: TemplateExpand [options] template <sidechains>

 Unless otherwise indicated, the template and sidechains are assumed to be
   Smiles

 Each sidechain entry should be:
   [-r] SMARTS filename
     The SMARTS pattern is used to recognize the attachment point,
     if the -r argument is not provided, then atoms matching the pattern
     will be removed from the sidechains.
   or
   -n filename
     where the attachment atom is the first atom in each molecule
   The filename provides the list of potential sidechains.

 options:
   -o filename.sdf:      provides the name of the output file, otherwise
                         stdout is used

   --sdf :               expect the sidechains to be in SD files

   --moltemplate:        the template(s) are in a mol/SD file, new depiction(s)
                         will not be generated unless the --redraw argument is also
                         provided

   --smilesFileTemplate: extract the template(s) from a SMILES file instead of 
                         expecting SMILES on the command line.

   --redraw:             generate a new depiction for the molecular template(s)

   --useall:
     or
   --useallmatches:      generate a product for each possible match of the attachment
                         pattern to each sidechain. If this is not provided, the first
                         match (not canonically defined) will be used.

   --force:              by default, the program prompts the user if the library is 
                         going to contain more than 1000 compounds. This argument 
                         disables the prompt.
   
   --templateSmarts="smarts":  provides a space-delimited list containing the SMARTS 
                               patterns to be used to recognize attachment points in
			                         the template
             
   --autoNames:          when set this toggle causes the resulting compounds to be named
                         based on there sequence id in the file, e.g. 
                         "TemplateEnum: Mol_1", "TemplateEnum: Mol_2", etc.
                         otherwise the names of the template and building blocks (from
                         the input files) will be combined to form a name for each
                         product molecule.

   --3D :                Generate 3d coordinates for the product molecules instead of 2d coordinates,
                         requires the --moltemplate option

   --tether :            refine the 3d conformations using a tethered minimization


"""
def Usage():
  print(_usage, file=sys.stderr)
  sys.exit(-1)

#pylint: disable=C0111,C0103,C0322,C0324,C0323
nDumped=0 
def _exploder(mol,depth,sidechains,core,chainIndices,autoNames=True,templateName='',
              resetCounter=True,do3D=False,useTethers=False):
  global nDumped
  if resetCounter:
    nDumped=0
  ourChains = sidechains[depth]
  patt = '[%d*]'%(depth+1)
  patt = Chem.MolFromSmiles(patt)
  for i,(chainIdx,chain) in enumerate(ourChains):
    tchain = chainIndices[:]
    tchain.append((i,chainIdx))
    rs = Chem.ReplaceSubstructs(mol,patt,chain,replaceAll=True)
    if rs:
      r = rs[0]
      if depth<len(sidechains)-1:
        for entry in _exploder(r,depth+1,sidechains,core,tchain,
                               autoNames=autoNames,templateName=templateName,
                               resetCounter=0,do3D=do3D,useTethers=useTethers):
          yield entry
      else:
        try:
          Chem.SanitizeMol(r)
        except ValueError:
          import traceback
          traceback.print_exc()
          continue
        if not do3D:
          if r.HasSubstructMatch(core):
            try:
              AlignDepict(r,core)
            except Exception:
              import traceback
              traceback.print_exc()
              print(Chem.MolToSmiles(r), file=sys.stderr)
          else:
            print('>>> no match', file=sys.stderr)
            AllChem.Compute2DCoords(r)
        else:
          r = Chem.AddHs(r)
          AllChem.ConstrainedEmbed(r,core,useTethers)
        Chem.Kekulize(r)
        if autoNames:
          tName = "TemplateEnum: Mol_%d"%(nDumped+1)
        else:
          tName = templateName
          for bbI,bb in enumerate(tchain):
            bbMol = sidechains[bbI][bb[0]][1]
            if bbMol.HasProp('_Name'):
              bbNm = bbMol.GetProp('_Name')
            else:
              bbNm = str(bb[1])
            tName += '_' + bbNm
          
        r.SetProp("_Name",tName)
        r.SetProp('seq_num',str(nDumped+1))
        r.SetProp('reagent_indices','_'.join([str(x[1]) for x in tchain]))
        for bbI,bb in enumerate(tchain):
          bbMol = sidechains[bbI][bb[0]][1]
          if bbMol.HasProp('_Name'):
            bbNm = bbMol.GetProp('_Name')
          else:
            bbNm = str(bb[1])
          r.SetProp('building_block_%d'%(bbI+1),bbNm)
          for propN in bbMol.GetPropNames():
            r.SetProp('building_block_%d_%s'%(bbI+1,propN),bbMol.GetProp(propN))
        nDumped += 1
        if not nDumped%100:
          logger.info('Done %d molecules'%nDumped)
        yield r
        
def Explode(template,sidechains,outF,autoNames=True,do3D=False,useTethers=False):
  chainIndices=[]
  core = Chem.DeleteSubstructs(template,Chem.MolFromSmiles('[*]'))
  try:
    templateName = template.GetProp('_Name')
  except KeyError:
    templateName="template"
  for mol in _exploder(template,0,sidechains,core,chainIndices,autoNames=autoNames,
                       templateName=templateName,do3D=do3D,useTethers=useTethers):
    outF.write(Chem.MolToMolBlock(mol))
    for pN in mol.GetPropNames():<commit_msg>Adds the default index to the building block templates<commit_after># $Id: TemplateExpand.py 1053 2008-07-30 12:03:29Z landrgr1 $
#
#  Created by <NAME>, 2006
#
#
from __future__ import print_function
from rdkit import RDLogger as logging
logger = logging.logger()
logger.setLevel(logging.INFO)
from rdkit import Chem
from rdkit.Chem import Crippen
from rdkit.Chem import AllChem
from rdkit.Chem.ChemUtils.AlignDepict import AlignDepict

import sys
_version="0.8.0"
_greet="This is TemplateExpand version %s"%_version

_usage="""
Usage: TemplateExpand [options] template <sidechains>

 Unless otherwise indicated, the template and sidechains are assumed to be
   Smiles

 Each sidechain entry should be:
   [-r] SMARTS filename
     The SMARTS pattern is used to recognize the attachment point,
     if the -r argument is not provided, then atoms matching the pattern
     will be removed from the sidechains.
   or
   -n filename
     where the attachment atom is the first atom in each molecule
   The filename provides the list of potential sidechains.

 options:
   -o filename.sdf:      provides the name of the output file, otherwise
                         stdout is used

   --sdf :               expect the sidechains to be in SD files

   --moltemplate:        the template(s) are in a mol/SD file, new depiction(s)
                         will not be generated unless the --redraw argument is also
                         provided

   --smilesFileTemplate: extract the template(s) from a SMILES file instead of 
                         expecting SMILES on the command line.

   --redraw:             generate a new depiction for the molecular template(s)

   --useall:
     or
   --useallmatches:      generate a product for each possible match of the attachment
                         pattern to each sidechain. If this is not provided, the first
                         match (not canonically defined) will be used.

   --force:              by default, the program prompts the user if the library is 
                         going to contain more than 1000 compounds. This argument 
                         disables the prompt.
   
   --templateSmarts="smarts":  provides a space-delimited list containing the SMARTS 
                               patterns to be used to recognize attachment points in
			                         the template
             
   --autoNames:          when set this toggle causes the resulting compounds to be named
                         based on there sequence id in the file, e.g. 
                         "TemplateEnum: Mol_1", "TemplateEnum: Mol_2", etc.
                         otherwise the names of the template and building blocks (from
                         the input files) will be combined to form a name for each
                         product molecule.

   --3D :                Generate 3d coordinates for the product molecules instead of 2d coordinates,
                         requires the --moltemplate option

   --tether :            refine the 3d conformations using a tethered minimization


"""
def Usage():
  print(_usage, file=sys.stderr)
  sys.exit(-1)

#pylint: disable=C0111,C0103,C0322,C0324,C0323
nDumped=0 
def _exploder(mol,depth,sidechains,core,chainIndices,autoNames=True,templateName='',
              resetCounter=True,do3D=False,useTethers=False):
  global nDumped
  if resetCounter:
    nDumped=0
  ourChains = sidechains[depth]
  patt = '[%d*]'%(depth+1)
  patt = Chem.MolFromSmiles(patt)
  for i,(chainIdx,chain) in enumerate(ourChains):
    tchain = chainIndices[:]
    tchain.append((i,chainIdx))
    rs = Chem.ReplaceSubstructs(mol,patt,chain,replaceAll=True)
    if rs:
      r = rs[0]
      if depth<len(sidechains)-1:
        for entry in _exploder(r,depth+1,sidechains,core,tchain,
                               autoNames=autoNames,templateName=templateName,
                               resetCounter=0,do3D=do3D,useTethers=useTethers):
          yield entry
      else:
        try:
          Chem.SanitizeMol(r)
        except ValueError:
          import traceback
          traceback.print_exc()
          continue
        if not do3D:
          if r.HasSubstructMatch(core):
            try:
              AlignDepict(r,core)
            except Exception:
              import traceback
              traceback.print_exc()
              print(Chem.MolToSmiles(r), file=sys.stderr)
          else:
            print('>>> no match', file=sys.stderr)
            AllChem.Compute2DCoords(r)
        else:
          r = Chem.AddHs(r)
          AllChem.ConstrainedEmbed(r,core,useTethers)
        Chem.Kekulize(r)
        if autoNames:
          tName = "TemplateEnum: Mol_%d"%(nDumped+1)
        else:
          tName = templateName
          for bbI,bb in enumerate(tchain):
            bbMol = sidechains[bbI][bb[0]][1]
            if bbMol.HasProp('_Name'):
              bbNm = bbMol.GetProp('_Name')
            else:
              bbNm = str(bb[1])
            tName += '_' + bbNm
          
        r.SetProp("_Name",tName)
        r.SetProp('seq_num',str(nDumped+1))
        r.SetProp('reagent_indices','_'.join([str(x[1]) for x in tchain]))
        for bbI,bb in enumerate(tchain):
          bbMol = sidechains[bbI][bb[0]][1]
          if bbMol.HasProp('_Name'):
            bbNm = bbMol.GetProp('_Name')
          else:
            bbNm = str(bb[1])
          r.SetProp('building_block_%d'%(bbI+1),bbNm)
          r.SetProp('_idx_building_block_%d'%(bbI+1),str(bb[1]))
          for propN in bbMol.GetPropNames():
            r.SetProp('building_block_%d_%s'%(bbI+1,propN),bbMol.GetProp(propN))
        nDumped += 1
        if not nDumped%100:
          logger.info('Done %d molecules'%nDumped)
        yield r
        
def Explode(template,sidechains,outF,autoNames=True,do3D=False,useTethers=False):
  chainIndices=[]
  core = Chem.DeleteSubstructs(template,Chem.MolFromSmiles('[*]'))
  try:
    templateName = template.GetProp('_Name')
  except KeyError:
    templateName="template"
  for mol in _exploder(template,0,sidechains,core,chainIndices,autoNames=autoNames,
                       templateName=templateName,do3D=do3D,useTethers=useTethers):
    outF.write(Chem.MolToMolBlock(mol))
    for pN in mol.GetPropNames():
{'fraction_non_alphanumeric': 0.08673551718573504, 'fraction_numerical': 0.014361787961917057, 'mean_word_length': 2.143545523712909, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2257131', 'n_tokens_mistral': 3850, 'n_tokens_neox': 3580, 'n_words': 1010}