/** * Lift over the given interval to the new genome build. * * @param interval Interval to be lifted over. * @param liftOverMinMatch Minimum fraction of bases that must remap. * @return Interval in the output build coordinates, or null if it cannot be lifted over. */ public Interval liftOver(final Interval interval, final double liftOverMinMatch) { if (interval.length() == 0) { throw new IllegalArgumentException( "Zero-length interval cannot be lifted over. Interval: " + interval.getName()); } Chain chainHit = null; TargetIntersection targetIntersection = null; // Number of bases in interval that can be lifted over must be >= this. double minMatchSize = liftOverMinMatch * interval.length(); // Find the appropriate Chain, and the part of the chain corresponding to the interval to be // lifted over. for (final Chain chain : chains.getOverlaps(interval)) { final TargetIntersection candidateIntersection = targetIntersection(chain, interval); if (candidateIntersection != null && candidateIntersection.intersectionLength >= minMatchSize) { if (chainHit != null) { // In basic liftOver, multiple hits are not allowed. return null; } chainHit = chain; targetIntersection = candidateIntersection; } else if (candidateIntersection != null) { LOG.info( "Interval " + interval.getName() + " failed to match chain " + chain.id + " because intersection length " + candidateIntersection.intersectionLength + " < minMatchSize " + minMatchSize + " (" + (candidateIntersection.intersectionLength / (float) interval.length()) + " < " + liftOverMinMatch + ")"); } } if (chainHit == null) { // Can't be lifted over. return null; } return createToInterval(interval.getName(), targetIntersection); }
public List<PartialLiftover> diagnosticLiftover(final Interval interval) { final List<PartialLiftover> ret = new ArrayList<PartialLiftover>(); if (interval.length() == 0) { throw new IllegalArgumentException( "Zero-length interval cannot be lifted over. Interval: " + interval.getName()); } for (final Chain chain : chains.getOverlaps(interval)) { Interval intersectingChain = interval.intersect(chain.interval); final TargetIntersection targetIntersection = targetIntersection(chain, intersectingChain); if (targetIntersection == null) { ret.add(new PartialLiftover(intersectingChain, chain.id)); } else { Interval toInterval = createToInterval(interval.getName(), targetIntersection); float percentLiftedOver = targetIntersection.intersectionLength / (float) interval.length(); ret.add( new PartialLiftover( intersectingChain, toInterval, targetIntersection.chain.id, percentLiftedOver)); } } return ret; }
public String toString() { if (toInterval == null) { // Matched a chain, but entirely within a gap. return fromInterval.toString() + " (len " + fromInterval.length() + ")=>null using chain " + chainId; } final String strand = toInterval.isNegativeStrand() ? "-" : "+"; return fromInterval.toString() + " (len " + fromInterval.length() + ")=>" + toInterval + "(" + strand + ") using chain " + chainId + " ; pct matched " + percentLiftedOver; }