/// <summary> /// Computes <see cref="SMARTSAtomInvariants"/> and stores on the <see cref="Key"/> or /// each <see cref="IAtom"/> in the <paramref name="container"/>. The <see cref="IMolecularEntity.IsInRing"/> /// is also set for each bond. This configuration /// includes the ring information as used by the Daylight implementation. /// That is the Smallest Set of Smallest Rings (SSSR) is used and only the /// smallest ring is stored for the <see cref="RingSize"/> . /// </summary> /// <example> /// <code> /// IAtomContainer container = ...; /// SMARTSAtomInvariants.ConfigureDaylightWithRingInfo(container); /// foreach (var atom in container.Atoms) { /// SMARTSAtomInvariants inv = atom.GetProperty<SMARTSAtomInvariants>(SMARTSAtomInvariants.Key); /// } /// </code> /// </example> /// <param name="container">the container to configure</param> public static void ConfigureDaylightWithRingInfo(IAtomContainer container) { var map = EdgeToBondMap.WithSpaceFor(container); var graph = GraphUtil.ToAdjList(container, map); ConfigureDaylight(container, graph, map, true); }
private static List <IAtomContainer> GenerateFragments(IAtomContainer mol) { var bmap = EdgeToBondMap.WithSpaceFor(mol); var adjlist = GraphUtil.ToAdjList(mol, bmap); Cycles.MarkRingAtomsAndBonds(mol, adjlist, bmap); var cuts = FindCutBonds(mol, bmap, adjlist); var atmidx = new Dictionary <IAtom, int>(); foreach (var atom in mol.Atoms) { atmidx[atom] = atmidx.Count; } // frags are ordered by biggest to smallest var frags = new List <IAtomContainer>(); foreach (var cut in cuts) { if (frags.Count >= MaxFragment) { break; } frags.AddRange(MakeCut(cut, mol, atmidx, adjlist)); } frags.Sort(delegate(IAtomContainer a, IAtomContainer b) { return(-a.Bonds.Count.CompareTo(b.Bonds.Count)); }); return(frags); }
public void RecogniseLeftHandedGlyceraldehyde() { var m = new AtomContainer(); m.Atoms.Add(Atom("C", 0, 0.80d, 1.24d)); m.Atoms.Add(Atom("C", 0, 0.80d, 0.42d)); m.Atoms.Add(Atom("O", 1, 0.09d, 1.66d)); m.Atoms.Add(Atom("O", 0, 1.52d, 1.66d)); m.Atoms.Add(Atom("O", 0, -0.02d, 0.42d)); m.Atoms.Add(Atom("C", 2, 0.80d, -0.41d)); m.Atoms.Add(Atom("H", 1, 1.63d, 0.42d)); m.Atoms.Add(Atom("O", 1, 1.52d, -0.82d)); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[3], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[1], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[5], m.Atoms[7], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); FischerRecognition recogniser = new FischerRecognition(m, graph, bondMap, Stereocenters.Of(m)); var elements = recogniser.Recognise(new[] { Projection.Fischer }).ToReadOnlyList(); Assert.AreEqual(1, elements.Count); AssertTetrahedralCenter(elements[0], m.Atoms[1], TetrahedralStereo.AntiClockwise, m.Atoms[0], m.Atoms[6], m.Atoms[5], m.Atoms[4]); }
public void RequireAtLeastTwoProjectedSubstituents() { var m = new AtomContainer(); m.Atoms.Add(Atom("O", 0, -0.71d, 1.24d)); m.Atoms.Add(Atom("C", 0, 0.00d, 0.83d)); m.Atoms.Add(Atom("O", 0, 0.71d, 1.24d)); m.Atoms.Add(Atom("C", 1, 0.00d, 0.00d)); m.Atoms.Add(Atom("C", 2, -0.67d, -0.48d)); m.Atoms.Add(Atom("C", 2, -0.41d, -1.27d)); m.Atoms.Add(Atom("C", 2, 0.41d, -1.27d)); m.Atoms.Add(Atom("N", 1, 0.67d, -0.48d)); m.AddBond(m.Atoms[6], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[0], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[2], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[5], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[6], m.Atoms[7], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); Stereocenters stereocenters = new Stereocenters(m, graph, bondMap); stereocenters.CheckSymmetry(); CyclicCarbohydrateRecognition recon = new CyclicCarbohydrateRecognition(m, graph, bondMap, stereocenters); var elements = recon.Recognise(new[] { Projection.Haworth }).ToReadOnlyList(); Assert.IsTrue(elements.Count == 0); }
/// <summary> /// Use the provided query and target to obtain the bond instances. /// </summary> /// <param name="query">the structure to be found</param> /// <param name="target">the structure being searched</param> public BondMaper(IAtomContainer query, IAtomContainer target) { this.bonds1 = EdgeToBondMap.WithSpaceFor(query); this.bonds2 = EdgeToBondMap.WithSpaceFor(target); this.g1 = GraphUtil.ToAdjList(query, bonds1); GraphUtil.ToAdjList(target, bonds2); }
/// <summary> /// Find the bonds of a <paramref name="molecule"/> which this model determined were aromatic. /// </summary> /// <example> /// <include file='IncludeExamples.xml' path='Comments/Codes[@id="NCDK.Aromaticities.Aromaticity_Example.cs+FindBonds"]/*' /> /// </example> /// <param name="molecule">the molecule to apply the model to</param> /// <returns>the set of bonds which are aromatic</returns> /// <exception cref="CDKException">a problem occurred with the cycle perception - one can retry with a simpler cycle set</exception> public IEnumerable <IBond> FindBonds(IAtomContainer molecule) { // build graph data-structures for fast cycle perception var bondMap = EdgeToBondMap.WithSpaceFor(molecule); var graph = GraphUtil.ToAdjList(molecule, bondMap); // initial ring/cycle search and get the contribution from each atom RingSearch ringSearch = new RingSearch(molecule, graph); var electrons = model.Contribution(molecule, ringSearch); // obtain the subset of electron contributions which are >= 0 (i.e. // allowed to be aromatic) - we then find the cycles in this subgraph // and 'lift' the indices back to the original graph using the subset // as a lookup var subset = Subset(electrons); var subgraph = GraphUtil.Subgraph(graph, subset); // for each cycle if the electron sum is valid add the bonds of the // cycle to the set or aromatic bonds foreach (var cycle in cycles.Find(molecule, subgraph, subgraph.Length).GetPaths()) { if (CheckElectronSum(cycle, electrons, subset)) { for (int i = 1; i < cycle.Length; i++) { yield return(bondMap[subset[cycle[i]], subset[cycle[i - 1]]]); } } } yield break; }
/// <summary> /// Obtain the MMFF symbolic types to the atoms of the provided structure. /// </summary> /// <param name="container">container structure representation</param> /// <returns>MMFF symbolic types for each atom index</returns> public string[] SymbolicTypes(IAtomContainer container) { var bonds = EdgeToBondMap.WithSpaceFor(container); var graph = GraphUtil.ToAdjList(container, bonds); return(SymbolicTypes(container, graph, bonds, new HashSet <IBond>())); }
internal AdjListCache(IAtomContainer mol) { this.bmap = EdgeToBondMap.WithSpaceFor(mol); this.g = GraphUtil.ToAdjList(mol, bmap); this.numAtoms = mol.Atoms.Count; this.numBonds = mol.Bonds.Count; this.tInit = DateTime.Now.Ticks; }
public void Mannitol() { var m = new AtomContainer(); m.Atoms.Add(Atom("C", 2, -0.53d, 6.25d)); m.Atoms.Add(Atom("C", 1, -0.53d, 5.42d)); m.Atoms.Add(Atom("O", 1, 0.18d, 6.66d)); m.Atoms.Add(Atom("O", 1, -1.36d, 5.42d)); m.Atoms.Add(Atom("C", 1, -0.53d, 4.60d)); m.Atoms.Add(Atom("O", 1, -1.36d, 4.60d)); m.Atoms.Add(Atom("C", 1, -0.53d, 3.77d)); m.Atoms.Add(Atom("O", 1, 0.29d, 3.77d)); m.Atoms.Add(Atom("C", 1, -0.53d, 2.95d)); m.Atoms.Add(Atom("O", 1, 0.29d, 2.95d)); m.Atoms.Add(Atom("C", 2, -0.53d, 2.12d)); m.Atoms.Add(Atom("O", 1, 0.05d, 1.54d)); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[6], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[6], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[9], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[10], BondOrder.Single); m.AddBond(m.Atoms[10], m.Atoms[11], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); FischerRecognition recogniser = new FischerRecognition(m, graph, bondMap, Stereocenters.Of(m)); var elements = recogniser.Recognise(new[] { Projection.Fischer }).ToReadOnlyList(); Assert.AreEqual(4, elements.Count); AssertTetrahedralCenter(elements[0], m.Atoms[1], TetrahedralStereo.AntiClockwise, m.Atoms[0], m.Atoms[1], m.Atoms[4], m.Atoms[3]); AssertTetrahedralCenter(elements[1], m.Atoms[4], TetrahedralStereo.AntiClockwise, m.Atoms[1], m.Atoms[4], m.Atoms[6], m.Atoms[5]); AssertTetrahedralCenter(elements[2], m.Atoms[6], TetrahedralStereo.AntiClockwise, m.Atoms[4], m.Atoms[7], m.Atoms[8], m.Atoms[6]); AssertTetrahedralCenter(elements[3], m.Atoms[8], TetrahedralStereo.AntiClockwise, m.Atoms[6], m.Atoms[9], m.Atoms[10], m.Atoms[8]); m.SetStereoElements(elements); }
/// <summary> /// Determine the stereocenter atoms in the provided container based on connectivity. /// </summary> /// <example> /// <include file='IncludeExamples.xml' path='Comments/Codes[@id="NCDK.Stereo.Stereocenters_Example.cs+Of"]/*' /> /// </example> /// <param name="container">input container</param> /// <returns>the stereocenters</returns> public static Stereocenters Of(IAtomContainer container) { var bondMap = EdgeToBondMap.WithSpaceFor(container); var g = GraphUtil.ToAdjList(container, bondMap); var stereocenters = new Stereocenters(container, g, bondMap); stereocenters.CheckSymmetry(); return(stereocenters); }
/// <summary> /// Non-public constructor for-now the atom/bond semantics are fixed. /// </summary> /// <param name="query">the query structure</param> /// <param name="atomMatcher">how atoms should be matched</param> /// <param name="bondMatcher">how bonds should be matched</param> private Ullmann(IAtomContainer query, AtomMatcher atomMatcher, BondMatcher bondMatcher) { this.query = query; this.atomMatcher = atomMatcher; this.bondMatcher = bondMatcher; this.bonds1 = EdgeToBondMap.WithSpaceFor(query); this.g1 = GraphUtil.ToAdjList(query, bonds1); DetermineFilters(query); }
public override Mappings MatchAll(IAtomContainer target) { var bonds2 = EdgeToBondMap.WithSpaceFor(target); var g2 = GraphUtil.ToAdjList(target, bonds2); var iterable = new UllmannIterable(query, target, g1, g2, bonds1, bonds2, atomMatcher, bondMatcher); var mappings = new Mappings(query, target, iterable); return(Filter(mappings, query, target)); }
/// <summary> /// Assign MMFF Symbolic atom types. The symbolic type can be accessed with /// <see cref="IAtomType.AtomTypeName"/>. An atom of unknown type is assigned the /// symbolic type <c>"UNK"</c>. /// All atoms, including hydrogens must be explicitly represented. /// </summary> /// <param name="mol">molecule</param> /// <returns>all atoms had a type assigned</returns> public virtual bool AssignAtomTypes(IAtomContainer mol) { // preconditions need explicit hydrogens foreach (var atom in mol.Atoms) { if (atom.ImplicitHydrogenCount == null || atom.ImplicitHydrogenCount > 0) { throw new ArgumentException("Hydrogens must be explicit nodes, each must have a zero (non-null) impl H count."); } } // conversion to faster data structures var edgeMap = EdgeToBondMap.WithSpaceFor(mol); var adjList = GraphUtil.ToAdjList(mol, edgeMap); mol.SetProperty(MMFF_ADJLIST_CACHE, adjList); mol.SetProperty(MMFF_EDGEMAP_CACHE, edgeMap); var aromBonds = new HashSet <IBond>(); var oldArom = GetAromatics(mol); // note: for MMFF we need to remove current aromatic flags for type // assignment (they are restored after) foreach (var chemObj in oldArom) { chemObj.IsAromatic = false; } var atomTypes = mmffAtomTyper.SymbolicTypes(mol, adjList, edgeMap, aromBonds); bool hasUnkType = false; for (int i = 0; i < mol.Atoms.Count; i++) { if (atomTypes[i] == null) { mol.Atoms[i].AtomTypeName = "UNK"; hasUnkType = true; } else { mol.Atoms[i].AtomTypeName = atomTypes[i]; } } // restore aromatic flags and mark the MMFF aromatic bonds foreach (var chemObj in oldArom) { chemObj.IsAromatic = true; } foreach (var bond in aromBonds) { bond.SetProperty(MMFF_AROM, true); } return(!hasUnkType); }
/// <summary> /// Non-public constructor for-now the atom/bond semantics are fixed. /// </summary> /// <param name="query">the query structure</param> /// <param name="atomMatcher">how atoms should be matched</param> /// <param name="bondMatcher">how bonds should be matched</param> /// <param name="substructure">substructure search</param> private VentoFoggia(IAtomContainer query, AtomMatcher atomMatcher, BondMatcher bondMatcher, bool substructure) { this.query = query; this.atomMatcher = atomMatcher; this.bondMatcher = bondMatcher; this.bonds1 = EdgeToBondMap.WithSpaceFor(query); this.g1 = GraphUtil.ToAdjList(query, bonds1); this.subgraph = substructure; DetermineFilters(query); }
/// <summary> /// Create a state for matching benzene to naphthalene Benzene: /// InChI=1/C6H6/c1-2-4-6-5-3-1/h1-6H Naphthalene: InChI=1/C10H8/c1-2-6-10-8-4-3-7-9(10)5-1/h1-8H /// </summary> UllmannState CreateBenzeneToNaphthalene(AtomMatcher atomMatcher, BondMatcher bondMatcher) { IAtomContainer container1 = TestMoleculeFactory.MakeBenzene(); IAtomContainer container2 = TestMoleculeFactory.MakeNaphthalene(); EdgeToBondMap bonds1 = EdgeToBondMap.WithSpaceFor(container1); EdgeToBondMap bonds2 = EdgeToBondMap.WithSpaceFor(container2); int[][] g1 = GraphUtil.ToAdjList(container1, bonds1); int[][] g2 = GraphUtil.ToAdjList(container2, bonds2); return(new UllmannState(container1, container2, g1, g2, bonds1, bonds2, atomMatcher, bondMatcher)); }
/// <summary> /// Create a new layout refiner for the provided molecule. /// </summary> /// <param name="mol">molecule to refine</param> internal LayoutRefiner(IAtomContainer mol, ISet <IAtom> afix, ISet <IBond> bfix) { this.mol = mol; this.afix = afix; this.bfix = bfix; this.bondMap = EdgeToBondMap.WithSpaceFor(mol); this.adjList = GraphUtil.ToAdjList(mol, bondMap); this.idxs = new Dictionary <IAtom, int>(); foreach (var atom in mol.Atoms) { idxs[atom] = idxs.Count; } this.atoms = mol.Atoms.ToArray(); // buffers for storing coordinates this.buffer1 = new Vector2[atoms.Length]; this.buffer2 = new Vector2[atoms.Length]; this.backup = new Vector2[atoms.Length]; for (int i = 0; i < buffer1.Length; i++) { buffer1[i] = new Vector2(); buffer2[i] = new Vector2(); backup[i] = new Vector2(); } this.stackBackup = new IntStack(atoms.Length); this.visited = new bool[atoms.Length]; this.congestion = new Congestion(mol, adjList); // note, this is lazy so only does the shortest path when needed // and does |V| search at maximum this.apsp = new AllPairsShortestPaths(mol); // index ring systems, idx -> ring system number (rnum) int rnum = 1; this.ringsystems = new int[atoms.Length]; for (int i = 0; i < atoms.Length; i++) { if (atoms[i].IsInRing && ringsystems[i] == 0) { TraverseRing(ringsystems, i, rnum++); } } }
/// <summary> /// Assign a Kekulé representation to the aromatic systems of a compound. /// </summary> /// <param name="ac">structural representation</param> /// <exception cref="CDKException">a Kekulé form could not be assigned</exception> public static void Kekulize(IAtomContainer ac) { // storage of pairs of atoms that have pi-bonded var matching = Matching.WithCapacity(ac.Atoms.Count); // exract data structures for efficient access var atoms = ac.Atoms.ToArray(); var bonds = EdgeToBondMap.WithSpaceFor(ac); var graph = GraphUtil.ToAdjList(ac, bonds); // determine which atoms are available to have a pi bond placed var available = IsAvailable(graph, atoms, bonds); // attempt to find a perfect matching such that a pi bond is placed // next to each available atom. if not found the solution is ambiguous if (!matching.Perfect(graph, available)) { throw new CDKException("Cannot assign Kekulé structure without randomly creating radicals."); } // propagate bond order information from the matching foreach (var bond in ac.Bonds) { if (bond.Order == BondOrder.Unset && bond.IsAromatic) { bond.Order = BondOrder.Single; } } for (int v = BitArrays.NextSetBit(available, 0); v >= 0; v = BitArrays.NextSetBit(available, v + 1)) { var w = matching.Other(v); var bond = bonds[v, w]; // sanity check, something wrong if this happens if (bond.Order.Numeric() > 1) { throw new CDKException("Cannot assign Kekulé structure, non-sigma bond order has already been assigned?"); } bond.Order = BondOrder.Double; available.Set(w, false); } }
/// <summary> /// Compute all rings up to an including the <paramref name="maxRingSize"/>. No /// pre-processing is done on the container. /// </summary> /// <param name="atomContainer">the molecule to be searched for rings</param> /// <param name="maxRingSize">Maximum ring size to consider. Provides a possible /// breakout from recursion for complex compounds.</param> /// <returns>a RingSet containing the rings in molecule</returns> /// <exception cref="CDKException">An exception thrown if the threshold was exceeded</exception> public IRingSet FindAllRingsInIsolatedRingSystem(IAtomContainer atomContainer, int maxRingSize) { var edges = EdgeToBondMap.WithSpaceFor(atomContainer); var graph = GraphUtil.ToAdjList(atomContainer, edges); var ac = new AllCycles(graph, maxRingSize, threshold.Value); if (!ac.Completed) { throw new CDKException("Threshold exceeded for AllRingsFinder"); } var ringSet = atomContainer.Builder.NewRingSet(); foreach (var path in ac.GetPaths()) { ringSet.Add(ToRing(atomContainer, edges, path)); } return(ringSet); }
public void Hexopyranose() { var m = new AtomContainer(); m.Atoms.Add(Atom("O", 1, 0.00d, 2.48d)); m.Atoms.Add(Atom("C", 2, 0.71d, 2.06d)); m.Atoms.Add(Atom("C", 1, 0.71d, 1.24d)); m.Atoms.Add(Atom("O", 0, 1.43d, 0.82d)); m.Atoms.Add(Atom("C", 1, 1.43d, -0.00d)); m.Atoms.Add(Atom("O", 1, 2.14d, -0.41d)); m.Atoms.Add(Atom("C", 1, 0.71d, -0.41d)); m.Atoms.Add(Atom("O", 1, 0.71d, -1.24d)); m.Atoms.Add(Atom("C", 1, -0.00d, 0.00d)); m.Atoms.Add(Atom("O", 1, -0.71d, -0.41d)); m.Atoms.Add(Atom("C", 1, 0.00d, 0.83d)); m.Atoms.Add(Atom("O", 1, -0.71d, 1.24d)); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[6], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[6], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[9], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[10], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[10], BondOrder.Single); m.AddBond(m.Atoms[10], m.Atoms[11], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); Stereocenters stereocenters = new Stereocenters(m, graph, bondMap); stereocenters.CheckSymmetry(); CyclicCarbohydrateRecognition recon = new CyclicCarbohydrateRecognition(m, graph, bondMap, stereocenters); Assert.IsTrue(recon.Recognise(new[] { Projection.Haworth }).Count() == 0); }
public void HorizontalBondsMustBeTerminal() { var m = new AtomContainer(); m.Atoms.Add(Atom("C", 0, 12.71d, -16.51d)); m.Atoms.Add(Atom("C", 1, 12.30d, -17.22d)); m.Atoms.Add(Atom("C", 1, 11.47d, -17.22d)); m.Atoms.Add(Atom("C", 1, 11.06d, -16.51d)); m.Atoms.Add(Atom("C", 1, 11.47d, -15.79d)); m.Atoms.Add(Atom("C", 1, 12.30d, -15.79d)); m.Atoms.Add(Atom("O", 1, 13.54d, -17.33d)); m.Atoms.Add(Atom("C", 0, 13.54d, -16.51d)); m.Atoms.Add(Atom("C", 0, 14.36d, -16.51d)); m.Atoms.Add(Atom("O", 1, 14.77d, -17.22d)); m.Atoms.Add(Atom("O", 0, 14.77d, -15.79d)); m.Atoms.Add(Atom("C", 3, 13.54d, -15.68d)); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[5], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[1], m.Atoms[2], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[2], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[4], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[7], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[7], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[9], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[10], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[0], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[11], m.Atoms[7], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); FischerRecognition recogniser = new FischerRecognition(m, graph, bondMap, Stereocenters.Of(m)); Assert.IsTrue(recogniser.Recognise(new[] { Projection.Fischer }).Count() == 0); }
public void HaworthFalsePositive() { var m = new AtomContainer(); m.Atoms.Add(Atom("C", 2, -0.71d, 0.41d)); m.Atoms.Add(Atom("C", 2, 0.71d, -0.41d)); m.Atoms.Add(Atom("C", 2, 0.71d, 0.41d)); m.Atoms.Add(Atom("C", 2, -0.71d, -0.41d)); m.Atoms.Add(Atom("C", 1, 0.00d, 0.82d)); m.Atoms.Add(Atom("C", 3, 0.00d, 1.65d)); m.Atoms.Add(Atom("C", 3, -0.71d, -2.06d)); m.Atoms.Add(Atom("C", 1, -0.00d, -1.65d)); m.Atoms.Add(Atom("C", 3, 0.71d, -2.06d)); m.Atoms.Add(Atom("C", 1, -0.00d, -0.83d)); m.AddBond(m.Atoms[9], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[9], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[0], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[9], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[7], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[7], m.Atoms[8], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); Stereocenters stereocenters = new Stereocenters(m, graph, bondMap); stereocenters.CheckSymmetry(); CyclicCarbohydrateRecognition recon = new CyclicCarbohydrateRecognition(m, graph, bondMap, stereocenters); var elements = recon.Recognise(new[] { Projection.Haworth }).ToReadOnlyList(); Assert.IsTrue(elements.Count == 0); }
/// <summary> /// Compute all rings up to and including the <paramref name="maxRingSize"/>. The /// container is first partitioned into ring systems which are then processed /// separately. If the molecule has already be partitioned, consider using <see cref="FindAllRingsInIsolatedRingSystem(IAtomContainer, int)"/>. /// </summary> /// <param name="container">The AtomContainer to be searched for rings</param> /// <param name="maxRingSize">Maximum ring size to consider. Provides a possible /// breakout from recursion for complex compounds.</param> /// <returns>A RingSet with all rings in the AtomContainer</returns> /// <exception cref="CDKException">An exception thrown if the threshold was exceeded</exception> public IRingSet FindAllRings(IAtomContainer container, int maxRingSize) { var edges = EdgeToBondMap.WithSpaceFor(container); var graph = GraphUtil.ToAdjList(container, edges); var rs = new RingSearch(container, graph); var ringSet = container.Builder.NewRingSet(); // don't need to run on isolated rings, just need to put vertices in // cyclic order foreach (var isolated in rs.Isolated()) { if (isolated.Length <= maxRingSize) { var ring = ToRing(container, edges, GraphUtil.Cycle(graph, isolated)); ringSet.Add(ring); } } // for each set of fused cyclic vertices run the separate search foreach (var fused in rs.Fused()) { var ac = new AllCycles(GraphUtil.Subgraph(graph, fused), Math.Min(maxRingSize, fused.Length), threshold.Value); if (!ac.Completed) { throw new CDKException("Threshold exceeded for AllRingsFinder"); } foreach (var path in ac.GetPaths()) { IRing ring = ToRing(container, edges, path, fused); ringSet.Add(ring); } } return(ringSet); }
public void BetaDGlucoseWithExplicitHydrogens_Haworth() { var m = new AtomContainer(); m.Atoms.Add(Atom("C", 0, 4.16d, 1.66d)); m.Atoms.Add(Atom("C", 0, 3.75d, 0.94d)); m.Atoms.Add(Atom("C", 0, 4.16d, 0.23d)); m.Atoms.Add(Atom("C", 0, 5.05d, 0.23d)); m.Atoms.Add(Atom("C", 0, 5.46d, 0.94d)); m.Atoms.Add(Atom("O", 0, 5.05d, 1.66d)); m.Atoms.Add(Atom("O", 1, 5.46d, 1.48d)); m.Atoms.Add(Atom("C", 2, 4.16d, 2.20d)); m.Atoms.Add(Atom("O", 1, 3.45d, 2.61d)); m.Atoms.Add(Atom("O", 1, 3.74d, 0.50d)); m.Atoms.Add(Atom("O", 1, 4.16d, 0.77d)); m.Atoms.Add(Atom("O", 1, 5.04d, -0.21d)); m.Atoms.Add(Atom("H", 0, 4.15d, -0.21d)); m.Atoms.Add(Atom("H", 0, 5.05d, 0.77d)); m.Atoms.Add(Atom("H", 0, 5.45d, 0.50d)); m.Atoms.Add(Atom("H", 0, 3.75d, 1.48d)); m.Atoms.Add(Atom("H", 0, 4.17d, 1.15d)); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[7], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[9], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[10], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[11], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[12], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[13], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[14], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[15], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[16], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); Stereocenters stereocenters = new Stereocenters(m, graph, bondMap); stereocenters.CheckSymmetry(); CyclicCarbohydrateRecognition recon = new CyclicCarbohydrateRecognition(m, graph, bondMap, stereocenters); var elements = recon.Recognise(new[] { Projection.Haworth }).ToReadOnlyList(); AssertTetrahedralCenter(elements[0], m.Atoms[1], TetrahedralStereo.AntiClockwise, m.Atoms[15], m.Atoms[0], m.Atoms[9], m.Atoms[2]); AssertTetrahedralCenter(elements[1], m.Atoms[2], TetrahedralStereo.AntiClockwise, m.Atoms[10], m.Atoms[1], m.Atoms[12], m.Atoms[3]); AssertTetrahedralCenter(elements[2], m.Atoms[3], TetrahedralStereo.AntiClockwise, m.Atoms[13], m.Atoms[2], m.Atoms[11], m.Atoms[4]); AssertTetrahedralCenter(elements[3], m.Atoms[4], TetrahedralStereo.AntiClockwise, m.Atoms[6], m.Atoms[3], m.Atoms[14], m.Atoms[5]); AssertTetrahedralCenter(elements[4], m.Atoms[0], TetrahedralStereo.AntiClockwise, m.Atoms[7], m.Atoms[5], m.Atoms[16], m.Atoms[1]); }
public void Atp_Haworth() { var m = new AtomContainer(); m.Atoms.Add(Atom("O", 0, 2.56d, -6.46d)); m.Atoms.Add(Atom("C", 1, 1.90d, -6.83d)); m.Atoms.Add(Atom("C", 1, 2.15d, -7.46d)); m.Atoms.Add(Atom("C", 1, 2.98d, -7.46d)); m.Atoms.Add(Atom("C", 1, 3.23d, -6.83d)); m.Atoms.Add(Atom("C", 2, 1.90d, -6.00d)); m.Atoms.Add(Atom("O", 0, 1.18d, -5.59d)); m.Atoms.Add(Atom("O", 1, 2.15d, -8.29d)); m.Atoms.Add(Atom("O", 1, 2.98d, -8.29d)); m.Atoms.Add(Atom("P", 0, 0.36d, -5.59d)); m.Atoms.Add(Atom("O", 0, -0.47d, -5.59d)); m.Atoms.Add(Atom("O", 0, 0.36d, -4.76d)); m.Atoms.Add(Atom("O", 1, 0.36d, -6.41d)); m.Atoms.Add(Atom("P", 0, -1.29d, -5.59d)); m.Atoms.Add(Atom("O", 0, -2.12d, -5.59d)); m.Atoms.Add(Atom("O", 0, -1.29d, -4.76d)); m.Atoms.Add(Atom("O", 1, -1.29d, -6.41d)); m.Atoms.Add(Atom("P", 0, -2.94d, -5.59d)); m.Atoms.Add(Atom("O", 1, -3.77d, -5.59d)); m.Atoms.Add(Atom("O", 0, -2.94d, -4.76d)); m.Atoms.Add(Atom("O", 1, -2.94d, -6.41d)); m.Atoms.Add(Atom("C", 0, 4.73d, -4.51d)); m.Atoms.Add(Atom("C", 0, 4.02d, -4.92d)); m.Atoms.Add(Atom("C", 0, 4.02d, -5.75d)); m.Atoms.Add(Atom("N", 0, 4.73d, -6.16d)); m.Atoms.Add(Atom("N", 0, 5.44d, -5.75d)); m.Atoms.Add(Atom("C", 1, 5.44d, -4.92d)); m.Atoms.Add(Atom("C", 1, 2.75d, -5.33d)); m.Atoms.Add(Atom("N", 0, 3.23d, -4.67d)); m.Atoms.Add(Atom("N", 2, 4.73d, -3.68d)); m.Atoms.Add(Atom("N", 0, 3.23d, -6.00d)); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[5], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[6], m.Atoms[9], BondOrder.Single); m.AddBond(m.Atoms[9], m.Atoms[10], BondOrder.Single); m.AddBond(m.Atoms[9], m.Atoms[11], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[9], m.Atoms[12], BondOrder.Single); m.AddBond(m.Atoms[13], m.Atoms[14], BondOrder.Single); m.AddBond(m.Atoms[13], m.Atoms[15], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[13], m.Atoms[16], BondOrder.Single); m.AddBond(m.Atoms[10], m.Atoms[13], BondOrder.Single); m.AddBond(m.Atoms[17], m.Atoms[18], BondOrder.Single); m.AddBond(m.Atoms[17], m.Atoms[19], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[17], m.Atoms[20], BondOrder.Single); m.AddBond(m.Atoms[14], m.Atoms[17], BondOrder.Single); m.AddBond(m.Atoms[21], m.Atoms[22], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[22], m.Atoms[23], BondOrder.Single); m.AddBond(m.Atoms[23], m.Atoms[24], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[24], m.Atoms[25], BondOrder.Single); m.AddBond(m.Atoms[25], m.Atoms[26], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[21], m.Atoms[26], BondOrder.Single); m.AddBond(m.Atoms[27], m.Atoms[28], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[22], m.Atoms[28], BondOrder.Single); m.AddBond(m.Atoms[21], m.Atoms[29], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[30], BondOrder.Single); m.AddBond(m.Atoms[30], m.Atoms[27], BondOrder.Single); m.AddBond(m.Atoms[23], m.Atoms[30], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); Stereocenters stereocenters = new Stereocenters(m, graph, bondMap); stereocenters.CheckSymmetry(); CyclicCarbohydrateRecognition recon = new CyclicCarbohydrateRecognition(m, graph, bondMap, stereocenters); var elements = recon.Recognise(new[] { Projection.Haworth }).ToReadOnlyList(); AssertTetrahedralCenter(elements[0], m.Atoms[1], TetrahedralStereo.AntiClockwise, m.Atoms[5], m.Atoms[0], m.Atoms[1], m.Atoms[2]); AssertTetrahedralCenter(elements[1], m.Atoms[2], TetrahedralStereo.AntiClockwise, m.Atoms[2], m.Atoms[1], m.Atoms[7], m.Atoms[3]); AssertTetrahedralCenter(elements[2], m.Atoms[3], TetrahedralStereo.AntiClockwise, m.Atoms[3], m.Atoms[2], m.Atoms[8], m.Atoms[4]); AssertTetrahedralCenter(elements[3], m.Atoms[4], TetrahedralStereo.AntiClockwise, m.Atoms[30], m.Atoms[3], m.Atoms[4], m.Atoms[0]); }
public void BetaDGlucose_Chair_Rotated() { var m = new AtomContainer(); m.Atoms.Add(Atom("C", 1, -0.77d, 10.34d)); m.Atoms.Add(Atom("C", 1, 0.03d, 10.13d)); m.Atoms.Add(Atom("O", 0, 0.83d, 10.34d)); m.Atoms.Add(Atom("C", 1, 1.24d, 9.63d)); m.Atoms.Add(Atom("C", 1, 0.44d, 9.84d)); m.Atoms.Add(Atom("C", 1, -0.35d, 9.63d)); m.Atoms.Add(Atom("O", 1, 0.86d, 9.13d)); m.Atoms.Add(Atom("O", 1, 2.04d, 9.84d)); m.Atoms.Add(Atom("C", 2, -0.68d, 10.54d)); m.Atoms.Add(Atom("O", 1, -0.68d, 11.37d)); m.Atoms.Add(Atom("O", 1, -1.48d, 9.93d)); m.Atoms.Add(Atom("O", 1, -1.15d, 9.84d)); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[5], m.Atoms[0], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[9], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[10], BondOrder.Single); m.AddBond(m.Atoms[5], m.Atoms[11], BondOrder.Single); Vector2 center = GeometryUtil.Get2DCenter(m); GeometryUtil.Rotate(m, center, Vectors.DegreeToRadian(-80)); for (int i = 0; i < 30; i++) { GeometryUtil.Rotate(m, center, Vectors.DegreeToRadian(5)); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); Stereocenters stereocenters = new Stereocenters(m, graph, bondMap); stereocenters.CheckSymmetry(); CyclicCarbohydrateRecognition recon = new CyclicCarbohydrateRecognition(m, graph, bondMap, stereocenters); var elements = recon.Recognise(new[] { Projection.Chair }).ToReadOnlyList(); m.SetStereoElements(elements); AssertTetrahedralCenter(elements[0], m.Atoms[1], TetrahedralStereo.Clockwise, m.Atoms[8], m.Atoms[0], m.Atoms[1], m.Atoms[2]); AssertTetrahedralCenter(elements[1], m.Atoms[3], TetrahedralStereo.Clockwise, m.Atoms[7], m.Atoms[2], m.Atoms[3], m.Atoms[4]); AssertTetrahedralCenter(elements[2], m.Atoms[4], TetrahedralStereo.Clockwise, m.Atoms[4], m.Atoms[3], m.Atoms[6], m.Atoms[5]); AssertTetrahedralCenter(elements[3], m.Atoms[5], TetrahedralStereo.Clockwise, m.Atoms[11], m.Atoms[4], m.Atoms[5], m.Atoms[0]); AssertTetrahedralCenter(elements[4], m.Atoms[0], TetrahedralStereo.Clockwise, m.Atoms[0], m.Atoms[5], m.Atoms[10], m.Atoms[1]); } }
public void IgnoreCyclicStereocenters() { var m = new AtomContainer(); m.Atoms.Add(Atom("C", 0, 6.87d, -5.59d)); m.Atoms.Add(Atom("C", 0, 6.87d, -6.61d)); m.Atoms.Add(Atom("C", 0, 7.82d, -5.62d)); m.Atoms.Add(Atom("C", 0, 6.87d, -4.59d)); m.Atoms.Add(Atom("O", 0, 8.18d, -6.34d)); m.Atoms.Add(Atom("C", 0, 7.62d, -6.91d)); m.Atoms.Add(Atom("C", 0, 5.90d, -5.59d)); m.Atoms.Add(Atom("C", 0, 8.39d, -5.06d)); m.Atoms.Add(Atom("C", 0, 5.60d, -4.80d)); m.Atoms.Add(Atom("C", 2, 6.16d, -4.24d)); m.Atoms.Add(Atom("O", 0, 8.22d, -4.29d)); m.Atoms.Add(Atom("C", 2, 6.10d, -6.90d)); m.Atoms.Add(Atom("C", 2, 5.54d, -6.29d)); m.Atoms.Add(Atom("C", 2, 7.46d, -4.07d)); m.Atoms.Add(Atom("O", 0, 7.79d, -7.72d)); m.Atoms.Add(Atom("O", 0, 9.18d, -5.29d)); m.Atoms.Add(Atom("O", 1, 6.87d, -7.44d)); m.Atoms.Add(Atom("C", 3, 6.76d, -3.77d)); m.Atoms.Add(Atom("C", 3, 4.82d, -5.07d)); m.Atoms.Add(Atom("C", 3, 5.19d, -4.08d)); m.Atoms.Add(Atom("H", 0, 8.64d, -5.76d)); m.Atoms.Add(Atom("H", 0, 5.08d, -5.69d)); m.AddBond(m.Atoms[1], m.Atoms[0], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[0], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[5], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[7], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[9], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[10], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[11], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[12], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[13], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[14], m.Atoms[5], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[15], m.Atoms[7], BondOrder.Double, BondStereo.EZByCoordinates); m.AddBond(m.Atoms[1], m.Atoms[16], BondOrder.Single, BondStereo.Up); m.AddBond(m.Atoms[3], m.Atoms[17], BondOrder.Single, BondStereo.Up); m.AddBond(m.Atoms[18], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[19], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[20], BondOrder.Single, BondStereo.Down); m.AddBond(m.Atoms[6], m.Atoms[21], BondOrder.Single, BondStereo.Down); m.AddBond(m.Atoms[5], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[11], m.Atoms[12], BondOrder.Single); m.AddBond(m.Atoms[10], m.Atoms[13], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[9], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); FischerRecognition recogniser = new FischerRecognition(m, graph, bondMap, Stereocenters.Of(m)); Assert.IsTrue(recogniser.Recognise(new[] { Projection.Fischer }).Count() == 0); }
public void Oxpene() { var m = new AtomContainer(); m.Atoms.Add(Atom("C", 1, 1.39d, 3.65d)); m.Atoms.Add(Atom("C", 2, 2.22d, 3.65d)); m.Atoms.Add(Atom("C", 1, 2.93d, 4.07d)); m.Atoms.Add(Atom("C", 1, 0.68d, 4.07d)); m.Atoms.Add(Atom("C", 1, 1.01d, 4.63d)); m.Atoms.Add(Atom("C", 1, 2.52d, 4.64d)); m.Atoms.Add(Atom("O", 0, 1.76d, 4.89d)); m.Atoms.Add(Atom("O", 1, 0.68d, 3.24d)); m.Atoms.Add(Atom("C", 2, 1.01d, 5.45d)); m.Atoms.Add(Atom("O", 1, 0.18d, 5.45d)); m.Atoms.Add(Atom("C", 3, 2.52d, 5.46d)); m.Atoms.Add(Atom("O", 0, 2.93d, 3.24d)); m.Atoms.Add(Atom("C", 2, 1.39d, 4.48d)); m.Atoms.Add(Atom("C", 3, 2.22d, 4.48d)); m.Atoms.Add(Atom("C", 2, 3.76d, 3.24d)); m.Atoms.Add(Atom("C", 2, 4.34d, 2.66d)); m.Atoms.Add(Atom("O", 0, 5.16d, 2.66d)); m.Atoms.Add(Atom("C", 3, 5.58d, 3.37d)); m.AddBond(m.Atoms[0], m.Atoms[1], BondOrder.Single); m.AddBond(m.Atoms[1], m.Atoms[2], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[3], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[4], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[5], BondOrder.Single); m.AddBond(m.Atoms[5], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[6], BondOrder.Single); m.AddBond(m.Atoms[3], m.Atoms[7], BondOrder.Single); m.AddBond(m.Atoms[4], m.Atoms[8], BondOrder.Single); m.AddBond(m.Atoms[8], m.Atoms[9], BondOrder.Single); m.AddBond(m.Atoms[5], m.Atoms[10], BondOrder.Single); m.AddBond(m.Atoms[2], m.Atoms[11], BondOrder.Single); m.AddBond(m.Atoms[0], m.Atoms[12], BondOrder.Single); m.AddBond(m.Atoms[12], m.Atoms[13], BondOrder.Single); m.AddBond(m.Atoms[11], m.Atoms[14], BondOrder.Single); m.AddBond(m.Atoms[14], m.Atoms[15], BondOrder.Single); m.AddBond(m.Atoms[15], m.Atoms[16], BondOrder.Single); m.AddBond(m.Atoms[16], m.Atoms[17], BondOrder.Single); EdgeToBondMap bondMap = EdgeToBondMap.WithSpaceFor(m); int[][] graph = GraphUtil.ToAdjList(m, bondMap); Stereocenters stereocenters = new Stereocenters(m, graph, bondMap); stereocenters.CheckSymmetry(); CyclicCarbohydrateRecognition recon = new CyclicCarbohydrateRecognition(m, graph, bondMap, stereocenters); var elements = recon.Recognise(new[] { Projection.Haworth }).ToReadOnlyList(); AssertTetrahedralCenter(elements[0], m.Atoms[2], TetrahedralStereo.AntiClockwise, m.Atoms[2], m.Atoms[1], m.Atoms[11], m.Atoms[5]); AssertTetrahedralCenter(elements[1], m.Atoms[5], TetrahedralStereo.AntiClockwise, m.Atoms[10], m.Atoms[2], m.Atoms[5], m.Atoms[6]); AssertTetrahedralCenter(elements[2], m.Atoms[4], TetrahedralStereo.AntiClockwise, m.Atoms[8], m.Atoms[6], m.Atoms[4], m.Atoms[3]); AssertTetrahedralCenter(elements[3], m.Atoms[3], TetrahedralStereo.AntiClockwise, m.Atoms[3], m.Atoms[4], m.Atoms[7], m.Atoms[0]); AssertTetrahedralCenter(elements[4], m.Atoms[0], TetrahedralStereo.AntiClockwise, m.Atoms[12], m.Atoms[3], m.Atoms[0], m.Atoms[1]); }
/// <inheritdoc/> public override IBitFingerprint GetBitFingerprint(IAtomContainer container) { var keys = GetKeys(container.Builder); var fp = new BitArray(keys.Count); // init SMARTS invariants (connectivity, degree, etc) SmartsPattern.Prepare(container); int numAtoms = container.Atoms.Count; var bmap = EdgeToBondMap.WithSpaceFor(container); var adjlist = GraphUtil.ToAdjList(container, bmap); for (int i = 0; i < keys.Count; i++) { var key = keys[i]; var pattern = key.Pattern; switch (key.Smarts) { case "[!*]": break; case "[!0]": foreach (IAtom atom in container.Atoms) { if (atom.MassNumber != null) { fp.Set(i, true); break; } } break; // ring bits case "[R]1@*@*@1": // 3M RING bit22 case "[R]1@*@*@*@1": // 4M RING bit11 case "[R]1@*@*@*@*@1": // 5M RING bit96 case "[R]1@*@*@*@*@*@1": // 6M RING bit163, x2=bit145 case "[R]1@*@*@*@*@*@*@1": // 7M RING, bit19 case "[R]1@*@*@*@*@*@*@*@1": // 8M RING, bit101 // handled separately break; case "(*).(*)": // bit 166 (*).(*) we can match this in SMARTS but it's faster to just // count the number of components or in this case try to traverse the // component, iff there are some atoms not visited we have more than // one component bool[] visit = new bool[numAtoms]; if (numAtoms > 1 && VisitPart(visit, adjlist, 0, -1) < numAtoms) { fp.Set(165, true); } break; default: if (key.Count == 0) { if (pattern.Matches(container)) { fp.Set(i, true); } } else { // check if there are at least 'count' unique hits, key.count = 0 // means find at least one match hence we add 1 to out limit if (pattern.MatchAll(container).GetUniqueAtoms().AtLeast(key.Count + 1)) { fp.Set(i, true); } } break; } } // Ring Bits // threshold=126, see AllRingsFinder.Threshold.PubChem_97 if (numAtoms > 2) { AllCycles allcycles = new AllCycles(adjlist, Math.Min(8, numAtoms), 126); int numArom = 0; foreach (int[] path in allcycles.GetPaths()) { // length is +1 as we repeat the closure vertex switch (path.Length) { case 4: // 3M bit22 fp.Set(21, true); break; case 5: // 4M bit11 fp.Set(10, true); break; case 6: // 5M bit96 fp.Set(95, true); break; case 7: // 6M bit163->bit145, bit124 numArom > 1 if (numArom < 2) { if (IsAromPath(path, bmap)) { numArom++; if (numArom == 2) { fp.Set(124, true); } } } if (fp[162]) { fp.Set(144, true); // >0 } else { fp.Set(162, true); // >1 } break; case 8: // 7M bit19 fp.Set(18, true); break; case 9: // 8M bit101 fp.Set(100, true); break; } } } return(new BitSetFingerprint(fp)); }