package edu.mit.broad.picard.util; import java.util.*; /** * Utility class to efficiently do in memory overlap detection between a large * set of mapping like objects, and one or more candidate mappings. */ public class OverlapDetector { private Map>> cache = new HashMap>>(); private final int lhsBuffer; private final int rhsBuffer; /** * Constructs an overlap detector. * @param lhsBuffer the amount by which to "trim" coordinates of mappings on the left * hand side when calculating overlaps * @param rhsBuffer the amount by which to "trim" coordinates of mappings on the right * hand side when calculating overlaps */ public OverlapDetector(int lhsBuffer, int rhsBuffer) { this.lhsBuffer = lhsBuffer; this.rhsBuffer = rhsBuffer; } /** Adds a mapping to the set of mappings against which to match candidates. */ public void addLhs(T object, Interval interval) { Object seqId = interval.getSequence(); IntervalTree> tree = this.cache.get(seqId); if (tree == null) { tree = new IntervalTree>(); this.cache.put(seqId, tree); } int start = interval.getStart() + this.lhsBuffer; int end = interval.getEnd() - this.lhsBuffer; Set objects = new HashSet(); objects.add(object); if (start <= end) // Don't put in sequences that have no overlappable bases { Set alreadyThere = tree.put(start, end, objects); if (alreadyThere != null) { alreadyThere.add(object); tree.put(start, end, alreadyThere); } } } /** Adds all items to the overlap detector. */ public void addAll(List objects, List intervals) { if (objects.size() != intervals.size()) { throw new IllegalArgumentException("Objects and intervals must be the same size."); } for (int i=0; i getOverlaps(Interval rhs) { Collection matches = new ArrayList(); Object seqId = rhs.getSequence(); IntervalTree> tree = this.cache.get(seqId); int start = rhs.getStart() + this.rhsBuffer; int end = rhs.getEnd() - this.rhsBuffer; if (tree != null && start <= end) { Iterator>> it = tree.overlappers(start, end); while (it.hasNext()) { IntervalTree.Node> node = it.next(); matches.addAll(node.getValue()); } } return matches; } /** Gets all the objects that could be returned by the overlap detector. */ public Collection getAll() { Collection all = new HashSet(); for (IntervalTree> tree : this.cache.values()) { for (IntervalTree.Node> node : tree) { all.addAll(node.getValue()); } } return all; } }