/// <summary> /// Get simple paths in the graph. /// </summary> /// <returns>List of simple paths.</returns> private List <ISequence> GetSimplePaths(bool createContigSequences) { //set flag to false so we can find any nodes that are missed during the build _graph.SetNodeVisitState(false); List <ISequence> paths = new List <ISequence>(); Parallel.ForEach(_graph.GetNodes(), node => { int validLeftExtensionsCount = node.LeftExtensionNodesCount; int validRightExtensionsCount = node.RightExtensionNodesCount; if (validLeftExtensionsCount + validRightExtensionsCount == 0) { node.IsVisited = true; // Island. Check coverage if (_coverageThreshold == -1) { if (createContigSequences) { lock (paths) { paths.Add(_graph.GetNodeSequence(node)); } } } else { if (node.KmerCount < _coverageThreshold) { node.MarkNodeForDelete(); } } } else if (validLeftExtensionsCount == 1 && validRightExtensionsCount == 0) { TraceSimplePath(paths, node, false, createContigSequences, true); } else if (validRightExtensionsCount == 1 && validLeftExtensionsCount == 0) { TraceSimplePath(paths, node, true, createContigSequences, true); } }); //All paths starting from ends have now been found, however graph nodes entirely enclosed in a //circular loop have been skipped, since these are small plasmids, etc. fast enough to do not in parallel. //Must also be done sequentially to avoid grabbing nodes from the same circle in the graph concurrently foreach (var node in _graph.GetUnvisitedNodes()) { TraceSimplePath(paths, node, true, createContigSequences, false); } // Reset flag state to false, likely unnecessary as any method using the visit state flag // should set it to false independently _graph.SetNodeVisitState(false); return(paths); }