// Path: src/main/java/abra/Logger.java
// public class Logger {
// 	
// 	enum Level { TRACE, DEBUG, INFO, WARN, ERROR };
// 	
// 	public static Level LEVEL = Level.INFO;
// 	
// 	private static Map<String, Level> stringToLevel;
// 	
// 	static {
// 		stringToLevel = new HashMap<String, Level>();
// 		stringToLevel.put("TRACE", Level.TRACE);
// 		stringToLevel.put("DEBUG", Level.DEBUG);
// 		stringToLevel.put("INFO", Level.INFO);
// 		stringToLevel.put("WARN", Level.WARN);
// 		stringToLevel.put("ERROR", Level.ERROR);
// 	}
// 	
// 	// For trace or debug messages, use varargs to avoid string concatenation unless enabled
// 	
// 	public static void trace(String format, Object... args) {
// 		if (LEVEL == Level.TRACE) {
// 			log(String.format(format, args), Level.TRACE);
// 		}
// 	}
// 	
// 	public static void debug(String format, Object... args) {
// 		if (LEVEL == Level.DEBUG || LEVEL == Level.TRACE) {
// 			log(String.format(format, args), Level.DEBUG);
// 		}
// 	}
// 	
// 	public static void info(String format, Object... args) {
// 		if (LEVEL == Level.TRACE || LEVEL == Level.DEBUG || LEVEL == Level.INFO) {
// 			log(String.format(format, args), Level.INFO);
// 		}
// 	}
// 		
// 	public static void warn(String message) {
// 		if (LEVEL == Level.TRACE || LEVEL == Level.DEBUG || LEVEL == Level.INFO || LEVEL == Level.WARN) {
// 			log(message, Level.WARN);
// 		}
// 	}
// 	
// 	public static void error(String message) {
// 		log(message, Level.ERROR);
// 	}
// 	
// 	public static void setLevel(String str) {
// 		Level level = stringToLevel.get(str.toUpperCase());
// 		if (level == null) {
// 			throw new IllegalArgumentException("Log level must be one of trace, debug, info, warn or error.");
// 		}
// 		
// 		Logger.LEVEL = level;
// 	}
// 	
// 	public static void log(String message, Level level) {
// 		
// 		String levelStr = "UNKNOWN";
// 		
// 		switch (level) {
// 			case ERROR:
// 				levelStr = "ERROR";
// 				break;
// 			case WARN:
// 				levelStr = "WARNING";
// 				break;
// 			case INFO:
// 				levelStr = "INFO";
// 				break;
// 			case DEBUG:
// 				levelStr = "DEBUG";
// 				break;
// 			case TRACE:
// 				levelStr = "TRACE";
// 				break;
// 		}
// 		
// 		System.err.println(levelStr + "\t" + new Date() + "\t" + message);
// 	}
// }
// 
// Path: src/main/java/abra/Options.java
// public abstract class Options {
// 	protected static final String HELP = "help";
// 	
// 	private OptionSet options;
// 
//     protected void printHelp() {
//         try {
//         	getOptionParser().printHelpOn(System.err);
//         }
//         catch (IOException e) {
//             e.printStackTrace();
//             throw new RuntimeException("IOException encountered when attempting to output help.");
//         }
//     }
//     
//     public void parseOptions(String[] args) {
// 
//         try {
//             options = getOptionParser().parse(args);
//         
//             if (options.has(HELP)) {
//                 printHelp();
//             } else {
//             	init();
//                 validate();
//             }
//         } catch (joptsimple.OptionException e) {
//             System.err.println(e.getMessage());
//             printHelp();
//             throw e;
//         }
//     }
//     
//     protected OptionSet getOptions() {
//     	return options;
//     }
// 
//     abstract protected OptionParser getOptionParser();
//     
//     abstract protected void validate();
//     
//     protected void init() {
//     }
// }


