public virtual void  saturateRingSystems(IAtomContainer atomContainer)
        {
            IRingSet rs = new SSSRFinder(atomContainer.Builder.newMolecule(atomContainer)).findSSSR();

            System.Collections.ArrayList ringSets = RingPartitioner.partitionRings(rs);
            IAtomContainer ac   = null;
            IAtom          atom = null;

            int[] temp;
            for (int f = 0; f < ringSets.Count; f++)
            {
                rs   = (IRingSet)ringSets[f];
                ac   = RingSetManipulator.getAllInOneContainer(rs);
                temp = new int[ac.AtomCount];
                for (int g = 0; g < ac.AtomCount; g++)
                {
                    atom    = ac.getAtomAt(g);
                    temp[g] = atom.getHydrogenCount();
                    atom.setHydrogenCount(atomContainer.getBondCount(atom) - ac.getBondCount(atom) - temp[g]);
                }
                saturate(ac);
                for (int g = 0; g < ac.AtomCount; g++)
                {
                    atom = ac.getAtomAt(g);
                    atom.setHydrogenCount(temp[g]);
                }
            }
        }
        /// <summary> Determines if the atom can be of type AtomType. That is, it sees if this
        /// AtomType only differs in bond orders, or implicit hydrogen count.
        /// </summary>
        public virtual bool couldMatchAtomType(IAtom atom, double bondOrderSum, double maxBondOrder, IAtomType type)
        {
            //logger.debug("couldMatchAtomType:   ... matching atom ", atom, " vs ", type);
            int hcount = atom.getHydrogenCount();
            int charge = atom.getFormalCharge();

            if (charge == type.getFormalCharge())
            {
                //logger.debug("couldMatchAtomType:     formal charge matches...");
                if (atom.Hybridization == type.Hybridization)
                {
                    //logger.debug("couldMatchAtomType:     hybridization is OK...");
                    if (bondOrderSum + hcount <= type.BondOrderSum)
                    {
                        //logger.debug("couldMatchAtomType:     bond order sum is OK...");
                        if (maxBondOrder <= type.MaxBondOrder)
                        {
                            //logger.debug("couldMatchAtomType:     max bond order is OK... We have a match!");
                            return(true);
                        }
                    }
                    else
                    {
                        //logger.debug("couldMatchAtomType:      no match", "" + (bondOrderSum + hcount), " > ", "" + type.BondOrderSum);
                    }
                }
            }
            else
            {
                //logger.debug("couldMatchAtomType:     formal charge does NOT match...");
            }
            //logger.debug("couldMatchAtomType:    No Match");
            return(false);
        }
        /// <summary> Checks if the current atom has exceeded its bond order sum value.
        ///
        /// </summary>
        /// <param name="atom">The Atom to check
        /// </param>
        /// <param name="ac">  The atomcontainer context
        /// </param>
        /// <returns>      oversaturated or not
        /// </returns>
        public virtual bool isOverSaturated(IAtom atom, IAtomContainer ac)
        {
            IAtomType[] atomTypes = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol);
            if (atomTypes.Length == 0)
            {
                return(false);
            }
            double bondOrderSum = ac.getBondOrderSum(atom);
            double maxBondOrder = ac.getMaximumBondOrder(atom);
            int    hcount       = atom.getHydrogenCount();
            int    charge       = atom.getFormalCharge();

            try
            {
                //logger.debug("*** Checking saturation of atom " + ac.getAtomNumber(atom) + " ***");
                //logger.debug("bondOrderSum: " + bondOrderSum);
                //logger.debug("maxBondOrder: " + maxBondOrder);
                //logger.debug("hcount: " + hcount);
            }
            catch (System.Exception exc)
            {
            }
            for (int f = 0; f < atomTypes.Length; f++)
            {
                if (bondOrderSum - charge + hcount > atomTypes[f].BondOrderSum)
                {
                    //logger.debug("*** Good ! ***");
                    return(true);
                }
            }
            //logger.debug("*** Bad ! ***");
            return(false);
        }
        /// <summary> Checks wether an Atom is saturated by comparing it with known AtomTypes.
        /// It returns true if the atom is an PseudoAtom and when the element is not in the list.
        /// </summary>
        public virtual bool isSaturated(IAtom atom, IAtomContainer container)
        {
            if (atom is IPseudoAtom)
            {
                //logger.debug("don't figure it out... it simply does not lack H's");
                return(true);
            }

            IAtomType[] atomTypes = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol);
            if (atomTypes.Length == 0)
            {
                //logger.warn("Missing entry in atom type list for ", atom.Symbol);
                return(true);
            }
            double bondOrderSum = container.getBondOrderSum(atom);
            double maxBondOrder = container.getMaximumBondOrder(atom);
            int    hcount       = atom.getHydrogenCount();
            int    charge       = atom.getFormalCharge();

            //logger.debug("Checking saturation of atom ", atom.Symbol);
            //logger.debug("bondOrderSum: ", bondOrderSum);
            //logger.debug("maxBondOrder: ", maxBondOrder);
            //logger.debug("hcount: ", hcount);
            //logger.debug("charge: ", charge);

            bool elementPlusChargeMatches = false;

            for (int f = 0; f < atomTypes.Length; f++)
            {
                IAtomType type = atomTypes[f];
                if (couldMatchAtomType(atom, bondOrderSum, maxBondOrder, type))
                {
                    if (bondOrderSum + hcount == type.BondOrderSum && maxBondOrder <= type.MaxBondOrder)
                    {
                        //logger.debug("We have a match: ", type);
                        //logger.debug("Atom is saturated: ", atom.Symbol);
                        return(true);
                    }
                    else
                    {
                        // ok, the element and charge matche, but unfulfilled
                        elementPlusChargeMatches = true;
                    }
                }                 // else: formal charges don't match
            }

            if (elementPlusChargeMatches)
            {
                //logger.debug("No, atom is not saturated.");
                return(false);
            }

            // ok, the found atom was not in the list
            throw new CDKException("The atom with element " + atom.Symbol + " and charge " + charge + " is not found.");
        }
 /// <summary> Determines if the atom can be of type AtomType.</summary>
 public virtual bool couldMatchAtomType(IAtomContainer atomContainer, IAtom atom, IAtomType atomType)
 {
     //logger.debug("   ... matching atom ", atom.Symbol, " vs ", atomType);
     if (atomContainer.getBondOrderSum(atom) + atom.getHydrogenCount() < atomType.BondOrderSum)
     {
         //logger.debug("    Match!");
         return(true);
     }
     //logger.debug("    No Match");
     return(false);
 }
