/// <inheritdoc/> public Cycles Find(IAtomContainer molecule, int[][] graph, int length) { RingSearch ringSearch = new RingSearch(molecule, graph); if (this.predefinedLength < length) { length = this.predefinedLength; } IList <int[]> walks = new List <int[]>(6); // all isolated cycles are relevant - all we need to do is walk around // the vertices in the subset 'isolated' foreach (var isolated in ringSearch.Isolated()) { if (isolated.Length <= length) { walks.Add(GraphUtil.Cycle(graph, isolated)); } } // each biconnected component which isn't an isolated cycle is processed // separately as a subgraph. foreach (var fused in ringSearch.Fused()) { // make a subgraph and 'apply' the cycle computation - the walk // (path) is then lifted to the original graph foreach (var cycle in FindInFused(GraphUtil.Subgraph(graph, fused), length)) { walks.Add(Lift(cycle, fused)); } } return(new Cycles(walks.ToArray(), molecule, null)); }
/// <inheritdoc/> public Cycles Find(IAtomContainer molecule, int length) { var bondMap = EdgeToBondMap.WithSpaceFor(molecule); var graph = GraphUtil.ToAdjList(molecule, bondMap); var ringSearch = new RingSearch(molecule, graph); var walks = new List <int[]>(6); // all isolated cycles are relevant - all we need to do is walk around // the vertices in the subset 'isolated' foreach (var isolated in ringSearch.Isolated()) { if (isolated.Length <= length) { walks.Add(GraphUtil.Cycle(graph, isolated)); } } // each biconnected component which isn't an isolated cycle is processed // separately as a subgraph. foreach (var fused in ringSearch.Fused()) { // make a subgraph and 'apply' the cycle computation - the walk // (path) is then lifted to the original graph foreach (var cycle in Apply(GraphUtil.Subgraph(graph, fused), length)) { walks.Add(Lift(cycle, fused)); } } return(new Cycles(walks.ToArray(), molecule, bondMap)); }
/// <summary> /// Recognise the cyclic carbohydrate projections. /// </summary> /// <param name="projections">the types of projections to recognise</param> /// <returns>recognised stereocenters</returns> public IEnumerable <IStereoElement <IChemObject, IChemObject> > Recognise(ICollection <Projection> projections) { if (!projections.Contains(Projection.Haworth) && !projections.Contains(Projection.Chair)) { yield break; } var ringSearch = new RingSearch(container, graph); foreach (var isolated in ringSearch.Isolated()) { if (isolated.Length < 5 || isolated.Length > 7) { continue; } var cycle = Arrays.CopyOf(GraphUtil.Cycle(graph, isolated), isolated.Length); var points = CoordinatesOfCycle(cycle, container); var turns = GetTurns(points); var projection = WoundProjection.OfTurns(turns); if (!projections.Contains(projection.Projection)) { continue; } // ring is not aligned correctly for Haworth if (projection.Projection == Projection.Haworth && !CheckHaworthAlignment(points)) { continue; } var horizontalXy = HorizontalOffset(points, turns, projection.Projection); // near vertical, should also flag as potentially ambiguous if (1 - Math.Abs(horizontalXy.Y) < QuartCardinalityThreshold) { continue; } var above = (int[])cycle.Clone(); var below = (int[])cycle.Clone(); if (!AssignSubstituents(cycle, above, below, projection, horizontalXy)) { continue; } foreach (var center in NewTetrahedralCenters(cycle, above, below, projection)) { yield return(center); } } yield break; }
void Main() { { #region // using NCDK.Graphs.GraphUtil; IAtomContainer m = TestMoleculeFactory.MakeAnthracene(); // compute on the whole graph RelevantCycles relevant = new RelevantCycles(ToAdjList(m)); // it is much faster to compute on the separate ring systems of the molecule int[][] graph = ToAdjList(m); RingSearch ringSearch = new RingSearch(m, graph); // all isolated cycles are relevant foreach (int[] isolated in ringSearch.Isolated()) { int[] path = Cycle(graph, isolated); } // compute the relevant cycles for each system foreach (int[] fused in ringSearch.Fused()) { int[][] subgraph = Subgraph(graph, fused); RelevantCycles relevantOfSubgraph = new RelevantCycles(subgraph); foreach (int[] path in relevantOfSubgraph.GetPaths()) { // convert the sub graph vertices back to the super graph indices for (int i = 0; i < path.Length; i++) { path[i] = fused[path[i]]; } } } #endregion } { IAtomContainer mol = null; #region GetPaths RelevantCycles relevant = new RelevantCycles(ToAdjList(mol)); // ensure the number is manageable if (relevant.Count() < 100) { foreach (int[] path in relevant.GetPaths()) { // process the path } } #endregion } }
public static void Main(string[] args) { // convert the molecule to adjacency list - may be redundant in future IAtomContainer m = TestMoleculeFactory.MakeAlphaPinene(); int[][] g = GraphUtil.ToAdjList(m); // efficient computation/partitioning of the ring systems RingSearch rs = new RingSearch(m, g); // isolated cycles don't need to be run rs.Isolated(); // process fused systems separately foreach (var fused in rs.Fused()) { const int maxDegree = 100; // given the fused subgraph, max cycle size is // the number of vertices AllCycles ac = new AllCycles(GraphUtil.Subgraph(g, fused), fused.Length, maxDegree); // cyclic walks int[][] paths = ac.GetPaths(); } }