bool OBConformerSearch::Setup(const OBMol &mol, int numConformers, int numChildren, int mutability, int convergence)
{
    // copy some variables
    m_mol = mol;
    m_numConformers = numConformers;
    m_numChildren = numChildren;
    m_mutability = mutability;
    m_convergence = convergence;

    if (m_mol.GetCoordinates() == NULL)
        return false;

    // Initialize the OBRotorList
    m_rotorList.SetFixedBonds(m_fixedBonds);
    m_rotorList.Setup(m_mol);
    if (!m_rotorList.Size()) { // only one conformer
        return false;
    }

    // create initial population
    OBRandom generator;
    generator.TimeSeed();

    RotorKey rotorKey(m_rotorList.Size() + 1, 0); // indexed from 1
    if (IsGood(rotorKey))
        m_rotorKeys.push_back(rotorKey);
    else {
        cout << "Initial conformer does not pass filter!" << endl;
    }

    int tries = 0;
    while (m_rotorKeys.size() < m_numConformers && tries < numConformers * 1000) {
        tries++;
        // perform random mutation(s)
        OBRotorIterator ri;
        OBRotor *rotor = m_rotorList.BeginRotor(ri);
        for (int i = 1; i < m_rotorList.Size() + 1; ++i, rotor = m_rotorList.NextRotor(ri)) {
            if (generator.NextInt() % m_mutability == 0)
                rotorKey[i] = generator.NextInt() % rotor->GetResolution().size();
        }
        // duplicates are always rejected
        if (!IsUniqueKey(m_rotorKeys, rotorKey))
            continue;
        // execute filter(s)
        if (!IsGood(rotorKey))
            continue;
        // add the key
        m_rotorKeys.push_back(rotorKey);
    }

    // print out initial conformers
    cout << "Initial conformer count: " << m_rotorKeys.size() << endl;
    for (unsigned int i = 0; i < m_rotorKeys.size(); ++i) {
        for (unsigned int j = 1; j < m_rotorKeys[i].size(); ++j)
            std::cout << m_rotorKeys[i][j] << " ";
        std::cout << std::endl;
    }

    return true;
}
예제 #2
0
파일: rotor.cpp 프로젝트: Reinis/openbabel
  bool OBRotorList::FindRotors(OBMol &mol, bool sampleRingBonds)
  {
    // Find ring atoms & bonds
    // This function will set OBBond::IsRotor().
    mol.FindRingAtomsAndBonds();

    obErrorLog.ThrowError(__FUNCTION__,
                          "Ran OpenBabel::FindRotors", obAuditMsg);

    //
    // Score the bonds using the graph theoretical distance (GTD).
    // The GTD is the distance from atom i to every other atom j.
    // Atoms on the "inside" of the molecule will have a lower GTD
    // value than atoms on the "outside"
    //
    // The scoring will rank "inside" bonds first.
    //
    vector<int> gtd;
    mol.GetGTDVector(gtd);
    // compute the scores
    vector<OBBond*>::iterator i;
    vector<pair<OBBond*,int> > vtmp;
    for (OBBond *bond = mol.BeginBond(i);bond;bond = mol.NextBond(i)) {
      // check if the bond is "rotatable"
      if (bond->IsRotor(sampleRingBonds)) {
        // check if the bond is fixed (using deprecated fixed atoms or new fixed bonds)
        if ((HasFixedAtoms() || HasFixedBonds()) && IsFixedBond(bond))
          continue;

        if (bond->IsInRing()) {
          //otherwise mark that we have them and add it to the pile
          _ringRotors = true;
        }

        int score = gtd[bond->GetBeginAtomIdx()-1] + gtd[bond->GetEndAtomIdx()-1];
        // compute the GTD bond score as sum of atom GTD scores
        vtmp.push_back(pair<OBBond*,int> (bond,score));
      }
    }

    // sort the rotatable bonds by GTD score
    sort(vtmp.begin(),vtmp.end(),CompareRotor);

    // create rotors for the bonds
    int count = 0;
    vector<pair<OBBond*,int> >::iterator j;
    for (j = vtmp.begin(); j != vtmp.end(); ++j, ++count) {
      OBRotor *rotor = new OBRotor;
      rotor->SetBond((*j).first);
      rotor->SetIdx(count);
      rotor->SetNumCoords(mol.NumAtoms()*3);
      _rotor.push_back(rotor);
    }

    return true;
  }
