Skip to content

Commit

Permalink
VariantFiltration - port and a near-complete rewrite for GATK4. It is…
Browse files Browse the repository at this point in the history
… now site-by-site independent (unlike GATK3).
  • Loading branch information
akiezun committed Jul 8, 2015
1 parent 9a30442 commit e8c266e
Show file tree
Hide file tree
Showing 72 changed files with 1,774 additions and 106 deletions.
1 change: 1 addition & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#Mon Jun 22 18:12:37 EDT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -603,8 +603,8 @@ private void handleArgumentAnnotation(final Field field, final Object parent) {
}
}
if (!canBeMadeFromString(getUnderlyingType(field))) {
throw new GATKException.CommandLineParserInternalException("@Argument member " + field.getName() +
" must have a String ctor or be an enum");
throw new GATKException.CommandLineParserInternalException("@Argument member \"" + field.getName() +
"\" must have a String constructor or be an enum");
}

final ArgumentDefinition argumentDefinition = new ArgumentDefinition(field, argumentAnnotation, parent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.broadinstitute.hellbender.engine;

import htsjdk.samtools.util.Locatable;
import org.broadinstitute.hellbender.exceptions.GATKException;
import org.broadinstitute.hellbender.utils.SimpleInterval;
import htsjdk.tribble.Feature;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
* Wrapper around FeatureManager that presents Feature data from a particular interval to a client tool
Expand Down Expand Up @@ -107,11 +110,77 @@ public <T extends Feature> Object getHeader( final FeatureInput<T> featureDescri
* this FeatureContext's query interval. Empty List if there is no backing data source and/or interval.
*/
public <T extends Feature> List<T> getValues( final FeatureInput<T> featureDescriptor ) {
if ( featureManager == null || interval == null ) {
return getValues(featureDescriptor, interval);
}

/**
* Gets all Features from the source represented by the provided FeatureInput argument that overlap
* this FeatureContext's query interval. Will return an empty List if this FeatureContext has
* no backing source of Features and/or interval.
*
* Returned Features are not guaranteed to be in any particular order.
*
* @param featureDescriptor FeatureInput argument for which to fetch Features
* @param <T> type of Feature in the data source backing the provided FeatureInput
* @param windowLeadingBases Number of extra reference bases to include before the start of our interval. Must be >= 0.
* @param windowTrailingBases Number of extra reference bases to include after the end of our interval. Must be >= 0.
* @return All Features in the data source backing the provided FeatureInput that overlap
* this FeatureContext's query interval. Empty List if there is no backing data source and/or interval.
*/
public <T extends Feature> List<T> getValues( final FeatureInput<T> featureDescriptor, final int windowLeadingBases, final int windowTrailingBases) {
return getValues(featureDescriptor, getWindow(windowLeadingBases, windowTrailingBases));
}

private <T extends Feature> List<T> getValues( final FeatureInput<T> featureDescriptor, final SimpleInterval window) {
if ( featureManager == null || window == null || featureDescriptor == null) {
return Collections.<T>emptyList();
}
return featureManager.getFeatures(featureDescriptor, window);
}

return featureManager.getFeatures(featureDescriptor, interval);
/**
* Gets our query interval (the interval that all Features returned by this FeatureContext overlap).
* Null if this context has no interval.
*
* @param windowLeadingBases Number of extra bases to include before the start of our interval. Must be >= 0.
* @param windowTrailingBases Number of extra bases to include after the end of our interval. Must be >= 0.
* @return full expanded window of bases spanned by this context as a SimpleInterval
* (will be null if this context has no interval)
*/
public SimpleInterval getWindow(final int windowLeadingBases, final int windowTrailingBases){
if( windowLeadingBases < 0 ) throw new GATKException("Window starts after the current interval");
if( windowTrailingBases < 0 ) throw new GATKException("Window ends before the current interval");

if (interval == null) {
return null;
}
if (windowLeadingBases == 0 && windowTrailingBases == 0){
return interval;
}
return new SimpleInterval(interval.getContig(), windowStart(interval, windowLeadingBases), windowStop(interval, windowTrailingBases));
}

/**
* Determines the start of the expanded reference window, bounded by 1.
*
* @param locus The locus to expand.
* @param windowLeadingBases number of bases to attempt to expand relative to the locus start (>= 0)
* @return The start of the expanded window.
*/
private int windowStart( final SimpleInterval locus, final int windowLeadingBases ) {
return Math.max(locus.getStart() - windowLeadingBases, 1);
}

/**
* Determines the stop of the expanded reference window.
*
* @param locus The locus to expand.
* @param windowTrailingBases number of bases to attempt to expand relative to the locus end (>= 0)
* @return The end of the expanded window.
*/
private int windowStop( final SimpleInterval locus, final int windowTrailingBases ) {
//XXX what about contig end? Is this a problem?
return locus.getEnd() + windowTrailingBases;
}

/**
Expand Down Expand Up @@ -195,12 +264,6 @@ public <T extends Feature> List<T> getValues( final Collection<FeatureInput<T>>
* @return List of all Features from the features list that start at the specified start position
*/
private <T extends Feature> List<T> subsetToStartPosition( final Collection<T> features, final int start ) {
List<T> subsettedFeatures = new ArrayList<>(features.size());
for ( T feature : features ) {
if ( feature.getStart() == start ) {
subsettedFeatures.add(feature);
}
}
return subsettedFeatures;
return features.stream().filter(feat -> feat.getStart() == start).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import htsjdk.tribble.Feature;
import org.broadinstitute.hellbender.exceptions.UserException;
import org.broadinstitute.hellbender.utils.Utils;

import java.io.File;
import java.util.Collections;
Expand Down Expand Up @@ -74,7 +75,7 @@ public final class FeatureInput<T extends Feature> {
* May have attributes.
*/
private static final class ParsedArgument{
private final HashMap<String, String> keyValueMap;
private final Map<String, String> keyValueMap;
private final String name;
private final File file;

Expand All @@ -98,7 +99,7 @@ public static ParsedArgument of( final String rawArgumentValue ) {
if ( tokens.length > 2 || tokens.length == 0 ) {
throw new UserException.BadArgumentValue("", rawArgumentValue, usage);
}
for ( String token : tokens ) {
for ( final String token : tokens ) {
if ( token.isEmpty() ) {
throw new UserException.BadArgumentValue("", rawArgumentValue, "Empty name/file encountered. " + usage);
}
Expand All @@ -118,10 +119,10 @@ public static ParsedArgument of( final String rawArgumentValue ) {
if (subtokens[0].isEmpty()){
throw new UserException.BadArgumentValue("", rawArgumentValue, usage);
}
ParsedArgument pa= new ParsedArgument(subtokens[0], new File(tokens[1]));
final ParsedArgument pa= new ParsedArgument(subtokens[0], new File(tokens[1]));
//note: starting from 1 because 0 is the name
for (int i = 1; i < subtokens.length; i++){
String[] kv = subtokens[i].split(FEATURE_ARGUMENT_KEY_VALUE_SEPARATOR, -1);
final String[] kv = subtokens[i].split(FEATURE_ARGUMENT_KEY_VALUE_SEPARATOR, -1);
if (kv.length != 2 || kv[0].isEmpty() || kv[1].isEmpty()){
throw new UserException.BadArgumentValue("", rawArgumentValue, usage);
}
Expand All @@ -133,7 +134,7 @@ public static ParsedArgument of( final String rawArgumentValue ) {
return pa;
}

private ParsedArgument(String name, File file) {
private ParsedArgument(final String name, final File file) {
this.name=name;
this.file=file;
this.keyValueMap = new HashMap<>(2);
Expand All @@ -154,24 +155,27 @@ public Map<String, String> keyValueMap() {
return Collections.unmodifiableMap(keyValueMap);
}

public void addKeyValue(String k, String v) {
public void addKeyValue(final String k, final String v) {
keyValueMap.put(k, v);
}

private boolean containsKey(String k) {
private boolean containsKey(final String k) {
return keyValueMap.containsKey(k);
}
}

/**
* Construct a FeatureInput from a String argument value either of the form "logical_name:feature_file"
* or simply "feature_file".
*
* Only meant to be called by the argument parsing system, and therefore marked as protected --
* Only meant to be called by the argument parsing system, and therefore marked as package-visible --
* FeatureInputs constructed some other way will not be recognized by the engine.
*
* Note: cannot delegate to another construtor because Java only allows a call to "this" on the first line of a constructor.
*
* @param rawArgumentValue String of the form "logical_name:feature_file" or "feature_file"
*/
protected FeatureInput( final String rawArgumentValue ) {
FeatureInput( final String rawArgumentValue ) {
final ParsedArgument parsedArgument = ParsedArgument.of(rawArgumentValue);

name = parsedArgument.getName();
Expand All @@ -180,15 +184,27 @@ protected FeatureInput( final String rawArgumentValue ) {
featureType = null; // Must be set after construction
}

/**
* Construct a FeatureInput from raw components: name, key value pairs and the file.
*
* This constructor is meant to be called by the engine and thus is package-visible --
* FeatureInputs constructed some other way will not be recognized by the engine.
*/
FeatureInput( final String name, final Map<String, String> kevValueMap, final File featureFile) {
this.name = name;
this.kevValueMap = Collections.unmodifiableMap(new HashMap<>(kevValueMap)); //make a unmodifiable copy
this.featureFile = featureFile;
this.featureType = null; // Must be set after construction
}


/**
* Gets the value for the given key associated with this Feature source or {@code null}
* if no value is associated with a given key.
* @throws IllegalArgumentException if the key is {@code null}.
*/
public String getAttribute(String key) {
if (key == null){
throw new IllegalArgumentException("null key");
}
public String getAttribute(final String key) {
Utils.nonNull(key);
return kevValueMap.get(key);
}

Expand Down Expand Up @@ -217,7 +233,7 @@ public File getFeatureFile() {
*
* @return the type of Feature contained in our file
*/
public final Class<? extends Feature> getFeatureType() {
public Class<? extends Feature> getFeatureType() {
return featureType;
}

Expand All @@ -226,7 +242,7 @@ public final Class<? extends Feature> getFeatureType() {
*
* @param featureType the type of Feature contained in our file
*/
public void setFeatureType( Class<? extends Feature> featureType ) {
public void setFeatureType( final Class<? extends Feature> featureType ) {
this.featureType = featureType;
}

Expand All @@ -247,12 +263,12 @@ public int hashCode() {
* @return true if this FeatureInput equals other, otherwise false
*/
@Override
public boolean equals( Object other ) {
public boolean equals( final Object other ) {
if (! (other instanceof FeatureInput) ) {
return false;
}

FeatureInput<?> otherFeature = (FeatureInput<?>)other;
final FeatureInput<?> otherFeature = (FeatureInput<?>)other;
return name.equals(otherFeature.name) && featureFile.equals(otherFeature.featureFile);
}

Expand Down

0 comments on commit e8c266e

Please sign in to comment.