/// <summary> /// Tries to saturate a bond by increasing its bond orders by 1.0. /// </summary> /// <returns>true if the bond could be increased</returns> public bool SaturateByIncreasingBondOrder(IBond bond, IAtomContainer atomContainer) { var atoms = BondManipulator.GetAtomArray(bond); var atom = atoms[0]; var partner = atoms[1]; Debug.WriteLine(" saturating bond: ", atom.Symbol, "-", partner.Symbol); var atomTypes1 = structgenATF.GetAtomTypes(atom.Symbol); var atomTypes2 = structgenATF.GetAtomTypes(partner.Symbol); foreach (var aType1 in atomTypes1) { Debug.WriteLine($" considering atom type: {aType1}"); if (CouldMatchAtomType(atomContainer, atom, aType1)) { Debug.WriteLine($" trying atom type: {aType1}"); foreach (var aType2 in atomTypes2) { Debug.WriteLine($" considering partner type: {aType1}"); if (CouldMatchAtomType(atomContainer, partner, aType2)) { Debug.WriteLine($" with atom type: {aType2}"); if (BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) && BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder)) { bond.Order = BondManipulator.IncreaseBondOrder(bond.Order); Debug.WriteLine($"Bond order now {bond.Order}"); return(true); } } } } } return(false); }
/// <summary> /// Saturate atom by adjusting its bond orders. /// This method is known to fail, especially on pyrrole-like compounds. /// Consider using <see cref="Smiles.DeduceBondSystemTool"/>, which should work better /// </summary> public bool NewSaturate(IBond bond, IAtomContainer atomContainer) { var atoms = BondManipulator.GetAtomArray(bond); var atom = atoms[0]; var partner = atoms[1]; Debug.WriteLine($" saturating bond: {atom.Symbol}-{partner.Symbol}"); var atomTypes1 = structgenATF.GetAtomTypes(atom.Symbol); var atomTypes2 = structgenATF.GetAtomTypes(partner.Symbol); bool bondOrderIncreased = true; while (bondOrderIncreased && !IsSaturated(bond, atomContainer)) { Debug.WriteLine("Can increase bond order"); bondOrderIncreased = false; foreach (var aType1 in atomTypes1) { if (bondOrderIncreased) { break; } Debug.WriteLine($" considering atom type: {aType1}"); if (CouldMatchAtomType(atomContainer, atom, aType1)) { Debug.WriteLine($" trying atom type: {aType1}"); foreach (var aType2 in atomTypes2) { if (bondOrderIncreased) { break; } Debug.WriteLine($" considering partner type: {aType1}"); if (CouldMatchAtomType(atomContainer, partner, aType2)) { Debug.WriteLine($" with atom type: {aType2}"); if (!BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) || !BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder)) { Debug.WriteLine("Bond order not increased: atoms has reached (or exceeded) maximum bond order for this atom type"); } else if (BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) && BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder)) { BondManipulator.IncreaseBondOrder(bond); Debug.WriteLine($"Bond order now {bond.Order}"); bondOrderIncreased = true; } } } } } } return(IsSaturated(bond, atomContainer)); }
/// <summary> /// The method calculates the number of rotatable bonds of an atom container. /// If the boolean parameter is set to <see langword="true"/>, terminal bonds are included. /// </summary> /// <returns>number of rotatable bonds</returns> /// <param name="includeTerminals"><see langword="true"/> if terminal bonds are included</param> /// <param name="excludeAmides"><see langword="true"/> if amide C-N bonds should be excluded</param> public Result Calculate(IAtomContainer container, bool includeTerminals = false, bool excludeAmides = false) { container = (IAtomContainer)container.Clone(); IRingSet ringSet; try { ringSet = new SpanningTree(container).GetBasicRings(); } catch (NoSuchAtomException) { return(new Result(0)); } foreach (var bond in container.Bonds) { if (ringSet.GetRings(bond).Count() > 0) { bond.IsInRing = true; } } int rotatableBondsCount = 0; foreach (var bond in container.Bonds) { var atom0 = bond.Atoms[0]; var atom1 = bond.Atoms[1]; if (atom0.AtomicNumber.Equals(AtomicNumbers.H) || atom1.AtomicNumber.Equals(AtomicNumbers.H)) { continue; } if (bond.Order == BondOrder.Single) { if (BondManipulator.IsLowerOrder(container.GetMaximumBondOrder(atom0), BondOrder.Triple) && BondManipulator.IsLowerOrder(container.GetMaximumBondOrder(atom1), BondOrder.Triple)) { if (!bond.IsInRing) { if (excludeAmides && (IsAmide(atom0, atom1, container) || IsAmide(atom1, atom0, container))) { continue; } // if there are explicit H's we should ignore those bonds var degree0 = container.GetConnectedBonds(atom0).Count() - GetConnectedHCount(container, atom0); var degree1 = container.GetConnectedBonds(atom1).Count() - GetConnectedHCount(container, atom1); if ((degree0 == 1) || (degree1 == 1)) { if (includeTerminals) { rotatableBondsCount += 1; } } else { rotatableBondsCount += 1; } } } } } return(new Result(rotatableBondsCount)); }