import abra.Logger;
import abra.Options;
import joptsimple.OptionParser;
	private OptionParser parser;
	private boolean isValid;
	
	private int numThreads;
	private String tumor;
	private String normal;
	private String reference;
	private int strpThreshold;
	private int hrunThreshold;
	private int pcrPenalty;
	private int ispanFilter;
	private float qualFilter;
	private int fsFilter;
	private float lowMQFilter;
	private float minQual;
	private float minMapq;
	private float minVaf;
	private float oddsr;
	
	@Override
	protected OptionParser getOptionParser() {
    	if (parser == null) {
            parser = new OptionParser();
            parser.accepts(NUM_THREADS, "Processing threads").withRequiredArg().ofType(Integer.class).defaultsTo(4);
            parser.accepts(TUMOR, "Tumor BAM file").withRequiredArg().ofType(String.class);
            parser.accepts(NORMAL, "Normal BAM file").withRequiredArg().ofType(String.class);
            parser.accepts(SAMPLE, "BAM file to be used for single sample calling").withRequiredArg().ofType(String.class);
            parser.accepts(REFERENCE, "Reference fasta").withRequiredArg().ofType(String.class);
            parser.accepts(STRP_THRESHOLD, "Filter variants with short tandem repeat period at or above this threshold(-1 to disable)").withRequiredArg().ofType(Integer.class).defaultsTo(5); 
            parser.accepts(HRUN_THRESHOLD, "Filter short indels with a nearby homopolymer run of this length or greater - only neighboring 20 bases searched (-1 to disable)").withRequiredArg().ofType(Integer.class).defaultsTo(6);
// Path: src/main/java/abra/Logger.java
// public class Logger {
// 	
// 	enum Level { TRACE, DEBUG, INFO, WARN, ERROR };
// 	
// 	public static Level LEVEL = Level.INFO;
// 	
// 	private static Map<String, Level> stringToLevel;
// 	
// 	static {
// 		stringToLevel = new HashMap<String, Level>();
// 		stringToLevel.put("TRACE", Level.TRACE);
// 		stringToLevel.put("DEBUG", Level.DEBUG);
// 		stringToLevel.put("INFO", Level.INFO);
// 		stringToLevel.put("WARN", Level.WARN);
// 		stringToLevel.put("ERROR", Level.ERROR);
// 	}
// 	
// 	// For trace or debug messages, use varargs to avoid string concatenation unless enabled
// 	
// 	public static void trace(String format, Object... args) {
// 		if (LEVEL == Level.TRACE) {
// 			log(String.format(format, args), Level.TRACE);
// 		}
// 	}
// 	
// 	public static void debug(String format, Object... args) {
// 		if (LEVEL == Level.DEBUG || LEVEL == Level.TRACE) {
// 			log(String.format(format, args), Level.DEBUG);
// 		}
// 	}
// 	
// 	public static void info(String format, Object... args) {
// 		if (LEVEL == Level.TRACE || LEVEL == Level.DEBUG || LEVEL == Level.INFO) {
// 			log(String.format(format, args), Level.INFO);
// 		}
// 	}
// 		
// 	public static void warn(String message) {
// 		if (LEVEL == Level.TRACE || LEVEL == Level.DEBUG || LEVEL == Level.INFO || LEVEL == Level.WARN) {
// 			log(message, Level.WARN);
// 		}
// 	}
// 	
// 	public static void error(String message) {
// 		log(message, Level.ERROR);
// 	}
// 	
// 	public static void setLevel(String str) {
// 		Level level = stringToLevel.get(str.toUpperCase());
// 		if (level == null) {
// 			throw new IllegalArgumentException("Log level must be one of trace, debug, info, warn or error.");
// 		}
// 		
// 		Logger.LEVEL = level;
// 	}
// 	
// 	public static void log(String message, Level level) {
// 		
// 		String levelStr = "UNKNOWN";
// 		
// 		switch (level) {
// 			case ERROR:
// 				levelStr = "ERROR";
// 				break;
// 			case WARN:
// 				levelStr = "WARNING";
// 				break;
// 			case INFO:
// 				levelStr = "INFO";
// 				break;
// 			case DEBUG:
// 				levelStr = "DEBUG";
// 				break;
// 			case TRACE:
// 				levelStr = "TRACE";
// 				break;
// 		}
// 		
// 		System.err.println(levelStr + "\t" + new Date() + "\t" + message);
// 	}
// }
// 
// Path: src/main/java/abra/Options.java
// public abstract class Options {
// 	protected static final String HELP = "help";
// 	
// 	private OptionSet options;
// 
//     protected void printHelp() {
//         try {
//         	getOptionParser().printHelpOn(System.err);
//         }
//         catch (IOException e) {
//             e.printStackTrace();
//             throw new RuntimeException("IOException encountered when attempting to output help.");
//         }
//     }
//     
//     public void parseOptions(String[] args) {
// 
//         try {
//             options = getOptionParser().parse(args);
//         
//             if (options.has(HELP)) {
//                 printHelp();
//             } else {
//             	init();
//                 validate();
//             }
//         } catch (joptsimple.OptionException e) {
//             System.err.println(e.getMessage());
//             printHelp();
//             throw e;
//         }
//     }
//     
//     protected OptionSet getOptions() {
//     	return options;
//     }
// 
//     abstract protected OptionParser getOptionParser();
//     
//     abstract protected void validate();
//     
//     protected void init() {
//     }
// }


// Path: src/main/java/abra/cadabra/CadabraOptions.java
import abra.Logger;
import abra.Options;
import joptsimple.OptionParser;

	private OptionParser parser;
	private boolean isValid;
	
	private int numThreads;
	private String tumor;
	private String normal;
	private String reference;
	private int strpThreshold;
	private int hrunThreshold;
	private int pcrPenalty;
	private int ispanFilter;
	private float qualFilter;
	private int fsFilter;
	private float lowMQFilter;
	private float minQual;
	private float minMapq;
	private float minVaf;
	private float oddsr;
	
	@Override
	protected OptionParser getOptionParser() {
    	if (parser == null) {
            parser = new OptionParser();
            parser.accepts(NUM_THREADS, "Processing threads").withRequiredArg().ofType(Integer.class).defaultsTo(4);
            parser.accepts(TUMOR, "Tumor BAM file").withRequiredArg().ofType(String.class);
            parser.accepts(NORMAL, "Normal BAM file").withRequiredArg().ofType(String.class);
            parser.accepts(SAMPLE, "BAM file to be used for single sample calling").withRequiredArg().ofType(String.class);
            parser.accepts(REFERENCE, "Reference fasta").withRequiredArg().ofType(String.class);
            parser.accepts(STRP_THRESHOLD, "Filter variants with short tandem repeat period at or above this threshold(-1 to disable)").withRequiredArg().ofType(Integer.class).defaultsTo(5); 
            parser.accepts(HRUN_THRESHOLD, "Filter short indels with a nearby homopolymer run of this length or greater - only neighboring 20 bases searched (-1 to disable)").withRequiredArg().ofType(Integer.class).defaultsTo(6);
            parser.accepts(PCR_PENALTY, "Penalize quality score for variants reaching strp or hrun thresholds by specified amount.").withRequiredArg().ofType(Integer.class).defaultsTo(30);