/// <summary> /// Close the ring bond with the specified 'rnum'. /// </summary> /// <param name="rnum">ring number</param> /// <param name="buffer"></param> /// <exception cref="InvalidSmilesException">bond types did not match</exception> private void CloseRing(int rnum, CharBuffer buffer) { var rbond = rings[rnum]; rings[rnum] = null; int u = rbond.u; int v = stack.Peek(); if (u == v) { throw new InvalidSmilesException("Endpoints of ringbond are the same - loops are not allowed", buffer); } if (g.Adjacent(u, v)) { throw new InvalidSmilesException("Endpoints of ringbond are already connected - multi-edges are not allowed", buffer); } bond = DecideBond(rbond.bond, bond.Inverse(), rbond.pos, buffer); var e = new Edge(u, v, bond); if (bond.IsDirectional) { BitArrays.EnsureCapacity(checkDirectionalBonds, Math.Max(u, v) + 1); checkDirectionalBonds.Set(u, true); checkDirectionalBonds.Set(v, true); if (rbond.bond.IsDirectional) { bondStrPos[e] = rbond.pos; } else { bondStrPos[e] = lastBondPos; } } g.AddEdge(e); bond = Bond.Implicit; // adjust the arrangement replacing where this ring number was openned arrangement[rbond.u].Replace(-rnum, stack.Peek()); if (arrangement.ContainsKey(v)) { arrangement[v].Add(rbond.u); } openRings--; }
/// <summary> /// Add an atom and bond with the atom on the stack (if available and non-dot bond). /// </summary> /// <param name="a">an atom to add</param> /// <param name="buffer"></param> private void AddAtom(IAtom a, CharBuffer buffer) { int v = g.AddAtom(a); if (!stack.IsEmpty) { int u = stack.Pop(); if (bond != Bond.Dot) { var e = new Edge(u, v, bond); if (bond.IsDirectional) { bondStrPos[e] = lastBondPos; BitArrays.EnsureCapacity(checkDirectionalBonds, Math.Max(u, v) + 1); checkDirectionalBonds.Set(u, true); checkDirectionalBonds.Set(v, true); } g.AddEdge(e); if (arrangement.ContainsKey(u)) { arrangement[u].Add(v); } } else { start.Add(v); // start of a new run } } stack.Push(v); bond = Bond.Implicit; // configurations used to create topologies after parsing if (configuration != Configuration.Unknown) { g.AddFlags(Graph.HAS_ATM_STRO); configurations.Add(v, configuration); configuration = Configuration.Unknown; } }
/// <summary> /// Create the topologies (stereo configurations) for the chemical graph. The /// topologies define spacial arrangement around atoms. /// </summary> private void CreateTopologies(CharBuffer buffer) { // create topologies (stereo configurations) foreach (var e in configurations) { AddTopology(e.Key, Topology.ToExplicit(g, e.Key, e.Value)); } for (int v = BitArrays.NextSetBit(checkDirectionalBonds, 0); v >= 0; v = BitArrays.NextSetBit(checkDirectionalBonds, v + 1)) { int nUpV = 0; int nDownV = 0; int nUpW = 0; int nDownW = 0; int w = -1; { int d = g.Degree(v); for (int j = 0; j < d; ++j) { Edge e = g.EdgeAt(v, j); Bond bond = e.GetBond(v); if (bond == Bond.Up) { nUpV++; } else if (bond == Bond.Down) { nDownV++; } else if (bond == Bond.Double) { w = e.Other(v); } } } if (w < 0) { continue; } BitArrays.EnsureCapacity(checkDirectionalBonds, w + 1); checkDirectionalBonds.Set(w, false); { int d = g.Degree(w); for (int j = 0; j < d; ++j) { Edge e = g.EdgeAt(w, j); Bond bond = e.GetBond(w); if (bond == Bond.Up) { nUpW++; } else if (bond == Bond.Down) { nDownW++; } } } if (nUpV + nDownV == 0 || nUpW + nDownW == 0) { continue; } if (nUpV > 1 || nDownV > 1) { int offset1 = -1, offset2 = -1; foreach (var e in g.GetEdges(v)) { if (e.Bond.IsDirectional) { if (offset1 < 0) { offset1 = bondStrPos[e]; } else { offset2 = bondStrPos[e]; } } } var errorPos = InvalidSmilesException.Display(buffer, offset1 - buffer.Length, offset2 - buffer.Length); if (strict) { throw new InvalidSmilesException($"Ignored invalid Cis/Trans specification: {errorPos}"); } else { warnings.Add($"Ignored invalid Cis/Trans specification: {errorPos}"); } } if (nUpW > 1 || nDownW > 1) { int offset1 = -1; int offset2 = -1; foreach (var e in g.GetEdges(w)) { if (e.Bond.IsDirectional) { if (offset1 < 0) { offset1 = bondStrPos[e]; } else { offset2 = bondStrPos[e]; } } } var errorPos = InvalidSmilesException.Display(buffer, offset1 - buffer.Length, offset2 - buffer.Length); if (strict) { throw new InvalidSmilesException($"Ignored invalid Cis/Trans specification: {errorPos}"); } else { warnings.Add($"Ignored invalid Cis/Trans specification: {errorPos}"); } } } }
/// <summary> /// Adds a new node to the RGraph. /// </summary> /// <param name="newNode">The node to add to the graph</param> public void AddNode(RNode newNode) { graph.Add(newNode); BitArrays.EnsureCapacity(graphBitSet, graph.Count); graphBitSet.Set(graph.Count - 1, true); }
/// <summary> /// Create the topologies (stereo configurations) for the chemical graph. The /// topologies define spacial arrangement around atoms. /// </summary> private void CreateTopologies(CharBuffer buffer) { // create topologies (stereo configurations) foreach (var e in configurations) { AddTopology(e.Key, Topology.ToExplicit(g, e.Key, e.Value)); } for (int v = BitArrays.NextSetBit(checkDirectionalBonds, 0); v >= 0; v = BitArrays.NextSetBit(checkDirectionalBonds, v + 1)) { int nUpV = 0; int nDownV = 0; int nUpW = 0; int nDownW = 0; int w = -1; { int d = g.Degree(v); for (int j = 0; j < d; ++j) { Edge e = g.EdgeAt(v, j); Bond bond = e.GetBond(v); if (bond == Bond.Up) { nUpV++; } else if (bond == Bond.Down) { nDownV++; } else if (bond == Bond.Double) { w = e.Other(v); } } } if (w < 0) { continue; } BitArrays.EnsureCapacity(checkDirectionalBonds, w + 1); checkDirectionalBonds.Set(w, false); { int d = g.Degree(w); for (int j = 0; j < d; ++j) { Edge e = g.EdgeAt(w, j); Bond bond = e.GetBond(w); if (bond == Bond.Up) { nUpW++; } else if (bond == Bond.Down) { nDownW++; } } } if (nUpV + nDownV == 0 || nUpW + nDownW == 0) { continue; } if (nUpV > 1) { throw new InvalidSmilesException("Multiple directional bonds on atom " + v, buffer); } if (nDownV > 1) { throw new InvalidSmilesException("Multiple directional bonds on atom " + v, buffer); } if (nUpW > 1) { throw new InvalidSmilesException("Multiple directional bonds on atom " + w, buffer); } if (nDownW > 1) { throw new InvalidSmilesException("Multiple directional bonds on atom " + w, buffer); } } }