All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.broadinstitute.hellbender.engine.AlignmentContext Maven / Gradle / Ivy

There is a newer version: 4.6.0.0
Show newest version
package org.broadinstitute.hellbender.engine;

import htsjdk.samtools.SAMFileHeader;
import htsjdk.samtools.SAMReadGroupRecord;
import htsjdk.samtools.util.Locatable;
import org.broadinstitute.hellbender.utils.HasGenomeLocation;
import org.broadinstitute.hellbender.utils.Utils;
import org.broadinstitute.hellbender.utils.pileup.ReadPileup;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Bundles together a pileup and a location.
 */
public final class AlignmentContext implements Locatable, HasGenomeLocation {
    // Definitions:
    //   COMPLETE = full alignment context
    //   FORWARD  = reads on forward strand
    //   REVERSE  = reads on reverse strand
    //
    public enum ReadOrientation { COMPLETE, FORWARD, REVERSE }

    private final Locatable loc;
    private final ReadPileup basePileup;

    private boolean hasPileupBeenDownsampled;

    public AlignmentContext(final Locatable loc, final ReadPileup basePileup) {
        this(loc, basePileup, false);
    }

    public AlignmentContext(final Locatable loc, final ReadPileup basePileup, final boolean hasPileupBeenDownsampled ) {
        Utils.nonNull(loc, "BUG: GenomeLoc in Alignment context is null");
        Utils.nonNull(basePileup, "BUG: ReadBackedPileup in Alignment context is null");

        this.loc = loc;
        this.basePileup = basePileup;
        this.hasPileupBeenDownsampled = hasPileupBeenDownsampled;
    }

    /**
     * How many reads cover this locus?
     * @return
     */
    public int size() {
        return basePileup.size();
    }

    @Override
    public String getContig() {
        return getLocation().getContig();
    }

    @Override
    public int getStart() {
        return getLocation().getStart();
    }

    @Override
    public int getEnd() {
        return getLocation().getEnd();
    }

    public long getPosition() { return getStart(); }

    @Override
    public Locatable getLocation() { return loc; }

    /**
     * Returns true if any reads have been filtered out of the pileup due to excess DoC.
     * @return True if reads have been filtered out.  False otherwise.
     */
    public boolean hasPileupBeenDownsampled() { return hasPileupBeenDownsampled; }

    public ReadPileup getBasePileup() {
        return basePileup;
    }

    /**
     * Returns a potentially derived subcontext containing only forward, reverse, or in fact all reads
     * in alignment context context.
     */
    public AlignmentContext stratify(final ReadOrientation type) {
        switch(type) {
            case COMPLETE:
                return this;
            case FORWARD:
                return new AlignmentContext(loc, basePileup.makeFilteredPileup(pe -> !pe.getRead().isReverseStrand()));
            case REVERSE:
                return new AlignmentContext(loc, basePileup.makeFilteredPileup(pe -> pe.getRead().isReverseStrand()));
            default:
                throw new IllegalArgumentException("Unable to get alignment context for type = " + type);
        }
    }

    public Map splitContextBySampleName(final SAMFileHeader header) {
        return this.splitContextBySampleName((String) null, header);
    }

    /**
     * Splits the given AlignmentContext into a StratifiedAlignmentContext per sample, but referenced by sample name instead
     * of sample object.
     *
     * @param assumedSingleSample If non-null, assume this is the only sample in our pileup and return immediately.
     *                            If null, get the list of samples from the provided header and do the work of splitting by sample.
     * @return a Map of sample name to StratifiedAlignmentContext; samples without coverage are not included
     **/
    public Map splitContextBySampleName(final String assumedSingleSample, final SAMFileHeader header) {
        if (assumedSingleSample != null){
            return Collections.singletonMap(assumedSingleSample, this);
        }
        final Locatable loc = this.getLocation();
        // this will throw an user error if there are samples without RG/sampleName
        final Map pileups = this.getBasePileup().splitBySample(header, assumedSingleSample);
        final Map contexts = new LinkedHashMap<>(pileups.size());
        for (final Map.Entry entry : pileups.entrySet()) {
            // Don't add empty pileups to the split context.
            if (entry.getValue().isEmpty()) {
                continue;
            }
            contexts.put(entry.getKey(), new AlignmentContext(loc, entry.getValue()));
        }
        return contexts;
    }

    public static Map splitContextBySampleName(final ReadPileup pileup, final SAMFileHeader header) {
        return new AlignmentContext(pileup.getLocation(), pileup).splitContextBySampleName(header);
    }

    @Override
    public String toString() {
        return "AlignmentContext{" +
                "loc=" + loc +
                ", basePileup=" + basePileup +
                ", hasPileupBeenDownsampled=" + hasPileupBeenDownsampled +
                '}';
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy