/// <summary> /// Determines if the atom can be of type <see cref="IAtomType"/>. That is, it sees if this /// <see cref="IAtomType"/> only differs in bond orders, or implicit hydrogen count. /// </summary> private static bool CouldMatchAtomType(IAtomContainer container, IAtom atom, IAtomType type) { var bondOrderSum = container.GetBondOrderSum(atom); var maxBondOrder = container.GetMaximumBondOrder(atom); return(CouldMatchAtomType(atom, bondOrderSum, maxBondOrder, type)); }
public bool IsSaturated(IAtom atom, IAtomContainer container) { var type = atomTypeList.GetAtomType(atom.AtomTypeName); if (type == null) { throw new CDKException($"Atom type is not a recognized CDK atom type: {atom.AtomTypeName}"); } if (type.FormalNeighbourCount == null) { throw new CDKException($"Atom type is too general; cannot decide the number of implicit hydrogen to add for: {atom.AtomTypeName}"); } if (type.GetProperty <object>(CDKPropertyName.PiBondCount) == null) { throw new CDKException($"Atom type is too general; cannot determine the number of pi bonds for: {atom.AtomTypeName}"); } var bondOrderSum = container.GetBondOrderSum(atom); var maxBondOrder = container.GetMaximumBondOrder(atom); int?hcount = atom.ImplicitHydrogenCount == null ? 0 : atom.ImplicitHydrogenCount; int piBondCount = type.GetProperty <int?>(CDKPropertyName.PiBondCount).Value; int formalNeighborCount = type.FormalNeighbourCount.Value; int typeMaxBondOrder = piBondCount + 1; int typeBondOrderSum = formalNeighborCount + piBondCount; if (bondOrderSum + hcount == typeBondOrderSum && maxBondOrder.Numeric() <= typeMaxBondOrder) { return(true); } 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 atom container context</param> /// <returns>oversaturated or not</returns> public bool IsOverSaturated(IAtom atom, IAtomContainer ac) { var atomTypes = structgenATF.GetAtomTypes(atom.Symbol); if (!atomTypes.Any()) { return(false); } var bondOrderSum = ac.GetBondOrderSum(atom); var maxBondOrder = ac.GetMaximumBondOrder(atom); var hcount = atom.ImplicitHydrogenCount ?? 0; var charge = atom.FormalCharge ?? 0; try { Debug.WriteLine($"*** Checking saturation of atom {ac.Atoms.IndexOf(atom)} ***"); Debug.WriteLine($"bondOrderSum: {bondOrderSum}"); Debug.WriteLine($"maxBondOrder: {maxBondOrder}"); Debug.WriteLine($"hcount: {hcount}"); } catch (Exception) { } foreach (var atomType in atomTypes) { if (bondOrderSum - charge + hcount > atomType.BondOrderSum) { Debug.WriteLine("*** Good ! ***"); return(true); } } Debug.WriteLine("*** Bad ! ***"); return(false); }
/// <summary> /// Function to set up an array of integers corresponding to indicate how many free valencies need fulfilling for each atom through ring bonds. /// </summary> /// <returns>The List of free valencies available for extra ring bonding</returns> private static List <int> GetFreeValenciesForRingGroup(IAtomContainer molecule, List <int> atomsToCheck, Matrix M, IRingSet rs) { List <int> fvtc = new List <int>(); for (int i = 0; i < atomsToCheck.Count; i++) { int j = atomsToCheck[i]; //Put in an implicit hydrogen atom for Planar3 C- atoms in 5-membered rings (it doesn't get put in by the Smiles parser) if (string.Equals("C", molecule.Atoms[j].Symbol, StringComparison.Ordinal) && (molecule.Atoms[j].Hybridization == Hybridization.Planar3)) { //Check that ring containing the atom is five-membered foreach (var ac in rs) { if (ac.Contains(molecule.Atoms[j])) { if ((int)molecule.GetBondOrderSum(molecule.Atoms[j]) == 2 && ac.Atoms.Count == 5) { molecule.Atoms[j].ImplicitHydrogenCount = 1; break; } } } } int implicitH = 0; if (!molecule.Atoms[j].ImplicitHydrogenCount.HasValue) { var ha = CDK.HydrogenAdder; try { ha.AddImplicitHydrogens(molecule, molecule.Atoms[j]); implicitH = molecule.Atoms[j].ImplicitHydrogenCount.Value; } catch (CDKException) { //No need to do anything because implicitH already set to 0 } } else { implicitH = molecule.Atoms[j].ImplicitHydrogenCount.Value; } fvtc.Add(molecule.Atoms[j].Valency.Value - (implicitH + (int)molecule.GetBondOrderSum(molecule.Atoms[j])) + M.SumOfRow(i)); } return(fvtc); }
// the Molecule tests private static ValidationReport ValidateBondOrderSum(IAtom atom, IAtomContainer molecule) { var report = new ValidationReport(); var checkBondSum = new ValidationTest(atom, "The atom's total bond order is too high."); try { var structgenATF = CDK.CdkAtomTypeFactory; int bos = (int)molecule.GetBondOrderSum(atom); var atomTypes = structgenATF.GetAtomTypes(atom.Symbol).ToReadOnlyList(); if (atomTypes.Count == 0) { checkBondSum.Details = $"Cannot validate bond order sum for atom not in valency atom type list: {atom.Symbol}"; report.Warnings.Add(checkBondSum); } else { IAtomType failedOn = null; bool foundMatchingAtomType = false; foreach (var type in atomTypes) { if (atom.FormalCharge == type.FormalCharge) { foundMatchingAtomType = true; if (bos == type.BondOrderSum) { // skip this atom type } else { failedOn = type; } } } if (foundMatchingAtomType) { report.OKs.Add(checkBondSum); } else { if (failedOn != null) { checkBondSum.Details = $"Bond order exceeds the one allowed for atom {atom.Symbol} for which the total bond order is {failedOn.BondOrderSum}"; } else { } report.Errors.Add(checkBondSum); } } } catch (Exception exception) { Trace.TraceError($"Error while performing atom bos validation: {exception.Message}"); Debug.WriteLine(exception); } return(report); }
/// <summary> /// Checks whether an atom is saturated by comparing it with known atom types. /// </summary> /// <returns><see langword="true"/> if the atom is an pseudo atom and when the element is not in the list.</returns> public bool IsSaturated(IAtom atom, IAtomContainer container) { if (atom is IPseudoAtom) { Debug.WriteLine("don't figure it out... it simply does not lack H's"); return(true); } var atomTypes = structgenATF.GetAtomTypes(atom.Symbol); if (atomTypes.Any()) { Trace.TraceWarning($"Missing entry in atom type list for {atom.Symbol}"); return(true); } var bondOrderSum = container.GetBondOrderSum(atom); var maxBondOrder = container.GetMaximumBondOrder(atom); var hcount = atom.ImplicitHydrogenCount.Value; var charge = atom.FormalCharge.Value; Debug.WriteLine($"Checking saturation of atom {atom.Symbol}"); Debug.WriteLine($"bondOrderSum: {bondOrderSum}"); Debug.WriteLine($"maxBondOrder: {maxBondOrder}"); Debug.WriteLine($"hcount: {hcount}"); Debug.WriteLine($"charge: {charge}"); bool elementPlusChargeMatches = false; foreach (var type in atomTypes) { if (CouldMatchAtomType(atom, bondOrderSum, maxBondOrder, type)) { if (bondOrderSum + hcount == type.BondOrderSum && !BondManipulator.IsHigherOrder(maxBondOrder, type.MaxBondOrder)) { Debug.WriteLine($"We have a match: {type}"); Debug.WriteLine($"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) { Debug.WriteLine("No, atom is not saturated."); return(false); } // ok, the found atom was not in the list Trace.TraceError("Could not find atom type!"); throw new CDKException($"The atom with element {atom.Symbol} and charge {charge} is not found."); }
/// <summary> /// Determines if the atom can be of atom type. /// </summary> private static bool CouldMatchAtomType(IAtomContainer atomContainer, IAtom atom, IAtomType atomType) { Debug.WriteLine($" ... matching atom {atom.Symbol} vs {atomType}"); if (atomContainer.GetBondOrderSum(atom) + atom.ImplicitHydrogenCount < atomType.BondOrderSum) { Debug.WriteLine(" Match!"); return(true); } Debug.WriteLine(" No Match"); return(false); }
/// <summary> /// Checks whether an atom is saturated by comparing it with known atom types. /// </summary> public bool IsSaturated(IAtom atom, IAtomContainer ac) { var atomTypes = structgenATF.GetAtomTypes(atom.Symbol); if (!atomTypes.Any()) { return(true); } double bondOrderSum = 0; var maxBondOrder = BondOrder.Unset; int hcount = 0; int charge = 0; bool isInited = false; foreach (var atomType in atomTypes) { if (!isInited) { isInited = true; bondOrderSum = ac.GetBondOrderSum(atom); maxBondOrder = ac.GetMaximumBondOrder(atom); hcount = atom.ImplicitHydrogenCount ?? 0; charge = atom.FormalCharge ?? 0; try { Debug.WriteLine($"*** Checking saturation of atom {atom.Symbol} {ac.Atoms.IndexOf(atom)} ***"); Debug.WriteLine($"bondOrderSum: {bondOrderSum}"); Debug.WriteLine($"maxBondOrder: {maxBondOrder}"); Debug.WriteLine($"hcount: {hcount}"); } catch (Exception exc) { Debug.WriteLine(exc); } } if (bondOrderSum - charge + hcount == atomType.BondOrderSum && !BondManipulator.IsHigherOrder(maxBondOrder, atomType.MaxBondOrder)) { Debug.WriteLine("*** Good ! ***"); return(true); } } Debug.WriteLine("*** Bad ! ***"); return(false); }
private static double GetAtomScore(double score, IReadOnlyDictionary <IAtom, IAtom> atomMapMCS, IAtomContainer reactant, IAtomContainer product) { foreach (var mappings in atomMapMCS) { IAtom rAtom = mappings.Key; IAtom pAtom = mappings.Value; int rHCount = 0; int pHCount = 0; double rBO = reactant.GetBondOrderSum(rAtom); double pBO = product.GetBondOrderSum(pAtom); if (rAtom.ImplicitHydrogenCount != null) { rHCount = rAtom.ImplicitHydrogenCount.Value; } if (pAtom.ImplicitHydrogenCount != null) { pHCount = pAtom.ImplicitHydrogenCount.Value; } int hScore = Math.Abs(rHCount - pHCount); double boScore = Math.Abs(rBO - pBO); if (rHCount != pHCount) { score -= hScore; } else { score += hScore; } if (rBO != pBO) { score -= boScore; } else { score += boScore; } } return(score); }
public bool HasPerfectConfiguration(IAtom atom, IAtomContainer ac) { var bondOrderSum = ac.GetBondOrderSum(atom); var maxBondOrder = ac.GetMaximumBondOrder(atom); var atomTypes = structgenATF.GetAtomTypes(atom.Symbol); if (!atomTypes.Any()) { return(true); } Debug.WriteLine("*** Checking for perfect configuration ***"); try { Debug.WriteLine($"Checking configuration of atom {ac.Atoms.IndexOf(atom)}"); Debug.WriteLine($"Atom has bondOrderSum = {bondOrderSum}"); Debug.WriteLine($"Atom has max = {bondOrderSum}"); } catch (Exception) { } foreach (var atomType in atomTypes) { if (bondOrderSum == atomType.BondOrderSum && maxBondOrder == atomType.MaxBondOrder) { try { Debug.WriteLine($"Atom {ac.Atoms.IndexOf(atom)} has perfect configuration"); } catch (Exception) { } return(true); } } try { Debug.WriteLine($"*** Atom {ac.Atoms.IndexOf(atom)} has imperfect configuration ***"); } catch (Exception) { } return(false); }
private void FixCarbonHCount(IAtomContainer mol) { // the following line are just a quick fix for this particluar // carbon-only molecule until we have a proper hydrogen count // configurator double bondCount = 0; IAtom atom; for (int f = 0; f < mol.Atoms.Count; f++) { atom = mol.Atoms[f]; bondCount = mol.GetBondOrderSum(atom); if (bondCount > 4) { Console.Out.WriteLine("bondCount: " + bondCount); } atom.ImplicitHydrogenCount = 4 - (int)bondCount - (int)(atom.Charge ?? 0); } }
/// <summary> /// Finds the AtomType matching the Atom's element symbol, formal charge and /// hybridization state. /// </summary> /// <param name="atomContainer">AtomContainer</param> /// <param name="atom">the target atom</param> /// <exception cref="CDKException">Exception thrown if something goes wrong</exception> /// <returns>the matching AtomType</returns> public IEnumerable <IAtomType> PossibleAtomTypes(IAtomContainer atomContainer, IAtom atom) { var bondOrderSum = atomContainer.GetBondOrderSum(atom); var maxBondOrder = atomContainer.GetMaximumBondOrder(atom); var charge = atom.FormalCharge.Value; var hcount = atom.ImplicitHydrogenCount.Value; var types = factory.GetAtomTypes(atom.Symbol); foreach (var type in types) { Debug.WriteLine(" ... matching atom ", atom, " vs ", type); if (bondOrderSum - charge + hcount <= type.BondOrderSum && !BondManipulator.IsHigherOrder(maxBondOrder, type.MaxBondOrder)) { yield return(type); } } Debug.WriteLine(" No Match"); yield break; }
/// <summary> /// Returns the currently maximum 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 bond order for this atom</returns> public double GetCurrentMaxBondOrder(IAtom atom, IAtomContainer ac) { var atomTypes = structgenATF.GetAtomTypes(atom.Symbol); if (!atomTypes.Any()) { return(0); } var bondOrderSum = ac.GetBondOrderSum(atom); var hcount = atom.ImplicitHydrogenCount ?? 0; double max = 0; double current = 0; foreach (var atomType in atomTypes) { current = hcount + bondOrderSum; if (atomType.BondOrderSum - current > max) { max = atomType.BondOrderSum.Value - current; } } return(max); }
/// <summary> /// The method is known to fail for certain compounds. For more information, see /// cdk.test.limitations package. /// This method is known to fail, especially on pyrrole-like compounds. /// Consider using <see cref="Smiles.DeduceBondSystemTool"/>, which should work better /// </summary> public void Saturate(IAtomContainer atomContainer) { 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.Atoms.Count; f++) { var atom = atomContainer.Atoms[f]; Debug.WriteLine($"symbol: {atom.Symbol}"); var atomTypes1 = structgenATF.GetAtomTypes(atom.Symbol); var atomType1 = atomTypes1.FirstOrDefault(); if (atomType1 != null) { Debug.WriteLine($"first atom type: {atomType1}"); if (atomContainer.GetConnectedBonds(atom).Count() == i) { var hcount = atom.ImplicitHydrogenCount ?? 0; if (atom.IsAromatic && atomContainer.GetBondOrderSum(atom) < atomType1.BondOrderSum - hcount) { var partners = atomContainer.GetConnectedAtoms(atom); foreach (var partner in partners) { Debug.WriteLine($"Atom has {partners.Count()} partners"); var atomType2 = structgenATF.GetAtomTypes(partner.Symbol).FirstOrDefault(); if (atomType2 == null) { return; } hcount = partner.ImplicitHydrogenCount ?? 0; if (atomContainer.GetBond(partner, atom).IsAromatic && atomContainer.GetBondOrderSum(partner) < atomType2.BondOrderSum - hcount) { Debug.WriteLine($"Partner has {atomContainer.GetBondOrderSum(partner)}, may have: {atomType2.BondOrderSum}"); var bond = atomContainer.GetBond(atom, partner); Debug.WriteLine($"Bond order was {bond.Order}"); BondManipulator.IncreaseBondOrder(bond); Debug.WriteLine($"Bond order now {bond.Order}"); break; } } } var bondOrderSum = atomType1.BondOrderSum ?? 0; var hydrogenCount = atom.ImplicitHydrogenCount ?? 0; var atomContainerBondOrderSum = atomContainer.GetBondOrderSum(atom); if (atomContainerBondOrderSum < bondOrderSum - hydrogenCount) { Debug.WriteLine("Atom has " + atomContainerBondOrderSum + ", may have: " + bondOrderSum); var partners = atomContainer.GetConnectedAtoms(atom); foreach (var partner in partners) { Debug.WriteLine("Atom has " + partners.Count() + " partners"); var atomType2 = structgenATF.GetAtomTypes(partner.Symbol).FirstOrDefault(); if (atomType2 == null) { return; } var bos2 = atomType2.BondOrderSum ?? 0; var hc2 = partner.ImplicitHydrogenCount ?? 0; var acbos2 = atomContainer.GetBondOrderSum(partner); if (acbos2 < bos2 - hc2) { Debug.WriteLine($"Partner has {acbos2}, may have: {bos2}"); var bond = atomContainer.GetBond(atom, partner); Debug.WriteLine($"Bond order was {bond.Order}"); BondManipulator.IncreaseBondOrder(bond); Debug.WriteLine($"Bond order now {bond.Order}"); break; } } } } } } } }
public int CalculateNumberOfImplicitHydrogens(IAtom atom, IAtomContainer container) { return(this.CalculateNumberOfImplicitHydrogens(atom, container.GetBondOrderSum(atom), container.GetMaximumBondOrder(atom), container.GetConnectedBonds(atom).Count())); }
private static int GetBadCount(IAtomContainer atomContainer, IRingSet ringSet) { // finds count of nitrogens in the rings that have 4 bonds // to non hydrogen atoms and one to hydrogen // or nitrogens with 2 double bonds to atoms in the ringset // or have S atom with more than 2 bonds // these arent necessarily bad- just unlikely int count = 0; for (int j = 0; j <= atomContainer.Atoms.Count - 1; j++) { var atom = atomContainer.Atoms[j]; if (InRingSet(atom, ringSet)) { if (atom.AtomicNumber.Equals(AtomicNumbers.N)) { if (atom.FormalCharge == 0) { if (atomContainer.GetBondOrderSum(atom) == 4) { count++; // } else if (atomContainer.GetBondOrderSum(atom) == 5) { // check if have 2 double bonds to atom in ring int doublebondcount = 0; var ca = atomContainer.GetConnectedAtoms(atom); foreach (var a in ca) { if (atomContainer.GetBond(atom, a).Order == BondOrder.Double) { if (InRingSet(a, ringSet)) { doublebondcount++; } } } if (doublebondcount == 2) { count++; } } } else if (atom.FormalCharge == 1) { if (atomContainer.GetBondOrderSum(atom) == 5) { count++; } } } else if (atom.AtomicNumber.Equals(AtomicNumbers.S)) { if (atomContainer.GetBondOrderSum(atom) > 2) { count++; } } } } return(count); }
/// <summary> /// Proposes a structure which can be accepted or rejected by an external /// entity. If rejected, the structure is not used as a starting point /// for the next random move in structure space. /// </summary> /// <returns>A proposed molecule</returns> public IAtomContainer ProposeStructure() { Debug.WriteLine("RandomGenerator->ProposeStructure() Start"); do { trial = (IAtomContainer)Molecule.Clone(); Mutate(trial); Debug.WriteLine("BondCounts: " + string.Join(" ", trial.Atoms.Select(n => trial.GetConnectedBonds(n).Count()))); Debug.WriteLine("BondOrderSums: " + string.Join(" ", trial.Atoms.Select(n => trial.GetBondOrderSum(n)))); } while (trial == null || !ConnectivityChecker.IsConnected(trial)); proposedStructure = trial; return(proposedStructure); }
public int CalculateNumberOfImplicitHydrogens(IAtom atom, IAtomContainer container, bool throwExceptionForUnknowAtom) { return(this.CalculateNumberOfImplicitHydrogens(atom, container.GetBondOrderSum(atom), container.GetConnectedSingleElectrons(atom).Count(), container.GetConnectedBonds(atom), throwExceptionForUnknowAtom)); }