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; }
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); }
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; }