Better formatting of available walkers, and only output them along with help. Cleanup JVMUtils.

git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@1290 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
hanna 2009-07-21 22:23:28 +00:00
parent 761d70faa1
commit 6e4fd8db4a
9 changed files with 252 additions and 68 deletions

View File

@ -13,7 +13,6 @@ import java.util.ArrayList;
import net.sf.samtools.SAMFileReader;
/*
* Copyright (c) 2009 The Broad Institute
*

View File

@ -2,8 +2,7 @@ package org.broadinstitute.sting.gatk;
import org.broadinstitute.sting.utils.cmdLine.*;
import java.util.List;
import java.util.ArrayList;
import java.util.*;
/**
*
@ -34,9 +33,6 @@ import java.util.ArrayList;
* the gatk engine should deal with any data related information.
*/
public class CommandLineGATK extends CommandLineExecutable {
// our genome analysis engine
private GenomeAnalysisEngine GATKEngine = null;
@Argument(fullName = "analysis_type", shortName = "T", doc = "Type of analysis to run")
private String analysisName = null;
@ -49,14 +45,10 @@ public class CommandLineGATK extends CommandLineExecutable {
* @return A list of Strings that contain pleasant info about the GATK.
*/
@Override
protected List<String> getApplicationHeader() {
List<String> header = new ArrayList<String>();
header.add("The Genome Analysis Toolkit (GATK)");
header.add("Copyright (c) 2009 The Broad Institute");
header.add("Please view our documentation at http://www.broadinstitute.org/gsa/wiki");
header.add("For support, email gsadevelopers@broadinstitute.org");
header.add("");
return header;
protected ApplicationDetails getApplicationDetails() {
return new ApplicationDetails( createApplicationHeader(),
ApplicationDetails.createDefaultRunningInstructions(getClass()),
getAdditionalHelp() );
}
@Override
@ -78,4 +70,60 @@ public class CommandLineGATK extends CommandLineExecutable {
exitSystemWithError(e);
}
}
/**
* Creates the a short blurb about the GATK, copyright info, and where to get documentation.
* @return The application header.
*/
private List<String> createApplicationHeader() {
List<String> header = new ArrayList<String>();
header.add("The Genome Analysis Toolkit (GATK)");
header.add("Copyright (c) 2009 The Broad Institute");
header.add("Please view our documentation at http://www.broadinstitute.org/gsa/wiki");
header.add("For support, email gsadevelopers@broadinstitute.org");
header.add("");
return header;
}
/**
* Retrieves additional information about GATK walkers.
* TODO: This functionality is very similar to that employed by the HelpFormatter. Generalize
* the code in HelpFormatter and supply it as a helper to this method.
* @return A string summarizing the walkers available in this distribution.
*/
private String getAdditionalHelp() {
// Get the list of walker names from the walker manager.
Set<String> walkerNames = GATKEngine.getWalkerNames();
// Sort the list of walker names.
walkerNames = new TreeSet<String>( walkerNames );
// Construct a help string to output available walkers.
StringBuilder additionalHelp = new StringBuilder();
Formatter formatter = new Formatter( additionalHelp );
formatter.format( "Available analyses:%n" );
// Compute the max size of any walker name
int maxNameLength = 0;
for( String walkerName: walkerNames ) {
if( maxNameLength < walkerName.length() )
maxNameLength = walkerName.length();
}
final int fieldWidth = maxNameLength + HelpFormatter.FIELD_SEPARATION_WIDTH;
final int walkersPerLine = Math.min(HelpFormatter.LINE_WIDTH / fieldWidth, 4 );
final int columnSpacing = (HelpFormatter.LINE_WIDTH - (fieldWidth * walkersPerLine)) / walkersPerLine;
int currentWalkerName = 0;
for( String walkerName: walkerNames ) {
formatter.format( "%-" + HelpFormatter.FIELD_SEPARATION_WIDTH + "s" +
"%-" + fieldWidth + "s" +
"%-" + columnSpacing + "s", "", walkerName, "" );
if( ++currentWalkerName % walkersPerLine == 0 )
formatter.format("%n");
}
return additionalHelp.toString();
}
}

View File

@ -41,6 +41,7 @@ import org.broadinstitute.sting.utils.cmdLine.ArgumentException;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class GenomeAnalysisEngine {
@ -144,20 +145,21 @@ public class GenomeAnalysisEngine {
return microScheduler.execute(my_walker, locs, argCollection.maximumEngineIterations);
}
/**
* Gets a set of the names of all walkers that the GATK has discovered.
* @return A set of the names of all discovered walkers.
*/
public Set<String> getWalkerNames() {
return walkerManager.getWalkerNames();
}
/**
* Retrieves an instance of the walker based on the walker name.
* @param walkerName Name of the walker. Must not be null. If the walker cannot be instantiated, an exception will be thrown.
* @return An instance of the walker.
*/
public Walker<?,?> getWalkerByName( String walkerName ) {
try {
return walkerManager.createWalkerByName(walkerName);
} catch (InstantiationException ex) {
throw new StingException("Unable to instantiate walker.", ex);
}
catch (IllegalAccessException ex) {
throw new StingException("Unable to access walker", ex);
}
return walkerManager.createWalkerByName(walkerName);
}

View File

@ -1,3 +1,28 @@
/*
* Copyright (c) 2009 The Broad Institute
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.broadinstitute.sting.gatk;
import java.util.*;
@ -47,12 +72,27 @@ public class WalkerManager {
* @param walkerName Name of the walker to retrieve.
* @return The walker object if found; null otherwise.
*/
public Walker createWalkerByName(String walkerName)
throws InstantiationException, IllegalAccessException {
Class<? extends Walker> walker = walkersByName.get(walkerName);
if( walker == null )
throw new StingException(String.format("Could not find walker with name: %s", walkerName));
return walker.newInstance();
public Walker createWalkerByName(String walkerName) {
try {
Class<? extends Walker> 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);
}
}
/**
* Get the list of walkers currently available to the GATK.
* @return Names of currently available walkers.
*/
public Set<String> getWalkerNames() {
return Collections.unmodifiableSet( walkersByName.keySet() );
}
/**
@ -177,7 +217,6 @@ public class WalkerManager {
for (Class<? extends Walker> walkerClass : walkerClasses) {
String walkerName = getWalkerName(walkerClass);
logger.info(String.format("* Adding module %s", walkerName));
walkers.put(walkerName, walkerClass);
}

View File

@ -1,6 +1,8 @@
package org.broadinstitute.sting.utils;
import java.lang.reflect.Modifier;
import java.io.File;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
@ -17,6 +19,25 @@ public class JVMUtils {
*/
private JVMUtils() { }
/**
* Determines which location contains the specified class.
*
* @return Location (either jar file or directory) of path containing class.
*/
public static File getLocationFor( Class clazz ) throws IOException {
try {
java.net.URI locationURI = clazz.getProtectionDomain().getCodeSource().getLocation().toURI();
return new File(locationURI);
}
catch (java.net.URISyntaxException ex) {
// a URISyntaxException here must be an IO error; wrap as such.
throw new IOException(ex);
}
catch ( NullPointerException ne ) {
throw new IOException("Can not extract code source location for "+clazz.getName());
}
}
/**
* Is the specified class a concrete implementation of baseClass?
* @param clazz Class to check.

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2009 The Broad Institute
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.broadinstitute.sting.utils.cmdLine;
import org.broadinstitute.sting.utils.JVMUtils;
import org.broadinstitute.sting.utils.StingException;
import java.util.List;
import java.util.Collections;
import java.io.IOException;
/**
* Contains details additional details that the program can
* supply about itself.
*
* @author hanna
* @version 0.1
*/
public class ApplicationDetails {
/**
* Retrieve key information about the application (name, who to contact for support, etc.).
*/
final List<String> applicationHeader;
/**
* Extract details covering exactly how to run this executable.
*/
final String runningInstructions;
/**
* Additional help particular to this command-line application.
*/
final String additionalHelp;
public ApplicationDetails( List<String> applicationHeader, String runningInstructions ) {
this(applicationHeader,runningInstructions,null);
}
public ApplicationDetails( List<String> applicationHeader, String runningInstructions, String additionalHelp ) {
this.applicationHeader = applicationHeader;
this.runningInstructions = runningInstructions;
this.additionalHelp = additionalHelp;
}
public static List<String> createDefaultHeader(Class<? extends CommandLineProgram> application) {
return Collections.singletonList("Program Name: " + application.getName());
}
public static String createDefaultRunningInstructions(Class<? extends CommandLineProgram> application) {
// Default implementation to find a command line that makes sense.
// If the user is running from a jar, return '-jar <jarname>'; otherwise
// return the full class name.
String runningInstructions = null;
try {
runningInstructions = JVMUtils.getLocationFor( application ).getName();
}
catch( IOException ex ) {
throw new StingException("Unable to determine running instructions", ex);
}
if( runningInstructions.endsWith(".jar") )
runningInstructions = String.format("-jar %s", runningInstructions);
else
runningInstructions = application.getName();
return runningInstructions;
}
}

View File

@ -1,16 +1,12 @@
package org.broadinstitute.sting.utils.cmdLine;
import org.apache.log4j.*;
import org.broadinstitute.sting.utils.JVMUtils;
import org.broadinstitute.sting.utils.StingException;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.Collections;
import java.util.List;
/**
* User: aaron
@ -91,30 +87,12 @@ public abstract class CommandLineProgram {
private static String debugPatternString = "%n[level] %p%n[date]\t\t %d{dd MMM yyyy HH:mm:ss,SSS} %n[class]\t\t %C %n[location]\t %l %n[line number]\t %L %n[message]\t %m %n";
/**
* Retrieves text from the application regarding what parameters to put on the
* JVM command line to run this application.
* @return helpful instructions on the class / jar to run.
* Allows a given application to return a brief description of itself.
* @return An ApplicationDetails object describing the current application. Should not be null.
*/
protected String getRunningInstructions() {
// Default implementation to find a command line that makes sense.
// If the user is running from a jar, return '-jar <jarname>'; otherwise
// return the full class name.
String runningInstructions = getClass().getName();
if( runningInstructions.endsWith(".jar") )
runningInstructions = String.format("-jar %s", runningInstructions);
else
runningInstructions = getClass().getName();
return runningInstructions;
}
/**
* Allows a given application to return a few lines of text describing the application.
* @return A few lines of text describing the application. Should not be null.
*/
protected List<String> getApplicationHeader() {
return Collections.singletonList("Program Name: " + getClass().getName());
protected ApplicationDetails getApplicationDetails() {
return new ApplicationDetails( ApplicationDetails.createDefaultHeader(getClass()),
ApplicationDetails.createDefaultRunningInstructions(getClass()) );
}
/**
@ -260,7 +238,7 @@ public abstract class CommandLineProgram {
System.exit(result);
}
catch (ArgumentException e) {
clp.parser.printHelp( clp.getRunningInstructions() );
clp.parser.printHelp( clp.getApplicationDetails() );
// Rethrow the exception to exit with an error.
throw e;
}
@ -307,7 +285,7 @@ public abstract class CommandLineProgram {
java.util.Date date = new java.util.Date();
logger.info("-------------------------------------------------------");
for( String headerLine: clp.getApplicationHeader() )
for( String headerLine: clp.getApplicationDetails().applicationHeader )
logger.info(headerLine);
String output = "";
for (String str : args) {
@ -378,7 +356,7 @@ public abstract class CommandLineProgram {
* @param parser True if help is present; false otherwise.
*/
private static void printHelpAndExit( CommandLineProgram clp, ParsingEngine parser ) {
parser.printHelp( clp.getRunningInstructions() );
parser.printHelp( clp.getApplicationDetails() );
System.exit(0);
}

View File

@ -30,16 +30,21 @@ public class HelpFormatter {
/**
* Target this line width.
*/
private static final int LINE_WIDTH = 100;
private static final int ARG_DOC_SEPARATION_WIDTH = 3;
public static final int LINE_WIDTH = 100;
public static final int FIELD_SEPARATION_WIDTH = 3;
/**
* Prints the help, given a collection of argument definitions.
* @param argumentDefinitions Argument definitions for which help should be printed.
*/
public void printHelp( String runningInstructions, ArgumentDefinitions argumentDefinitions ) {
public void printHelp( ApplicationDetails applicationDetails, ArgumentDefinitions argumentDefinitions ) {
List<ArgumentDefinitionGroup> argumentGroups = prepareArgumentGroups( argumentDefinitions );
System.out.printf("%s%s%n",getSynopsis(runningInstructions,argumentGroups),getDetailed(argumentGroups) );
String synopsis = getSynopsis(applicationDetails.runningInstructions,argumentGroups);
String additionalDetails = applicationDetails.additionalHelp != null ? applicationDetails.additionalHelp : "";
String detailedDescription = getDetailed(argumentGroups);
System.out.printf("%s%n%s%n%s%n",synopsis,detailedDescription,additionalDetails );
}
/**
@ -114,8 +119,8 @@ public class HelpFormatter {
// Try to fit the entire argument definition across the screen, but impose an arbitrary cap of 3/4 *
// LINE_WIDTH in case the length of the arguments gets out of control.
int argWidth = Math.min( findLongestArgumentCallingInfo(argumentDefinitions), (LINE_WIDTH*3)/4 - ARG_DOC_SEPARATION_WIDTH );
int docWidth = LINE_WIDTH - argWidth - ARG_DOC_SEPARATION_WIDTH;
int argWidth = Math.min( findLongestArgumentCallingInfo(argumentDefinitions), (LINE_WIDTH*3)/4 - FIELD_SEPARATION_WIDTH );
int docWidth = LINE_WIDTH - argWidth - FIELD_SEPARATION_WIDTH;
for( ArgumentDefinition argumentDefinition: argumentDefinitions ) {
Iterator<String> wordWrappedArgs = wordWrap( getArgumentCallingInfo(argumentDefinition), argWidth ).iterator();
@ -125,7 +130,7 @@ public class HelpFormatter {
String arg = wordWrappedArgs.hasNext() ? wordWrappedArgs.next() : "";
String doc = wordWrappedDoc.hasNext() ? wordWrappedDoc.next() : "";
String formatString = "%-" + argWidth + "s%" + ARG_DOC_SEPARATION_WIDTH + "s%s%n";
String formatString = "%-" + argWidth + "s%" + FIELD_SEPARATION_WIDTH + "s%s%n";
formatter.format( formatString, arg, "", doc );
}
}

View File

@ -291,8 +291,8 @@ public class ParsingEngine {
/**
* Prints out the help associated with these command-line argument definitions.
*/
public void printHelp( String runningInstructions ) {
new HelpFormatter().printHelp(runningInstructions,argumentDefinitions);
public void printHelp( ApplicationDetails applicationDetails ) {
new HelpFormatter().printHelp(applicationDetails,argumentDefinitions);
}
/**