1 /********************************************************************** 2 rotor.h - Rotate torsional according to rotor rules. 3 4 Copyright (C) 1998-2000 by OpenEye Scientific Software, Inc. 5 Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison 6 7 This file is part of the Open Babel project. 8 For more information, see <http://openbabel.org/> 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation version 2 of the License. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 ***********************************************************************/ 19 20 #ifndef OB_ROTOR_H 21 #define OB_ROTOR_H 22 23 #include <openbabel/parsmart.h> 24 #include <openbabel/typer.h> 25 #include <openbabel/bitvec.h> 26 27 #ifdef UNUSED 28 #elif (__GNUC__ == 4) 29 # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 30 #elif defined(__LCLINT__) 31 # define UNUSED(x) /*@unused@*/ x 32 #else 33 # define UNUSED(x) x 34 #endif 35 36 namespace OpenBabel 37 { 38 class OBRing; 39 40 #ifndef SQUARE 41 #define SQUARE(x) ((x)*(x)) 42 #endif 43 44 //! \class OBRotorRule rotor.h <openbabel/rotor.h> 45 //! \brief A rule for torsional conformer searching, defined by a SMARTS pattern 46 //! 47 //! Rules define a SMARTS pattern to match and a set of 4 reference atoms 48 //! defining the dihedral angle. The rule can either define a set of possible 49 //! dihedral angles in degrees and/or a "delta" (i.e., all multiples of delta will 50 //! be considered) 51 class OBAPI OBRotorRule 52 { 53 int _ref[4]; //!< Reference atoms specifying the dihedral angle (as integers), numbered from 1 inside the SMARTS pattern 54 double _delta; //!< (optional) the resolution of a dihedral step in degrees 55 std::string _s; //!< Text of the SMARTS pattern 56 OBSmartsPattern* _sp; //!< The SMARTS pattern for the rotation rule 57 std::vector<double> _vals; //!< At least one torsion angle (in radians) to evaluate 58 public: 59 OBRotorRule(char * buffer,int ref[4],std::vector<double> & vals,double d)60 OBRotorRule(char *buffer,int ref[4],std::vector<double> &vals,double d): 61 _delta(d), _s(buffer), _vals(vals) 62 { 63 _sp = new OBSmartsPattern; 64 _sp->Init(buffer); 65 memcpy(_ref,ref,sizeof(int)*4); 66 } 67 ~OBRotorRule()68 ~OBRotorRule() 69 { 70 if (_sp) 71 { 72 delete _sp; 73 _sp = nullptr; 74 } 75 } 76 77 //! \return whether this rotor rule is valid (i.e., is the SMARTS pattern valid) IsValid()78 bool IsValid() { return(_sp->IsValid()); } 79 //! \return a copy of the reference atom indexes inside the SMARTS pattern 80 //! 81 //! These should be freed after use. GetReferenceAtoms(int ref[4])82 void GetReferenceAtoms(int ref[4]) { memcpy(ref,_ref,sizeof(int)*4); } 83 //! Set the resolution (delta) of a torsional step in degrees SetDelta(double d)84 void SetDelta(double d) { _delta = d; } 85 //! \return the resolution (delta) of a torsional step in degrees GetDelta()86 double GetDelta() { return(_delta); } 87 //! \return a reference to the dihedral angles to evaluate (in radians) GetTorsionVals()88 std::vector<double> &GetTorsionVals() { return(_vals); } 89 //! \return the text of the SMARTS pattern for this rule GetSmartsString()90 std::string &GetSmartsString(){ return(_s); } 91 //! \return the exact OBSmartsPattern object for this rule GetSmartsPattern()92 OBSmartsPattern *GetSmartsPattern() { return(_sp); } 93 }; 94 95 //! \class OBRotorRules rotor.h <openbabel/rotor.h> 96 //! \brief Database of default hybridization torsional rules and SMARTS-defined OBRotorRule objects 97 //! 98 //! Use to automatically evaluate potentially rotatable bonds to generate 99 //! lists of dihedral angles to consider. 100 //! e.g., rotamer/conformer energy calculations 101 class OBAPI OBRotorRules : public OBGlobalDataBase 102 { 103 bool _quiet; //!< Control debugging output from GetRotorIncrements() 104 std::vector<OBRotorRule*> _vr; //!< Database of specific OBRotorRules defined by SMARTS patterns 105 std::vector<double> _sp3sp3; //!< Default dihedral angles to check for generic sp3 - sp3 hybridized rotatable bonds (in radians) 106 std::vector<double> _sp3sp2; //!< Default dihedral angles to check for generic sp3 - sp2 hybridized rotatable bonds (in radians) 107 std::vector<double> _sp2sp2; //!< Default dihedral angles to check for generic sp2 - sp2 hybridized rotatable bonds (in radians) 108 public: 109 OBRotorRules(); 110 ~OBRotorRules(); 111 112 void ParseLine(const char*); 113 //! \return the number of rotor rules GetSize()114 size_t GetSize() { return _vr.size();} 115 116 //! Set the filename to be used for the database. Default = torlib.txt SetFilename(std::string & s)117 void SetFilename(std::string &s) { _filename = s; } 118 119 //! Determine the torsional angles to evaluate based on the database 120 //! \param mol molecule to evaluate 121 //! \param bond rotatable bond to evaluate 122 //! \param refs set to be the atom indexes (in mol) of the dihedral angle 123 //! \param vals set to be the list of angles to evaluate (in radians) 124 //! \param delta potential dihedral angle steps (in degrees) 125 void GetRotorIncrements(OBMol& mol,OBBond* bond,int refs[4], 126 std::vector<double> &vals,double &delta); 127 //! Turn off debugging output from GetRotorIncrements() Quiet()128 void Quiet() { _quiet=true; } 129 }; 130 131 /** 132 * @class OBRotor rotor.h <openbabel/rotor.h> 133 * @brief A single rotatable OBBond as part of rotamer searching 134 */ 135 class OBAPI OBRotor 136 { 137 int _idx; //!< the index in an OBRotorList 138 std::vector<int> _rotatoms; //!< the atoms to rotate 139 double _imag, _refang; //!< inverse magnitude and reference angle (see Precompute()) 140 OBBond *_bond; //!< the bond associated with this rotor 141 std::vector<int> _ref, _torsion; //!< indexes for atom coordinates (from 0, multiplied by 3) 142 OBBitVec _fixedatoms,_fixedbonds, _evalatoms; //!< fixed atoms/bonds 143 std::vector<double> _torsionAngles; //!< torsion resolution 144 std::vector<double> _invmag; //!< the inverse magnitudes (see Precalc) 145 std::vector<std::vector<double> > _sn,_cs,_t; //!< the rotation matrix (see Precalc()) 146 std::vector<OBRing *> _rings; //!< the parent ring (if this is a rotor in a ring) 147 public: 148 /** 149 * Constructor. 150 */ 151 OBRotor(); 152 /** 153 * Destructor. 154 */ ~OBRotor()155 ~OBRotor() 156 { 157 } 158 159 ///@name Setup 160 ///@{ 161 /** 162 * Set the OBBond associated with this OBRotor. 163 */ SetBond(OBBond * bond)164 void SetBond(OBBond *bond) 165 { 166 _bond = bond; 167 SetRings(); 168 } 169 /** 170 * Set the rings associated with this bond (if it's a ring bond) 171 * \since Version 2.4 172 */ 173 void SetRings(); 174 /** 175 * Set the index for this rotor. Used by OBRotorList 176 */ SetIdx(int idx)177 void SetIdx(int idx) 178 { 179 _idx = idx; 180 } 181 /** 182 * Set the dihedral atoms. 183 * @param ref The dihedral atom indexes. These indexes start from 1. 184 */ 185 void SetDihedralAtoms(std::vector<int> &ref); 186 /** 187 * Set the dihedral atoms. 188 * @param ref The dihedral atom indexes. These indexes start from 1. 189 */ 190 void SetDihedralAtoms(int ref[4]); 191 /** 192 * Set the atom indexes that will be displaced when this rotor 193 * changes torsion angle. These indexes start from 0 and are multiplied 194 * by 3 for easy coordinate access. 195 */ 196 void SetRotAtoms(std::vector<int> &atoms); 197 /** 198 * Set the possible torsion values or angles. 199 */ SetTorsionValues(std::vector<double> & angles)200 void SetTorsionValues(std::vector<double> &angles) 201 { 202 _torsionAngles = angles; 203 } 204 /** 205 * Set the bonds that will be fixed. 206 */ SetFixedBonds(OBBitVec & bv)207 void SetFixedBonds(OBBitVec &bv) 208 { 209 _fixedbonds = bv; 210 } 211 ///@} 212 213 ///@name Performing rotations 214 ///@{ 215 /** 216 * Rotate the atoms in the specified @p coordinates to the specified angle. 217 * @param coordinates The coordinates to rotate. 218 * @param setang The new torsion angle in radians. 219 */ SetToAngle(double * coordinates,double setang)220 inline void SetToAngle(double *coordinates, double setang) 221 { 222 double /*dx,dy,dz,*/ sn,cs,t,ang,mag; 223 // compute the angle to rotate (radians) 224 ang = setang - CalcTorsion(coordinates); 225 // if the angle to rotate is too small, we're done 226 if (fabs(ang) < 1e-5) 227 return; 228 229 // compute the bond length 230 mag = CalcBondLength(coordinates); 231 // compute some rotation matrix elements 232 sn = sin(ang); 233 cs = cos(ang); 234 t = 1 - cs; 235 236 // perform rotation 237 Set(coordinates, sn, cs, t, 1.0 / mag); 238 } 239 /** 240 * Rotate the atoms in the specified @p coordinates. This function does not 241 * require any precomputation and will compute all needed information when 242 * needed. 243 * @param coordinates The coordinates for the molecules as pointer to double. 244 * @param next The index of the new rotor angle. This is an index for the 245 * GetTorsionValues() list. 246 * @param prev If specified, the torsion current torsion angle can be 247 * looked up and does not have to be calculated again. 248 */ 249 void SetRotor(double *coordinates, int next, int prev = -1); 250 /** 251 * Rotate the specified @p coordinates by using the specified rotation matrix. 252 * 253 */ 254 void Set(double *coordinates, double sine, double cosine, double translation, double invmag); 255 /** 256 * Precompute the reference angle and inverse bond length of this rotor for 257 * a single conformer. This function should be used in combination with 258 * Set(double *coordinates, int idx). 259 * @param coordinates The coordinates to use in the computation. 260 * 261 * @code 262 * OBMol mol; 263 * ... 264 * 265 * unsigned int numCoords = mol.NumAtoms() * 3; 266 * double *coords = mol.GetCoordinates(); 267 * OBRotor rotor; 268 * rotor.SetBond(mol.GetBond(3)); 269 * 270 * // set the possible torsion values 271 * std::vector<double> angles; 272 * angles.push_back(0.0); 273 * angles.push_back(3.1415); 274 * rotor.SetTorsionValues(angles); 275 * 276 * // precompute inverse bond length (i.e. the bond length of bond with index 3 277 * // using the specified coordinates) and reference angle (i.e. torsion angle 278 * //in coords) 279 * rotor.Precompute(coords); 280 * 281 * // copy coordinates to coords_1 282 * double *coords_1 = new double[numCoords]; 283 * for (unsigned int i = 0; i < numCoords; ++i) 284 * coords_1[i] = coords[i]; 285 * // rotate the atoms in coords_1 to angle with index 0 (i.e. 0.0 degrees) 286 * // note: on input, the coordinates should be the same as the coordinates used 287 * // to precompute the inverse bond length and reference angle (in other 288 * // words, the inverse magnitude and reference angle in the specfied 289 * // coordinates should be the same as the one used for Precompute) 290 * rotor.Set(coords_1, 0) 291 * 292 * // copy coordinates to coords_2 293 * double *coords_2 = new double[numCoords]; 294 * for (unsigned int i = 0; i < numCoords; ++i) 295 * coords_2[i] = coords[i]; 296 * // rotate the atoms in coords_2 to angle with index 1 (i.e. 180.0 degrees) 297 * rotor.Set(coords_2, 1) 298 * 299 * delete coords_1; 300 * delete coords_2; 301 * @endcode 302 */ 303 void Precompute(double *coordinates); 304 /** 305 * Rotate the @p coordinates to set the torsion angle of this rotor to the angle 306 * specified by the index @p idx. Make sure to call Precompute before calling 307 * this function. 308 * @param coordinates The coordinates to rotate. 309 * @param idx The index of the torsion angle in the GetTorsionValues() list. 310 */ 311 void Set(double *coordinates, int idx); 312 /** 313 * Precompute the inverse bond lengths, rotation matrices for all 314 * specified conformers and all possible torsion values. This method is 315 * used in combination with Set(double *coordinates, int conformer, int idx). 316 * @param conformers The pointers to the conformer coordinates 317 */ 318 void Precalc(std::vector<double*> &conformers); 319 /** 320 * Rotate the @p coordinates to set the torsion to the torsion value with the 321 * specified @p index. The coordinates should be the same as the conformer used 322 * for calling Precalc (i.e. conformers[conformer] == coordinates). Make sure 323 * to call Precalc before calling this method. 324 * @param coordinates The conformer coordinates. 325 * @param conformer The conformer index in the conformer list given to Precalc(). 326 * @param idx The torsion value index in the GetTorsionValues() list. 327 */ Set(double * coordinates,int conformer,int idx)328 void Set(double *coordinates, int conformer, int idx) 329 { 330 Set(coordinates, _sn[conformer][idx], _cs[conformer][idx], _t[conformer][idx], _invmag[conformer]); 331 } 332 ///@} 333 334 335 ///@name Methods to retrieve information 336 ///@{ 337 /** 338 * Get the OBBond object associated with this OBRotor. 339 */ GetBond()340 OBBond *GetBond() 341 { 342 return(_bond); 343 } 344 /** 345 * Get the number of possible torsion angles for this OBRotor. This 346 * is the length of the GetTorsionValues() list. 347 */ Size()348 size_t Size() 349 { 350 return _torsionAngles.size(); 351 } 352 /** 353 * Get the index for this rotor (index in an OBRotorList). 354 */ GetIdx()355 int GetIdx() const 356 { 357 return _idx; 358 } 359 /** 360 * Get the dihedral atom indexes. These indexes start from 1. 361 */ GetDihedralAtoms(int ref[4])362 void GetDihedralAtoms(int ref[4]) 363 { 364 for (int i = 0; i < 4; ++i) 365 ref[i] = _ref[i]; 366 } 367 /** 368 * Get the dihedral atom indexes. These indexes start from 1. 369 */ GetDihedralAtoms()370 std::vector<int> &GetDihedralAtoms() 371 { 372 return _ref; 373 } 374 /** 375 * Get the atom indexes that will be displaced when this rotor changes 376 * torsion angle. These indexes start from 1. 377 */ GetRotAtoms()378 const std::vector<int>& GetRotAtoms() const 379 { 380 return _rotatoms; 381 } 382 /** 383 * Get the possible torsion angles for this OBRotor. 384 */ GetTorsionValues()385 const std::vector<double> &GetTorsionValues() const 386 { 387 return _torsionAngles; 388 } 389 /** 390 * Get an OBBitVec objects with bits set for all bonds that are fixed. 391 * Bonds are indexed from 0. 392 */ GetFixedBonds()393 OBBitVec &GetFixedBonds() 394 { 395 return _fixedbonds; 396 } 397 /** 398 * Calculate the torsion for this OBRotor using the specified coordinates. 399 * @param coordinates The coordinates (e.g. OBMol::GetCoordinates()). 400 * @return The torsion angle in radians. 401 */ 402 double CalcTorsion(double *coordinates); 403 /** 404 * Calculate the bond length for this OBRotor using the specified coordinates. 405 * @param coordinates The coordinates (e.g. OBMol::GetCoordinates()). 406 */ 407 double CalcBondLength(double *coordinates); 408 ///@} 409 410 411 ///@name Iterator methods 412 ///@{ BeginTorIncrement()413 std::vector<double>::iterator BeginTorIncrement() 414 { 415 return _torsionAngles.begin(); 416 } EndTorIncrement()417 std::vector<double>::iterator EndTorIncrement() 418 { 419 return _torsionAngles.end(); 420 } 421 ///@} 422 423 void RemoveSymTorsionValues(int); 424 425 ///@name Deprecated 426 ///@{ 427 /** @deprecated Has no effect. */ SetDelta(double UNUSED (d))428 void SetDelta(double UNUSED(d)) {} 429 /** @deprecated Has no effect. */ GetDelta()430 double GetDelta() { return 10.0; } 431 /** @deprecated */ GetFixedAtoms()432 OBBitVec &GetFixedAtoms() { return _fixedatoms; } 433 /** @deprecated See SetFixedBonds */ SetFixedAtoms(OBBitVec & bv)434 void SetFixedAtoms(OBBitVec &bv) { _fixedatoms = bv; } 435 /** @deprecated */ GetEvalAtoms()436 OBBitVec &GetEvalAtoms() { return _evalatoms; } 437 /** @deprecated */ SetEvalAtoms(OBBitVec & bv)438 void SetEvalAtoms(OBBitVec &bv) { _evalatoms = bv; } 439 /** @deprecated */ GetRotAtoms()440 void* GetRotAtoms() { return &_rotatoms; } 441 /** @deprecated Bad name, see GetTorsionValues() */ GetResolution()442 std::vector<double> &GetResolution() { return _torsionAngles; } 443 /** @deprecated */ SetNumCoords(int UNUSED (nc))444 void SetNumCoords(int UNUSED(nc)) {} 445 ///@} 446 447 }; 448 449 450 //! A standard iterator over a vector of rotors 451 typedef std::vector<OBRotor*>::iterator OBRotorIterator; 452 453 /** 454 * @class OBRotorList rotor.h <openbabel/rotor.h> 455 * @brief Given an OBMol, set up a list of possibly rotatable torsions, 456 */ 457 class OBAPI OBRotorList 458 { 459 bool _quiet; //!< Control debugging output 460 bool _removesym; //!< Control removal of symmetric rotations 461 bool _ringRotors; //!< Are there ring rotors 462 OBBitVec _fixedatoms, _fixedbonds; //!< Bit vector of fixed (i.e., invariant) atoms 463 OBRotorRules _rr; //!< Database of rotatable bonds and dihedral angles to test 464 std::vector<int> _dffv; //!< Distance from fixed 465 std::vector<OBRotor*> _rotor; //!< List of individual OBRotor torsions 466 //! 467 std::vector<std::pair<OBSmartsPattern*,std::pair<int,int> > > _vsym2; 468 //! 469 std::vector<std::pair<OBSmartsPattern*,std::pair<int,int> > > _vsym3; 470 public: 471 /** 472 * Constructor. 473 */ 474 OBRotorList(); 475 /** 476 * Destructor. 477 */ 478 ~OBRotorList(); 479 480 /** 481 * Clear the internal list of rotors and reset. 482 */ 483 void Clear(); 484 /** 485 * @return the number of rotors in this list 486 */ Size()487 size_t Size() 488 { 489 return _rotor.size(); 490 } 491 /** 492 * When no atoms/bonds are fixed or when bonds are fixed, this function will 493 * return true if the bond is fixed. When using the deprecated fixed atoms, 494 * this function will return true if the bond and at least one neighboring 495 * bond has fixed atoms. 496 */ 497 bool IsFixedBond(OBBond*); 498 /** 499 * @return True if this rotor list has any fixed bonds. 500 */ HasFixedBonds()501 bool HasFixedBonds() 502 { 503 return !_fixedbonds.IsEmpty(); 504 } 505 //! Rotates each bond to zero and 180 degrees and tests 506 //! if the 2 conformers are duplicates. if so - the symmetric torsion 507 //! values are removed from consideration during a search 508 void RemoveSymVals(OBMol&); 509 510 /** 511 * @return True if this rotor list has any ring bonds. 512 * @since version 2.4 513 */ HasRingRotors()514 bool HasRingRotors() 515 { return _ringRotors; } 516 517 ///@name Setup 518 /** 519 * Setup this rotor list for the supplied molecule. This method calls 520 * FindRotors(), SetEvalAtoms(), and AssignTorVals(). 521 * @param mol The molecule. 522 * @param sampleRings Whether to sample ring conformers - default = false 523 * @return True if rotatable bonds were found. 524 */ 525 bool Setup(OBMol &mol, bool sampleRings = false); 526 /** 527 * Set the bonds that will be fixed. 528 */ SetFixedBonds(OBBitVec & fix)529 void SetFixedBonds(OBBitVec &fix) 530 { 531 _fixedbonds = fix; 532 _fixedatoms.Clear(); 533 } 534 /** 535 * Initialize the private OBRotorRules database from a specific file. 536 */ Init(std::string & fname)537 void Init(std::string &fname) 538 { 539 _rr.SetFilename(fname); 540 _rr.Init(); 541 } 542 /** 543 * Turn off debugging output. 544 */ SetQuiet()545 void SetQuiet() { 546 _quiet=true; 547 _rr.Quiet(); 548 } 549 //! \brief Set the atoms to rotate from the dihedral atoms for each rotor 550 //! Uses OBRotor->GetDihedralAtoms() to call OBRotor->SetRotAtoms() 551 //! and standarizes the dihedral angles via OBRotor->SetDihedralAtoms() 552 //! \return True 553 bool SetRotAtoms(OBMol&); 554 /** 555 * Find all potentially rotatable bonds in the molecule. This method uses 556 * OBBond::IsRotor() for initial evaluation which depends on ring perception 557 * (i.e. ring bonds are considered rotatable). Fixed bonds, specified using the 558 * deprecated fixed atoms or the new fixed bonds methods are not added to 559 * the list. All rotatable bonds will be sorted by their graph theoretical 560 * distance (GTD) score (see OBMol::GetGTDVector()). This results in the 561 * the rotors going from the inside to the outside of the mol. 562 * @param mol The molecule. 563 * @param sampleRingBonds whether to sample ring bonds from analysis (default = false) 564 * @return True. 565 */ 566 bool FindRotors(OBMol &mol, bool sampleRingBonds = false); 567 //! Determines which atoms should be used to calculate the internal energy 568 //! if the dihedral angle of the rotor is modified 569 //! \return True 570 bool SetEvalAtoms(OBMol&); 571 /** 572 * Using the OBRotorRules database, set the torsion values (and delta) 573 * to be evaluated and tested. This method also sets the rotatable atoms 574 * for the rotors to the smallest possible set. For each bond there are 575 * two candidate sets, one on either side. The smallest of these is used 576 * and the torsion indexes for the rotor are inverted if needed 577 * (i.e. a-b-c-d -> d-c-b-a). 578 */ 579 bool AssignTorVals(OBMol &); 580 ///@} 581 582 //! \name Iterator methods 583 //@{ 584 /** 585 * Initialize the @p i iterator and get a pointer to the first OBRotor. 586 * @param i OBRotorIterator object. 587 */ BeginRotor(OBRotorIterator & i)588 OBRotor *BeginRotor(OBRotorIterator &i) 589 { 590 i = _rotor.begin(); 591 return((i ==_rotor.end()) ? nullptr:*i); 592 } 593 /** 594 * Get a pointer to the next iterator. 595 * @param i OBRotorIterator object. 596 */ NextRotor(OBRotorIterator & i)597 OBRotor *NextRotor(OBRotorIterator &i) 598 { 599 ++i; 600 return((i ==_rotor.end()) ? nullptr:*i); 601 } 602 /** 603 * Get the rotor list begin iterator. 604 */ BeginRotors()605 OBRotorIterator BeginRotors() { return(_rotor.begin()); } 606 /** 607 * Get the rotor list end iterator. 608 */ EndRotors()609 OBRotorIterator EndRotors() { return(_rotor.end()); } 610 //@} 611 612 ///@name Deprecated 613 ///@{ 614 // Not declared 615 //! \deprecated Not declared. Use Setup() for top-level functionality IdentifyEvalAtoms(OBMol & mol)616 bool IdentifyEvalAtoms(OBMol &mol) { return SetEvalAtoms(mol); } 617 /** 618 * Set the list of fixed (invariant) atoms to the supplied OBBitVec 619 * @deprecated See SetFixedBonds() 620 */ SetFixAtoms(OBBitVec & fix)621 void SetFixAtoms(OBBitVec &fix) 622 { 623 _fixedatoms = fix; 624 _fixedbonds.Clear(); 625 } 626 /** 627 * @return whether this rotor list has any fixed (invariant) atoms 628 * @deprecated See HasFixedBonds() 629 */ HasFixedAtoms()630 bool HasFixedAtoms() 631 { 632 return(!_fixedatoms.IsEmpty()); 633 } 634 //! Has no effect 635 //! \deprecated Currently has no effect IgnoreSymmetryRemoval()636 void IgnoreSymmetryRemoval() { _removesym = false;} 637 //! \brief Set the atoms to rotate from the dihedral atoms for each rotor 638 //! Insures the fixed atoms are respected, but otherwise functions like 639 //! SetRotAtoms() 640 void SetRotAtomsByFix(OBMol&); 641 ///@} 642 643 }; 644 645 /// @cond DEV 646 class rotor_digit { 647 public: rotor_digit(unsigned int rs)648 rotor_digit(unsigned int rs) 649 { 650 resolution_size = rs; 651 state = 0; 652 } 653 rotor_digit()654 rotor_digit() 655 { 656 resolution_size = 0; 657 state = 0; 658 } 659 set_size(unsigned int rs)660 void set_size(unsigned int rs) 661 { 662 resolution_size = rs; 663 state = 0; 664 } 665 set_state(int st)666 void set_state(int st) 667 { 668 state = st; 669 } 670 get_state()671 int get_state() 672 { 673 return state; 674 } 675 size()676 unsigned int size() 677 { 678 return resolution_size; 679 } 680 next()681 bool next() 682 { 683 if (state < static_cast<int>(resolution_size - 1)) { 684 ++state; 685 return false; 686 } else 687 state = 0; 688 689 return true; 690 } 691 private: 692 unsigned int resolution_size; 693 int state; 694 #ifndef SWIG 695 } typedef rotor_digit; 696 #else 697 }; 698 #endif 699 /// @endcond 700 701 //! \class OBRotorKeys rotor.h <openbabel/rotor.h> 702 //! \brief A class to generate all possible rotorKeys 703 class OBAPI OBRotorKeys 704 { 705 /** 706 \brief A class to generate all possible rotorKeys 707 708 This class can generate all possible rotor keys for a set of OBRotors 709 which can all have their own resolution. Thanks to Yongjin Xu for this 710 patch. 711 712 the code blow is taken from OBForceField::SystematicRotorSearch(): 713 \code 714 #include <openbabel/rotor.h> 715 #include <openbabel/mol.h> 716 717 // See OBConversion class to fill the mol object. 718 OBMol mol; 719 OBRotorList rl; 720 OBRotamerList rotamers; 721 722 rl.Setup(_mol); 723 rotamers.SetBaseCoordinateSets(_mol); 724 rotamers.Setup(_mol, rl); 725 726 cout << "number of rotatable bonds: " << rl.Size() << endl; 727 728 if (!rl.Size()) { // only one conformer 729 cout << "generated only one conformer" << endl; 730 // exit here 731 } 732 733 OBRotorKeys rotorKeys; 734 OBRotorIterator ri; 735 OBRotor *rotor = rl.BeginRotor(ri); 736 for (int i = 1; i < rl.Size() + 1; ++i, rotor = rl.NextRotor(ri)) { // foreach rotor 737 rotorKeys.AddRotor(rotor->GetResolution().size()); 738 } 739 740 while (rotorKeys.Next()) { 741 std::vector<int> rotorKey = rotorKeys.GetKey(); 742 cout << "rotorKey = " << rotorKey[1] << " " << rotorKey[2] << endl; 743 rotamers.AddRotamer(rotorKey); 744 } 745 746 rotamers.ExpandConformerList(_mol, _mol.GetConformers()); 747 \endcode 748 **/ 749 750 public: 751 //! Constructor OBRotorKeys()752 OBRotorKeys() 753 { 754 _vr.clear(); 755 } 756 757 //! Clear all rotors Clear()758 void Clear(){ 759 _vr.clear(); 760 } 761 762 //! Number of rotor keys (= number of possible conformers) NumKeys()763 unsigned int NumKeys() 764 { 765 unsigned int numKeys = 0; 766 767 while (Next()) 768 numKeys++; 769 770 return numKeys; 771 } 772 773 //! Add a rotor 774 //! \param size the rotor resolution AddRotor(unsigned int size)775 void AddRotor(unsigned int size) 776 { 777 rotor_digit rd(size); 778 _vr.push_back(rd); 779 } 780 781 //! Select the next rotor key 782 //! \return true if there are more rotor keys Next()783 bool Next() 784 { 785 if(_vr.size() == 0) 786 return false; 787 788 bool carry = _vr[0].next(); 789 unsigned int i = 1; 790 while (carry) { 791 if(i == _vr.size()) 792 return false; 793 794 carry = _vr[i].next(); 795 i++; 796 } 797 return true; 798 } 799 800 //! Get the currently selected rotor key 801 //! \return current rotor key GetKey()802 std::vector<int> GetKey() 803 { 804 std::vector<int> rt; 805 rt.clear(); 806 rt.push_back(0); 807 for(unsigned int i = 0; i < _vr.size(); i++){ 808 rt.push_back(_vr[i].get_state()); 809 } 810 811 return rt; 812 } 813 814 private: 815 std::vector<rotor_digit> _vr; 816 }; 817 818 819 } // end namespace OpenBabel 820 821 #endif // OB_ROTOR_H 822 823 //! \file rotor.h 824 //! \brief Rotate torsional according to rotor rules. 825