Ejemplo n.º 1
0
OpenBabel::OBMol
Schuffenhauer::RemoveRing(OpenBabel::OBMol& oldMol, 
std::vector<OpenBabel::OBRing*>& rings, unsigned int ringIdx)
{
	OpenBabel::OBMol newMol(oldMol);

	// Make list of the ring bonds
	std::set<OpenBabel::OBBond*> ringBonds;
	OpenBabel::OBBond* bond;
	std::vector<OpenBabel::OBBond*>::iterator bvi;
	for (bond = newMol.BeginBond(bvi); bond; bond = newMol.NextBond(bvi))
	{
		if (rings[ringIdx]->IsMember(bond))
		{
			ringBonds.insert(bond);
		}
	}
	
	// Make list of delocalizable bonds (aromatic, single and flanked by two double bonds)
	std::set<OpenBabel::OBBond*> delocalizableBonds;
	std::set<OpenBabel::OBBond*>::iterator bli;
	OpenBabel::OBBondIterator bi;
	OpenBabel::OBAtom* atom;
	OpenBabel::OBBond* nbrBond;
	unsigned int n;
	for (bli = ringBonds.begin(); bli != ringBonds.end(); ++bli)
	{
		bond = *bli;
		if ((bond->GetBondOrder() == 1) && 
			bond->IsAromatic())
		{
			n = 0;
			atom = bond->GetBeginAtom();
			for (nbrBond = atom->BeginBond(bi); nbrBond; nbrBond = atom->NextBond(bi))
			{
				if ((nbrBond != bond) && 
					ringBonds.count(nbrBond) && 
					(nbrBond->GetBondOrder() == 2))
				{
					++n;
				}
			}
			atom = bond->GetEndAtom();
			for (nbrBond = atom->BeginBond(bi); nbrBond; nbrBond = atom->NextBond(bi))
			{
				if ((nbrBond != bond) && 
					ringBonds.count(nbrBond) &&
					(nbrBond->GetBondOrder() == 2))
				{
					++n;
				}
			}
		}
		if (n == 2)
		{
			delocalizableBonds.insert(bond);
		}
	}
	
	// Make list of bonds which form the fusion with other rings
	std::set<OpenBabel::OBBond*> fusionBonds;
	for (bli = ringBonds.begin(); bli != ringBonds.end(); ++bli)
	{
		bond = *bli;
		for (unsigned int i(0); i < rings.size(); ++i)
		{
			if (i != ringIdx)
			{
				if (rings[i]->IsMember(bond))
				{
					fusionBonds.insert(bond);
				}
			}
		}
	}
   
	// Make list of bonds which are the fusion between aromatic and non-aromatic
	std::set<OpenBabel::OBBond*> aromaticNonaromaticFusionBonds;
	if (rings[ringIdx]->IsAromatic())
	{
		for (bli = fusionBonds.begin(); bli != fusionBonds.end(); ++bli)
		{
			bond = *bli;
			for (unsigned int i(0); i < rings.size(); ++i)
			{
				if (i != ringIdx)
				{
					if (rings[i]->IsMember(bond) && 
						!rings[i]->IsAromatic())
					{
						aromaticNonaromaticFusionBonds.insert(bond);
					}
				}
			}
		}
	}
   
	// Make list of bonds which are the fusion between aromatic and aromatic
	std::set<OpenBabel::OBBond*> aromaticAromaticFusionBonds;
	if (rings[ringIdx]->IsAromatic())
	{
		for (bli = fusionBonds.begin(); bli != fusionBonds.end(); ++bli)
		{
			bond = *bli;
			for (unsigned int i(0); i < rings.size(); ++i)
			{
				if (i != ringIdx)
				{
					if (rings[i]->IsMember(bond) &&
						rings[i]->IsAromatic())
					{
						aromaticAromaticFusionBonds.insert(bond);
					}
				}
 			}
		}
	}

	// Remove ring
	std::set<OpenBabel::OBBond*> bondsToBeDeleted;  
	std::set<OpenBabel::OBAtom*> atomsToBeDeleted;  
	OpenBabel::OBAtom* nbrAtom[2];
	for (bli = ringBonds.begin(); bli != ringBonds.end(); ++bli)
	{
		bond = *bli;
		if (fusionBonds.count(bond))
		{
			continue;
		}
		else
		{
			bondsToBeDeleted.insert(bond);
			nbrAtom[0] = bond->GetBeginAtom();
			nbrAtom[1] = bond->GetEndAtom();
			if (nbrAtom[0] && nbrAtom[1])
			{
				if (nbrAtom[0]->MemberOfRingCount() == 1)
				{
					atomsToBeDeleted.insert(nbrAtom[0]);
				}
				if (nbrAtom[1]->MemberOfRingCount() == 1)
				{
					atomsToBeDeleted.insert(nbrAtom[1]);
				}
			}
		}
	}
	newMol.BeginModify();
	for (bli = bondsToBeDeleted.begin(); bli != bondsToBeDeleted.end(); ++bli)
	{
		newMol.DeleteBond(*bli);
	}
	newMol.EndModify();
	newMol.BeginModify();
	std::set<OpenBabel::OBAtom*>::iterator ali;
	for (ali = atomsToBeDeleted.begin(); ali != atomsToBeDeleted.end(); ++ali)
	{
		newMol.DeleteAtom(*ali);
	}
	newMol.EndModify();
	
	// Correct the bond orders of the ex-fusion bond(s)
	newMol.BeginModify();
	for (bond = newMol.BeginBond(bvi); bond; bond = newMol.NextBond(bvi))
	{
		if (aromaticNonaromaticFusionBonds.count(bond))
		{
			bond->SetBondOrder(2);
		} 
		else
		if (aromaticAromaticFusionBonds.count(bond) && 
			delocalizableBonds.count(bond))
		{
			bond->SetBondOrder(2);
		} 
 	}
	newMol.EndModify();
   
	// Remove single atoms that originate from exocyclic bonds at ring
	(void) RemoveSidechains(&newMol);
	
	// Check if there are atoms with valences that are not allowed
	std::vector<OpenBabel::OBAtom*>::iterator avi;
	for (atom = newMol.BeginAtom(avi); atom; atom = newMol.NextAtom(avi))
	{
		if (atom->IsCarbon() &&
			(atom->BOSum() > 4))
		{
			newMol.Clear();
			break;
		}
		else
		if (atom->IsNitrogen() &&
			(atom->BOSum() > 3))
		{
			newMol.Clear();
			break;
		}
		else
		if (atom->IsOxygen() &&
			(atom->BOSum() > 2))
		{
			newMol.Clear();
			break;
		}
	}
	
	// Check if there are no discontinuous fragments
	if (newMol.Separate().size() > 1)
	{
		newMol.Clear();
	}
	
	return newMol;
}
Ejemplo n.º 2
0
OpenBabel::OBMol
Schuffenhauer::Rule_7(OpenBabel::OBMol& oldMol)
{
   	std::vector<OpenBabel::OBRing*> allrings(oldMol.GetSSSR());
   	if (allrings.size() <= _ringsToBeRetained)
   	{
      	return oldMol;
   	}

   	// Are all atoms and bonds aromatic?
   	std::vector<OpenBabel::OBAtom*>::iterator avi;
   	OpenBabel::OBAtom* atom;
   	for (atom = oldMol.BeginAtom(avi); atom; atom = oldMol.NextAtom(avi))
   	{
      	if (!atom->IsAromatic())
      	{
         	return oldMol;
      	}
   	}
   	std::vector<OpenBabel::OBBond*>::iterator bvi;
   	OpenBabel::OBBond* bond;
   	for (bond = oldMol.BeginBond(bvi); bond; bond = oldMol.NextBond(bvi))
   	{
      	if (!bond->IsAromatic())
      	{
         	return oldMol;
      	}
   	}

   	std::vector<OpenBabel::OBMol> mols;
   	for (unsigned int i(0); i < allrings.size(); ++i)
   	{
      	mols.push_back(oldMol);
   	}
   
   	std::vector<OpenBabel::OBMol> validMols;
   	for (unsigned int i(0); i < mols.size(); ++i)
   	{
      	mols[i] = RemoveRing(mols[i], allrings, i);
      	if (!mols[i].Empty())
      	{
         	// Has aromaticity been broken?
         	bool broken(false);
         	for (atom = mols[i].BeginAtom(avi); atom; atom = mols[i].NextAtom(avi))
         	{
            	if (atom->IsInRing() && !atom->IsAromatic())
            	{
               		broken = true;
               		break;
            	}
         	}
         	if (!broken)
         	{
            	validMols.push_back(mols[i]);
         	}
      	}
   	}

	if (validMols.size() == 1)
   	{
      	return validMols[0];
   	}

   	return oldMol;
}