Exemple #6
0
        /// <summary> Method that saturates an atom in a molecule by adding implicit hydrogens.
        ///
        /// </summary>
        /// <param name="container"> Molecule to saturate
        /// </param>
        /// <param name="atom">     Atom to satureate.
        /// </param>
        /// <cdk.keyword>           hydrogen, adding </cdk.keyword>
        /// <cdk.keyword>           implicit hydrogen </cdk.keyword>
        public virtual int[] addImplicitHydrogensToSatisfyValency(IAtomContainer container, IAtom atom)
        {
            int formerHydrogens  = atom.getHydrogenCount();
            int missingHydrogens = valencyChecker.calculateNumberOfImplicitHydrogens(atom, container);

            atom.setHydrogenCount(missingHydrogens);
            int[] hydrogens = new int[2];
            hydrogens[0] = formerHydrogens;
            hydrogens[1] = missingHydrogens;
            return(hydrogens);
        }
Exemple #7
0
        /// <summary> Determines if the atom can be of type AtomType.</summary>
        public virtual bool couldMatchAtomType(IAtom atom, double bondOrderSum, double maxBondOrder, IAtomType type)
        {
            //logger.debug("   ... matching atom ", atom.Symbol, " vs ", type);
            int hcount = atom.getHydrogenCount();
            int charge = atom.getFormalCharge();

            if (charge == type.getFormalCharge())
            {
                if (bondOrderSum + hcount <= type.BondOrderSum && maxBondOrder <= type.MaxBondOrder)
                {
                    //logger.debug("    We have a match!");
                    return(true);
                }
            }
            //logger.debug("    No Match");
            return(false);
        }
