Prototype, buggy implementation of walker command-line arguments. Doesn't
(yet) deal elegantly with even simple cases. git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@180 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
919a86e876
commit
9e2a373184
|
|
@ -110,6 +110,7 @@
|
|||
<!-- Compile the java code from ${src} into build -->
|
||||
<javac destdir="build" classpathref="thirdparty.dependencies"
|
||||
debug="true" debuglevel="lines,vars,source">
|
||||
<!--compilerarg value="-Xlint:unchecked" /-->
|
||||
<src refid="source"/>
|
||||
</javac>
|
||||
</target>
|
||||
|
|
@ -196,7 +197,7 @@
|
|||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="javadoc">
|
||||
<target name="javadoc" description="generates javadoc">
|
||||
<mkdir dir="javadoc"/>
|
||||
<javadoc sourcepathref="${target}.srcdir" destdir="javadoc"/>
|
||||
</target>
|
||||
|
|
|
|||
2
ivy.xml
2
ivy.xml
|
|
@ -7,6 +7,6 @@
|
|||
<dependency org="junit" name="junit" rev="4.4" />
|
||||
<dependency org="log4j" name="log4j" rev="1.2.15" />
|
||||
<dependency org="colt" name="colt" rev="1.2.0" />
|
||||
<dependency org="commons-cli" name="commons-cli" rev="1.1" />
|
||||
<dependency org="commons-cli" name="commons-cli" rev="1.2" />
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import org.broadinstitute.sting.gatk.refdata.rodDbSNP;
|
|||
import org.broadinstitute.sting.gatk.refdata.rodGFF;
|
||||
import org.broadinstitute.sting.gatk.walkers.LocusWalker;
|
||||
import org.broadinstitute.sting.gatk.walkers.ReadWalker;
|
||||
import org.broadinstitute.sting.gatk.walkers.Walker;
|
||||
import org.broadinstitute.sting.utils.FastaSequenceFile2;
|
||||
import org.broadinstitute.sting.utils.GenomeLoc;
|
||||
import org.broadinstitute.sting.utils.Utils;
|
||||
|
|
@ -42,6 +43,7 @@ public class GenomeAnalysisTK extends CommandLineProgram {
|
|||
|
||||
// our walker manager
|
||||
private WalkerManager walkerManager = null;
|
||||
private Walker my_walker = null;
|
||||
|
||||
public String pluginPathName = null;
|
||||
private TraversalEngine engine = null;
|
||||
|
|
@ -60,12 +62,12 @@ public class GenomeAnalysisTK extends CommandLineProgram {
|
|||
* Flags don't take an argument, the associated Boolean gets set to true if the flag appears on the command line.
|
||||
*/
|
||||
protected void setupArgs() {
|
||||
m_parser.addRequiredlArg("input_file", "I", "SAM or BAM file for validation", "INPUT_FILE");
|
||||
m_parser.addRequiredArg("input_file", "I", "SAM or BAM file for validation", "INPUT_FILE");
|
||||
m_parser.addOptionalArg("maximum_reads", "M", "Maximum number of reads to process before exiting", "MAX_READS_ARG");
|
||||
m_parser.addOptionalArg("validation_strictness", "S", "How strict should we be with validation", "STRICTNESS_ARG");
|
||||
m_parser.addOptionalArg("reference_sequence", "R", "Reference sequence file", "REF_FILE_ARG");
|
||||
m_parser.addOptionalArg("genome_region", "L", "Genome region to operation on: from chr:start-end", "REGION_STR");
|
||||
m_parser.addRequiredlArg("analysis_type", "T", "Type of analysis to run", "Analysis_Name");
|
||||
m_parser.addRequiredArg("analysis_type", "T", "Type of analysis to run", "Analysis_Name");
|
||||
m_parser.addOptionalArg("DBSNP", "D", "DBSNP file", "DBSNP_FILE");
|
||||
m_parser.addOptionalArg("Hapmap", "H", "Hapmap file", "HAPMAP_FILE");
|
||||
m_parser.addOptionalFlag("threaded_IO", "P", "If set, enables threaded I/O operations", "ENABLED_THREADED_IO");
|
||||
|
|
@ -74,6 +76,32 @@ public class GenomeAnalysisTK extends CommandLineProgram {
|
|||
m_parser.addOptionalArg("intervals_file", "V", "File containing list of genomic intervals to operate on. line := <contig> <start> <end>", "INTERVALS_FILE");
|
||||
}
|
||||
|
||||
/**
|
||||
* GATK can add arguments dynamically based on analysis type.
|
||||
* @return true
|
||||
*/
|
||||
@Override
|
||||
protected boolean canAddArgumentsDynamically() { return true; }
|
||||
|
||||
/**
|
||||
* GATK provides the walker as an argument source. As a side-effect, initializes the walker variable.
|
||||
* @return List of walkers to load dynamically.
|
||||
*/
|
||||
@Override
|
||||
protected Object[] getArgumentSources() {
|
||||
if( Analysis_Name == null )
|
||||
throw new IllegalArgumentException("Must provide analysis name");
|
||||
|
||||
walkerManager = new WalkerManager( pluginPathName );
|
||||
|
||||
if( !walkerManager.doesWalkerExist(Analysis_Name) )
|
||||
throw new IllegalArgumentException("Invalid analysis name");
|
||||
|
||||
my_walker = walkerManager.getWalkerByName(Analysis_Name);
|
||||
|
||||
return new Object[] { my_walker };
|
||||
}
|
||||
|
||||
/**
|
||||
* Required main method implementation.
|
||||
*/
|
||||
|
|
@ -82,10 +110,6 @@ public class GenomeAnalysisTK extends CommandLineProgram {
|
|||
}
|
||||
|
||||
protected int execute() {
|
||||
|
||||
|
||||
walkerManager = new WalkerManager(pluginPathName);
|
||||
|
||||
final boolean TEST_ROD = false;
|
||||
List<ReferenceOrderedData> rods = new ArrayList<ReferenceOrderedData>();
|
||||
|
||||
|
|
@ -155,15 +179,10 @@ public class GenomeAnalysisTK extends CommandLineProgram {
|
|||
|
||||
//LocusWalker<Integer,Integer> walker = new PileupWalker();
|
||||
|
||||
// Try to get the walker specified
|
||||
Object my_walker;
|
||||
if (walkerManager.doesWalkerExist(Analysis_Name)) {
|
||||
my_walker = walkerManager.getWalkerByName(Analysis_Name);
|
||||
} else {
|
||||
logger.fatal("Could not find walker " + Analysis_Name);
|
||||
return 0;
|
||||
}
|
||||
if( my_walker == null )
|
||||
throw new RuntimeException( "Sanity check failed -- no walker present." );
|
||||
|
||||
// Try to get the walker specified
|
||||
try {
|
||||
LocusWalker<?, ?> walker = (LocusWalker<?, ?>) my_walker;
|
||||
if ( INTERVALS_FILE == null )
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import net.sf.functionalj.reflect.JdkStdReflect;
|
|||
import net.sf.functionalj.FunctionN;
|
||||
import net.sf.functionalj.Functions;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
|
|
@ -20,6 +21,7 @@ import java.util.jar.JarEntry;
|
|||
import java.util.jar.JarInputStream;
|
||||
|
||||
import org.broadinstitute.sting.gatk.walkers.Walker;
|
||||
import org.broadinstitute.sting.utils.cmdLine.Argument;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
|
|
@ -88,7 +90,8 @@ public class WalkerManager {
|
|||
* @return The walker object if found; null otherwise.
|
||||
*/
|
||||
public Walker getWalkerByName(String walkerName) {
|
||||
return walkers.get(walkerName);
|
||||
Walker walker = walkers.get(walkerName);
|
||||
return walker;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package org.broadinstitute.sting.utils.cmdLine;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: hanna
|
||||
* Date: Mar 24, 2009
|
||||
* Time: 11:11:36 AM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
@Documented
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface Argument {
|
||||
String fullName() default "";
|
||||
String shortName() default "";
|
||||
String doc() default "";
|
||||
boolean required() default true;
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.broadinstitute.sting.utils.Pair;
|
||||
|
||||
/**
|
||||
* User: aaron
|
||||
* Date: Mar 19, 2009
|
||||
|
|
@ -33,7 +35,7 @@ public class ArgumentParser {
|
|||
private ArrayList<String> m_option_names = new ArrayList<String>();
|
||||
|
||||
// where we eventually want the values to land
|
||||
private HashMap<String, Field> m_storageLocations = new HashMap<String, Field>();
|
||||
private HashMap<String, Pair<Object,Field>> m_storageLocations = new HashMap<String, Pair<Object,Field>>();
|
||||
|
||||
// create Options object
|
||||
protected Options m_options = new Options();
|
||||
|
|
@ -100,7 +102,18 @@ public class ArgumentParser {
|
|||
* @param opt the option
|
||||
*/
|
||||
private void AddToOptionStorage(String name, String letterform, String fieldname, Option opt) {
|
||||
AddToOptionStorage(name, letterform, getField(prog, fieldname), opt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used locally to add to the options storage we have, for latter processing
|
||||
*
|
||||
* @param name the name of the option
|
||||
* @param letterform it's short form
|
||||
* @param field what field it should be stuck into on the calling class
|
||||
* @param opt the option
|
||||
*/
|
||||
private void AddToOptionStorage(String name, String letterform, Pair<Object,Field> field, Option opt) {
|
||||
// add to the option list
|
||||
m_options.addOption(opt);
|
||||
|
||||
|
|
@ -110,20 +123,23 @@ public class ArgumentParser {
|
|||
}
|
||||
|
||||
// add the object with it's name to the storage location
|
||||
try {
|
||||
m_storageLocations.put(name, prog.getClass().getField(fieldname));
|
||||
} catch (NoSuchFieldException e) {
|
||||
logger.fatal("Failed to find the field specified by the fieldname parameter.");
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
m_storageLocations.put( name, field );
|
||||
|
||||
// add to the list of m_options
|
||||
m_option_names.add(letterform);
|
||||
}
|
||||
|
||||
|
||||
private Pair<Object,Field> getField( Object obj, String fieldName ) {
|
||||
try {
|
||||
return new Pair<Object,Field>( obj, obj.getClass().getField(fieldName) );
|
||||
} catch (NoSuchFieldException e) {
|
||||
logger.fatal("Failed to find the field specified by the fieldname parameter.");
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* addRequiredlArg
|
||||
* addRequiredArg
|
||||
* <p/>
|
||||
* Adds a required argument to check on the command line
|
||||
*
|
||||
|
|
@ -132,7 +148,7 @@ public class ArgumentParser {
|
|||
* @param description the description of the argument
|
||||
* @param fieldname what field it should be stuck into on the calling class
|
||||
*/
|
||||
public void addRequiredlArg(String name, String letterform, String description, String fieldname) {
|
||||
public void addRequiredArg(String name, String letterform, String description, String fieldname) {
|
||||
// we always want the help option to be available
|
||||
Option opt = OptionBuilder.isRequired()
|
||||
.withLongOpt(name)
|
||||
|
|
@ -169,7 +185,7 @@ public class ArgumentParser {
|
|||
|
||||
|
||||
/**
|
||||
* addRequiredlArg
|
||||
* addRequiredArg
|
||||
* <p/>
|
||||
* Adds a required argument to check on the command line
|
||||
*
|
||||
|
|
@ -178,7 +194,7 @@ public class ArgumentParser {
|
|||
* @param description the description of the argument
|
||||
* @param fieldname what field it should be stuck into on the calling class
|
||||
*/
|
||||
public void addRequiredlArgList(String name, String letterform, String description, String fieldname) {
|
||||
public void addRequiredArgList(String name, String letterform, String description, String fieldname) {
|
||||
|
||||
// we always want the help option to be available
|
||||
Option opt = OptionBuilder.isRequired()
|
||||
|
|
@ -226,7 +242,7 @@ public class ArgumentParser {
|
|||
|
||||
|
||||
/**
|
||||
* addRequiredlFlag
|
||||
* addRequiredFlag
|
||||
* <p/>
|
||||
* Adds a required argument to check on the command line
|
||||
*
|
||||
|
|
@ -235,7 +251,7 @@ public class ArgumentParser {
|
|||
* @param description the description of the argument
|
||||
* @param fieldname what field it should be stuck into on the calling class
|
||||
*/
|
||||
public void addRequiredlFlag(String name, String letterform, String description, String fieldname) {
|
||||
public void addRequiredFlag(String name, String letterform, String description, String fieldname) {
|
||||
|
||||
// if they've passed a non-Boolean as a object, beat them
|
||||
try {
|
||||
|
|
@ -254,7 +270,6 @@ public class ArgumentParser {
|
|||
|
||||
// add it to the option
|
||||
AddToOptionStorage(name, letterform, fieldname, opt);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -265,45 +280,87 @@ public class ArgumentParser {
|
|||
*
|
||||
* @param args the command line arguments we recieved
|
||||
*/
|
||||
public void processArgs(String[] args) throws ParseException {
|
||||
CommandLineParser parser = new PosixParser();
|
||||
public void processArgs(String[] args, boolean allowUnrecognized) throws ParseException {
|
||||
OurPosixParser parser = new OurPosixParser();
|
||||
Collection<Option> opts = m_options.getOptions();
|
||||
|
||||
try {
|
||||
Collection<Option> opts = m_options.getOptions();
|
||||
parser.parse(m_options, args, !allowUnrecognized);
|
||||
}
|
||||
catch (UnrecognizedOptionException e) {
|
||||
// we don't care about unknown exceptions right now
|
||||
logger.warn(e.getMessage());
|
||||
if(!allowUnrecognized)
|
||||
throw e;
|
||||
}
|
||||
|
||||
CommandLine cmd = parser.parse(m_options, args);
|
||||
// Apache CLI can ignore unrecognized arguments with a boolean flag, but
|
||||
// you can't get to the unparsed args. Override PosixParser with a class
|
||||
// that can reach in and extract the protected command line.
|
||||
// TODO: Holy crap this is wacky. Find a cleaner way.
|
||||
CommandLine cmd = parser.getCmd();
|
||||
|
||||
// logger.info("We have " + opts.size() + " options");
|
||||
for (Option opt : opts) {
|
||||
if (cmd.hasOption(opt.getOpt())) {
|
||||
if (opt.hasArg()) {
|
||||
//logger.info("looking at " + m_storageLocations.get(opt.getLongOpt()));
|
||||
Field f = m_storageLocations.get(opt.getLongOpt());
|
||||
try {
|
||||
f.set(prog, constructFromString(f, cmd.getOptionValue(opt.getOpt())));
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.fatal("processArgs: cannot convert field " + f.toString());
|
||||
throw new RuntimeException("processArgs: Failed conversion " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
// logger.info("We have " + opts.size() + " options");
|
||||
for (Option opt : opts) {
|
||||
if (cmd.hasOption(opt.getOpt())) {
|
||||
if (opt.hasArg()) {
|
||||
//logger.info("looking at " + m_storageLocations.get(opt.getLongOpt()));
|
||||
Object obj = m_storageLocations.get(opt.getLongOpt()).first;
|
||||
Field field = m_storageLocations.get(opt.getLongOpt()).second;
|
||||
|
||||
Field f = m_storageLocations.get(opt.getLongOpt());
|
||||
try {
|
||||
//logger.fatal("about to parse field " + f.getName());
|
||||
f.set(prog, new Boolean(true));
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.fatal("processArgs: cannot convert field " + f.toString());
|
||||
throw new RuntimeException("processArgs: Failed conversion " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
field.set(obj, constructFromString(field, cmd.getOptionValue(opt.getOpt())));
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.fatal("processArgs: cannot convert field " + field.toString());
|
||||
throw new RuntimeException("processArgs: Failed conversion " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
Object obj = m_storageLocations.get(opt.getLongOpt()).first;
|
||||
Field field = m_storageLocations.get(opt.getLongOpt()).second;
|
||||
|
||||
try {
|
||||
//logger.fatal("about to parse field " + f.getName());
|
||||
field.set(obj, new Boolean(true));
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.fatal("processArgs: cannot convert field " + field.toString());
|
||||
throw new RuntimeException("processArgs: Failed conversion " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (UnrecognizedOptionException e) {
|
||||
// we don't care about unknown exceptions right now
|
||||
logger.warn(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private class OurPosixParser extends PosixParser {
|
||||
public CommandLine getCmd() { return cmd; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract arguments stored in annotations from fields of a given class.
|
||||
* @param source
|
||||
*/
|
||||
public void addArgumentSource( Object source ) {
|
||||
Field[] fields = source.getClass().getFields();
|
||||
for(Field field: fields) {
|
||||
Argument arg = field.getAnnotation(Argument.class);
|
||||
if(arg == null)
|
||||
continue;
|
||||
|
||||
String fullName = (arg.fullName().length() != 0) ? arg.fullName() : field.getName().trim().toLowerCase();
|
||||
String shortName = (arg.shortName().length() != 0) ? arg.shortName() : fullName.substring(0,1);
|
||||
if(shortName.length() != 1)
|
||||
throw new IllegalArgumentException("Invalid short name: " + shortName);
|
||||
String description = arg.required() ? "(Required Flag) " + arg.doc() : arg.doc();
|
||||
|
||||
// TODO: Handle flags, handle lists
|
||||
OptionBuilder ob = OptionBuilder.withLongOpt(fullName).withArgName(fullName).hasArg();
|
||||
if( arg.required() ) ob = ob.isRequired();
|
||||
if( description.length() != 0 ) ob = ob.withDescription( description );
|
||||
|
||||
Option option = ob.create( shortName );
|
||||
|
||||
AddToOptionStorage(fullName, shortName, new Pair<Object,Field>( source, field ), option );
|
||||
}
|
||||
}
|
||||
|
||||
private Object constructFromString(Field f, String str) {
|
||||
Type type = f.getType();
|
||||
|
|
@ -352,8 +409,8 @@ public class ArgumentParser {
|
|||
public static void main(String[] args) {
|
||||
ArgumentParser p = new ArgumentParser("CrapApp");
|
||||
p.setupDefaultArgs();
|
||||
p.addRequiredlArg("Flag","F","a required arg");
|
||||
p.addRequiredlFlag("Sub","S","a required flag");
|
||||
p.addRequiredArg("Flag","F","a required arg");
|
||||
p.addRequiredFlag("Sub","S","a required flag");
|
||||
p.addOptionalArg("Boat","T","Maybe you want a boat?");
|
||||
String[] str = {"--Flag","rrr","-T","ppp", "--Flag","ttt"};
|
||||
p.processArgs(str);
|
||||
|
|
@ -368,4 +425,4 @@ public class ArgumentParser {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -69,6 +69,20 @@ public abstract class CommandLineProgram {
|
|||
*/
|
||||
protected abstract void setupArgs();
|
||||
|
||||
/**
|
||||
* Will this application want to vary its argument list dynamically?
|
||||
* If so, parse the command-line options and then prompt the subclass to return
|
||||
* a list of argument providers.
|
||||
* @return Whether the application should vary command-line arguments dynamically.
|
||||
*/
|
||||
protected boolean canAddArgumentsDynamically() { return false; }
|
||||
|
||||
/**
|
||||
* Provide a list of object to inspect, looking for additional command-line arguments.
|
||||
* @return A list of objects to inspect.
|
||||
*/
|
||||
protected Object[] getArgumentSources() { return new Object[] {}; }
|
||||
|
||||
/**
|
||||
* this is the function that the inheriting class can expect to have called
|
||||
* when all the argument processing is done
|
||||
|
|
@ -111,8 +125,17 @@ public abstract class CommandLineProgram {
|
|||
clp.setupArgs();
|
||||
|
||||
// process the args
|
||||
clp.m_parser.processArgs(args);
|
||||
|
||||
if( clp.canAddArgumentsDynamically() ) {
|
||||
// if the command-line program can toss in extra args, fetch them and reparse the arguments.
|
||||
clp.m_parser.processArgs(args, true);
|
||||
Object[] argumentSources = clp.getArgumentSources();
|
||||
for( Object argumentSource: argumentSources )
|
||||
clp.addArgumentSource( argumentSource );
|
||||
clp.m_parser.processArgs(args, false);
|
||||
}
|
||||
else {
|
||||
clp.m_parser.processArgs(args, false);
|
||||
}
|
||||
|
||||
// if we're in debug mode, set the mode up
|
||||
if (clp.debugMode) {
|
||||
|
|
@ -164,13 +187,17 @@ public abstract class CommandLineProgram {
|
|||
// return the result
|
||||
System.exit(result);
|
||||
}
|
||||
catch (org.apache.commons.cli.ParseException e) {
|
||||
logger.fatal("Unable to pass command line arguments: " + e.getMessage() );
|
||||
clp.m_parser.printHelp();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// we catch all exceptions here. if it makes it to this level, we're in trouble. Let's bail!
|
||||
// TODO: what if the logger is the exception? hmm...
|
||||
logger.fatal("Exception caught by base Command Line Program, with message: " + e.getMessage());
|
||||
logger.fatal("with cause: " + e.getCause());
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,6 +256,14 @@ public abstract class CommandLineProgram {
|
|||
logger.setLevel(par);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass along a new set of valid command line arguments. In this case,
|
||||
* probably a class with @argument or @flag annotations.
|
||||
* @param source
|
||||
*/
|
||||
private void addArgumentSource( Object source ) {
|
||||
m_parser.addArgumentSource(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* we have some default options that should always get checked for in the
|
||||
|
|
|
|||
Loading…
Reference in New Issue