/// <summary> /// Checks if 'node' can be added to 'link' without /// violating any conditions pertaining to dangling links. /// Returns null if loop is found or length exceeds threshold. /// Otherwise, adds node to link and returns /// </summary> /// <param name="link">Dangling link</param> /// <param name="node">Node to be added</param> /// <param name="reachedErrorEndPoint">Indicates if we have reached end of dangling link</param> /// <returns>Updated dangling link</returns> private DeBruijnPath CheckAndAddDanglingNode(DeBruijnPath link, DeBruijnNode node, out bool reachedErrorEndPoint) { if (_erodeThreshold != -1 && link.PathNodes.Count == 0 && node.KmerCount < _erodeThreshold) { if (node.IsMarked()) { // There is a loop in this link. No need to update link. // Set flag for end point reached as true and return. reachedErrorEndPoint = true; return(link); } else { node.MarkNode(); reachedErrorEndPoint = false; return(link); } } if (link.PathNodes.Contains(node)) { // There is a loop in this link. No need to update link. // Set flag for end point reached as true and return. reachedErrorEndPoint = true; return(link); } if (link.PathNodes.Count >= _lengthThreshold) { // Length crosses threshold. Not a dangling link. // So set reached error end point as true and return null. reachedErrorEndPoint = true; return(null); } // No error conditions found. Add node to link. reachedErrorEndPoint = false; link.PathNodes.Add(node); return(link); }
/// <summary> /// Starting from potential end of dangling link, trace back along /// extension edges in graph to find if it is a valid dangling link. /// Parallelization Note: No locks used in TraceDanglingLink. /// We only read graph structure here. No modifications are made. /// </summary> /// <param name="isForwardDirection">Boolean indicating direction of dangling link</param> /// <param name="link">Dangling Link</param> /// <param name="node">Node that is next on the link</param> /// <param name="sameOrientation">Orientation of link</param> /// <returns>List of nodes in dangling link</returns> private DeBruijnPath TraceDanglingExtensionLink(bool isForwardDirection, DeBruijnPath link, DeBruijnNode node, bool sameOrientation) { Dictionary <DeBruijnNode, DeBruijnEdge> sameDirectionExtensions, oppDirectionExtensions; bool reachedEndPoint = false; while (!reachedEndPoint) { // Get extensions going in same and opposite directions. if (isForwardDirection ^ sameOrientation) { sameDirectionExtensions = node.LeftExtensionNodes; oppDirectionExtensions = node.RightExtensionNodes; } else { sameDirectionExtensions = node.RightExtensionNodes; oppDirectionExtensions = node.LeftExtensionNodes; } if (sameDirectionExtensions.Count == 0) { // Found other end of dangling link // Add this and return return(CheckAndAddDanglingNode(link, node, out reachedEndPoint)); } else if (oppDirectionExtensions.Count > 1) { // Have reached a point of ambiguity. Return list without updating it if (_erodeThreshold != -1 && !node.IsMarked()) { lock (_danglingLinkExtensionTasks) { _danglingLinkExtensionTasks.Add(new Task <int>((o) => ExtendDanglingLink(isForwardDirection, link, node, sameOrientation, false), TaskCreationOptions.None)); } return(null); } return(link); } else if (sameDirectionExtensions.Count > 1) { // Have reached a point of ambiguity. Return list after updating it link = CheckAndAddDanglingNode(link, node, out reachedEndPoint); if (_erodeThreshold != -1 && reachedEndPoint != true && !node.IsMarked()) { lock (_danglingLinkExtensionTasks) { _danglingLinkExtensionTasks.Add(new Task <int>((o) => ExtendDanglingLink(isForwardDirection, link, node, sameOrientation, true), TaskCreationOptions.None)); } return(null); } return(link); } else { // (sameDirectionExtensions == 1 && oppDirectionExtensions == 1) // Continue traceback. Add this node to that list and recurse. link = CheckAndAddDanglingNode(link, node, out reachedEndPoint); if (reachedEndPoint) { // Loop is found or threshold length has been exceeded. return(link); } else { node = sameDirectionExtensions.First().Key; sameOrientation = !(sameOrientation ^ sameDirectionExtensions.First().Value.IsSameOrientation); } } } return(null); // code will never reach here. Valid returns happen within the while loop. }