// Simplify the graph by compacting edges in the given direction void Bigraph::simplify(EdgeDir dir) { bool graph_changed = true; while(graph_changed) { graph_changed = false; VertexPtrMapIter iter = m_vertices.begin(); while(iter != m_vertices.end()) { // Get the edges for this direction EdgePtrVec edges = iter->second->getEdges(dir); // If there is a single edge in this direction, merge the vertices // Don't merge singular self edges though if(edges.size() == 1 && !edges.front()->isSelf()) { // Check that the edge back is singular as well Edge* pSingle = edges.front(); Edge* pTwin = pSingle->getTwin(); Vertex* pV2 = pSingle->getEnd(); if(pV2->countEdges(pTwin->getDir()) == 1) { merge(iter->second, pSingle); graph_changed = true; } } ++iter; } } }
// Construct the walk structure from a vector of edges SGWalk::SGWalk(const EdgePtrVec& edgeVec, bool bIndexWalk) : m_extensionDistance(0), m_extensionFinished(false) { assert(!edgeVec.empty()); if(bIndexWalk) m_pWalkIndex = new WalkIndex; else m_pWalkIndex = NULL; // The start vector is the start vertex of the first edge Edge* first = edgeVec.front(); m_pStartVertex = first->getStart(); for(EdgePtrVec::const_iterator iter = edgeVec.begin(); iter != edgeVec.end(); ++iter) { addEdge(*iter); } }
// Find bubbles (nodes where there is a split and then immediate rejoin) and mark them for removal bool SGBubbleVisitor::visit(StringGraph* /*pGraph*/, Vertex* pVertex) { bool bubble_found = false; for(size_t idx = 0; idx < ED_COUNT; idx++) { EdgeDir dir = EDGE_DIRECTIONS[idx]; EdgePtrVec edges = pVertex->getEdges(dir); if(edges.size() > 1) { Vertex* pStart = pVertex; Vertex* pEnd = NULL; // Check the vertices for(size_t i = 0; i < edges.size(); ++i) { Edge* pVWEdge = edges[i]; Vertex* pWVert = pVWEdge->getEnd(); // Get the edges from w in the same direction EdgeDir transDir = !pVWEdge->getTwinDir(); EdgePtrVec wEdges = pWVert->getEdges(transDir); if(pWVert->getColor() == GC_RED) return false; // If the bubble has collapsed, there should only be one edge if(wEdges.size() == 1) { Vertex* pBubbleEnd = wEdges.front()->getEnd(); if(pBubbleEnd->getColor() == GC_RED) return false; } } // Mark the vertices for(size_t i = 0; i < edges.size(); ++i) { Edge* pVWEdge = edges[i]; Vertex* pWVert = pVWEdge->getEnd(); // Get the edges from w in the same direction EdgeDir transDir = !pVWEdge->getTwinDir(); EdgePtrVec wEdges = pWVert->getEdges(transDir); // If the bubble has collapsed, there should only be one edge if(wEdges.size() == 1) { Vertex* pBubbleEnd = wEdges.front()->getEnd(); if(pBubbleEnd->getColor() == GC_BLACK) { // The endpoint has been visited, set this vertex as needing removal // and set the endpoint as unvisited pWVert->setColor(GC_RED); bubble_found = true; pEnd = pBubbleEnd; } else { pBubbleEnd->setColor(GC_BLACK); pWVert->setColor(GC_BLUE); } } } // Unmark vertices for(size_t i = 0; i < edges.size(); ++i) { Edge* pVWEdge = edges[i]; Vertex* pWVert = pVWEdge->getEnd(); // Get the edges from w in the same direction EdgeDir transDir = !pVWEdge->getTwinDir(); EdgePtrVec wEdges = pWVert->getEdges(transDir); // If the bubble has collapsed, there should only be one edge if(wEdges.size() == 1) { Vertex* pBubbleEnd = wEdges.front()->getEnd(); pBubbleEnd->setColor(GC_WHITE); } if(pWVert->getColor() == GC_BLUE) pWVert->setColor(GC_WHITE); } (void)pStart; (void)pEnd; if(bubble_found) { /* SGWalkVector walkVector; SGSearch::findWalks(pStart, pEnd, dir, 1000, 20, walkVector); if(walkVector.size() == 2) { SGWalk& walk1 = walkVector[0]; SGWalk& walk2 = walkVector[1]; int len1 = walk1.getStartToEndDistance(); int len2 = walk2.getStartToEndDistance(); int diff = len1 - len2; std::string type = "SNP"; if(diff != 0) { type = "INDEL"; } std::cout << "Bubble " << pStart->getID() << " to " << pEnd->getID() << " is a " << type << "(d: " << diff << ")\n"; } */ ++num_bubbles; } } } return bubble_found; }