/// <summary> /// Classifies the node for purposes of creating a graph where links of singly joined nodes are combined /// </summary> /// <returns></returns> public static NODE_TYPE ClassifyNode(DeBruijnNode startNode) { var lefts = startNode.GetLeftExtensionNodes().ToArray(); var rights = startNode.GetRightExtensionNodes().ToArray(); if (lefts.Any(x => rights.Contains(x))) { return(NODE_TYPE.END_LOOPS_ON_ITSELF); } //First to check if this guy can form an infinite circle with itself int validLeftExtensionsCount = lefts.Length; int validRightExtensionsCount = rights.Length; if (validLeftExtensionsCount != 1 && validRightExtensionsCount == 1) { return(NODE_TYPE.GO_RIGHT); } else if (validLeftExtensionsCount == 1 && validRightExtensionsCount != 1) { return(NODE_TYPE.GO_LEFT); } else if (validRightExtensionsCount == 1 && validLeftExtensionsCount == 1) { return(NODE_TYPE.LINK_IN_CHAIN); } else if (validRightExtensionsCount > 1 && validLeftExtensionsCount > 1) { return(NODE_TYPE.NEXUS); } else if (validLeftExtensionsCount != 1 && validRightExtensionsCount != 1) { return(NODE_TYPE.ISLAND); } throw new Exception("Apparently you did not handle all cases..."); }
public IEnumerable <DeBruijnNode> GetNodesLeavingBottom() { //if chain is longer than one, use previous node to get latest if (this.ConstituentNodes.Count > 1) { var bottomNode = ConstituentNodes.Last(); DeBruijnNode penUltimate = ConstituentNodes[ConstituentNodes.Count - 2]; bool goingRight = penUltimate.GetRightExtensionNodes().Contains(bottomNode); var next = goingRight ? penUltimate.GetRightExtensionNodesWithOrientation().Where(x => x.Key == bottomNode).First() : penUltimate.GetLeftExtensionNodesWithOrientation().Where(x => x.Key == bottomNode).First(); var nextSet = goingRight ^ next.Value ? next.Key.GetLeftExtensionNodes() : next.Key.GetRightExtensionNodes(); foreach (var k in nextSet) { yield return(k); } } else { var baseNode = this.ConstituentNodes[0]; Debug.Assert(KmerLength == Sequence.Length); var ns = new Sequence(DnaAlphabet.Instance, baseNode.GetOriginalSymbols(MetaNode.KmerLength)); bool orientationRight; // = baseNode.GetOriginalSymbols(KmerLength).SequenceEqual(new DnaAlphabet(DnaAlphabet.Instance, Sequence)); if (ns.ConvertToString().Equals(Sequence)) { orientationRight = true; } else if ((new Sequence(ns.GetReverseComplementedSequence()).ConvertToString().Equals(Sequence))) { orientationRight = false; } else { throw new Exception("AAA"); } var nextNodes = orientationRight ? baseNode.GetRightExtensionNodes() : baseNode.GetLeftExtensionNodes(); foreach (var v in nextNodes) { yield return(v); } } }
/// <summary> /// Follow a node with one neighbor on either side and make sure it never reaches itself, which is problematic for making these things. /// Note that nodes can go to A->A->C if they refer to themselves but match the reverse compliment of themselves /// </summary> /// <param name="currentNode"></param> /// <param name="goRight"></param> /// <param name="graph"></param> /// <returns></returns> private bool VerifyNotCircular(DeBruijnNode currentNode) { List <DeBruijnNode> visitedNodes = new List <DeBruijnNode>(); if (ClassifyNode(currentNode) != NODE_TYPE.LINK_IN_CHAIN) { throw new Exception("Node type doesn't match well!"); } else { //go right, if we wind up where we started, circle. var nextNode = currentNode.GetRightExtensionNodesWithOrientation().First(); bool goingRight = true; //we now either have the second or third node in path as next while (ClassifyNode(nextNode.Key) == NODE_TYPE.LINK_IN_CHAIN) { visitedNodes.Add(nextNode.Key); //determine if this is a kink or not, which will trigger issue at only first node. if (nextNode.Key == currentNode) { //only one way to get back to the start, either we are in a circle, or the first node loops in to its reverse compliment and exits //the other way, a "kink" so to speak, we know we have visited the right node since we started there, if we visited the left, problems bool leftVisited = visitedNodes.Contains(currentNode.GetLeftExtensionNodes().First()); if (leftVisited) { return(false); } Debug.Assert(visitedNodes.Contains(currentNode.GetRightExtensionNodes().First())); } goingRight = !(goingRight ^ nextNode.Value); var nextSet = goingRight ? nextNode.Key.GetRightExtensionNodesWithOrientation() : nextNode.Key.GetLeftExtensionNodesWithOrientation(); if (nextSet.Count != 1) { return(true); } nextNode = nextSet.First(); } return(true); } }