/// <summary> /// Get integer FormalCharge for an atom /// </summary> /// <param name="atom"></param> /// <returns></returns> public static int GetFormalCharge(IAtom atom) { if (atom.getFormalCharge() == null) { return(0); } else { return(atom.getFormalCharge().intValue()); } }
/// <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> Calculate the number of missing hydrogens by substracting the number of /// bonds for the atom from the expected number of bonds. Charges are included /// in the calculation. The number of expected bonds is defined by the AtomType /// generated with the AtomTypeFactory. /// /// </summary> /// <param name="atom"> Description of the Parameter /// </param> /// <param name="throwExceptionForUnknowAtom"> Should an exception be thrown if an unknown atomtype is found or 0 returned ? /// </param> /// <returns> Description of the Return Value /// </returns> /// <seealso cref="AtomTypeFactory"> /// </seealso> public virtual int calculateNumberOfImplicitHydrogens(IAtom atom, double bondOrderSum, IBond[] connectedBonds, bool throwExceptionForUnknowAtom) { int missingHydrogen = 0; if (atom is IPseudoAtom) { // don't figure it out... it simply does not lack H's } else if (atom.AtomicNumber == 1 || atom.Symbol.Equals("H")) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" missingHydrogen = (int)(1 - bondOrderSum - atom.getFormalCharge()); } else { //logger.info("Calculating number of missing hydrogen atoms"); // get default atom IAtomType[] atomTypes = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol); if (atomTypes.Length == 0 && throwExceptionForUnknowAtom) { return(0); } //logger.debug("Found atomtypes: " + atomTypes.Length); if (atomTypes.Length > 0) { IAtomType defaultAtom = atomTypes[0]; //logger.debug("DefAtom: ", defaultAtom); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" missingHydrogen = (int)(defaultAtom.BondOrderSum - bondOrderSum + atom.getFormalCharge()); if (atom.getFlag(CDKConstants.ISAROMATIC)) { bool subtractOne = true; for (int i = 0; i < connectedBonds.Length; i++) { if (connectedBonds[i].Order == 2 || connectedBonds[i].Order == CDKConstants.BONDORDER_AROMATIC) { subtractOne = false; } } if (subtractOne) { missingHydrogen--; } } //logger.debug("Atom: ", atom.Symbol); //logger.debug(" max bond order: " + defaultAtom.BondOrderSum); //logger.debug(" bond order sum: " + bondOrderSum); //logger.debug(" charge : " + atom.getFormalCharge()); } else { //logger.warn("Could not find atom type for ", atom.Symbol); } } return(missingHydrogen); }
/// <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(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); }
/// <summary> Writes a Molecule to an OutputStream in MDL sdf format. /// /// </summary> /// <param name="container"> Molecule that is written to an OutputStream /// </param> /// <param name="isVisible">Should a certain atom be written to mdl? /// </param> public virtual void writeMolecule(IMolecule container, bool[] isVisible) { System.String line = ""; // taking care of the $$$$ signs: // we do not write such a sign at the end of the first molecule, thus we have to write on BEFORE the second molecule if (moleculeNumber == 2) { writer.Write("$$$$"); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); } // write header block // lines get shortened to 80 chars, that's in the spec System.String title = (System.String)container.getProperty(CDKConstants.TITLE); if (title == null) { title = ""; } if (title.Length > 80) { title = title.Substring(0, (80) - (0)); } writer.Write(title + "\n"); /* From CTX spec * This line has the format: * IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR * (FORTRAN: A2<--A8--><---A10-->A2I2<--F10.5-><---F12.5--><-I6-> ) * User's first and last initials (l), program name (P), * date/time (M/D/Y,H:m), dimensional codes (d), scaling factors (S, s), * energy (E) if modeling program input, internal registry number (R) * if input through MDL form. * A blank line can be substituted for line 2. */ writer.Write(" CDK "); //UPGRADE_ISSUE: Constructor 'java.text.SimpleDateFormat.SimpleDateFormat' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javatextSimpleDateFormat'" //UPGRADE_TODO: The equivalent in .NET for method 'java.util.Calendar.getTime' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'" System.TimeZone generatedAux3 = System.TimeZone.CurrentTimeZone; //writer.Write(SupportClass.FormatDateTime(new SimpleDateFormat("M/d/y,H:m", new System.Globalization.CultureInfo("en-US")), SupportClass.CalendarManager.manager.GetDateTime(new System.Globalization.GregorianCalendar()))); writer.Write('\n'); System.String comment = (System.String)container.getProperty(CDKConstants.REMARK); if (comment == null) { comment = ""; } if (comment.Length > 80) { comment = comment.Substring(0, (80) - (0)); } writer.Write(comment + "\n"); // write Counts line int upToWhichAtom = 0; for (int i = 0; i < isVisible.Length; i++) { if (isVisible[i]) { upToWhichAtom++; } } line += formatMDLInt(upToWhichAtom, 3); int numberOfBonds = 0; if (upToWhichAtom < container.AtomCount) { for (int i = 0; i < container.getBondCount(); i++) { if (isVisible[container.getAtomNumber(container.getBondAt(i).getAtoms()[0])] && isVisible[container.getAtomNumber(container.getBondAt(i).getAtoms()[1])]) { numberOfBonds++; } } } else { numberOfBonds = container.getBondCount(); } line += formatMDLInt(numberOfBonds, 3); line += " 0 0 0 0 0 0 0 0999 V2000\n"; writer.Write(line); // write Atom block IAtom[] atoms = container.Atoms; for (int f = 0; f < atoms.Length; f++) { if (isVisible[f]) { IAtom atom = atoms[f]; line = ""; if (atom.getPoint3d() != null) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" line += formatMDLFloat((float)atom.X3d); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" line += formatMDLFloat((float)atom.Y3d); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" line += (formatMDLFloat((float)atom.Z3d) + " "); } else if (atom.getPoint2d() != null) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" line += formatMDLFloat((float)atom.X2d); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" line += formatMDLFloat((float)atom.Y2d); line += " 0.0000 "; } else { // if no coordinates available, then output a number // of zeros line += formatMDLFloat((float)0.0); line += formatMDLFloat((float)0.0); line += (formatMDLFloat((float)0.0) + " "); } if (container.getAtomAt(f) is IPseudoAtom) { line += formatMDLString(((IPseudoAtom)container.getAtomAt(f)).Label, 3); } else { line += formatMDLString(container.getAtomAt(f).Symbol, 3); } line += " 0 0 0 0 0 0 0 0 0 0 0 0"; writer.Write(line); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); } } // write Bond block IBond[] bonds = container.Bonds; for (int g = 0; g < bonds.Length; g++) { if (upToWhichAtom == container.AtomCount || (isVisible[container.getAtomNumber(container.getBondAt(g).getAtoms()[0])] && isVisible[container.getAtomNumber(container.getBondAt(g).getAtoms()[1])])) { IBond bond = bonds[g]; if (bond.getAtoms().Length != 2) { //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Object.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'" //logger.warn("Skipping bond with more/less than two atoms: " + bond); } else { if (bond.Stereo == CDKConstants.STEREO_BOND_UP_INV || bond.Stereo == CDKConstants.STEREO_BOND_DOWN_INV) { // turn around atom coding to correct for inv stereo line = formatMDLInt(container.getAtomNumber(bond.getAtomAt(1)) + 1, 3); line += formatMDLInt(container.getAtomNumber(bond.getAtomAt(0)) + 1, 3); } else { line = formatMDLInt(container.getAtomNumber(bond.getAtomAt(0)) + 1, 3); line += formatMDLInt(container.getAtomNumber(bond.getAtomAt(1)) + 1, 3); } //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" line += formatMDLInt((int)bond.Order, 3); line += " "; switch (bond.Stereo) { case CDKConstants.STEREO_BOND_UP: line += "1"; break; case CDKConstants.STEREO_BOND_UP_INV: line += "1"; break; case CDKConstants.STEREO_BOND_DOWN: line += "6"; break; case CDKConstants.STEREO_BOND_DOWN_INV: line += "6"; break; default: line += "0"; break; } line += " 0 0 0 "; writer.Write(line); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); } } } // write formal atomic charges for (int i = 0; i < atoms.Length; i++) { IAtom atom = atoms[i]; int charge = atom.getFormalCharge(); if (charge != 0) { writer.Write("M CHG 1 "); writer.Write(formatMDLInt(i + 1, 3)); writer.Write(" "); writer.Write(formatMDLInt(charge, 3)); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); } } // write formal isotope information for (int i = 0; i < atoms.Length; i++) { IAtom atom = atoms[i]; if (!(atom is IPseudoAtom)) { int atomicMass = atom.MassNumber; int majorMass = IsotopeFactory.getInstance(atom.Builder).getMajorIsotope(atom.Symbol).MassNumber; if (atomicMass != 0 && atomicMass != majorMass) { writer.Write("M ISO 1 "); writer.Write(formatMDLInt(i + 1, 3)); writer.Write(" "); writer.Write(formatMDLInt(atomicMass, 3)); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); } } } // close molecule writer.Write("M END"); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); //write sdfields, if any if (sdFields != null) { //UPGRADE_TODO: Method 'java.util.Map.keySet' was converted to 'CSGraphT.SupportClass.HashSetSupport' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilMapkeySet'" CSGraphT.SupportClass.SetSupport set_Renamed = new CSGraphT.SupportClass.HashSetSupport(sdFields.Keys); System.Collections.IEnumerator iterator = set_Renamed.GetEnumerator(); //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'" while (iterator.MoveNext()) { //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'" System.Object element = iterator.Current; writer.Write("> <" + ((System.String)element) + ">"); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Object.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'" writer.Write(sdFields[element].ToString()); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); } } // taking care of the $$$$ signs: // we write such a sign at the end of all except the first molecule if (moleculeNumber != 1) { writer.Write("$$$$"); //UPGRADE_TODO: Method 'java.io.BufferedWriter.newLine' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" writer.WriteLine(); } moleculeNumber++; writer.Flush(); }
/// <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> Creates a string for the charge of atom <code>a</code>. If the charge is 1 /// + is returned if it is -1 - is returned. The positive values all have + in /// front of them. /// /// </summary> /// <param name="a"> Description of Parameter /// </param> /// <returns> string representing the charge on <code>a</code> /// </returns> private System.String generateChargeString(IAtom a) { int charge = a.getFormalCharge(); System.Text.StringBuilder buffer = new System.Text.StringBuilder(3); if (charge > 0) { //Positive buffer.Append('+'); if (charge > 1) { buffer.Append(charge); } } else if (charge < 0) { //Negative if (charge == -1) { buffer.Append('-'); } else { buffer.Append(charge); } } return buffer.ToString(); }
/// <summary> Tests the <code>ring</code> in the <code>molecule</code> for aromaticity. Uses the /// Hückle rule (4n + 2) pie electrons. sp<sup>2</sup> hybridized C contibute 1 electron non /// sp<sup>2</sup> hybridized heteroatoms contribute 2 electrons (N and O should never be sp in /// or anything else in a ring and d electron elements get to complicated) /// sp<sup>2</sup> hybridized heteroatoms contribute 1 electron hybridization is worked out by /// counting the number of bonds with order 2. Therefore sp<sup>2</sup> hybridization is assumed /// if there is one bond of order 2. Otherwise sp<sup>3</sup> hybridization is assumed. /// /// </summary> /// <param name="ring"> the ring to test /// </param> /// <param name="atomContainer"> the AtomContainer the ring is in /// </param> /// <returns> true if the ring is aromatic false otherwise. /// </returns> protected internal static bool isAromatic(IRing ring, IAtomContainer atomContainer) { IAtom[] ringAtoms = ring.Atoms; int eCount = 0; IBond[] conectedBonds; int numDoubleBond = 0; bool allConnectedBondsSingle; for (int i = 0; i < ringAtoms.Length; i++) { IAtom atom = ringAtoms[i]; numDoubleBond = 0; allConnectedBondsSingle = true; conectedBonds = atomContainer.getConnectedBonds(atom); for (int j = 0; j < conectedBonds.Length; j++) { IBond bond = conectedBonds[j]; if (bond.Order == 2 && ring.contains(bond)) { numDoubleBond++; } // Count the Electron if bond order = 1.5 else if (bond.Order == 1.5 && ring.contains(bond)) { numDoubleBond = 1; } if (bond.Order != 1) { allConnectedBondsSingle = false; } } if (numDoubleBond == 1) { //C or heteroatoms both contibute 1 electron in sp2 hybridized form eCount++; } else if (!atom.Symbol.Equals("C")) { //Heteroatom probably in sp3 hybrid therefore 2 electrons contributed. eCount = eCount + 2; } else if (atom.getFlag(CDKConstants.ISAROMATIC)) { eCount++; } else if (allConnectedBondsSingle && atom.Symbol.Equals("C") && atom.getFormalCharge() == 1.0) { // This is for tropylium and kinds. // Dependence on hybridisation would be better: // empty p-orbital is needed continue; } else { return(false); } } if (eCount - 2 != 0 && (eCount - 2) % 4 == 0) { return(true); } return(false); }
/// <summary> Calculate the number of missing hydrogens by substracting the number of /// bonds for the atom from the expected number of bonds. Charges are included /// in the calculation. The number of expected bonds is defined by the AtomType /// generated with the AtomTypeFactory. /// /// </summary> /// <param name="atom"> Description of the Parameter /// </param> /// <param name="throwExceptionForUnknowAtom"> Should an exception be thrown if an unknown atomtype is found or 0 returned ? /// </param> /// <returns> Description of the Return Value /// </returns> /// <seealso cref="AtomTypeFactory"> /// </seealso> public virtual int calculateNumberOfImplicitHydrogens(IAtom atom, double bondOrderSum, IBond[] connectedBonds, bool throwExceptionForUnknowAtom) { int missingHydrogen = 0; if (atom is IPseudoAtom) { // don't figure it out... it simply does not lack H's } else if (atom.AtomicNumber == 1 || atom.Symbol.Equals("H")) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" missingHydrogen = (int) (1 - bondOrderSum - atom.getFormalCharge()); } else { //logger.info("Calculating number of missing hydrogen atoms"); // get default atom IAtomType[] atomTypes = getAtomTypeFactory(atom.Builder).getAtomTypes(atom.Symbol); if (atomTypes.Length == 0 && throwExceptionForUnknowAtom) return 0; //logger.debug("Found atomtypes: " + atomTypes.Length); if (atomTypes.Length > 0) { IAtomType defaultAtom = atomTypes[0]; //logger.debug("DefAtom: ", defaultAtom); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" missingHydrogen = (int) (defaultAtom.BondOrderSum - bondOrderSum + atom.getFormalCharge()); if (atom.getFlag(CDKConstants.ISAROMATIC)) { bool subtractOne = true; for (int i = 0; i < connectedBonds.Length; i++) { if (connectedBonds[i].Order == 2 || connectedBonds[i].Order == CDKConstants.BONDORDER_AROMATIC) subtractOne = false; } if (subtractOne) missingHydrogen--; } //logger.debug("Atom: ", atom.Symbol); //logger.debug(" max bond order: " + defaultAtom.BondOrderSum); //logger.debug(" bond order sum: " + bondOrderSum); //logger.debug(" charge : " + atom.getFormalCharge()); } else { //logger.warn("Could not find atom type for ", atom.Symbol); } } return missingHydrogen; }
/// <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; }