Fixed the logic of the @Output annotation and its interaction with 'required'.

ALL GATK DEVELOPERS PLEASE READ NOTES BELOW:

I have updated the @Output annotation to behave differently and to include a 'defaultToStdout' tag.
  * The 'defaultToStdout' tags lets walkers specify whether to default to stdout if -o is not provided.
  * The logic for @Output is now:
    * if required==true then -o MUST be provided or a User Error is generated.
    * if required==false and defaultToStdout==true then the output is assigned to stdout if no -o is provided.
      * this is the default behavior (i.e. @Output with no modifiers).
    * if required==false and defaultToStdout==false then the output object is null.
      * use this combination for truly optional outputs (e.g. the -badSites option in AssessNA12878).

  * I have updated walkers so that previous behavior has been maintained (as best I could).
    * In general, all @Outputs with default long/short names have required=false.
    * Walkers with nWayOut options must have required==false and defaultToStdout==false (I added checks for this)
  * I added unit tests for @Output changes with David's help (thanks!).
  * #resolve GSA-837
This commit is contained in:
Eric Banks 2013-03-13 14:57:28 -04:00
parent acaa96f853
commit 7cab709a88
42 changed files with 262 additions and 57 deletions

View File

@ -91,7 +91,7 @@ public class RecalibrationArgumentCollection {
* If not provided, then no plots will be generated (useful for queue scatter/gathering).
* However, we *highly* recommend that users generate these plots whenever possible for QC checking.
*/
@Output(fullName = "plot_pdf_file", shortName = "plots", doc = "The output recalibration pdf file to create", required = false)
@Output(fullName = "plot_pdf_file", shortName = "plots", doc = "The output recalibration pdf file to create", required = false, defaultToStdout = false)
public File RECAL_PDF_FILE = null;
/**
@ -220,7 +220,7 @@ public class RecalibrationArgumentCollection {
public String FORCE_PLATFORM = null;
@Hidden
@Output(fullName = "recal_table_update_log", shortName = "recal_table_update_log", required = false, doc = "If provided, log all updates to the recalibration tables to the given file. For debugging/testing purposes only")
@Output(fullName = "recal_table_update_log", shortName = "recal_table_update_log", required = false, doc = "If provided, log all updates to the recalibration tables to the given file. For debugging/testing purposes only", defaultToStdout = false)
public PrintStream RECAL_TABLE_UPDATE_LOG = null;
/**

View File

@ -66,7 +66,7 @@ import java.io.*;
@PartitionBy(PartitionType.READ)
public class RecalibrationPerformance extends RodWalker<Integer, Integer> implements NanoSchedulable {
@Output(doc="Write output to this file", required = true)
@Output(doc="Write output to this file")
public PrintStream out;
@Input(fullName="recal", shortName="recal", required=false, doc="The input covariates table file")

View File

@ -69,6 +69,7 @@ import org.broadinstitute.sting.utils.GenomeLoc;
import org.broadinstitute.sting.utils.Utils;
import org.broadinstitute.sting.utils.clipping.ReadClipper;
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;
import org.broadinstitute.sting.utils.exceptions.UserException;
import org.broadinstitute.sting.utils.help.DocumentedGATKFeature;
import org.broadinstitute.sting.utils.help.HelpConstants;
import org.broadinstitute.sting.utils.sam.BySampleSAMFileWriter;
@ -112,7 +113,7 @@ import org.broadinstitute.sting.utils.sam.ReadUtils;
@Downsample(by=DownsampleType.BY_SAMPLE, toCoverage=40)
public class ReduceReads extends ReadWalker<ObjectArrayList<GATKSAMRecord>, ReduceReadsStash> {
@Output(required=true)
@Output(required = false, defaultToStdout = false)
private StingSAMFileWriter out = null;
private SAMFileWriter writerToUse = null;
@ -259,6 +260,13 @@ public class ReduceReads extends ReadWalker<ObjectArrayList<GATKSAMRecord>, Redu
@Override
public void initialize() {
super.initialize();
if ( !nwayout && out == null )
throw new UserException.MissingArgument("out", "the output must be provided and is optional only for certain debugging modes");
if ( nwayout && out != null )
throw new UserException.CommandLineException("--out and --nwayout can not be used simultaneously; please use one or the other");
GenomeAnalysisEngine toolkit = getToolkit();
readNameHash = new Object2LongOpenHashMap<String>(100000); // prepare the read name hash to keep track of what reads have had their read names compressed
intervalList = new ObjectAVLTreeSet<GenomeLoc>(); // get the interval list from the engine. If no interval list was provided, the walker will work in WGS mode
@ -266,7 +274,6 @@ public class ReduceReads extends ReadWalker<ObjectArrayList<GATKSAMRecord>, Redu
if (toolkit.getIntervals() != null)
intervalList.addAll(toolkit.getIntervals());
final boolean preSorted = true;
final boolean indexOnTheFly = true;
final boolean keep_records = true;

View File

@ -99,7 +99,7 @@ public class BaseCoverageDistribution extends LocusWalker<ArrayList<Integer>, Ma
/**
* The output GATK Report table
*/
@Output(required = true, doc = "The output GATK Report table")
@Output(doc = "The output GATK Report table")
private PrintStream out;
/**

View File

@ -110,7 +110,7 @@ import java.util.*;
@PartitionBy(PartitionType.INTERVAL)
public class DiagnoseTargets extends LocusWalker<Long, Long> {
@Output(doc = "File to which variants should be written", required = true)
@Output(doc = "File to which variants should be written")
private VariantContextWriter vcfWriter = null;
@Argument(fullName = "minimum_base_quality", shortName = "BQ", doc = "The minimum Base Quality that is considered for calls", required = false)

View File

@ -92,7 +92,7 @@ import java.io.PrintStream;
@PartitionBy(PartitionType.CONTIG)
@ActiveRegionTraversalParameters(extension = 0, maxRegion = 50000)
public class FindCoveredIntervals extends ActiveRegionWalker<GenomeLoc, Long> {
@Output(required = true)
@Output
private PrintStream out;
@Argument(fullName = "uncovered", shortName = "u", required = false, doc = "output intervals that fail the coverage threshold instead")

View File

@ -180,7 +180,7 @@ public class UnifiedGenotyper extends LocusWalker<List<VariantCallContext>, Unif
* A raw, unfiltered, highly sensitive callset in VCF format.
*/
//@Gather(className = "org.broadinstitute.sting.queue.extensions.gatk.CatVariantsGatherer")
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter writer = null;
@Hidden

View File

@ -139,10 +139,10 @@ public class HaplotypeCaller extends ActiveRegionWalker<Integer, Integer> implem
/**
* A raw, unfiltered, highly sensitive callset in VCF format.
*/
@Output(doc="File to which variants should be written", required = true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter vcfWriter = null;
@Output(fullName="graphOutput", shortName="graph", doc="File to which debug assembly graph information should be written", required = false)
@Output(fullName="graphOutput", shortName="graph", doc="File to which debug assembly graph information should be written", required = false, defaultToStdout = false)
protected PrintStream graphWriter = null;
/**
@ -170,14 +170,14 @@ public class HaplotypeCaller extends ActiveRegionWalker<Integer, Integer> implem
* in the following screenshot: https://www.dropbox.com/s/xvy7sbxpf13x5bp/haplotypecaller%20bamout%20for%20docs.png
*
*/
@Output(fullName="bamOutput", shortName="bamout", doc="File to which assembled haplotypes should be written", required = false)
@Output(fullName="bamOutput", shortName="bamout", doc="File to which assembled haplotypes should be written", required = false, defaultToStdout = false)
protected StingSAMFileWriter bamWriter = null;
private HaplotypeBAMWriter haplotypeBAMWriter;
/**
* The type of BAM output we want to see.
*/
@Output(fullName="bamWriterType", shortName="bamWriterType", doc="How should haplotypes be written to the BAM?", required = false)
@Argument(fullName="bamWriterType", shortName="bamWriterType", doc="How should haplotypes be written to the BAM?", required = false)
public HaplotypeBAMWriter.Type bamWriterType = HaplotypeBAMWriter.Type.CALLED_HAPLOTYPES;
/**

View File

@ -125,7 +125,7 @@ public class HaplotypeResolver extends RodWalker<Integer, Integer> {
@Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true)
public List<RodBinding<VariantContext>> variants;
@Output(doc="File to which variants should be written", required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter baseWriter = null;
private VariantContextWriter writer;

View File

@ -189,7 +189,7 @@ public class IndelRealigner extends ReadWalker<Integer, Integer> {
/**
* The realigned bam file.
*/
@Output(required=false, doc="Output bam")
@Output(required=false, doc="Output bam", defaultToStdout=false)
protected StingSAMFileWriter writer = null;
protected ConstrainedMateFixingManager manager = null;
protected SAMFileWriter writerToUse = null;
@ -295,15 +295,15 @@ public class IndelRealigner extends ReadWalker<Integer, Integer> {
protected boolean KEEP_ALL_PG_RECORDS = false;
@Hidden
@Output(fullName="indelsFileForDebugging", shortName="indels", required=false, doc="Output file (text) for the indels found; FOR DEBUGGING PURPOSES ONLY")
@Output(fullName="indelsFileForDebugging", shortName="indels", required=false, defaultToStdout=false, doc="Output file (text) for the indels found; FOR DEBUGGING PURPOSES ONLY")
protected String OUT_INDELS = null;
@Hidden
@Output(fullName="statisticsFileForDebugging", shortName="stats", doc="print out statistics (what does or doesn't get cleaned); FOR DEBUGGING PURPOSES ONLY", required=false)
@Output(fullName="statisticsFileForDebugging", shortName="stats", doc="print out statistics (what does or doesn't get cleaned); FOR DEBUGGING PURPOSES ONLY", required=false, defaultToStdout=false)
protected String OUT_STATS = null;
@Hidden
@Output(fullName="SNPsFileForDebugging", shortName="snps", doc="print out whether mismatching columns do or don't get cleaned out; FOR DEBUGGING PURPOSES ONLY", required=false)
@Output(fullName="SNPsFileForDebugging", shortName="snps", doc="print out whether mismatching columns do or don't get cleaned out; FOR DEBUGGING PURPOSES ONLY", required=false, defaultToStdout=false)
protected String OUT_SNPS = null;
// fasta reference reader to supplement the edges of the reference sequence

View File

@ -131,7 +131,7 @@ public class ReadBackedPhasing extends RodWalker<PhasingStatsAndOutput, PhasingS
@ArgumentCollection
protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
@Output(doc = "File to which variants should be written", required = true)
@Output(doc = "File to which variants should be written")
protected VariantContextWriter writer = null;
@Argument(fullName = "cacheWindowSize", shortName = "cacheWindow", doc = "The window size (in bases) to cache variant sites and their reads for the phasing procedure", required = false)

View File

@ -145,7 +145,7 @@ public class ValidationSiteSelector extends RodWalker<Integer, Integer> {
/**
* The output VCF file
*/
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter vcfWriter = null;
/**

View File

@ -128,7 +128,7 @@ public class ApplyRecalibration extends RodWalker<Integer, Integer> implements T
/////////////////////////////
// Outputs
/////////////////////////////
@Output( doc="The output filtered and recalibrated VCF file in which each variant is annotated with its VQSLOD value", required=true)
@Output( doc="The output filtered and recalibrated VCF file in which each variant is annotated with its VQSLOD value")
private VariantContextWriter vcfWriter = null;
/////////////////////////////

View File

@ -194,7 +194,7 @@ public class VariantRecalibrator extends RodWalker<ExpandingArrayList<VariantDat
private double[] TS_TRANCHES = new double[] {100.0, 99.9, 99.0, 90.0};
@Argument(fullName="ignore_filter", shortName="ignoreFilter", doc="If specified the variant recalibrator will use variants even if the specified filter name is marked in the input VCF file", required=false)
private String[] IGNORE_INPUT_FILTERS = null;
@Output(fullName="rscript_file", shortName="rscriptFile", doc="The output rscript file generated by the VQSR to aid in visualization of the input data and learned model", required=false)
@Output(fullName="rscript_file", shortName="rscriptFile", doc="The output rscript file generated by the VQSR to aid in visualization of the input data and learned model", required=false, defaultToStdout=false)
private File RSCRIPT_FILE = null;
@Argument(fullName="ts_filter_level", shortName="ts_filter_level", doc="The truth sensitivity level at which to start filtering, used here to indicate filtered variants in the model reporting plots", required=false)
protected double TS_FILTER_LEVEL = 99.0;

View File

@ -104,7 +104,7 @@ public class RegenotypeVariants extends RodWalker<Integer, Integer> implements T
@ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter vcfWriter = null;
private UnifiedGenotyperEngine UG_engine = null;

View File

@ -175,6 +175,14 @@ public class ArgumentSource {
return field.isAnnotationPresent(Deprecated.class);
}
/**
* Returns whether the field should default to stdout if not provided explicitly on the command-line.
* @return True if field should default to stdout.
*/
public boolean defaultsToStdout() {
return field.isAnnotationPresent(Output.class) && (Boolean)CommandLineUtils.getValue(ArgumentTypeDescriptor.getArgumentAnnotation(this),"defaultToStdout");
}
/**
* Returns false if a type-specific default can be employed.
* @return True to throw in a type specific default. False otherwise.

View File

@ -66,6 +66,13 @@ public @interface Output {
*/
boolean required() default false;
/**
* If this argument is not required, should it default to use stdout if no
* output file is explicitly provided on the command-line?
* @return True if the argument should default to stdout. False otherwise.
*/
boolean defaultToStdout() default true;
/**
* Should this command-line argument be exclusive of others. Should be
* a comma-separated list of names of arguments of which this should be

View File

@ -66,7 +66,7 @@ public class OutputStreamArgumentTypeDescriptor extends ArgumentTypeDescriptor {
@Override
public boolean createsTypeDefault(ArgumentSource source) {
return source.isRequired();
return !source.isRequired() && source.defaultsToStdout();
}
@Override
@ -76,7 +76,7 @@ public class OutputStreamArgumentTypeDescriptor extends ArgumentTypeDescriptor {
@Override
public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) {
if(!source.isRequired())
if(source.isRequired() || !source.defaultsToStdout())
throw new ReviewedStingException("BUG: tried to create type default for argument type descriptor that can't support a type default.");
OutputStreamStub stub = new OutputStreamStub(defaultOutputStream);
engine.addOutput(stub);
@ -90,7 +90,7 @@ public class OutputStreamArgumentTypeDescriptor extends ArgumentTypeDescriptor {
// This parser has been passed a null filename and the GATK is not responsible for creating a type default for the object;
// therefore, the user must have failed to specify a type default
if(fileName == null && !source.isRequired())
if(fileName == null && source.isRequired())
throw new MissingArgumentValueException(definition);
OutputStreamStub stub = new OutputStreamStub(new File(fileName));

View File

@ -89,7 +89,7 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
@Override
public boolean createsTypeDefault(ArgumentSource source) {
return source.isRequired();
return !source.isRequired() && source.defaultsToStdout();
}
@Override
@ -99,7 +99,7 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
@Override
public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) {
if(!source.isRequired())
if(source.isRequired() || !source.defaultsToStdout())
throw new ReviewedStingException("BUG: tried to create type default for argument type descriptor that can't support a type default.");
SAMFileWriterStub stub = new SAMFileWriterStub(engine,defaultOutputStream);
engine.addOutput(stub);
@ -162,7 +162,7 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
DEFAULT_ARGUMENT_FULLNAME,
DEFAULT_ARGUMENT_SHORTNAME,
ArgumentDefinition.getDoc(annotation),
false,
source.isRequired(),
false,
source.isMultiValued(),
source.isHidden(),

View File

@ -110,7 +110,7 @@ public class VCFWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor {
*/
@Override
public boolean createsTypeDefault(ArgumentSource source) {
return source.isRequired();
return !source.isRequired() && source.defaultsToStdout();
}
@Override
@ -119,8 +119,8 @@ public class VCFWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor {
}
@Override
public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) {
if(!source.isRequired())
public Object createTypeDefault(ParsingEngine parsingEngine, ArgumentSource source, Type type) {
if(source.isRequired() || !source.defaultsToStdout())
throw new ReviewedStingException("BUG: tried to create type default for argument type descriptor that can't support a type default.");
VariantContextWriterStub stub = new VariantContextWriterStub(engine, defaultOutputStream, argumentSources);
engine.addOutput(stub);
@ -143,7 +143,7 @@ public class VCFWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor {
// This parser has been passed a null filename and the GATK is not responsible for creating a type default for the object;
// therefore, the user must have failed to specify a type default
if(writerFile == null && !source.isRequired())
if(writerFile == null && source.isRequired())
throw new MissingArgumentValueException(defaultArgumentDefinition);
// Create a stub for the given object.

View File

@ -67,7 +67,7 @@ public abstract class ActiveRegionWalker<MapType, ReduceType> extends Walker<Map
*
* Intended to make debugging the activity profile calculations easier
*/
@Output(fullName="activityProfileOut", shortName="APO", doc="Output the raw activity profile results in IGV format", required = false)
@Output(fullName="activityProfileOut", shortName="APO", doc="Output the raw activity profile results in IGV format", required = false, defaultToStdout = false)
public PrintStream activityProfileOutStream = null;
/**
@ -78,7 +78,7 @@ public abstract class ActiveRegionWalker<MapType, ReduceType> extends Walker<Map
*
* Intended to make debugging the active region calculations easier
*/
@Output(fullName="activeRegionOut", shortName="ARO", doc="Output the active region to this IGV formatted file", required = false)
@Output(fullName="activeRegionOut", shortName="ARO", doc="Output the active region to this IGV formatted file", required = false, defaultToStdout = false)
public PrintStream activeRegionOutStream = null;
@Input(fullName="activeRegionIn", shortName="AR", doc="Use this interval list file as the active regions to process", required = false)

View File

@ -125,7 +125,7 @@ public class VariantAnnotator extends RodWalker<Integer, Integer> implements Ann
public List<RodBinding<VariantContext>> resources = Collections.emptyList();
public List<RodBinding<VariantContext>> getResourceRodBindings() { return resources; }
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter vcfWriter = null;
/**

View File

@ -106,7 +106,7 @@ public class BeagleOutputToVCF extends RodWalker<Integer, Integer> {
@Input(fullName="beaglePhased", shortName = "beaglePhased", doc="Beagle-produced .phased file containing phased genotypes", required=true)
public RodBinding<BeagleFeature> beaglePhased;
@Output(doc="VCF File to which variants should be written",required=true)
@Output(doc="VCF File to which variants should be written")
protected VariantContextWriter vcfWriter = null;
/**

View File

@ -89,11 +89,11 @@ public class ProduceBeagleInput extends RodWalker<Integer, Integer> {
public RodBinding<VariantContext> validation;
@Output(doc="File to which BEAGLE input should be written",required=true)
@Output(doc="File to which BEAGLE input should be written")
protected PrintStream beagleWriter = null;
@Hidden
@Output(doc="File to which BEAGLE markers should be written", shortName="markers", fullName = "markers", required = false)
@Output(doc="File to which BEAGLE markers should be written", shortName="markers", fullName = "markers", required = false, defaultToStdout = false)
protected PrintStream markers = null;
int markerCounter = 1;

View File

@ -62,7 +62,7 @@ public class VariantsToBeagleUnphased extends RodWalker<Integer, Integer> {
@Input(fullName="variants", shortName = "V", doc="Input VCF file", required=true)
public RodBinding<VariantContext> variants;
@Output(doc="File to which BEAGLE unphased genotypes should be written",required=true)
@Output(doc="File to which BEAGLE unphased genotypes should be written")
protected PrintStream beagleWriter = null;
@Argument(fullName = "bootstrap_fraction", shortName = "bs", doc = "Proportion of records to be used in bootstrap set", required = false)

View File

@ -75,7 +75,7 @@ import java.util.Collection;
@By(DataSource.REFERENCE_ORDERED_DATA)
public class CoveredByNSamplesSites extends RodWalker<GenomeLoc, Integer> implements TreeReducible<Integer> {
@Output(fullName = "OutputIntervals", shortName = "out", doc = "Name of file for output intervals", required = true)
@Output(fullName = "OutputIntervals", shortName = "out", doc = "Name of file for output intervals")
PrintStream outputStream;
@ArgumentCollection

View File

@ -146,7 +146,7 @@ public class DiffObjects extends RodWalker<Integer, Integer> {
*
* See http://www.broadinstitute.org/gatk/guide/article?id=1299 for details.
*/
@Output(doc="File to which results should be written",required=true)
@Output(doc="File to which results should be written")
protected PrintStream out;
/**

View File

@ -92,7 +92,7 @@ public class VariantFiltration extends RodWalker<Integer, Integer> {
@Input(fullName="mask", doc="Input ROD mask", required=false)
public RodBinding<Feature> mask;
@Output(doc="File to which variants should be written", required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter writer = null;
/**

View File

@ -73,7 +73,7 @@ public class DocumentationTest extends RodWalker<Integer, Integer> {
@Input(fullName="featureArg", shortName = "featureArg", doc="A RodBinding of feature", required=false)
private RodBinding<Feature> featureArg = null;
@Output(doc="VCFWriter",required=true)
@Output(doc="VCFWriter")
protected VariantContextWriter vcfWriter = null;
@Advanced

View File

@ -161,13 +161,13 @@ public class ClipReads extends ReadWalker<ClipReads.ReadClipperWithData, ClipRea
* If provided, ClipReads will write summary statistics about the clipping operations applied
* to the reads to this file.
*/
@Output(fullName = "outputStatistics", shortName = "os", doc = "Write output statistics to this file", required = false)
@Output(fullName = "outputStatistics", shortName = "os", doc = "Write output statistics to this file", required = false, defaultToStdout = false)
PrintStream out = null;
/**
* The output SAM/BAM file will be written here
*/
@Output(doc = "Write BAM output here", required = true)
@Output(doc = "Write BAM output here")
StingSAMFileWriter outputBam;
/**

View File

@ -107,7 +107,7 @@ import java.util.*;
@Requires({DataSource.READS, DataSource.REFERENCE})
public class PrintReads extends ReadWalker<GATKSAMRecord, SAMFileWriter> implements NanoSchedulable {
@Output(doc="Write output to this BAM filename instead of STDOUT", required = true)
@Output(doc="Write output to this BAM filename instead of STDOUT")
StingSAMFileWriter out;
@Argument(fullName = "readGroup", shortName = "readGroup", doc="Exclude all reads with this read group from the output", required = false)

View File

@ -133,7 +133,7 @@ public class CombineVariants extends RodWalker<Integer, Integer> implements Tree
@Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true)
public List<RodBinding<VariantContext>> variants;
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter vcfWriter = null;
@Argument(shortName="genotypeMergeOptions", doc="Determines how we should merge genotype records for samples shared across the ROD files", required=false)

View File

@ -56,7 +56,7 @@ public class FilterLiftedVariants extends RodWalker<Integer, Integer> {
private static final int MAX_VARIANT_SIZE = 100;
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter writer = null;
private long failedLocs = 0, totalLocs = 0;

View File

@ -87,7 +87,7 @@ public class LeftAlignVariants extends RodWalker<Integer, Integer> {
@ArgumentCollection
protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter baseWriter = null;
private VariantContextWriter writer;

View File

@ -62,7 +62,7 @@ public class LiftoverVariants extends RodWalker<Integer, Integer> {
@ArgumentCollection
protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected File file = null;
protected VariantContextWriter writer = null;

View File

@ -110,7 +110,7 @@ public class SelectHeaders extends RodWalker<Integer, Integer> implements TreeRe
@ArgumentCollection
protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
@Output(doc = "File to which variants should be written", required = true)
@Output(doc = "File to which variants should be written")
protected VariantContextWriter vcfWriter;
@Argument(fullName = "header_name", shortName = "hn", doc = "Include header. Can be specified multiple times", required = false)

View File

@ -199,7 +199,7 @@ public class SelectVariants extends RodWalker<Integer, Integer> implements TreeR
@Input(fullName="concordance", shortName = "conc", doc="Output variants that were also called in this comparison track", required=false)
protected RodBinding<VariantContext> concordanceTrack;
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter vcfWriter = null;
@Argument(fullName="sample_name", shortName="sn", doc="Include genotypes from this sample. Can be specified multiple times", required=false)

View File

@ -91,7 +91,7 @@ public class VariantValidationAssessor extends RodWalker<VariantContext,Integer>
@ArgumentCollection
protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter vcfwriter = null;
@Argument(fullName="maxHardy", doc="Maximum phred-scaled Hardy-Weinberg violation pvalue to consider an assay valid", required=false)

View File

@ -84,7 +84,7 @@ public class VariantsToAllelicPrimitives extends RodWalker<Integer, Integer> {
@ArgumentCollection
protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter baseWriter = null;
private VariantContextWriter vcfWriter;

View File

@ -111,7 +111,7 @@ public class VariantsToTable extends RodWalker<Integer, Integer> {
@Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true)
public List<RodBinding<VariantContext>> variants;
@Output(doc="File to which results should be written",required=true)
@Output(doc="File to which results should be written")
protected PrintStream out;
/**

View File

@ -87,7 +87,7 @@ import java.util.*;
@Reference(window=@Window(start=-40,stop=40))
public class VariantsToVCF extends RodWalker<Integer, Integer> {
@Output(doc="File to which variants should be written",required=true)
@Output(doc="File to which variants should be written")
protected VariantContextWriter baseWriter = null;
private VariantContextWriter vcfwriter; // needed because hapmap/dbsnp indel records move

View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2012 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.commandline;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.sf.samtools.SAMFileWriter;
import org.broadinstitute.sting.BaseTest;
import org.broadinstitute.sting.gatk.GenomeAnalysisEngine;
import org.broadinstitute.sting.gatk.io.stubs.*;
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;
import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collection;
public class ArgumentTypeDescriptorUnitTest extends BaseTest {
////////////////////////////////////////////////////////////////////
// This section tests the functionality of the @Output annotation //
////////////////////////////////////////////////////////////////////
private class ATDTestCommandLineProgram extends CommandLineProgram {
public int execute() { return 0; }
@Override
public Collection<ArgumentTypeDescriptor> getArgumentTypeDescriptors() {
final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
return Arrays.asList( new SAMFileWriterArgumentTypeDescriptor(engine, System.out),
new OutputStreamArgumentTypeDescriptor(engine, System.out),
new VCFWriterArgumentTypeDescriptor(engine, System.out, null));
}
protected abstract class ATDTestOutputArgumentSource {
public abstract Object getOut();
}
protected class OutputRequiredSamArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = true)
public SAMFileWriter out;
public Object getOut() { return out; }
}
protected class OutputRequiredVcfArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = true)
public VariantContextWriter out;
public Object getOut() { return out; }
}
protected class OutputRequiredStreamArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = true)
public PrintStream out;
public Object getOut() { return out; }
}
protected class OutputNotRequiredNoDefaultSamArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = false, defaultToStdout = false)
public SAMFileWriter out;
public Object getOut() { return out; }
}
protected class OutputNotRequiredNoDefaultVcfArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = false, defaultToStdout = false)
public VariantContextWriter out;
public Object getOut() { return out; }
}
protected class OutputNotRequiredNoDefaultStreamArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = false, defaultToStdout = false)
public PrintStream out;
public Object getOut() { return out; }
}
protected class OutputNotRequiredSamArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = false)
public SAMFileWriter out;
public Object getOut() { return out; }
}
protected class OutputNotRequiredVcfArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = false)
public VariantContextWriter out;
public Object getOut() { return out; }
}
protected class OutputNotRequiredStreamArgumentSource extends ATDTestOutputArgumentSource {
@Output(shortName="o", doc="output file", required = false)
public PrintStream out;
public Object getOut() { return out; }
}
}
@DataProvider(name = "OutputProvider")
public Object[][] OutputProvider() {
ObjectArrayList<Object[]> tests = new ObjectArrayList<Object[]>();
final ATDTestCommandLineProgram clp = new ATDTestCommandLineProgram();
for ( final Object obj : Arrays.asList(clp.new OutputRequiredSamArgumentSource(), clp.new OutputRequiredVcfArgumentSource(), clp.new OutputRequiredStreamArgumentSource()) ) {
for ( final boolean provided : Arrays.asList(true, false) ) {
tests.add(new Object[]{obj, true, true, provided});
}
}
for ( final Object obj : Arrays.asList(clp.new OutputNotRequiredSamArgumentSource(), clp.new OutputNotRequiredVcfArgumentSource(), clp.new OutputNotRequiredStreamArgumentSource()) ) {
for ( final boolean provided : Arrays.asList(true, false) ) {
tests.add(new Object[]{obj, false, true, provided});
}
}
for ( final Object obj : Arrays.asList(clp.new OutputNotRequiredNoDefaultSamArgumentSource(), clp.new OutputNotRequiredNoDefaultVcfArgumentSource(), clp.new OutputNotRequiredNoDefaultStreamArgumentSource()) ) {
for ( final boolean provided : Arrays.asList(true, false) ) {
tests.add(new Object[]{obj, false, false, provided});
}
}
return tests.toArray(new Object[][]{});
}
@Test(dataProvider = "OutputProvider")
public void testOutput(final ATDTestCommandLineProgram.ATDTestOutputArgumentSource argumentSource, final boolean required, final boolean hasDefault, final boolean provided) {
final ParsingEngine parser = new ParsingEngine(new ATDTestCommandLineProgram());
parser.addArgumentSource(argumentSource.getClass());
parser.parse(provided ? new String[] {"out", "foo"} : new String[] {});
try {
parser.loadArgumentsIntoObject(argumentSource);
if ( !provided && (required || !hasDefault) )
Assert.assertEquals(argumentSource.getOut(), null);
else if ( !provided )
Assert.assertNotEquals(argumentSource.getOut(), null);
else if ( argumentSource.getOut() == null || !(argumentSource.getOut() instanceof SAMFileWriterStub) ) // can't test this one case
Assert.assertEquals(!provided, outputIsStdout(argumentSource.getOut()));
} catch (Exception e) {
throw new ReviewedStingException(e.getMessage());
}
}
private static boolean outputIsStdout(final Object out) {
if ( out == null ) {
return false;
} else if ( out instanceof SAMFileWriterStub ) {
return ((SAMFileWriterStub)out).getOutputStream() != System.out;
} else if ( out instanceof VariantContextWriterStub ) {
return ((VariantContextWriterStub)out).getOutputStream() == System.out;
} else if ( out instanceof OutputStreamStub ) {
return ((OutputStreamStub)out).getOutputStream() == System.out;
}
return false;
}
}