bool SVLocus:: isNoiseNode( const unsigned minMergeEdgeCount, const NodeIndexType nodeIndex) const { const SVLocusNode& node(getNode(nodeIndex)); const SVLocusEdgeManager edgeMap(node.getEdgeManager()); for (const SVLocusEdgesType::value_type& edge : edgeMap.getMap()) { if (edge.second.getCount() >= minMergeEdgeCount) return false; if (getEdge(edge.first,nodeIndex).getCount() >= minMergeEdgeCount) return false; } return true; }
void SVLocus:: clearNodeEdges(NodeIndexType nodePtr) { using namespace illumina::common; static const std::string logtag("SVLocus::clearNodeEdges"); #ifdef DEBUG_SVL log_os << logtag << " from nodeIndex: " << nodePtr << "\n"; #endif SVLocusNode& node(getNode(nodePtr)); const SVLocusEdgeManager edgeMap(node.getEdgeManager()); for (const SVLocusEdgesType::value_type& edgeIter : edgeMap.getMap()) { #ifdef DEBUG_SVL log_os << logtag << " clearing remote Index: " << edgeIter.first << "\n"; #endif // skip self edge (otherwise we invalidate iterators in this foreach loop) if (edgeIter.first == nodePtr) continue; SVLocusNode& remoteNode(getNode(edgeIter.first)); try { remoteNode.eraseEdge(nodePtr); } catch (illumina::common::ExceptionData& e) { std::ostringstream oss; oss << "ERROR: " << logtag << " no return edge on remote node.\n" << "\tlocal_node: " << node << "\tremote_node: " << remoteNode; e << illumina::common::ExceptionMsg(oss.str()); throw; } } node.clear(); }
void SVLocus:: mergeNode( const NodeIndexType fromIndex, const NodeIndexType toIndex, flyweight_observer_t* obs) { using namespace illumina::common; assert(fromIndex != toIndex); #ifdef DEBUG_SVL static const std::string logtag("SVLocus::mergeNode"); log_os << logtag << " from: " << fromIndex << " to: " << toIndex << " size: " << size() << "\n"; #endif SVLocusNode& fromNode(getNode(fromIndex)); SVLocusNode& toNode(getNode(toIndex)); #ifdef DEBUG_SVL log_os << logtag << " BEFORE fromNode: " << fromNode; log_os << logtag << " BEFORE toNode: " << toNode; #endif if (fromNode.getInterval().tid != toNode.getInterval().tid) { std::ostringstream oss; oss << "ERROR: Attempting to merge nodes on different chromosomes\n" << "\tNode1: " << fromNode << "\tNode2: " << toNode; BOOST_THROW_EXCEPTION(LogicException(oss.str())); } notifyDelete(obs,toIndex); toNode.setIntervalRange(merge_range(toNode.getInterval().range,fromNode.getInterval().range)); const bool isToCount(toNode.isOutCount()); const bool isFromCount(fromNode.isOutCount()); if ((! isToCount) && (isFromCount)) { toNode.setEvidenceRange(fromNode.getEvidenceRange()); } else if ((! isFromCount) && (isToCount)) { // pass (keep toNode value as is) } else { toNode.setEvidenceRange(merge_range(toNode.getEvidenceRange(),fromNode.getEvidenceRange())); } notifyAdd(obs,toIndex); // now take all fromNode edges and 'redirect' them to the toNode index // const SVLocusEdgeManager edgeMap(fromNode.getEdgeManager()); for (const SVLocusEdgesType::value_type& fromNodeEdgeIter : edgeMap.getMap()) { // alias value_type components (not required, but makes the logic easier to follow): const NodeIndexType& fromNodeEdgeIndex(fromNodeEdgeIter.first); const SVLocusEdge* fromNodeEdgePtr(&(fromNodeEdgeIter.second)); #ifdef DEBUG_SVL // is this edge between the to and from nodes? const bool isToFromEdge(fromNodeEdgeIndex == toIndex); log_os << logtag << " handle fromEdge: " << _index << ":" << fromNodeEdgeIndex << " isToFromEdge: " << isToFromEdge << "\n"; #endif // is this a self edge of the from node? const bool isSelfFromEdge(fromNodeEdgeIndex == fromIndex); if (isSelfFromEdge) { // self-edge needs to be handled as a special case: toNode.mergeEdge(toIndex,*(fromNodeEdgePtr)); continue; } // Check for the special case when there is an edge between from and to, in this case // the counts have to be handled so that counts in each region still approximate // fragment support. Normally (the chimera case) -- a single fragment will create // edges and nodes with weight X. If this is a non-chimera and the nodes collide and // merge, we want to prevent the evidence from being doubled to 2X when it should not be. // // To achieve this, we take the max edge counts from the two nodes being merged instead // of the sum. This is an approximate solution, but very simple to add into the // graph without blowing up per-node/edge storage. // const bool isFromToEdge(fromNodeEdgeIndex == toIndex); unsigned mergeCount(0); if (isFromToEdge) { auto getNodeEdgeCount = [](const SVLocusNode& node, const NodeIndexType index) -> unsigned { if (! node.isEdge(index)) return 0u; return node.getEdge(index).getCount(); }; // determine what the override edge count should be: const unsigned fromCount(fromNodeEdgePtr->getCount()); const unsigned toCount(getNodeEdgeCount(toNode,fromIndex)); const unsigned maxCount(std::max(fromCount,toCount)); mergeCount = getNodeEdgeCount(toNode,toIndex) + maxCount; } // update local edge: toNode.mergeEdge(fromNodeEdgeIndex,*(fromNodeEdgePtr)); if (isFromToEdge) { toNode.setEdgeCount(toIndex,mergeCount); toNode.setEdgeCount(fromIndex,0); } // update remote inputNodeEdgeIter { SVLocusNode& remoteNode(getNode(fromNodeEdgeIndex)); try { const SVLocusEdge remoteEdge(remoteNode.getEdge(fromIndex)); remoteNode.mergeEdge(toIndex, remoteEdge); } catch (illumina::common::ExceptionData& e) { // decorate an in-flight exception: std::ostringstream oss; oss << "ERROR: Can't find return edge to node index: " << _index << ":" << fromIndex << " in remote node index: " << _index << ":" << fromNodeEdgeIter.first << "\n" << "\tlocal_node: " << fromNode << "\tremote_node: " << remoteNode; e << illumina::common::ExceptionMsg(oss.str()); throw; } } } #ifdef DEBUG_SVL log_os << logtag << " AFTER toNode: " << toNode; #endif clearNodeEdges(fromIndex); }
void SVLocus:: eraseNode( const NodeIndexType nodePtr, flyweight_observer_t* obs) { using namespace illumina::common; if (nodePtr >= _graph.size()) return; clearNodeEdges(nodePtr); NodeIndexType fromPtr(_graph.size()-1); #ifdef DEBUG_SVL static const std::string logtag("SVLocus::eraseNode"); log_os << logtag << " " << _index << ":" << nodePtr << " transfer_in: " << _index << ":" << fromPtr << " \n"; log_os << logtag << " BEFORE: " << getNode(nodePtr) << "\n"; #endif if (fromPtr != nodePtr) { #ifdef DEBUG_SVL log_os << logtag << " transfer_in: BEFORE: " << getNode(fromPtr) << "\n"; #endif // reassign fromNode's remote edges before shifting its address: // bool isHandleSelfEdge(false); SVLocusNode& fromNode(getNode(fromPtr)); const SVLocusEdgeManager edgeMap(fromNode.getEdgeManager()); for (const SVLocusEdgesType::value_type& edgeIter : edgeMap.getMap()) { const bool isSelfEdge(edgeIter.first == fromPtr); if (isSelfEdge) { // have to handle this outside the foreach loop so that we // don't invalidate our iterators: isHandleSelfEdge=true; continue; } SVLocusNode& remoteNode(getNode(edgeIter.first)); remoteNode.moveEdge(fromPtr,nodePtr); } if (isHandleSelfEdge) { fromNode.moveEdge(fromPtr,nodePtr); } notifyDelete(obs,nodePtr); _graph[nodePtr] = _graph[fromPtr]; notifyAdd(obs,nodePtr); #ifdef DEBUG_SVL log_os << logtag << " transfer_in: AFTER: " << getNode(nodePtr) << "\n"; #endif } notifyDelete(obs,fromPtr); _graph.resize(fromPtr); }
unsigned SVLocus:: cleanNodeCore( const unsigned minMergeEdgeCount, const NodeIndexType nodeIndex, std::set<NodeIndexType>& emptyNodes) { #ifdef DEBUG_SVL static const std::string logtag("SVLocus::cleanNodeCore"); log_os << logtag << " nodeAddy: " << _index << ":" << nodeIndex << "\n"; #endif unsigned totalCleaned(0); SVLocusNode& queryNode(getNode(nodeIndex)); std::vector<NodeIndexType> eraseEdges; const SVLocusEdgeManager edgeMap(queryNode.getEdgeManager()); for (const SVLocusEdgesType::value_type& edgeIter : edgeMap.getMap()) { const SVLocusEdge* edgePtr(&(edgeIter.second)); if (0 != edgePtr->getCount()) { if (edgePtr->getCount() < minMergeEdgeCount) { // clean criteria met -- go ahead and erase edge count: totalCleaned += edgePtr->getCount(); queryNode.setEdgeCount(edgeIter.first,0); // we've just snuck around the const iterator by calling the clearEdge function against this edge, // so we have to fix this by hand: edgePtr=&(queryNode.getEdge(edgeIter.first)); } } if (0 == edgePtr->getCount()) { // if the out edge count is zero, see if the in-edge count is also zero -- // if so, erase edge // const SVLocusEdge& fromRemoteEdge(getEdge(edgeIter.first,nodeIndex)); if (0 == fromRemoteEdge.getCount()) { eraseEdges.push_back(edgeIter.first); // also check to see if the remote node will be empty after // this edge deletion: const SVLocusNode& remoteNode(getNode(edgeIter.first)); if ((! remoteNode.isOutCount()) && (1 == remoteNode.size())) { emptyNodes.insert(edgeIter.first); } } } } // delete empty edges: for (const NodeIndexType toIndex : eraseEdges) { #ifdef DEBUG_SVL log_os << logtag << " deleting edge: " << _index << ":" << nodeIndex << "->" << _index << ":" << toIndex << "\n"; #endif eraseEdgePair(nodeIndex,toIndex); } // if true add the target node to the erase list: if ((queryNode.empty()) && (! queryNode.isOutCount())) { emptyNodes.insert(nodeIndex); } #ifdef DEBUG_SVL log_os << logtag << " emptyEdges:\n"; for (const NodeIndexType toIndex : eraseEdges) { log_os << logtag << "\tedge: " << _index << ":" << nodeIndex << "->" << _index << ":" << toIndex << "\n"; } log_os << "cleanNodeCore emptyNodes\n"; for (const NodeIndexType nodeIndex2 : emptyNodes) { log_os << logtag << "\tnodeAddy: " << _index << ":" << nodeIndex2 << "\n"; } log_os << logtag << " totalCleaned: " << totalCleaned << "\n"; #endif return totalCleaned; }
void EdgeRetrieverJumpBin:: advanceEdge() { typedef SVLocusEdgesType::const_iterator edgeiter_t; const bool isFilterNodes(_graphNodeMaxEdgeCount>0); // advance to next edge unless this is the first iteration: if (0 != _edgeIndex) _edge.nodeIndex2++; while (_edge.locusIndex < _set.size()) { const SVLocus& locus(_set.getLocus(_edge.locusIndex)); while (_edge.nodeIndex1<locus.size()) { const SVLocusNode& node1(locus.getNode(_edge.nodeIndex1)); const bool isEdgeFilterNode1(isFilterNodes && (node1.size()>_graphNodeMaxEdgeCount)); const SVLocusEdgeManager node1Manager(node1.getEdgeManager()); edgeiter_t edgeIter(node1Manager.getMap().lower_bound(_edge.nodeIndex2)); const edgeiter_t edgeIterEnd(node1Manager.getMap().cend()); for (; edgeIter != edgeIterEnd; ++edgeIter) { _edge.nodeIndex2 = edgeIter->first; // if both nodes have high edge counts we filter out the edge: if (isEdgeFilterNode1) { const SVLocusNode& node2(locus.getNode(_edge.nodeIndex2)); const bool isEdgeFilterNode2(node2.size()>_graphNodeMaxEdgeCount); if (isEdgeFilterNode2) { #ifdef DEBUG_EDGER log_os << "EDGER: advance filtering @ index: " << _edgeIndex << "\n"; #endif continue; } } const unsigned firstTargetBin(_edgeIndex%_binCount); unsigned targetBin(firstTargetBin); do { if (_binTotalCount[targetBin] < _avgBinTotalCount) break; targetBin=((targetBin+1)%_binCount); } while (targetBin != firstTargetBin); #ifdef DEBUG_EDGER log_os << "EDGER: edgeIndex,ftarget,target,binIndex " << _edgeIndex << " " << firstTargetBin << " " << targetBin << " " << _binIndex << "\n"; #endif _edgeIndex++; if (targetBin == _binIndex) { // get edge count: unsigned edgeCount(edgeIter->second.getCount()); { const bool isSelfEdge(edgeIter->first == _edge.nodeIndex1); if (! isSelfEdge) edgeCount += locus.getEdge(edgeIter->first,_edge.nodeIndex1).getCount(); } _binTotalCount[targetBin] += edgeCount; return; } } ++_edge.nodeIndex1; _edge.nodeIndex2=_edge.nodeIndex1; } ++_edge.locusIndex; _edge.nodeIndex1=0; _edge.nodeIndex2=0; } }
void EdgeRetrieverBin:: jumpToFirstEdge() { typedef SVLocusEdgesType::const_iterator edgeiter_t; const bool isFilterNodes(_graphNodeMaxEdgeCount>0); // first catch headCount up to the begin edge if required: while (true) { assert(_edge.locusIndex<_set.size()); const SVLocus& locus(_set.getLocus(_edge.locusIndex)); const unsigned locusObservationCount(locus.totalObservationCount()); if ((_headCount+locusObservationCount) > _beginCount) { while (true) { const SVLocusNode& node1(locus.getNode(_edge.nodeIndex1)); const bool isEdgeFilterNode1(isFilterNodes && (node1.size()>_graphNodeMaxEdgeCount)); const SVLocusEdgeManager node1Manager(node1.getEdgeManager()); edgeiter_t edgeIter(node1Manager.getMap().lower_bound(_edge.nodeIndex1)); const edgeiter_t edgeiterEnd(node1Manager.getMap().end()); for (; edgeIter != edgeiterEnd; ++edgeIter) { unsigned edgeCount(edgeIter->second.getCount()); const bool isSelfEdge(edgeIter->first == _edge.nodeIndex1); if (! isSelfEdge) edgeCount += locus.getEdge(edgeIter->first,_edge.nodeIndex1).getCount(); _headCount += edgeCount; if (_headCount > _beginCount) { _edge.nodeIndex2 = edgeIter->first; // if both nodes have high edge counts we filter out the edge: if (isEdgeFilterNode1) { const SVLocusNode& node2(locus.getNode(_edge.nodeIndex2)); const bool isEdgeFilterNode2(node2.size()>_graphNodeMaxEdgeCount); if (isEdgeFilterNode2) { #ifdef DEBUG_EDGER log_os << "EDGER: jump filtering @ hc: " << _headCount << "\n"; #endif continue; } } return; } } _edge.nodeIndex1++; } assert(_headCount >= _beginCount); } _headCount += locusObservationCount; _edge.locusIndex++; } assert(false && "jumpToFirstEdge: invalid state"); }
void EdgeRetrieverBin:: advanceEdge() { typedef SVLocusEdgesType::const_iterator edgeiter_t; const bool isFilterNodes(_graphNodeMaxEdgeCount>0); if (0 != _headCount) _edge.nodeIndex2++; bool isLastFiltered(false); while (true) { if (isLastFiltered && (_edge.locusIndex == _set.size())) { _headCount = (_endCount + 1); return; } assert(_edge.locusIndex<_set.size()); const SVLocus& locus(_set.getLocus(_edge.locusIndex)); while (_edge.nodeIndex1<locus.size()) { const SVLocusNode& node1(locus.getNode(_edge.nodeIndex1)); const bool isEdgeFilterNode1(isFilterNodes && (node1.size()>_graphNodeMaxEdgeCount)); const SVLocusEdgeManager node1Manager(node1.getEdgeManager()); edgeiter_t edgeIter(node1Manager.getMap().lower_bound(_edge.nodeIndex2)); const edgeiter_t edgeIterEnd(node1Manager.getMap().end()); for (; edgeIter != edgeIterEnd; ++edgeIter) { unsigned edgeCount(edgeIter->second.getCount()); const bool isSelfEdge(edgeIter->first == _edge.nodeIndex1); if (! isSelfEdge) edgeCount += locus.getEdge(edgeIter->first,_edge.nodeIndex1).getCount(); _headCount += edgeCount; _edge.nodeIndex2 = edgeIter->first; // if both nodes have high edge counts we filter out the edge: if (isEdgeFilterNode1) { const SVLocusNode& node2(locus.getNode(_edge.nodeIndex2)); const bool isEdgeFilterNode2(node2.size()>_graphNodeMaxEdgeCount); if (isEdgeFilterNode2) { #ifdef DEBUG_EDGER log_os << "EDGER: advance filtering @ hc: " << _headCount << "\n"; #endif isLastFiltered=true; continue; } } return; } ++_edge.nodeIndex1; _edge.nodeIndex2=_edge.nodeIndex1; } ++_edge.locusIndex; _edge.nodeIndex1=0; _edge.nodeIndex2=0; } assert(false && "advanceEdge: invalid state"); }
void SVLocusSet:: getNodeMergeableIntersect( const LocusIndexType inputLocusIndex, const NodeIndexType inputNodeIndex, const bool isInputLocusMoved, std::set<NodeAddressType>& mergeIntersectNodes) const { // // TODO: There's room for significant optimization of these methods. The improvements are not trivial, // but they would allow us to filter fewer nodes from being merged when node intersection counts become large. // // // There are two ways sets of mergeable nodes can occur: // // (1) There is a set of nodes which overlap with both input node and one // of the remote nodes that the input points to (ie they have a shared edge). // When totaled together, the edge count of this set + the inputNode edge // exceeds minMergeEdgeCount. // // (2) The input node either contains an edge which is greater than minMergeEdgeCount // or will contain such an edge due to (1), in this case the input node can be merged // with a locally overlapping node which also contains an edge which is greater than // minMergeEdgeCount. Note that in case (2) remote node intersection is not required. // const NodeAddressType inputAddy(std::make_pair(inputLocusIndex,inputNodeIndex)); const SVLocusNode& inputNode(getNode(inputAddy)); #ifdef DEBUG_SVL static const std::string logtag("SVLocusSet::getNodeMergableIntersect"); log_os << logtag << " inputNode: " << inputAddy << " " << inputNode; checkState(); #endif // reuse this intersectNodes as a temporary throughout the methods below std::set<NodeAddressType> intersectNodes; // // build a new index, which contains, for all nodes x which intersect the input, an // enumeration of the remote nodes Y connected by edges to node x (remoteIntersectNodes) // and a map for each node y \in Y pointing back to node x (remoteIntersectNodeToLocalNodeMap) // LocusSetIndexerType remoteIntersectNodes(*this); EdgeMapType remoteIntersectNodeToLocalNodeMap; // nodes which intersect the input and have already been certified as signal: std::set<NodeAddressType> signalIntersectNodes; { // get a standard intersection of the input node: getNodeIntersect(inputLocusIndex, inputNodeIndex, intersectNodes); // // 1. build the new remoteIntersectNodes/remoteIntersectNodeToLocalNodeMap index // for (const NodeAddressType& intersectAddy : intersectNodes) { const SVLocusNode& intersectNode(getNode(intersectAddy)); // get the remotes of each node which intersect with the query node, // place these in remoteIntersectNodes const SVLocusEdgeManager edgeMap(intersectNode.getEdgeManager()); for (const SVLocusEdgesType::value_type& intersectEdge : edgeMap.getMap()) { // build remote <-> local indexing structures: NodeAddressType remoteAddy(std::make_pair(intersectAddy.first,intersectEdge.first)); remoteIntersectNodes.data().insert(remoteAddy); remoteIntersectNodeToLocalNodeMap.insert(std::make_pair(remoteAddy,intersectAddy.second)); } } #ifdef DEBUG_SVL log_os << logtag << " remoteIntersectNodes.size(): " << remoteIntersectNodes.data().size() << "\n"; for (const NodeAddressType& addy : remoteIntersectNodes.data()) { log_os << logtag << "\tremoteIntersectNode: " << addy << " " << getNode(addy); } #endif // // 2. get the signal node set: // // Note that the signal node search is not transitive b/c we have required all signal nodes // in the graph to have merged already. // for (const NodeAddressType& intersectAddy : intersectNodes) { if (! isNoiseNode(intersectAddy)) { signalIntersectNodes.insert(intersectAddy); } } #ifdef DEBUG_SVL log_os << logtag << " signalIntersect.size(): " << signalIntersectNodes.size() << "\n"; for (const NodeAddressType& addy : signalIntersectNodes) { log_os << logtag << "\tsignalIntersectNode: " << addy << " " << getNode(addy); } #endif } // // begin building the primary function output, mergeIntersectNodes, by enumerating all edges of the input node // mergeIntersectNodes.clear(); // loop through each edge connected to the input node const SVLocusEdgeManager edgeMap(inputNode.getEdgeManager()); for (const SVLocusEdgesType::value_type& inputEdge : edgeMap.getMap()) { #ifdef DEBUG_SVL log_os << logtag << " processing edge: " << inputAddy << "->" << inputLocusIndex << ":" << inputEdge.first << "\n"; checkState(); #endif // // for each edge from the input node, get all intersecting edges // // 'intersecting edge' means that the nodes connected by the two edges each overlap // std::vector<EdgeInfoType> inputIntersectEdges; getIntersectingEdgeNodes(inputLocusIndex, inputEdge.first, remoteIntersectNodeToLocalNodeMap, remoteIntersectNodes, inputIntersectEdges); unsigned intersectCount(inputIntersectEdges.size()); if (! isInputLocusMoved) { /// TODO: doc this adjustment, does this normalize the edge count to always include self-intersect? intersectCount++; } // isRegionCheck initiates a more detailed evidence signal threshold check process // // - The default process checks the total evidence summed over the entire // Node intersect set. This neglects to account for the possibility that that evidence // density could be low, and yet a high evidence sum could be achieved by transitive over // lap of many nodes. // // - The regioncheck pathway sums up evidence at each genomic region. It more accurately // reflects peak evidence but is somewhat slower to compute. // // Example: // // Assume each node below has an evidence count of 1. // // |---node1-----| // |-----node2-----| // |-----node3---| // // Default evidence count: // 33333333333333333333333333333333333333 // // isRegionCheck evidence count: // 11111111112222211111111222211111111111 // // // peak RegionCheck count will always equal default count when 2 or fewer nodes exist, // so there's no reason to turn it on until we have more nodes const bool isRegionCheck(intersectCount>2); if (isRegionCheck) { _mergeRegions.clear(); } // enumerate counts as part of the (non-RegionCheck) process to determine if the intersection set // contains sufficient evidence to initiate a merge unsigned mergedLocalEdgeCount(0); unsigned mergedRemoteEdgeCount(0); /// /// enumerate node evidence using either the default or RegionCheck process: /// auto addEdgeEvidenceCount = [&]( const SVLocus& edgeLocus, const NodeIndexType localNodeIndex, const NodeIndexType remoteNodeIndex) { // total edge counts on the remote->local edge: const unsigned remoteEdgeCount = edgeLocus.getEdge(remoteNodeIndex,localNodeIndex).getCount(); // total edge counts on the local->remote edge: const unsigned localEdgeCount = edgeLocus.getEdge(localNodeIndex,remoteNodeIndex).getCount(); if (isRegionCheck) { const known_pos_range2& localRange(edgeLocus.getNode(localNodeIndex).getInterval().range); const known_pos_range2& remoteRange(edgeLocus.getNode(remoteNodeIndex).getInterval().range); _mergeRegions.localNodeOutbound.add(localRange,localEdgeCount); _mergeRegions.localNodeInbound.add(localRange,remoteEdgeCount); _mergeRegions.remoteNodeOutbound.add(remoteRange,remoteEdgeCount); _mergeRegions.remoteNodeInbound.add(remoteRange,localEdgeCount); } else { mergedLocalEdgeCount += localEdgeCount; mergedRemoteEdgeCount += remoteEdgeCount; } }; for (const EdgeInfoType& edgeInfo : inputIntersectEdges) { addEdgeEvidenceCount(getLocus(edgeInfo.first.first),edgeInfo.first.second,edgeInfo.second); } // if the input hasn't been moved into the primary locus graph yet, then we need to include the inputLocus // in order to get an accurate edge intersection count: if (! isInputLocusMoved) { addEdgeEvidenceCount(getLocus(inputAddy.first),inputNodeIndex,inputEdge.first); } if (isRegionCheck) { mergedLocalEdgeCount=(std::min(_mergeRegions.localNodeOutbound.maxVal(),_mergeRegions.remoteNodeInbound.maxVal())); mergedRemoteEdgeCount=(std::min(_mergeRegions.localNodeInbound.maxVal(),_mergeRegions.remoteNodeOutbound.maxVal())); } #ifdef DEBUG_SVL log_os << logtag << " isRegionCheck: " << isRegionCheck << "\n"; log_os << logtag << " final merge counts" << " local: " << mergedLocalEdgeCount << " remote: " << mergedRemoteEdgeCount << "\n"; checkState(); #endif if ((mergedLocalEdgeCount < getMinMergeEdgeCount()) && (mergedRemoteEdgeCount < getMinMergeEdgeCount())) continue; // // Add type1 mergeable nodes: // for (const EdgeInfoType& edgeInfo : inputIntersectEdges) { mergeIntersectNodes.insert(edgeInfo.first); } /// for each type1 node, add any new intersections to the signal node set: /// /// this is not very efficient for now -- each type1 edge added in potentially /// expands the current node to intersect new signal nodes /// -- this loop looks for those new signal nodes /// { // this is used to search for the (rare) case where the intersection set // locals overlap with the intersection set remotes std::set<NodeAddressType> inputIntersectRemotes; for (const EdgeInfoType& edgeInfo : inputIntersectEdges) { inputIntersectRemotes.insert(std::make_pair(edgeInfo.first.first,edgeInfo.second)); } bool isIntersectRemotes(false); // check both the original node and intersected nodes for intersection to // any of the group's remotes, and for new type2 signal intersect: findSignalNodes(inputLocusIndex, inputAddy, signalIntersectNodes, inputIntersectRemotes, isIntersectRemotes); for (const EdgeInfoType& edgeInfo : inputIntersectEdges) { findSignalNodes(inputLocusIndex, edgeInfo.first, signalIntersectNodes, inputIntersectRemotes, isIntersectRemotes); } if (isIntersectRemotes) { for (const NodeAddressType& intersectAddy : inputIntersectRemotes) { #ifdef DEBUG_SVL log_os << logtag << " adding ownRemote: " << intersectAddy << "\n"; #endif mergeIntersectNodes.insert(intersectAddy); // check to see if this adds even more signal nodes! findSignalNodes(inputLocusIndex, intersectAddy, signalIntersectNodes, inputIntersectRemotes, isIntersectRemotes); } } } // // Add type2 mergeable nodes: // for (const NodeAddressType& signalAddy : signalIntersectNodes) { mergeIntersectNodes.insert(signalAddy); } } #ifdef DEBUG_SVL log_os << logtag << " END. IntersectNodeSize: " << mergeIntersectNodes.size() << " Nodes:\n"; for (const NodeAddressType addy : mergeIntersectNodes) { log_os << logtag << "\tInode: " << addy << "\n"; } #endif }