Exemple #8
0
        /// <summary>  Says if an atom is the start of a double bond configuration
        ///
        /// </summary>
        /// <param name="a">                       The atom which is the start of configuration
        /// </param>
        /// <param name="container">               The atomContainer the atom is in
        /// </param>
        /// <param name="parent">                  The atom we came from
        /// </param>
        /// <param name="doubleBondConfiguration"> The array indicating where double bond
        /// configurations are specified (this method ensures that there is
        /// actually the possibility of a double bond configuration)
        /// </param>
        /// <returns>                          false=is not start of configuration, true=is
        /// </returns>
        private static bool isStartOfDoubleBond(IAtomContainer container, IAtom a, IAtom parent, bool[] doubleBondConfiguration)
        {
            int lengthAtom = container.getConnectedAtoms(a).Length + a.getHydrogenCount();

            if (lengthAtom != 3 && (lengthAtom != 2 && (System.Object)a.Symbol != (System.Object)("N")))
            {
                return(false);
            }
            IAtom[] atoms      = container.getConnectedAtoms(a);
            IAtom   one        = null;
            IAtom   two        = null;
            bool    doubleBond = false;
            IAtom   nextAtom   = null;

            for (int i = 0; i < atoms.Length; i++)
            {
                if (atoms[i] != parent && container.getBond(atoms[i], a).Order == CDKConstants.BONDORDER_DOUBLE && isEndOfDoubleBond(container, atoms[i], a, doubleBondConfiguration))
                {
                    doubleBond = true;
                    nextAtom   = atoms[i];
                }
                if (atoms[i] != nextAtom && one == null)
                {
                    one = atoms[i];
                }
                else if (atoms[i] != nextAtom && one != null)
                {
                    two = atoms[i];
                }
            }
            System.String[] morgannumbers = MorganNumbersTools.getMorganNumbersWithElementSymbol(container);
            if (one != null && ((!a.Symbol.Equals("N") && two != null && !morgannumbers[container.getAtomNumber(one)].Equals(morgannumbers[container.getAtomNumber(two)]) && doubleBond && doubleBondConfiguration[container.getBondNumber(a, nextAtom)]) || (doubleBond && a.Symbol.Equals("N") && System.Math.Abs(giveAngleBothMethods(nextAtom, a, parent, true)) > System.Math.PI / 10)))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #9
0
        /// <summary>  Says if an atom is the end of a double bond configuration
        ///
        /// </summary>
        /// <param name="atom">                    The atom which is the end of configuration
        /// </param>
        /// <param name="container">               The atomContainer the atom is in
        /// </param>
        /// <param name="parent">                  The atom we came from
        /// </param>
        /// <param name="doubleBondConfiguration"> The array indicating where double bond
        /// configurations are specified (this method ensures that there is
        /// actually the possibility of a double bond configuration)
        /// </param>
        /// <returns>                          false=is not end of configuration, true=is
        /// </returns>
        private static bool isEndOfDoubleBond(IAtomContainer container, IAtom atom, IAtom parent, bool[] doubleBondConfiguration)
        {
            if (container.getBondNumber(atom, parent) == -1 || doubleBondConfiguration.Length <= container.getBondNumber(atom, parent) || !doubleBondConfiguration[container.getBondNumber(atom, parent)])
            {
                return(false);
            }
            int lengthAtom   = container.getConnectedAtoms(atom).Length + atom.getHydrogenCount();
            int lengthParent = container.getConnectedAtoms(parent).Length + parent.getHydrogenCount();

            if (container.getBond(atom, parent) != null)
            {
                if (container.getBond(atom, parent).Order == CDKConstants.BONDORDER_DOUBLE && (lengthAtom == 3 || (lengthAtom == 2 && atom.Symbol.Equals("N"))) && (lengthParent == 3 || (lengthParent == 2 && parent.Symbol.Equals("N"))))
                {
                    IAtom[] atoms = container.getConnectedAtoms(atom);
                    IAtom   one   = null;
                    IAtom   two   = null;
                    for (int i = 0; i < atoms.Length; i++)
                    {
                        if (atoms[i] != parent && one == null)
                        {
                            one = atoms[i];
                        }
                        else if (atoms[i] != parent && one != null)
                        {
                            two = atoms[i];
                        }
                    }
                    System.String[] morgannumbers = MorganNumbersTools.getMorganNumbersWithElementSymbol(container);
                    if ((one != null && two == null && atom.Symbol.Equals("N") && System.Math.Abs(giveAngleBothMethods(parent, atom, one, true)) > System.Math.PI / 10) || (!atom.Symbol.Equals("N") && one != null && two != null && !morgannumbers[container.getAtomNumber(one)].Equals(morgannumbers[container.getAtomNumber(two)])))
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            return(false);
        }
        /// <summary> Returns the currently maximum formable bond order for this atom.
        ///
        /// </summary>
        /// <param name="atom"> The atom to be checked
        /// </param>
        /// <param name="ac">   The AtomContainer that provides the context
        /// </param>
        /// <returns>       the currently maximum formable bond order for this atom
        /// </returns>
        public virtual double getCurrentMaxBondOrder(IAtom atom, IAtomContainer ac)
        {
            IAtomType[] atomTypes = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol);
            if (atomTypes.Length == 0)
            {
                return(0);
            }
            double bondOrderSum = ac.getBondOrderSum(atom);
            int    hcount       = atom.getHydrogenCount();
            double max          = 0;
            double current      = 0;

            for (int f = 0; f < atomTypes.Length; f++)
            {
                current = hcount + bondOrderSum;
                if (atomTypes[f].BondOrderSum - current > max)
                {
                    max = atomTypes[f].BondOrderSum - current;
                }
            }
            return(max);
        }
		/// <summary> Method that saturates an atom in a molecule by adding implicit hydrogens.
		/// 
		/// </summary>
		/// <param name="container"> Molecule to saturate
		/// </param>
		/// <param name="atom">     Atom to satureate.
		/// </param>
		/// <cdk.keyword>           hydrogen, adding </cdk.keyword>
		/// <cdk.keyword>           implicit hydrogen </cdk.keyword>
		public virtual int[] addImplicitHydrogensToSatisfyValency(IAtomContainer container, IAtom atom)
		{
			int formerHydrogens = atom.getHydrogenCount();
			int missingHydrogens = valencyChecker.calculateNumberOfImplicitHydrogens(atom, container);
			atom.setHydrogenCount(missingHydrogens);
			int[] hydrogens = new int[2];
			hydrogens[0] = formerHydrogens;
			hydrogens[1] = missingHydrogens;
			return hydrogens;
		}
        /// <summary> The method is known to fail for certain compounds. For more information, see
        /// cdk.test.limitations package.
        ///
        /// </summary>
        public virtual void  saturate(IAtomContainer atomContainer)
        {
            /* newSaturate(atomContainer);
             * }
             * public void oldSaturate(AtomContainer atomContainer) throws CDKException { */
            IAtom partner = null;
            IAtom atom    = null;

            IAtom[]     partners   = null;
            IAtomType[] atomTypes1 = null;
            IAtomType[] atomTypes2 = null;
            IBond       bond       = null;

            for (int i = 1; i < 4; i++)
            {
                // handle atoms with degree 1 first and then proceed to higher order
                for (int f = 0; f < atomContainer.AtomCount; f++)
                {
                    atom = atomContainer.getAtomAt(f);
                    //logger.debug("symbol: ", atom.Symbol);
                    atomTypes1 = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol);
                    if (atomTypes1.Length > 0)
                    {
                        //logger.debug("first atom type: ", atomTypes1[0]);
                        if (atomContainer.getBondCount(atom) == i)
                        {
                            if (atom.getFlag(CDKConstants.ISAROMATIC) && atomContainer.getBondOrderSum(atom) < atomTypes1[0].BondOrderSum - atom.getHydrogenCount())
                            {
                                partners = atomContainer.getConnectedAtoms(atom);
                                for (int g = 0; g < partners.Length; g++)
                                {
                                    partner = partners[g];
                                    //logger.debug("Atom has " + partners.Length + " partners");
                                    atomTypes2 = getAtomTypeFactory(atom.Builder).getAtomTypes(partner.Symbol);
                                    if (atomTypes2.Length == 0)
                                    {
                                        return;
                                    }
                                    if (atomContainer.getBond(partner, atom).getFlag(CDKConstants.ISAROMATIC) && atomContainer.getBondOrderSum(partner) < atomTypes2[0].BondOrderSum - partner.getHydrogenCount())
                                    {
                                        //logger.debug("Partner has " + atomContainer.getBondOrderSum(partner) + ", may have: " + atomTypes2[0].BondOrderSum);
                                        bond = atomContainer.getBond(atom, partner);
                                        //logger.debug("Bond order was " + bond.Order);
                                        bond.Order = bond.Order + 1;
                                        //logger.debug("Bond order now " + bond.Order);
                                        break;
                                    }
                                }
                            }
                            if (atomContainer.getBondOrderSum(atom) < atomTypes1[0].BondOrderSum - atom.getHydrogenCount())
                            {
                                //logger.debug("Atom has " + atomContainer.getBondOrderSum(atom) + ", may have: " + atomTypes1[0].BondOrderSum);
                                partners = atomContainer.getConnectedAtoms(atom);
                                for (int g = 0; g < partners.Length; g++)
                                {
                                    partner = partners[g];
                                    //logger.debug("Atom has " + partners.Length + " partners");
                                    atomTypes2 = getAtomTypeFactory(atom.Builder).getAtomTypes(partner.Symbol);
                                    if (atomTypes2.Length == 0)
                                    {
                                        return;
                                    }
                                    if (atomContainer.getBondOrderSum(partner) < atomTypes2[0].BondOrderSum - partner.getHydrogenCount())
                                    {
                                        //logger.debug("Partner has " + atomContainer.getBondOrderSum(partner) + ", may have: " + atomTypes2[0].BondOrderSum);
                                        bond = atomContainer.getBond(atom, partner);
                                        //logger.debug("Bond order was " + bond.Order);
                                        bond.Order = bond.Order + 1;
                                        //logger.debug("Bond order now " + bond.Order);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #13
0
        /// <summary> Produces an AtomContainer without explicit Hs but with H count from one with Hs.
        /// The new molecule is a deep copy.
        ///
        /// </summary>
        /// <param name="atomContainer">The AtomContainer from which to remove the hydrogens
        /// </param>
        /// <returns>              The molecule without Hs.
        /// </returns>
        /// <cdk.keyword>          hydrogen, removal </cdk.keyword>
        public static IAtomContainer removeHydrogens(IAtomContainer atomContainer)
        {
            //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilHashMap'"
            System.Collections.IDictionary map    = new System.Collections.Hashtable(); // maps original atoms to clones.
            System.Collections.IList       remove = new System.Collections.ArrayList(); // lists removed Hs.

            // Clone atoms except those to be removed.
            IMolecule mol   = atomContainer.Builder.newMolecule();
            int       count = atomContainer.AtomCount;

            for (int i = 0; i < count; i++)
            {
                // Clone/remove this atom?
                IAtom atom = atomContainer.getAtomAt(i);
                if (!atom.Symbol.Equals("H"))
                {
                    IAtom clonedAtom = null;
                    try
                    {
                        clonedAtom = (IAtom)atom.Clone();
                    }
                    //UPGRADE_NOTE: Exception 'java.lang.CloneNotSupportedException' was converted to 'System.Exception' which has different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1100'"
                    catch (System.Exception e)
                    {
                        // TODO Auto-generated catch block
                        SupportClass.WriteStackTrace(e, Console.Error);
                    }
                    clonedAtom.setHydrogenCount(0);
                    mol.addAtom(clonedAtom);
                    map[atom] = clonedAtom;
                }
                else
                {
                    remove.Add(atom); // maintain list of removed H.
                }
            }

            // Clone bonds except those involving removed atoms.
            count = atomContainer.getBondCount();
            for (int i = 0; i < count; i++)
            {
                // Check bond.
                //UPGRADE_NOTE: Final was removed from the declaration of 'bond '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                IBond   bond        = atomContainer.getBondAt(i);
                IAtom[] atoms       = bond.getAtoms();
                bool    removedBond = false;
                //UPGRADE_NOTE: Final was removed from the declaration of 'length '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                int length = atoms.Length;
                for (int k = 0; k < length; k++)
                {
                    if (remove.Contains(atoms[k]))
                    {
                        removedBond = true;
                        break;
                    }
                }

                // Clone/remove this bond?
                if (!removedBond)
                // if (!remove.contains(atoms[0]) && !remove.contains(atoms[1]))
                {
                    IBond clone = null;
                    try
                    {
                        clone = (IBond)atomContainer.getBondAt(i).Clone();
                    }
                    //UPGRADE_NOTE: Exception 'java.lang.CloneNotSupportedException' was converted to 'System.Exception' which has different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1100'"
                    catch (System.Exception e)
                    {
                        // TODO Auto-generated catch block
                        SupportClass.WriteStackTrace(e, Console.Error);
                    }
                    clone.setAtoms(new IAtom[] { (IAtom)map[atoms[0]], (IAtom)map[atoms[1]] });
                    mol.addBond(clone);
                }
            }

            // Recompute hydrogen counts of neighbours of removed Hydrogens.
            //UPGRADE_TODO: Method 'java.util.Iterator.hasNext' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratorhasNext'"
            for (System.Collections.IEnumerator i = remove.GetEnumerator(); i.MoveNext();)
            {
                // Process neighbours.
                //UPGRADE_TODO: Method 'java.util.Iterator.next' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratornext'"
                //UPGRADE_TODO: Method 'java.util.Iterator.hasNext' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratorhasNext'"
                for (System.Collections.IEnumerator n = atomContainer.getConnectedAtomsVector((IAtom)i.Current).GetEnumerator(); n.MoveNext();)
                {
                    //UPGRADE_NOTE: Final was removed from the declaration of 'neighb '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                    //UPGRADE_TODO: Method 'java.util.Iterator.next' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilIteratornext'"
                    IAtom neighb = (IAtom)map[n.Current];
                    neighb.setHydrogenCount(neighb.getHydrogenCount() + 1);
                }
            }
            mol.Properties = atomContainer.Properties;
            mol.Flags      = atomContainer.Flags;

            return(mol);
        }
		/// <summary> Checks wether an Atom is saturated by comparing it with known AtomTypes.
		/// It returns true if the atom is an PseudoAtom and when the element is not in the list.
		/// </summary>
		public virtual bool isSaturated(IAtom atom, IAtomContainer container)
		{
			if (atom is IPseudoAtom)
			{
				//logger.debug("don't figure it out... it simply does not lack H's");
				return true;
			}
			
			IAtomType[] atomTypes = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol);
			if (atomTypes.Length == 0)
			{
				//logger.warn("Missing entry in atom type list for ", atom.Symbol);
				return true;
			}
			double bondOrderSum = container.getBondOrderSum(atom);
			double maxBondOrder = container.getMaximumBondOrder(atom);
			int hcount = atom.getHydrogenCount();
			int charge = atom.getFormalCharge();
			
			//logger.debug("Checking saturation of atom ", atom.Symbol);
			//logger.debug("bondOrderSum: ", bondOrderSum);
			//logger.debug("maxBondOrder: ", maxBondOrder);
			//logger.debug("hcount: ", hcount);
			//logger.debug("charge: ", charge);
			
			bool elementPlusChargeMatches = false;
			for (int f = 0; f < atomTypes.Length; f++)
			{
				IAtomType type = atomTypes[f];
				if (couldMatchAtomType(atom, bondOrderSum, maxBondOrder, type))
				{
					if (bondOrderSum + hcount == type.BondOrderSum && maxBondOrder <= type.MaxBondOrder)
					{
						//logger.debug("We have a match: ", type);
						//logger.debug("Atom is saturated: ", atom.Symbol);
						return true;
					}
					else
					{
						// ok, the element and charge matche, but unfulfilled
						elementPlusChargeMatches = true;
					}
				} // else: formal charges don't match
			}
			
			if (elementPlusChargeMatches)
			{
				//logger.debug("No, atom is not saturated.");
				return false;
			}
			
			// ok, the found atom was not in the list
			throw new CDKException("The atom with element " + atom.Symbol + " and charge " + charge + " is not found.");
		}
		/// <summary> Determines if the atom can be of type AtomType. That is, it sees if this
		/// AtomType only differs in bond orders, or implicit hydrogen count.
		/// </summary>
		public virtual bool couldMatchAtomType(IAtom atom, double bondOrderSum, double maxBondOrder, IAtomType type)
		{
			//logger.debug("couldMatchAtomType:   ... matching atom ", atom, " vs ", type);
			int hcount = atom.getHydrogenCount();
			int charge = atom.getFormalCharge();
			if (charge == type.getFormalCharge())
			{
				//logger.debug("couldMatchAtomType:     formal charge matches...");
				if (atom.Hybridization == type.Hybridization)
				{
					//logger.debug("couldMatchAtomType:     hybridization is OK...");
					if (bondOrderSum + hcount <= type.BondOrderSum)
					{
						//logger.debug("couldMatchAtomType:     bond order sum is OK...");
						if (maxBondOrder <= type.MaxBondOrder)
						{
							//logger.debug("couldMatchAtomType:     max bond order is OK... We have a match!");
							return true;
						}
					}
					else
					{
						//logger.debug("couldMatchAtomType:      no match", "" + (bondOrderSum + hcount), " > ", "" + type.BondOrderSum);
					}
				}
			}
			else
			{
				//logger.debug("couldMatchAtomType:     formal charge does NOT match...");
			}
			//logger.debug("couldMatchAtomType:    No Match");
			return false;
		}
 /// <summary>  Says if an atom is the start of a double bond configuration
 /// 
 /// </summary>
 /// <param name="a">                       The atom which is the start of configuration
 /// </param>
 /// <param name="container">               The atomContainer the atom is in
 /// </param>
 /// <param name="parent">                  The atom we came from
 /// </param>
 /// <param name="doubleBondConfiguration"> The array indicating where double bond
 /// configurations are specified (this method ensures that there is
 /// actually the possibility of a double bond configuration)
 /// </param>
 /// <returns>                          false=is not start of configuration, true=is
 /// </returns>
 private bool isStartOfDoubleBond(IAtomContainer container, IAtom a, IAtom parent, bool[] doubleBondConfiguration)
 {
     int lengthAtom = container.getConnectedAtoms(a).Length + a.getHydrogenCount();
     if (lengthAtom != 3 && (lengthAtom != 2 && (System.Object)a.Symbol != (System.Object)("N")))
     {
         return (false);
     }
     IAtom[] atoms = container.getConnectedAtoms(a);
     IAtom one = null;
     IAtom two = null;
     bool doubleBond = false;
     IAtom nextAtom = null;
     for (int i = 0; i < atoms.Length; i++)
     {
         if (atoms[i] != parent && container.getBond(atoms[i], a).Order == CDKConstants.BONDORDER_DOUBLE && isEndOfDoubleBond(container, atoms[i], a, doubleBondConfiguration))
         {
             doubleBond = true;
             nextAtom = atoms[i];
         }
         if (atoms[i] != nextAtom && one == null)
         {
             one = atoms[i];
         }
         else if (atoms[i] != nextAtom && one != null)
         {
             two = atoms[i];
         }
     }
     System.String[] morgannumbers = MorganNumbersTools.getMorganNumbersWithElementSymbol(container);
     if (one != null && ((!a.Symbol.Equals("N") && two != null && !morgannumbers[container.getAtomNumber(one)].Equals(morgannumbers[container.getAtomNumber(two)]) && doubleBond && doubleBondConfiguration[container.getBondNumber(a, nextAtom)]) || (doubleBond && a.Symbol.Equals("N") && System.Math.Abs(BondTools.giveAngleBothMethods(nextAtom, a, parent, true)) > System.Math.PI / 10)))
     {
         return (true);
     }
     else
     {
         return (false);
     }
 }
 /// <summary>  Says if an atom is the end of a double bond configuration
 /// 
 /// </summary>
 /// <param name="atom">                    The atom which is the end of configuration
 /// </param>
 /// <param name="container">               The atomContainer the atom is in
 /// </param>
 /// <param name="parent">                  The atom we came from
 /// </param>
 /// <param name="doubleBondConfiguration"> The array indicating where double bond
 /// configurations are specified (this method ensures that there is
 /// actually the possibility of a double bond configuration)
 /// </param>
 /// <returns>                          false=is not end of configuration, true=is
 /// </returns>
 private bool isEndOfDoubleBond(IAtomContainer container, IAtom atom, IAtom parent, bool[] doubleBondConfiguration)
 {
     if (container.getBondNumber(atom, parent) == -1 || doubleBondConfiguration.Length <= container.getBondNumber(atom, parent) || !doubleBondConfiguration[container.getBondNumber(atom, parent)])
     {
         return false;
     }
     int lengthAtom = container.getConnectedAtoms(atom).Length + atom.getHydrogenCount();
     int lengthParent = container.getConnectedAtoms(parent).Length + parent.getHydrogenCount();
     if (container.getBond(atom, parent) != null)
     {
         if (container.getBond(atom, parent).Order == CDKConstants.BONDORDER_DOUBLE && (lengthAtom == 3 || (lengthAtom == 2 && atom.Symbol.Equals("N"))) && (lengthParent == 3 || (lengthParent == 2 && parent.Symbol.Equals("N"))))
         {
             IAtom[] atoms = container.getConnectedAtoms(atom);
             IAtom one = null;
             IAtom two = null;
             for (int i = 0; i < atoms.Length; i++)
             {
                 if (atoms[i] != parent && one == null)
                 {
                     one = atoms[i];
                 }
                 else if (atoms[i] != parent && one != null)
                 {
                     two = atoms[i];
                 }
             }
             System.String[] morgannumbers = MorganNumbersTools.getMorganNumbersWithElementSymbol(container);
             if ((one != null && two == null && atom.Symbol.Equals("N") && System.Math.Abs(BondTools.giveAngleBothMethods(parent, atom, one, true)) > System.Math.PI / 10) || (!atom.Symbol.Equals("N") && one != null && two != null && !morgannumbers[container.getAtomNumber(one)].Equals(morgannumbers[container.getAtomNumber(two)])))
             {
                 return (true);
             }
             else
             {
                 return (false);
             }
         }
     }
     return (false);
 }
		/// <summary> Determines if the atom can be of type AtomType.</summary>
		public virtual bool couldMatchAtomType(IAtomContainer atomContainer, IAtom atom, IAtomType atomType)
		{
			//logger.debug("   ... matching atom ", atom.Symbol, " vs ", atomType);
			if (atomContainer.getBondOrderSum(atom) + atom.getHydrogenCount() < atomType.BondOrderSum)
			{
				//logger.debug("    Match!");
				return true;
			}
			//logger.debug("    No Match");
			return false;
		}
		/// <summary> Returns the currently maximum formable bond order for this atom.
		/// 
		/// </summary>
		/// <param name="atom"> The atom to be checked
		/// </param>
		/// <param name="ac">   The AtomContainer that provides the context
		/// </param>
		/// <returns>       the currently maximum formable bond order for this atom
		/// </returns>
		public virtual double getCurrentMaxBondOrder(IAtom atom, IAtomContainer ac)
		{
			IAtomType[] atomTypes = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol);
			if (atomTypes.Length == 0)
				return 0;
			double bondOrderSum = ac.getBondOrderSum(atom);
			int hcount = atom.getHydrogenCount();
			double max = 0;
			double current = 0;
			for (int f = 0; f < atomTypes.Length; f++)
			{
				current = hcount + bondOrderSum;
				if (atomTypes[f].BondOrderSum - current > max)
				{
					max = atomTypes[f].BondOrderSum - current;
				}
			}
			return max;
		}
		/// <summary> Checks if the current atom has exceeded its bond order sum value.
		/// 
		/// </summary>
		/// <param name="atom">The Atom to check
		/// </param>
		/// <param name="ac">  The atomcontainer context
		/// </param>
		/// <returns>      oversaturated or not
		/// </returns>
		public virtual bool isOverSaturated(IAtom atom, IAtomContainer ac)
		{
			IAtomType[] atomTypes = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol);
			if (atomTypes.Length == 0)
				return false;
			double bondOrderSum = ac.getBondOrderSum(atom);
			double maxBondOrder = ac.getMaximumBondOrder(atom);
			int hcount = atom.getHydrogenCount();
			int charge = atom.getFormalCharge();
			try
			{
				//logger.debug("*** Checking saturation of atom " + ac.getAtomNumber(atom) + " ***");
				//logger.debug("bondOrderSum: " + bondOrderSum);
				//logger.debug("maxBondOrder: " + maxBondOrder);
				//logger.debug("hcount: " + hcount);
			}
			catch (System.Exception exc)
			{
			}
			for (int f = 0; f < atomTypes.Length; f++)
			{
				if (bondOrderSum - charge + hcount > atomTypes[f].BondOrderSum)
				{
					//logger.debug("*** Good ! ***");
					return true;
				}
			}
			//logger.debug("*** Bad ! ***");
			return false;
		}
		/// <summary> Determines if the atom can be of type AtomType.</summary>
		public virtual bool couldMatchAtomType(IAtom atom, double bondOrderSum, double maxBondOrder, IAtomType type)
		{
			//logger.debug("   ... matching atom ", atom.Symbol, " vs ", type);
			int hcount = atom.getHydrogenCount();
			int charge = atom.getFormalCharge();
			if (charge == type.getFormalCharge())
			{
				if (bondOrderSum + hcount <= type.BondOrderSum && maxBondOrder <= type.MaxBondOrder)
				{
					//logger.debug("    We have a match!");
					return true;
				}
			}
			//logger.debug("    No Match");
			return false;
		}