int SetMM3Type(OBAtom *atom) { OBAtom *b; // neighbor OBBondIterator i, j; int countNeighborO, countNeighborS, countNeighborN, countNeighborC; countNeighborO = countNeighborS = countNeighborN = countNeighborC = 0; // The MM2 typing isn't very good, so we do this ourselves for the most common atom types switch (atom->GetAtomicNum()) { case 1: // Hydrogen b = atom->BeginNbrAtom(j); if (b->IsCarboxylOxygen()) return 24; if (b->GetAtomicNum() == OBElements::Sulfur) return 44; if (b->GetAtomicNum() == OBElements::Nitrogen) { if (b->IsAmideNitrogen()) return 28; if (b->GetValence() > 3) return 48;// ammonium return 23; // default amine/imine } if (b->GetAtomicNum() == OBElements::Carbon && b->GetHyb() == 1) return 124; // acetylene if (b->GetAtomicNum() == OBElements::Oxygen) { if (b->HasAlphaBetaUnsat()) return 73; // includes non-enol/phenol, but has the right spirit return 21; // default alcohol } return 5; // default H break; case 2: // Helium return 51; break; case 3: // Li return 163; break; case 5: // B if (atom->GetValence() >= 4) return 27; // tetrahedral return 26; break; case 6: // C if (atom->IsInRingSize(3)) { // cyclopropane / cyclopropene if (atom->GetHyb() == 3) return 22; if (atom->GetHyb() == 2) { if (atom->CountFreeOxygens() == 1) // propanone return 67; return 38; // propane } } if (atom->IsInRingSize(4)) { // cyclobutane or cyclobutene if (atom->GetHyb() == 3) return 56; if (atom->GetHyb() == 2) { if (atom->CountFreeOxygens() == 1) // butanone return 58; return 57; // regular cyclobutane } } if (atom->CountBondsOfOrder(2) == 2) { // allene if (atom->CountFreeOxygens() == 1) // ketene return 106; return 68; } if (atom->GetFormalCharge() == +1) return 30; if (atom->GetSpinMultiplicity() == 2) return 29; if (atom->GetHyb() == 3) return 1; else if (atom->GetHyb() == 2) { if (atom->CountFreeOxygens() >= 1) return 3; return 2; } else if (atom->GetHyb() == 1) return 4; break; case 7: // N // TODO if (atom->IsAmideNitrogen()) return 151; if (atom->IsAromatic()) { if (atom->GetFormalCharge() == 1) return 111; if (atom->IsInRingSize(5)) // pyrrole return 40; if (atom->IsInRingSize(6)) // pyridine return 37; } if (atom->CountFreeOxygens() == 2) // nitro return 46; if (atom->GetHyb() == 3) { if (atom->GetValence() > 3) return 39; // ammonium return 8; } else if (atom->GetHyb() == 2) return 9; else if (atom->GetHyb() == 1) return 10; break; case 8: // O //TODO if (atom->IsPhosphateOxygen()) return 159; if (atom->IsCarboxylOxygen()) return 75; if (atom->IsInRingSize(3)) return 49; // epoxy b = atom->BeginNbrAtom(j); if (atom->HasBondOfOrder(2) && b->GetAtomicNum() == OBElements::Carbon) { // O=C return 7; } if (atom->IsAromatic()) return 41; // furan return 6; break; case 9: // F return 11; break; case 10: // Ne return 52; break; case 12: // Mg return 59; break; case 14: // Si return 19; break; case 15: // P if (atom->CountFreeOxygens() > 0) return 153; // phosphate if (atom->BOSum() > 3) return 60; // phosphorus V return 25; break; case 16: // S if (atom->IsAromatic()) return 42; // thiophene if (atom->GetFormalCharge() == 1) return 16; // sulfonium // look at the neighbors for (b = atom->BeginNbrAtom(j); b; b = atom->NextNbrAtom(j)) { switch (b->GetAtomicNum()) { case 6: if (b->GetHyb() == 2) // S=C countNeighborC++; break; case 7: countNeighborN++; break; case 8: if (b->GetHvyValence() == 1) countNeighborO++; break; case 16: countNeighborS++; break; default: continue; } } if (countNeighborO == 1) return 17; // sulfoxide if (countNeighborO >= 2) { if (countNeighborN) return 154; // sulfonamide return 18; // sulfone or sulfate } if (countNeighborC) return 74; // S=C if (countNeighborS == 1) return 104; // S-S disulfide else if (countNeighborS > 1) return 105; return 15; break; case 17: // Cl return 12; break; case 18: // Ar return 153; break; case 20: // Ca return 125; break; case 26: // Fe if (atom->GetFormalCharge() == 2) return 61; return 62; break; case 27: // Co if (atom->GetFormalCharge() == 2) return 65; return 66; break; case 28: // Ni if (atom->GetFormalCharge() == 2) return 63; return 64; break; case 32: // Ge return 31; break; case 34: // Se return 34; break; case 35: // Br return 13; break; case 36: // Kr return 54; break; case 38: // Sr return 126; break; case 50: // Sn return 32; break; case 52: // Te return 35; break; case 53: // I return 14; break; case 54: // Xe return 55; break; case 56: // Ba return 127; break; case 57: return 128; break; case 58: return 129; break; case 59: return 130; break; case 60: return 131; break; case 61: return 132; break; case 62: return 133; break; case 63: return 134; break; case 64: return 135; break; case 65: return 136; break; case 66: return 137; break; case 67: return 138; break; case 68: return 139; break; case 69: return 140; break; case 70: return 141; break; case 71: return 142; break; case 82: // Pb return 33; break; default: break; } return 0; }
void OBAromaticTyper::AssignAromaticFlags(OBMol &mol) { if (!_init) Init(); if (mol.HasAromaticPerceived()) return; mol.SetAromaticPerceived(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::AssignAromaticFlags", obAuditMsg); _vpa.clear(); _vpa.resize(mol.NumAtoms()+1); _velec.clear(); _velec.resize(mol.NumAtoms()+1); _root.clear(); _root.resize(mol.NumAtoms()+1); OBBond *bond; OBAtom *atom; vector<OBAtom*>::iterator i; vector<OBBond*>::iterator j; //unset all aromatic flags for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) atom->UnsetAromatic(); for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j)) bond->UnsetAromatic(); int idx; vector<vector<int> >::iterator m; vector<OBSmartsPattern*>::iterator k; //mark atoms as potentially aromatic for (idx=0,k = _vsp.begin();k != _vsp.end();++k,++idx) if ((*k)->Match(mol)) { _mlist = (*k)->GetMapList(); for (m = _mlist.begin();m != _mlist.end();++m) { _vpa[(*m)[0]] = true; _velec[(*m)[0]] = _verange[idx]; } } //sanity check - exclude all 4 substituted atoms and sp centers for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) { if (atom->GetImplicitValence() > 3) { _vpa[atom->GetIdx()] = false; continue; } switch(atom->GetAtomicNum()) { //phosphorus and sulfur may be initially typed as sp3 case 6: case 7: case 8: if (atom->GetHyb() != 2) _vpa[atom->GetIdx()] = false; break; } } //propagate potentially aromatic atoms for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) if (_vpa[atom->GetIdx()]) PropagatePotentialAromatic(atom); //select root atoms SelectRootAtoms(mol); ExcludeSmallRing(mol); //remove 3 membered rings from consideration //loop over root atoms and look for aromatic rings _visit.clear(); _visit.resize(mol.NumAtoms()+1); for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) if (_root[atom->GetIdx()]) CheckAromaticity(atom,14); //for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) // if (atom->IsAromatic()) // cerr << "aro = " <<atom->GetIdx() << endl; //for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j)) //if (bond->IsAromatic()) //cerr << bond->GetIdx() << ' ' << bond->IsAromatic() << endl; }