package nl.tudelft.lifetiles.graph.traverser;
import java.util.HashSet;
import java.util.Set;
import nl.tudelft.lifetiles.core.util.Timer;
import nl.tudelft.lifetiles.graph.model.Edge;
import nl.tudelft.lifetiles.graph.model.Graph;
import nl.tudelft.lifetiles.sequence.model.SegmentEmpty;
import nl.tudelft.lifetiles.sequence.model.Sequence;
import nl.tudelft.lifetiles.sequence.model.SequenceSegment;
/**
* Places empty vertices in the graph where there are unified gaps.
*
* @author Jos
*
*/
public final class EmptySegmentTraverser {
/**
* Don't instantiate.
*/
private EmptySegmentTraverser() {
}
/**
* Traverses the graph. Adds empty vertices to the graph which are being
* used to indicate mutations on.
*
* @param graph
* the graph to traverse.
*/
public static void addEmptySegmentsGraph(final Graph<SequenceSegment> graph) {
Timer timer = Timer.getAndStart();
for (SequenceSegment vertex : graph.getAllVertices()) {
addEmptySegmentsVertex(graph, vertex);
}
timer.stopAndLog("Adding empty segments");
}
/**
* Traverses a vertex in the graph. Adds empty vertices to the graph which
* are being used to indicate mutations on.
*
* @param graph
* The graph to traverse.
* @param vertex
* the vertex to traverse.
*/
private static void addEmptySegmentsVertex(
final Graph<SequenceSegment> graph, final SequenceSegment vertex) {
Set<Sequence> buffer = new HashSet<Sequence>(vertex.getSources());
for (Edge<SequenceSegment> edge : graph.getOutgoing(vertex)) {
SequenceSegment destination = graph.getDestination(edge);
// Need a new set on each iteration, so we do need this.
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
Set<Sequence> sources = new HashSet<Sequence>(
destination.getSources());
sources.retainAll(buffer);
if (vertex.distanceTo(destination) > 0) {
graph.splitEdge(edge,
bridgeSequence(vertex, destination, sources));
}
buffer.removeAll(sources);
}
}
/**
* Creates a bridge sequence segment between a source and destination
* segment.
*
* @param source
* The vertex that is the source segment.
* @param destination
* The vertex that is the destination segment.
* @param sources
* The set of sources in the to be constructed segment.
* @return sequence segment between source and destination segment
*/
private static SequenceSegment bridgeSequence(final SequenceSegment source,
final SequenceSegment destination, final Set<Sequence> sources) {
SequenceSegment vertex = new SequenceSegment(sources,
source.getUnifiedEnd(), destination.getUnifiedStart(),
new SegmentEmpty(source.distanceTo(destination) + 1));
vertex.setUnifiedStart(vertex.getStart());
vertex.setUnifiedEnd(vertex.getEnd());
return vertex;
}
}