code: def steric_strain_filter(
      mol, cutoff=0.82, max_attempts_embed=20, max_num_iters=200
  ):
      """
      Flag molecules based on a steric energy cutoff after max_num_iters
      iterations of MMFF94 forcefield minimization. Cutoff is based on average
      angle bend strain energy of molecule
  
      Args:
          mol: Rdkit mol object
          cutoff (float, optional): Kcal/mol per angle . If minimized energy is above this
              threshold, then molecule fails the steric strain filter. (default: :obj:`0.82`)
          max_attempts_embed (int, optional): Number of attempts to generate initial 3d
              coordinates. (default: :obj:`20`)
          max_num_iters (int, optional): Number of iterations of forcefield minimization. (default: :obj:`200`)
  
      :rtype:
          :class:`bool`, True if molecule could be successfully minimized, and resulting
          energy is below cutoff, otherwise False.
      """
  
      # check for the trivial cases of a single atom or only 2 atoms, in which
      # case there is no angle bend strain energy (as there are no angles!)
      if mol.GetNumAtoms() <= 2:
          return True
  
      # make copy of input mol and add hydrogens
      m = copy.deepcopy(mol)
      m_h = Chem.AddHs(m)
  
      # generate an initial 3d conformer
      try:
          flag = AllChem.EmbedMolecule(
              m_h, maxAttempts=max_attempts_embed
          )
          if flag == -1:
              # print("Unable to generate 3d conformer")
              return False
      except:  # to catch error caused by molecules such as C=[SH]1=C2OC21ON(N)OC(=O)NO
          # print("Unable to generate 3d conformer")
          return False
  
      # set up the forcefield
      AllChem.MMFFSanitizeMolecule(m_h)
      if AllChem.MMFFHasAllMoleculeParams(m_h):
          mmff_props = AllChem.MMFFGetMoleculeProperties(m_h)
          try:  # to deal with molecules such as CNN1NS23(=C4C5=C2C(=C53)N4Cl)S1
              ff = AllChem.MMFFGetMoleculeForceField(m_h, mmff_props)
          except:
              # print("Unable to get forcefield or sanitization error")
              return False
      else:
          # print("Unrecognized atom type")
          return False
  
      # minimize steric energy
      try:
          ff.Minimize(maxIts=max_num_iters)
      except:
          # print("Minimization error")
          return False
  
      # ### debug ###
      # min_e = ff.CalcEnergy()
      # print("Minimized energy: {}".format(min_e))
      # ### debug ###
  
      # get the angle bend term contribution to the total molecule strain energy
      mmff_props.SetMMFFBondTerm(False)
      mmff_props.SetMMFFAngleTerm(True)
      mmff_props.SetMMFFStretchBendTerm(False)
      mmff_props.SetMMFFOopTerm(False)
      mmff_props.SetMMFFTorsionTerm(False)
      mmff_props.SetMMFFVdWTerm(False)
      mmff_props.SetMMFFEleTerm(False)
  
      ff = AllChem.MMFFGetMoleculeForceField(m_h, mmff_props)
  
      min_angle_e = ff.CalcEnergy()
      # print("Minimized angle bend energy: {}".format(min_angle_e))
  
      # find number of angles in molecule
      # from molecule... This is too hacky
      num_atoms = m_h.GetNumAtoms()
      atom_indices = range(num_atoms)
      angle_atom_triplets = itertools.permutations(
          atom_indices, 3
      )  # get all
      # possible 3 atom indices groups. Currently, each angle is represented by
      #  2 duplicate groups. Should remove duplicates here to be more efficient
      double_num_angles = 0
      for triplet in list(angle_atom_triplets):
          if mmff_props.GetMMFFAngleBendParams(m_h, *triplet):
              double_num_angles += 1
      num_angles = double_num_angles / 2  # account for duplicate angles
  
      # print("Number of angles: {}".format(num_angles))
  
      avr_angle_e = min_angle_e / num_angles
  
      if avr_angle_e < cutoff:
          return True
      else:
          return False
  
file_path: DIG/dig/ggraph/utils/environment.py
imports: import copy
  import itertools
  import networkx
  from rdkit import Chem, DataStructs
  from rdkit.Chem import AllChem, rdMolDescriptors
  from rdkit.Chem.Descriptors import MolLogP, qed
  from rdkit.Chem.FilterCatalog import FilterCatalogParams, FilterCatalog
  from .sascorer import calculateScore
label_desc: Use image node_id 6 for calling a global function with example usage: steric_strain_filter(mol, cutoff, max_attempts_embed, max_num_iters) and returns: True, False, True, False, False, False, False, False