Ignore:
Timestamp:
Apr 1, 2010, 6:52:09 PM (16 years ago)
Author:
Frederik Heber <heber@…>
Children:
6dd8d3
Parents:
794482
Message:

Enhanced CountHydrogenBridgeBonds() a bit.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • molecuilder/src/analysis_bonds.cpp

    r794482 r6250e5  
    8282};
    8383
     84/** Calculate the angle between \a *first and \a *origin and \a *second and \a *origin.
     85 * \param *first first Vector
     86 * \param *origin origin of angle taking
     87 * \param *second second Vector
     88 * \return angle between \a *first and \a *second, both relative to origin at \a *origin.
     89 */
     90double CalculateAngle(Vector *first, Vector *central, Vector *second)
     91{
     92  Vector OHBond;
     93  Vector OOBond;
     94
     95  OHBond.CopyVector(first);
     96  OHBond.SubtractVector(central);
     97  OOBond.CopyVector(second);
     98  OOBond.SubtractVector(central);
     99  const double angle = OHBond.Angle(&OOBond);
     100  return angle;
     101};
     102
     103/** Checks whether the angle between \a *Oxygen and \a *Hydrogen and \a *Oxygen and \a *OtherOxygen is less than 30 degrees.
     104 * Note that distance criterion is not checked.
     105 * \param *Oxygen first oxygen atom, bonded to \a *Hydrogen
     106 * \param *Hydrogen hydrogen bonded to \a *Oxygen
     107 * \param *OtherOxygen other oxygen atom
     108 * \return true - angle criteria fulfilled, false - criteria not fulfilled, angle greater than 30 degrees.
     109 */
     110bool CheckHydrogenBridgeBondAngle(atom *Oxygen, atom *Hydrogen, atom *OtherOxygen)
     111{
     112  Info FunctionInfo(__func__);
     113
     114  // check angle
     115  if (CalculateAngle(&Hydrogen->x, &Oxygen->x, &OtherOxygen->x) < M_PI*(30./180.)) {
     116    return true;
     117  } else {
     118    return false;
     119  }
     120};
    84121
    85122/** Counts the number of hydrogen bridge bonds.
     
    91128int CountHydrogenBridgeBonds(MoleculeListClass *molecules, element * InterfaceElement = NULL)
    92129{
    93   Info FunctionInfo(__func__);
    94130  atom *Walker = NULL;
    95131  atom *Runner = NULL;
    96   Vector OHBond;
    97   Vector OOBond;
    98132  int count = 0;
     133  int OtherHydrogens = 0;
     134  double Otherangle = 0.;
    99135  bool InterfaceFlag = false;
     136  bool OtherHydrogenFlag = true;
    100137  for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin();MolWalker != molecules->ListOfMolecules.end(); MolWalker++) {
    101138    Walker = (*MolWalker)->start;
    102139    while (Walker->next != (*MolWalker)->end) {
    103140      Walker = Walker->next;
    104       for (MoleculeList::const_iterator MolRunner = molecules->ListOfMolecules.begin();MolRunner != MolWalker; MolRunner++) {
     141      for (MoleculeList::const_iterator MolRunner = molecules->ListOfMolecules.begin();MolRunner != molecules->ListOfMolecules.end(); MolRunner++) {
    105142        Runner = (*MolRunner)->start;
    106143        while (Runner->next != (*MolRunner)->end) {
    107144          Runner = Runner->next;
    108           if ((Runner != Walker) && (Walker->type->Z  == 8) && (Runner->type->Z  == 8)) {
     145          if ((Walker->type->Z  == 8) && (Runner->type->Z  == 8)) {
    109146            // check distance
    110147            const double distance = Runner->x.DistanceSquared(&Walker->x);
    111148            if ((distance > MYEPSILON) && (distance < HBRIDGEDISTANCE*HBRIDGEDISTANCE)) { // distance >0 means  different atoms
     149              // on other atom(Runner) we check for bond to interface element and
     150              // check that O-O line is not in between the shanks of the two connected hydrogens (Otherangle > 104.5)
     151              OtherHydrogenFlag = true;
     152              Otherangle = 0.;
     153              OtherHydrogens = 0;
    112154              InterfaceFlag = (InterfaceElement == NULL);
    113               // on other atom(Runner) we check for bond to interface element
    114               for (BondList::const_iterator BondRunner = Runner->ListOfBonds.begin(); ((!InterfaceFlag) && (BondRunner != Runner->ListOfBonds.end())); BondRunner++) {
     155              for (BondList::const_iterator BondRunner = Runner->ListOfBonds.begin(); BondRunner != Runner->ListOfBonds.end(); BondRunner++) {
    115156                atom * const OtherAtom = (*BondRunner)->GetOtherAtom(Runner);
     157                // if hydrogen, check angle to be greater(!) than 30 degrees
     158                if (OtherAtom->type->Z == 1) {
     159                  const double angle = CalculateAngle(&OtherAtom->x, &Runner->x, &Walker->x);
     160                  OtherHydrogenFlag = OtherHydrogenFlag && (angle > M_PI*(30./180.) + MYEPSILON);
     161                  Otherangle += angle;
     162                  OtherHydrogens++;
     163                }
    116164                InterfaceFlag = InterfaceFlag || (OtherAtom->type == InterfaceElement);
    117165              }
    118               if (InterfaceFlag) {
     166              DoLog(1) && (Log() << Verbose(1) << "Otherangle is " << Otherangle << " for " << OtherHydrogens << " hydrogens." << endl);
     167              switch (OtherHydrogens) {
     168                case 0:
     169                case 1:
     170                  break;
     171                case 2:
     172                  OtherHydrogenFlag = OtherHydrogenFlag && (Otherangle > M_PI*(104.5/180.) + MYEPSILON);
     173                  break;
     174                default: // 3 or more hydrogens ...
     175                  OtherHydrogenFlag = false;
     176                  break;
     177              }
     178              if (InterfaceFlag && OtherHydrogenFlag) {
    119179                // on this element (Walker) we check for bond to hydrogen, i.e. part of water molecule
    120180                for (BondList::const_iterator BondRunner = Walker->ListOfBonds.begin(); BondRunner != Walker->ListOfBonds.end(); BondRunner++) {
     
    122182                  if (OtherAtom->type->Z == 1) {
    123183                    // check angle
    124                     OHBond.CopyVector(&OtherAtom->x);
    125                     OHBond.SubtractVector(&Walker->x);
    126                     OOBond.CopyVector(&Runner->x);
    127                     OOBond.SubtractVector(&Walker->x);
    128                     const double angle = OHBond.Angle(&OOBond);
    129                     if (angle < M_PI*(30./180.)) {
    130                       DoLog(1) && (Log() << Verbose(1) << Walker->Name << ", " << OtherAtom->Name << " and " << Runner->Name << " have a hydrogen bridge bond with " << sqrt(distance) << " and at angle " << (180./M_PI)*angle << " degrees." << endl);
     184                    if (CheckHydrogenBridgeBondAngle(Walker, OtherAtom, Runner)) {
     185                      DoLog(1) && (Log() << Verbose(1) << Walker->Name << ", " << OtherAtom->Name << " and " << Runner->Name << " has a hydrogen bridge bond with distance " << sqrt(distance) << " and angle " << CalculateAngle(&OtherAtom->x, &Walker->x, &Runner->x)*(180./M_PI) << "." << endl);
    131186                      count++;
    132187                      break;
Note: See TracChangeset for help on using the changeset viewer.