File: ConjugHybrid.cpp

package info (click to toggle)
rdkit 201809.1%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 123,688 kB
  • sloc: cpp: 230,509; python: 70,501; java: 6,329; ansic: 5,427; sql: 1,899; yacc: 1,739; lex: 1,243; makefile: 445; xml: 229; fortran: 183; sh: 123; cs: 93
file content (196 lines) | stat: -rw-r--r-- 5,838 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// $Id$
//
//  Copyright (C) 2001-2008 Greg Landrum and Rational Discovery LLC
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//
#include "ROMol.h"
#include "RWMol.h"
#include "Atom.h"
#include "Bond.h"
#include "MolOps.h"
#include "PeriodicTable.h"
#include "AtomIterators.h"
#include "BondIterators.h"

namespace RDKit {
// local utility namespace:
namespace {
bool isAtomConjugCand(const Atom *at) {
  // the second check here is for Issue211, where the c-P bonds in
  // Pc1ccccc1 were being marked as conjugated.  This caused the P atom
  // itself to be SP2 hybridized.  This is wrong.  For now we'll do a quick
  // hack and forbid this check from adding conjugation to anything out of
  // the first row of the periodic table.  (Conjugation in aromatic rings
  // has already been attended to, so this is safe.)
  int nouter = PeriodicTable::getTable()->getNouterElecs(at->getAtomicNum());
  if (((at->getAtomicNum() <= 10) || (nouter != 5 && nouter != 6) ||
       (nouter == 6 && at->getTotalDegree() < 2)) &&
      (MolOps::countAtomElec(at) > 0)) {
    return true;
  }
  return false;
}

void markConjAtomBonds(Atom *at) {
  if (!isAtomConjugCand(at)) return;
  ROMol &mol = at->getOwningMol();
  Atom *at2;

  int atx = at->getIdx();
  // make sure that have either 2 or 3 subtitutions on this atom
  int sbo = at->getDegree() + at->getTotalNumHs();
  if ((sbo < 2) || (sbo > 3)) {
    return;
  }

  ROMol::OEDGE_ITER bnd1, end1, bnd2, end2;
  boost::tie(bnd1, end1) = mol.getAtomBonds(at);
  while (bnd1 != end1) {
    if (mol[*bnd1]->getValenceContrib(at) < 1.5) {
      bnd1++;
      continue;
    }
    boost::tie(bnd2, end2) = mol.getAtomBonds(at);
    while (bnd2 != end2) {
      if (bnd1 == bnd2) {
        bnd2++;
        continue;
      }
      at2 = mol.getAtomWithIdx(mol[*bnd2]->getOtherAtomIdx(atx));
      sbo = at2->getDegree() + at2->getTotalNumHs();
      if (sbo > 3) {
        bnd2++;
        continue;
      }
      if (isAtomConjugCand(at2)) {
        mol[*bnd1]->setIsConjugated(true);
        mol[*bnd2]->setIsConjugated(true);
      }
      bnd2++;
    }
    bnd1++;
  }
}

int numBondsPlusLonePairs(Atom *at) {
  PRECONDITION(at, "bad atom");
  int deg = at->getTotalDegree();
  ROMol::OEDGE_ITER beg, end;
  boost::tie(beg, end) = at->getOwningMol().getAtomBonds(at);
  while (beg != end) {
    Bond* bond = at->getOwningMol()[*beg];
    if (bond->getBondType() == Bond::ZERO) --deg;
    ++beg;
  }

  if (at->getAtomicNum() <= 1) {
    return deg;
  }
  int nouter = PeriodicTable::getTable()->getNouterElecs(at->getAtomicNum());
  int totalValence = at->getExplicitValence() + at->getImplicitValence();
  int chg = at->getFormalCharge();

  int numFreeElectrons = nouter - (totalValence + chg);
  if (totalValence + nouter - chg < 8) {
    // we're below an octet, so we need to think
    // about radicals:
    int numRadicals = at->getNumRadicalElectrons();
    int numLonePairs = (numFreeElectrons - numRadicals) / 2;
    return deg + numLonePairs + numRadicals;
  } else {
    int numLonePairs = numFreeElectrons / 2;
    return deg + numLonePairs;
  }
}
}  // end of utility namespace

namespace MolOps {
bool atomHasConjugatedBond(const Atom *at) {
  PRECONDITION(at, "bad atom");

  ROMol::OEDGE_ITER beg, end;
  boost::tie(beg, end) = at->getOwningMol().getAtomBonds(at);
  while (beg != end) {
    if (at->getOwningMol()[*beg]->getIsConjugated()) return true;
    beg++;
  }
  return false;
}

void setConjugation(ROMol &mol) {
  // start with all bonds being marked unconjugated
  // except for aromatic bonds
  ROMol::BondIterator bi;
  for (bi = mol.beginBonds(); bi != mol.endBonds(); bi++) {
    if ((*bi)->getIsAromatic()) {
      (*bi)->setIsConjugated(true);
    } else {
      (*bi)->setIsConjugated(false);
    }
  }

  ROMol::AtomIterator ai;
  // loop over each atom and check if the bonds connecting to it can
  // be conjugated
  for (ai = mol.beginAtoms(); ai != mol.endAtoms(); ai++) {
    markConjAtomBonds(*ai);
  }
}

void setHybridization(ROMol &mol) {
  ROMol::AtomIterator ai;
  int norbs;
  for (ai = mol.beginAtoms(); ai != mol.endAtoms(); ai++) {
    if ((*ai)->getAtomicNum() == 0) {
      (*ai)->setHybridization(Atom::UNSPECIFIED);
    } else {
      norbs = numBondsPlusLonePairs(*ai);
      switch (norbs) {
        case 0:
          // This occurs for things like Na+
          (*ai)->setHybridization(Atom::S);
          break;
        case 1:
          (*ai)->setHybridization(Atom::S);
          break;
        case 2:
          (*ai)->setHybridization(Atom::SP);
          break;
        case 3:
          (*ai)->setHybridization(Atom::SP2);
          break;
        case 4:
          // potentially SP3, but we'll set it down to SP2
          // if we have a conjugated bond (like the second O
          // in O=CO)
          // we'll also avoid setting the hybridization down to
          // SP2 in the case of an atom with degree higher than 3
          // (e.g. things like CP1(C)=CC=CN=C1C, where the P
          //   has norbs = 4, and a conjugated bond, but clearly should
          //   not be SP2)
          // This is Issue276
          if ((*ai)->getDegree() > 3 || !MolOps::atomHasConjugatedBond(*ai)) {
            (*ai)->setHybridization(Atom::SP3);
          } else {
            (*ai)->setHybridization(Atom::SP2);
          }
          break;
        case 5:
          (*ai)->setHybridization(Atom::SP3D);
          break;
        case 6:
          (*ai)->setHybridization(Atom::SP3D2);
          break;
        default:
          (*ai)->setHybridization(Atom::UNSPECIFIED);
      }
    }
  }
}
}  // end of namespace MolOps
}  // end of namespace RDKit