예제 #3
0
 void OBRotorList::RemoveSymVals(OBMol &mol)
  {
    OBGraphSym gs(&mol);
    vector<unsigned int> sym_classes;
    gs.GetSymmetry(sym_classes);

    OBRotor *rotor;
    vector<OBRotor*>::iterator i;
    std::set<unsigned int> syms;
    for (rotor = BeginRotor(i);rotor;rotor = NextRotor(i)) {
      OBBond* bond = rotor->GetBond();
      OBAtom* end = bond->GetEndAtom();
      OBAtom* begin = bond->GetBeginAtom();
      int N_fold_symmetry = 1;
      for (int here=0; here <= 1; ++here) { // Try each side of the bond in turn
        
        OBAtom *this_side, *other_side;
        if (here == 0) {
          this_side = begin; other_side = end;
        }
        else {
          this_side = end; other_side = begin;
        }

        for (int hyb=2; hyb<=3; ++hyb) { // sp2 and sp3 carbons, with explicit Hs
          if (this_side->GetAtomicNum() == 6 && this_side->GetHyb() == hyb && this_side->GetValence() == (hyb + 1) ) {
            syms.clear();
            FOR_NBORS_OF_ATOM(nbr, this_side) {
              if ( &(*nbr) == other_side ) continue;
              syms.insert(sym_classes[nbr->GetIdx() - 1]);
            }
            if (syms.size() == 1) // All of the rotated atoms have the same symmetry class
              N_fold_symmetry *= hyb;
          }
        }
      }

      if (N_fold_symmetry  > 1) {
        size_t old_size = rotor->Size();
        rotor->RemoveSymTorsionValues(N_fold_symmetry);
        if (!_quiet) {
          cout << "...." << N_fold_symmetry << "-fold symmetry at rotor between " << 
                 begin->GetIdx() << " and " << end->GetIdx();
          cout << " - reduced from " << old_size << " to " << rotor->Size() << endl;
        }
      }
    }
예제 #4
0
void testOBRotorSetToAngle()
{
  // 1 2 3 4 5 6 7 8
  // C-C-C-C-C-C-C-C
  //  0 1 2 3 4 5 6
  OBMolPtr mol = OBTestUtil::ReadFile("octane.cml");
  
  OBBond *bond = mol->GetBond(3);

  OBRotor rotor;
  // set the bond to rotate
  rotor.SetBond(bond);
  // set the dihedral indexes (these start from 1)
  int ref[4] = {3, 4, 5, 6};
  rotor.SetDihedralAtoms(ref);

  // find atoms to rotate
  std::vector<int> atoms;
  mol->FindChildren(atoms, 4, 5);
  // convert to coordinate indexes (start from 0, multiplied by 3)
  for (unsigned int i = 0; i < atoms.size(); ++i)
    atoms[i] = (atoms[i] - 1) * 3;
  rotor.SetRotAtoms(atoms);

  OB_ASSERT(IsNear_mod(fabs(RAD_TO_DEG * rotor.CalcTorsion(mol->GetCoordinates())), 180.0, 360.0, 1.0));

  // rotate
  rotor.SetToAngle(mol->GetCoordinates(), 60.0 * DEG_TO_RAD);

  OB_ASSERT(IsNear(RAD_TO_DEG * rotor.CalcTorsion(mol->GetCoordinates()), 60.0, 1.0));
}
void OBConformerSearch::NextGeneration()
{
    // create next generation population
    OBRandom generator;
    generator.TimeSeed();

    // generate the children
    int numConformers = m_rotorKeys.size();
    for (int c = 0; c < numConformers; ++c) {
        for (int child = 0; child < m_numChildren; ++child) {
            bool foundKey = false;
            int tries = 0;
            while (!foundKey) {
                tries++;
                if (tries > 1000)
                    foundKey = true;
                RotorKey rotorKey = m_rotorKeys[c]; // copy parent gene
                // perform random mutation(s)
                OBRotorIterator ri;
                OBRotor *rotor = m_rotorList.BeginRotor(ri);
                for (int i = 1; i < m_rotorList.Size() + 1; ++i, rotor = m_rotorList.NextRotor(ri)) {
                    if (generator.NextInt() % m_mutability == 0)
                        rotorKey[i] = generator.NextInt() % rotor->GetResolution().size(); // permutate gene
                }
                // duplicates are always rejected
                if (!IsUniqueKey(m_rotorKeys, rotorKey))
                    continue;
                // execute the filter(s)
                if (!IsGood(rotorKey))
                    continue;
                // add the key
                m_rotorKeys.push_back(rotorKey); // append child to population
                // set foundKey to generate the next child
                foundKey = true;
            }
        }
    }
}
예제 #6
0
int main(int argc,char *argv[])
{
  if (argc != 2)
    {
      cout << "Usage: obrotamer <file>" << endl;
      cout << "  Outputs the number of rotable bonds and generate a random"
           << " rotamer" << endl;
      return(-1);
    }

  ifstream ifs(argv[1]);
  if (!ifs)
    {
      cerr << "Error! Cannot read input file!" << endl;
      return(-1);
    }
  
  OBConversion conv(&ifs, &cout);
  OBFormat* pFormat;
  
  pFormat = conv.FormatFromExt(argv[1]);
  if ( pFormat == NULL )
    {
      cerr << "Error! Cannot read file format!" << endl;
      return(-1);
    }
  
  // Finally, we can do some work!
  OBMol mol;
  if (! conv.SetInAndOutFormats(pFormat, pFormat))
    {
      cerr << "Error! File format isn't loaded" << endl;
      return (-1);
    }
  
  OBRotorList rl;
  OBRotamerList rotamers;
  int *rotorKey = NULL;
  OBRandom rand;
  rand.TimeSeed();

  while(ifs.peek() != EOF && ifs.good())
    {
      mol.Clear();
      conv.Read(&mol);

      rl.Setup(mol);
      
      cerr << " Number of rotatable bonds: " << rl.Size() << endl;

      // indexed from 1, rotorKey[0] = 0
      std::vector<int> rotorKey(rl.Size() + 1, 0);

      // each entry represents the configuration of a rotor
      // e.g. indexes into OBRotor::GetResolution()
      //       (the different angles to sample from the OBRotorRules database)
      OBRotorIterator ri;
      OBRotor *rotor = rl.BeginRotor(ri);
      for (int i = 1; i < rl.Size() + 1; ++i, rotor = rl.NextRotor(ri))
        rotorKey[i] = rand.NextInt() % rotor->GetResolution().size();

      rotamers.SetBaseCoordinateSets(mol);
      rotamers.Setup(mol, rl);
      rotamers.AddRotamer(rotorKey);

      // This is more useful when you have added many rotamers
      // rather than the one in this example
      rotamers.ExpandConformerList(mol, mol.GetConformers());
      
      // Change the molecule conformation -- from 0 .. rotamers.NumRotamers()
      mol.SetConformer(0);
      conv.Write(&mol);
    } // while reading molecules
  
  return(0);
}
예제 #7
0
void testOBRotorGetSet()
{
  OBBond bond;
  OBRotor rotor;
  
  // SetBond/GetBond
  rotor.SetBond(&bond);
  OB_ASSERT(rotor.GetBond()->GetIdx() == bond.GetIdx());
  // SetIdx/GetIdx
  rotor.SetIdx(45);
  OB_ASSERT(rotor.GetIdx() == 45);
  // SetDihedralAtoms/GetDihedralAtoms
  int ref_ptr[4] = {1, 2, 3, 4};
  rotor.SetDihedralAtoms(ref_ptr);
  rotor.GetDihedralAtoms(ref_ptr);
  OB_ASSERT(ref_ptr[0] == 1);
  OB_ASSERT(ref_ptr[1] == 2);
  OB_ASSERT(ref_ptr[2] == 3);
  OB_ASSERT(ref_ptr[3] == 4);
  std::vector<int> ref_vector = rotor.GetDihedralAtoms();
  OB_ASSERT(ref_vector[0] == 1);
  OB_ASSERT(ref_vector[1] == 2);
  OB_ASSERT(ref_vector[2] == 3);
  OB_ASSERT(ref_vector[3] == 4);
  rotor.SetDihedralAtoms(ref_vector);
  ref_vector = rotor.GetDihedralAtoms();
  OB_ASSERT(ref_vector[0] == 1);
  OB_ASSERT(ref_vector[1] == 2);
  OB_ASSERT(ref_vector[2] == 3);
  OB_ASSERT(ref_vector[3] == 4);
  // SetTorsionValues/GetTorsionValues/Size
  std::vector<double> angles;
  angles.push_back(0.0);
  angles.push_back(3.1415);
  rotor.SetTorsionValues(angles);
  OB_ASSERT(rotor.GetTorsionValues().size() == 2);
  OB_ASSERT(rotor.Size() == 2);
}
예제 #8
0
int OBForceField::DiverseConfGen(double rmsd, unsigned int nconfs, double energy_gap, bool verbose)
  {
    _energies.clear(); // Wipe any energies from previous conformer generators

    // Remove all conformers (e.g. from previous conformer generators) even the current conformer
    double *initialCoord = new double [_mol.NumAtoms() * 3]; // initial state
    double *store_initial = new double [_mol.NumAtoms() * 3]; // store the initial state
    memcpy((char*)initialCoord,(char*)_mol.GetCoordinates(),sizeof(double)*3*_mol.NumAtoms());
    memcpy((char*)store_initial,(char*)_mol.GetCoordinates(),sizeof(double)*3*_mol.NumAtoms());
    std::vector<double *> newConfs(1, initialCoord);
    _mol.SetConformers(newConfs);

    if (_mol.NumRotors() == 0) {
      SetupPointers();
      _energies.push_back(Energy(false));
      delete [] store_initial;
      return 0;
    }

    // Get estimate of lowest energy conf using FastRotorSearch
    FastRotorSearch(true);
    double lowest_energy = Energy(false);

    OBRotorList rl;
    OBBitVec fixed = _constraints.GetFixedBitVec();
    rl.SetFixAtoms(fixed);
    if (_loglvl == 0)
      rl.SetQuiet(); // Don't print info on symmetry removal
    rl.Setup(_mol);

    OBRotorIterator ri;
    OBRotamerList rotamerlist;
    rotamerlist.SetBaseCoordinateSets(_mol);
    rotamerlist.Setup(_mol, rl);

    // Can take shortcut later, as 4 components of the energy will be constant
    SetupPointers();
    double energy_offset = E_Bond(false) + E_Angle(false) + E_StrBnd(false) + E_OOP(false);
    lowest_energy -= energy_offset;
    _energies.push_back(lowest_energy);

    OBRotorKeys rotorKeys;
    OBRotor* rotor = rl.BeginRotor(ri);
    unsigned int combinations = 1;
    vector<size_t> rotor_sizes;
    for (unsigned int i = 1; i < rl.Size() + 1; ++i, rotor = rl.NextRotor(ri)) { // foreach rotor
      size_t size = rotor->GetResolution().size();
      rotorKeys.AddRotor(size);
      combinations *= size;
      rotor_sizes.push_back(size);
      if(verbose) {
        cout << "....rotor " << i << " from " << rotor->GetBond()->GetBeginAtomIdx() << " to "
             << rotor->GetBond()->GetEndAtomIdx() << " has " << size << " values" << endl;
      }
    }
    if (rotor_sizes.size() > 0 && combinations == 0) { // Overflow!
      combinations = UINT_MAX;
    }
    cout << "..tot conformations = " << combinations << "\n";

    if (nconfs == 0)
      nconfs = 1 << 20;
    unsigned int max_combinations = min<unsigned int>(nconfs , combinations);
    LFSR lfsr(max_combinations); // Systematic random number generator
    if (verbose && combinations > max_combinations) {
      cout << "....Using a cutoff of "
           << nconfs << " we will only explore " << std::fixed << setprecision(1)
           << static_cast<float>(nconfs * 100)/static_cast<float>(combinations) << "% of these\n";
    }

    unsigned int combination;
    OBDiversePoses divposes(_mol, rmsd, false);
    vector<int> my_rotorkey(rotor_sizes.size() + 1, 0);
    unsigned int counter = 0;

    // Main loop over rotamers
    unsigned int N_low_energy = 0;
    do {
      _mol.SetCoordinates(store_initial);

      combination = lfsr.GetNext();
      unsigned int t = combination;
      // Convert the combination number into a rotorkey
      for (unsigned int i = 0 ; i < rotor_sizes.size(); ++i) {
        my_rotorkey[i + 1] = t % rotor_sizes[i];
        t /= rotor_sizes[i];
      }

      rotamerlist.SetCurrentCoordinates(_mol, my_rotorkey);
      SetupPointers();
      double currentE = E_VDW(false) + E_Torsion(false) + E_Electrostatic(false);
      if (currentE < lowest_energy + energy_gap) { // Don't retain high energy poses
        divposes.AddPose(_mol.GetCoordinates(), currentE);
        N_low_energy++;
        if (currentE < lowest_energy)
          lowest_energy = currentE;
      }
      counter++;
    } while (combination != 1 && counter < nconfs); // The LFSR always terminates with a 1
    cout << "..tot confs tested = " << counter << "\n..below energy threshold = " << N_low_energy << "\n";

    // Reset the coordinates to those of the initial structure
    _mol.SetCoordinates(store_initial);

    // Get results from the tree
    UpdateConformersFromTree(&_mol, _energies, &divposes, verbose);

    // Add back the energy offset
    transform(_energies.begin(), _energies.end(), _energies.begin(), bind2nd(plus<double>(), energy_offset));

    // Clean up
    delete [] store_initial;

    return 0;
 }
예제 #9
0
  void OBForceField::SystematicRotorSearch() 
  {
    OBRotorList rl;
    OBRotamerList rotamers;

    rl.Setup(_mol);
    rotamers.SetBaseCoordinateSets(_mol);
    rotamers.Setup(_mol, rl);
    
    IF_OBFF_LOGLVL_LOW {
      OBFFLog("\nS Y S T E M A T I C   R O T O R   S E A R C H\n\n");
      sprintf(logbuf, "  NUMBER OF ROTATABLE BONDS: %d\n", rl.Size());
      OBFFLog(logbuf);
    }

    if (!rl.Size()) { // only one conformer
      IF_OBFF_LOGLVL_LOW
        OBFFLog("  GENERATED ONLY ONE CONFORMER\n\n");
 
      ConjugateGradients(2500); // final energy minimizatin for best conformation
      
      return;
    }

    std::vector<int> rotorKey(rl.Size() + 1, 0); // indexed from 1

    OBRotorIterator ri;
    OBRotor *rotor = rl.BeginRotor(ri);
    for (int i = 1; i < rl.Size() + 1; ++i, rotor = rl.NextRotor(ri)) { // foreach rotor
      for (unsigned int j = 0; j < rotor->GetResolution().size(); j++) { // foreach torsion
        rotorKey[i] = j;
        rotamers.AddRotamer(rotorKey);
      }
    }

    rotamers.ExpandConformerList(_mol, _mol.GetConformers());
      
    IF_OBFF_LOGLVL_LOW {
      sprintf(logbuf, "  GENERATED %d CONFORMERS\n\n", _mol.NumConformers());
      OBFFLog(logbuf);
      OBFFLog("CONFORMER     ENERGY\n");
      OBFFLog("--------------------\n");
    }
    
    // Calculate energy for all conformers
    char logbuf[100];
    std::vector<double> energies(_mol.NumConformers(), 0.0);
    for (int i = 0; i < _mol.NumConformers(); i++) {
      _mol.SetConformer(i); // select conformer

      energies[i] = Energy(); // calculate and store energy
      
      IF_OBFF_LOGLVL_LOW {
        sprintf(logbuf, "   %3d      %8.3f\n", (i + 1), energies[i]);
        OBFFLog(logbuf);
      }
    }

    // Select conformer with lowest energy
    int best_conformer = 0;
    for (int i = 1; i < _mol.NumConformers(); i++) {
      if (energies[i] < energies[best_conformer])
        best_conformer = i;
    }
  
    IF_OBFF_LOGLVL_LOW {
      sprintf(logbuf, "\n  CONFORMER %d HAS THE LOWEST ENERGY\n\n",  best_conformer + 1);
      OBFFLog(logbuf);
    }

    _mol.SetConformer(best_conformer);
    current_conformer = best_conformer;
  }
예제 #10
0
  void OBRotamerList::Setup(OBMol &mol,OBRotorList &rl)
  {
    //clear the old stuff out if necessary
    _vres.clear();
    vector<unsigned char*>::iterator j;
    for (j = _vrotamer.begin();j != _vrotamer.end();++j)
      delete [] *j;
    _vrotamer.clear();

    vector<pair<OBAtom**,vector<int> > >::iterator k;
    for (k = _vrotor.begin();k != _vrotor.end();++k)
      delete [] k->first;
    _vrotor.clear();
    _vrings.clear();
    _vringTors.clear();

    //create the new list
    OBRotor *rotor;
    vector<OBRotor*>::iterator i;
    vector<int> children;

    int ref[4];
    OBAtom **atomlist;
    for (rotor = rl.BeginRotor(i);rotor;rotor = rl.NextRotor(i))
      {
        atomlist = new OBAtom* [4];
        rotor->GetDihedralAtoms(ref);
        atomlist[0] = mol.GetAtom(ref[0]);
        atomlist[1] = mol.GetAtom(ref[1]);
        atomlist[2] = mol.GetAtom(ref[2]);
        atomlist[3] = mol.GetAtom(ref[3]);
        mol.FindChildren(children,ref[1],ref[2]);
        _vrotor.push_back(pair<OBAtom**,vector<int> > (atomlist,children));
        _vres.push_back(rotor->GetResolution());
      }

    // if the rotor list has ring bonds, build up an index
    if (rl.HasRingRotors()){
      // go through rings
      // for each step of the path, see if there's a matching rotor
      vector<int> path;
      int pSize;
      vector<double> ringTorsions;
      vector<int> ringRotors;
      FOR_RINGS_OF_MOL(r, mol)
      {
        ringTorsions.clear();
        ringRotors.clear();

        pSize = r->Size();
        if (pSize < 4)
          continue; // not rotatable

        path = r->_path;
        for (int j = 0; j < pSize; ++j) {
          double torsion = mol.GetTorsion(path[(j + pSize - 1) % pSize],
                                       path[(j + pSize) % pSize],
                                       path[(j + pSize + 1) % pSize],
                                       path[(j + pSize + 2) % pSize]);
          ringTorsions.push_back(torsion);

          // now check to see if any of these things are rotors
          int rotorIndex = -1; // not a rotor
          OBBond *bond = mol.GetBond(path[(j + pSize) % pSize], path[(j + pSize + 1) % pSize]);
          for (rotor = rl.BeginRotor(i);rotor;rotor = rl.NextRotor(i))
            {
              if (bond != rotor->GetBond())
                continue; // no match at all

              // Central bond matches, make sure 1..4 atoms are in the path
              rotor->GetDihedralAtoms(ref);
              if ( (ref[0] == path[(j + pSize - 1) % pSize] &&
                    ref[3] == path[(j + pSize + 2) % pSize])
                   ||
                   (ref[3] == path[(j + pSize - 1) % pSize] &&
                    ref[0] == path[(j + pSize + 2) % pSize]) ) {
                rotorIndex = rotor->GetIdx();
              }
            } // end checking all the rotors
          ringRotors.push_back(rotorIndex); // could be -1 if it's not rotatable
        }

        _vringTors.push_back(ringTorsions);
        _vrings.push_back(ringRotors);
      } // finished with the rings