Example #1
0
 /// <summary>
 /// Add the given list of paths to local variable.
 /// </summary>
 /// <param name="pathsList">List of paths to add.</param>
 public void AddPath(DeBruijnPath path)
 {
     this.paths.Add(path);
 }
Example #2
0
        /// <summary>
        /// Try and extend dangling links following
        /// graph clean-up after erosion.
        /// </summary>
        /// <param name="isForwardDirection">Boolean indicating direction of dangling link.</param>
        /// <param name="danglingLink">Dangling Link.</param>
        /// <param name="node">Node that is next on the link.</param>
        /// <param name="sameOrientation">Orientation of link.</param>
        /// <param name="removeLast">Boolean indicating if last node 
        /// in link has to be removed before extending.</param>
        /// <returns>Length of dangling link found after extension.</returns>
        private int ExtendDanglingLink(bool isForwardDirection, DeBruijnPath danglingLink, DeBruijnNode node, bool sameOrientation, bool removeLast)
        {
            if (removeLast)
            {
                danglingLink.PathNodes.Remove(node);
            }

            if (danglingLink.PathNodes.Count == 0)
            {
                // DanglingLink is empty. So check if node is an end-point.
                if (node.RightExtensionNodesCount == 0)
                {
                    danglingLink = TraceDanglingExtensionLink(false, new DeBruijnPath(), node, true);
                }
                else if (node.LeftExtensionNodesCount == 0)
                {
                    danglingLink = TraceDanglingExtensionLink(true, new DeBruijnPath(), node, true);
                }
                else
                {
                    // Not an end-point. Return length as 0
                    return 0;
                }
            }
            else
            {
                // Extend existing link.
                danglingLink = TraceDanglingExtensionLink(isForwardDirection, danglingLink, node, sameOrientation);
            }

            // Return length of dangling link found.
            return danglingLink == null ? 0 : danglingLink.PathNodes.Count;

        }
Example #3
0
        /// <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)
        {
            for (; ;)
            {
                // Get extensions going in same and opposite directions.
                Dictionary<DeBruijnNode, bool> sameDirectionExtensions;
                int sameDirectionExtensionsCount, oppDirectionExtensionsCount;
                
                if (isForwardDirection ^ sameOrientation)
                {
                    sameDirectionExtensionsCount = node.LeftExtensionNodesCount;
                    oppDirectionExtensionsCount = node.RightExtensionNodesCount;
                    sameDirectionExtensions = node.GetLeftExtensionNodesWithOrientation();
                }
                else
                {
                    sameDirectionExtensionsCount = node.RightExtensionNodesCount;
                    oppDirectionExtensionsCount = node.LeftExtensionNodesCount;
                    sameDirectionExtensions = node.GetRightExtensionNodesWithOrientation();
                }

                bool reachedEndPoint;
                if (sameDirectionExtensionsCount == 0)
                {
                    // Found other end of dangling link
                    return CheckAndAddDanglingNode(link, node, out reachedEndPoint);
                }

                if (oppDirectionExtensionsCount > 1)
                {
                    // Have reached a point of ambiguity. Return list without updating it.
                    if (this.erodeThreshold != -1 && !node.IsMarkedForDelete)
                    {
                        lock (this.danglingLinkExtensionTasks)
                        {
                            // This task essentially just returns back to this method after other ones are removed
                            this.danglingLinkExtensionTasks.Add(new Task<int>(_ => 
                                ExtendDanglingLink(isForwardDirection, link, node, sameOrientation, false), TaskCreationOptions.None));
                        }
                        return null;
                    }
                    return link;
                }

                if (sameDirectionExtensionsCount > 1)
                {
                    // Have reached a point of ambiguity. Return list after updating it.
                    link = CheckAndAddDanglingNode(link, node, out reachedEndPoint);
                    if (this.erodeThreshold != -1 && reachedEndPoint != true && !node.IsMarkedForDelete)
                    {
                        lock (this.danglingLinkExtensionTasks)
                        {
                            this.danglingLinkExtensionTasks.Add(new Task<int>(_ => 
                                ExtendDanglingLink(isForwardDirection, link, node, sameOrientation, true), TaskCreationOptions.None));
                        }
                        return null;
                    }
                    return link;
                }

                // (sameDirectionExtensions == 1 && oppDirectionExtensions == 1)
                // Continue trace back. 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;
                }

                // Still in loop, so just add the extension and keeps going
                var item = sameDirectionExtensions.First();
                node = item.Key;
                sameOrientation = !(sameOrientation ^ item.Value);
            }
        }
Example #4
0
        /// <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 (this.erodeThreshold != -1 && link.PathNodes.Count == 0 && node.KmerCount < this.erodeThreshold)
            {
                if (node.IsMarkedForDelete)
                {
                    // 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;
                }
                
                node.MarkNodeForDelete();
                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;
        }
Example #5
0
        /// <summary>
        /// Removes nodes in link from the graph.
        /// Parallelization Note: Locks required here. We are modifying graph structure here.
        /// </summary>
        /// <param name="nodes">List of nodes to remove.</param>
        /// <param name="lastNodes">Set of all nodes occurring at end of dangling links.</param>
        private static void RemoveLinkNodes(DeBruijnPath nodes, HashSet<DeBruijnNode> lastNodes)
        {
            // Nodes in the list are part of a single dangling link.
            // Only the last element of link can have left or right extensions that are valid parts of graph.
            DeBruijnNode linkStartNode = nodes.PathNodes.Last();

            // Update adjacency of nodes connected to the last node. 
            // Read lock not required as linkStartNode's dictionary will not get updated
            // Locks used during removal of extensions.
            foreach (DeBruijnNode graphNode in linkStartNode.GetExtensionNodes())
            {
                // Condition to avoid updating other linkStartNode's dictionary. Reduces conflicts.
                if (!lastNodes.Contains(graphNode))
                {
                    graphNode.RemoveExtensionThreadSafe(linkStartNode);
                }
            }
        }