diff --git a/java/src/org/broadinstitute/sting/gatk/CommandLineExecutable.java b/java/src/org/broadinstitute/sting/gatk/CommandLineExecutable.java index 9407d9d8f..e0e1b3892 100644 --- a/java/src/org/broadinstitute/sting/gatk/CommandLineExecutable.java +++ b/java/src/org/broadinstitute/sting/gatk/CommandLineExecutable.java @@ -123,7 +123,7 @@ public abstract class CommandLineExecutable extends CommandLineProgram { @Override protected String getArgumentSourceName( Class argumentSource ) { - return WalkerManager.getWalkerName((Class) argumentSource); + return GATKEngine.getWalkerName((Class)argumentSource); } /** diff --git a/java/src/org/broadinstitute/sting/gatk/GATKArgumentCollection.java b/java/src/org/broadinstitute/sting/gatk/GATKArgumentCollection.java index b399da0a7..dfa23f830 100755 --- a/java/src/org/broadinstitute/sting/gatk/GATKArgumentCollection.java +++ b/java/src/org/broadinstitute/sting/gatk/GATKArgumentCollection.java @@ -56,6 +56,10 @@ public class GATKArgumentCollection { @Argument(fullName = "input_file", shortName = "I", doc = "SAM or BAM file(s)", required = false) public List samFiles = new ArrayList(); + @ElementList(required = false) + @Argument(fullName = "read_filters", shortName = "rf", doc = "Specify filtration criteria on the each read.", required=false) + public List readFilters = new ArrayList(); + @ElementList(required = false) @Argument(fullName = "intervals", shortName = "L", doc = "A list of genomic intervals over which to operate. Can be explicitly specified on the command line or in a file.", required = false) public List intervals = null; diff --git a/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java b/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java index 1db9e406d..5d8297a4e 100755 --- a/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java +++ b/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java @@ -40,6 +40,7 @@ import org.broadinstitute.sting.gatk.refdata.ReferenceOrderedData; import org.broadinstitute.sting.gatk.refdata.ReferenceOrderedDatum; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.gatk.filters.ZeroMappingQualityReadFilter; +import org.broadinstitute.sting.gatk.filters.FilterManager; import org.broadinstitute.sting.gatk.io.OutputTracker; import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.bed.BedParser; @@ -97,6 +98,11 @@ public class GenomeAnalysisEngine { */ private final WalkerManager walkerManager; + /** + * Manage lists of filters. + */ + private final FilterManager filterManager; + /** * our constructor, where all the work is done *

@@ -107,6 +113,7 @@ public class GenomeAnalysisEngine { // make sure our instance variable points to this analysis engine instance = this; walkerManager = new WalkerManager(); + filterManager = new FilterManager(); } /** @@ -184,7 +191,16 @@ public class GenomeAnalysisEngine { * @return An instance of the walker. */ public Walker getWalkerByName(String walkerName) { - return walkerManager.createWalkerByName(walkerName); + return walkerManager.createByName(walkerName); + } + + /** + * Gets the name of a given walker type. + * @param walkerType Type of walker. + * @return Name of the walker. + */ + public String getWalkerName(Class walkerType) { + return walkerManager.getName(walkerType); } private void initializeDataSources(Walker my_walker, GATKArgumentCollection argCollection) { @@ -240,7 +256,7 @@ public class GenomeAnalysisEngine { Utils.scareUser(String.format("Read-based traversals require a reference file but none was given")); microScheduler = MicroScheduler.create(my_walker, readsDataSource, referenceDataSource, rodDataSources, argCollection.numberOfThreads); } else { - Utils.scareUser(String.format("Unable to create the appropriate TraversalEngine for analysis type %s", WalkerManager.getWalkerName(my_walker.getClass()))); + Utils.scareUser(String.format("Unable to create the appropriate TraversalEngine for analysis type %s", walkerManager.getName(my_walker.getClass()))); } return microScheduler; @@ -377,9 +393,11 @@ public class GenomeAnalysisEngine { private Reads extractSourceInfo(Walker walker, GATKArgumentCollection argCollection) { List filters = new ArrayList(); - filters.addAll(WalkerManager.getReadFilters(walker)); + filters.addAll(WalkerManager.getReadFilters(walker,filterManager)); if (argCollection.filterZeroMappingQualityReads != null && argCollection.filterZeroMappingQualityReads) filters.add(new ZeroMappingQualityReadFilter()); + for(String filterName: argCollection.readFilters) + filters.add(filterManager.createByName(filterName)); return new Reads(argCollection.samFiles, argCollection.strictnessLevel, diff --git a/java/src/org/broadinstitute/sting/gatk/WalkerManager.java b/java/src/org/broadinstitute/sting/gatk/WalkerManager.java index 3408e7ad3..e8d81210d 100755 --- a/java/src/org/broadinstitute/sting/gatk/WalkerManager.java +++ b/java/src/org/broadinstitute/sting/gatk/WalkerManager.java @@ -30,8 +30,9 @@ import java.util.*; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.gatk.refdata.ReferenceOrderedDatum; import org.broadinstitute.sting.gatk.refdata.ReferenceOrderedData; +import org.broadinstitute.sting.gatk.filters.FilterManager; import org.broadinstitute.sting.utils.StingException; -import org.broadinstitute.sting.utils.PackageUtils; +import org.broadinstitute.sting.utils.PluginManager; import org.apache.log4j.Logger; import net.sf.picard.filter.SamRecordFilter; @@ -42,49 +43,15 @@ import net.sf.picard.filter.SamRecordFilter; * Time: 3:14:28 PM * To change this template use File | Settings | File Templates. */ -public class WalkerManager { +public class WalkerManager extends PluginManager { /** * our log, which we want to capture anything from this class */ private static Logger logger = Logger.getLogger(WalkerManager.class); - private Map> walkersByName; - public WalkerManager() { - List> walkers = PackageUtils.getClassesImplementingInterface(Walker.class); - walkersByName = createWalkerDatabase(walkers); - } - - /** - * Does a walker with the given name exist? - * - * @param walkerName Name of the walker for which to search. - * @return True if the walker exists, false otherwise. - */ - public boolean doesWalkerExist(String walkerName) { - return walkersByName.containsKey(walkerName); - } - - /** - * Gets a walker with the given name, or null if no walker exists. - * - * @param walkerName Name of the walker to retrieve. - * @return The walker object if found; null otherwise. - */ - public Walker createWalkerByName(String walkerName) { - try { - Class walker = walkersByName.get(walkerName); - if( walker == null ) - throw new StingException(String.format("Could not find walker with name: %s", walkerName)); - return walker.newInstance(); - } - catch( InstantiationException ex ) { - throw new StingException("Unable to instantiate walker " + walkerName, ex); - } - catch( IllegalAccessException ex ) { - throw new StingException("Unable to access walker " + walkerName, ex); - } + super(Walker.class,"walker","Walker"); } /** @@ -92,7 +59,7 @@ public class WalkerManager { * @return Names of currently available walkers. */ public Set getWalkerNames() { - return Collections.unmodifiableSet( walkersByName.keySet() ); + return Collections.unmodifiableSet( pluginsByName.keySet() ); } /** @@ -101,7 +68,7 @@ public class WalkerManager { * @return Class representing the walker. */ public Class getWalkerClassByName(String walkerName) { - return walkersByName.get(walkerName); + return pluginsByName.get(walkerName); } /** @@ -185,61 +152,30 @@ public class WalkerManager { /** * Extracts filters that the walker has requested be run on the dataset. * @param walker Walker to inspect for filtering requests. + * @param filterManager Manages the creation of filters. * @return A non-empty list of filters to apply to the reads. */ - public static List getReadFilters(Walker walker) { - Class[] filterTypes = getReadFilterTypes(walker); + public static List getReadFilters(Walker walker, FilterManager filterManager) { List filters = new ArrayList(); - - for( Class filterType: filterTypes ) { - try { - filters.add(filterType.newInstance()); - } - catch( InstantiationException ex ) { - throw new StingException("Unable to instantiate filter: " + filterType, ex); - } - catch( IllegalAccessException ex ) { - throw new StingException("Unable to access filter: " + filterType, ex); - } - } - + for(Class filterType: getReadFilterTypes(walker)) + filters.add(filterManager.createFilterByType(filterType)); return filters; } - /** - * Instantiate the list of walker classes. Add them to the walker hashmap. - * - * @param walkerClasses Classes to instantiate. - * @return map of walker name to walker. - */ - private Map> createWalkerDatabase(List> walkerClasses) { - Map> walkers = new HashMap>(); - - for (Class walkerClass : walkerClasses) { - String walkerName = getWalkerName(walkerClass); - walkers.put(walkerName, walkerClass); - } - - return walkers; - } - /** * Create a name for this type of walker. * * @param walkerType The type of walker. * @return A name for this type of walker. */ - public static String getWalkerName(Class walkerType) { + @Override + public String getName(Class walkerType) { String walkerName = ""; if (walkerType.getAnnotation(WalkerName.class) != null) walkerName = walkerType.getAnnotation(WalkerName.class).value().trim(); - - if (walkerName.length() == 0) { - walkerName = walkerType.getSimpleName(); - if (walkerName.endsWith("Walker")) - walkerName = walkerName.substring(0, walkerName.lastIndexOf("Walker")); - } + else + walkerName = super.getName(walkerType); return walkerName; } diff --git a/java/src/org/broadinstitute/sting/gatk/filters/FilterManager.java b/java/src/org/broadinstitute/sting/gatk/filters/FilterManager.java new file mode 100644 index 000000000..956868548 --- /dev/null +++ b/java/src/org/broadinstitute/sting/gatk/filters/FilterManager.java @@ -0,0 +1,34 @@ +package org.broadinstitute.sting.gatk.filters; + +import org.apache.log4j.Logger; +import org.broadinstitute.sting.utils.PluginManager; + +import net.sf.picard.filter.SamRecordFilter; + +/** + * Manage filters and filter options. Any requests for basic filtering classes + * should ultimately be made through this class. + * + * @author mhanna + * @version 0.1 + */ +public class FilterManager extends PluginManager { + /** + * our log, which we want to capture anything from this class + */ + private static Logger logger = Logger.getLogger(FilterManager.class); + + public FilterManager() { + super(SamRecordFilter.class,"filter","Filter"); + } + + /** + * Instantiate a filter of the given type. Along the way, scream bloody murder if + * the filter is not available. + * @param filterType + * @return + */ + public SamRecordFilter createFilterByType(Class filterType) { + return this.createByName(getName(filterType)); + } +} diff --git a/java/src/org/broadinstitute/sting/utils/PluginManager.java b/java/src/org/broadinstitute/sting/utils/PluginManager.java new file mode 100644 index 000000000..12c2ed8e1 --- /dev/null +++ b/java/src/org/broadinstitute/sting/utils/PluginManager.java @@ -0,0 +1,109 @@ +package org.broadinstitute.sting.utils; + +import java.util.Map; +import java.util.List; +import java.util.HashMap; + +/** + * Manage plugins and plugin configuration. + * @author mhanna + * @version 0.1 + */ +public abstract class PluginManager { + /** + * Defines the category of plugin defined by the subclass. + */ + protected final String pluginCategory; + + /** + * Define common strings to trim off the end of the name. + */ + protected final String pluginSuffix; + + /** + * Plugins stored based on their name. + */ + protected final Map> pluginsByName; + + /** + * Create a new plugin manager. + * @param pluginType Core type for a plugin. + * @param pluginCategory Provides a category name to the plugin. Must not be null. + * @param pluginSuffix Provides a suffix that will be trimmed off when converting to a plugin name. Can be null. + */ + protected PluginManager(Class pluginType, String pluginCategory, String pluginSuffix) { + this.pluginCategory = pluginCategory; + this.pluginSuffix = pluginSuffix; + List> plugins = PackageUtils.getClassesImplementingInterface(pluginType); + pluginsByName = createPluginDatabase(plugins); + } + + /** + * Does a plugin with the given name exist? + * + * @param pluginName Name of the plugin for which to search. + * @return True if the plugin exists, false otherwise. + */ + public boolean exists(String pluginName) { + return pluginsByName.containsKey(pluginName); + } + + + /** + * Gets a plugin with the given name, or null if no plugin exists. + * + * @param pluginName Name of the plugin to retrieve. + * @return The plugin object if found; null otherwise. + */ + public PluginType createByName(String pluginName) { + try { + Class plugin = pluginsByName.get(pluginName); + if( plugin == null ) + throw new StingException(String.format("Could not find %s with name: %s", pluginCategory,pluginName)); + return plugin.newInstance(); + } + catch( InstantiationException ex ) { + throw new StingException(String.format("Unable to instantiate %s %s",pluginCategory,pluginName), ex); + } + catch( IllegalAccessException ex ) { + throw new StingException(String.format("Unable to access %s %s",pluginCategory,pluginName), ex); + } + } + + + + /** + * Create the list of available plugins and add them to the database. + * + * @param pluginClasses Classes to record. + * @return map of plugin name -> plugin. + */ + private Map> createPluginDatabase(List> pluginClasses) { + Map> plugins = new HashMap>(); + + for (Class pluginClass : pluginClasses) { + String pluginName = getName(pluginClass); + plugins.put(pluginName, pluginClass); + } + + return plugins; + } + + /** + * Create a name for this type of plugin. + * + * @param pluginType The type of plugin. + * @return A name for this type of plugin. + */ + public String getName(Class pluginType) { + String pluginName = ""; + + if (pluginName.length() == 0) { + pluginName = pluginType.getSimpleName(); + if (pluginSuffix != null && pluginName.endsWith(pluginSuffix)) + pluginName = pluginName.substring(0, pluginName.lastIndexOf(pluginSuffix)); + } + + return pluginName; + } +}