1 package var2; 2 3 import java.io.File; 4 import java.io.PrintStream; 5 import java.util.ArrayList; 6 import java.util.HashMap; 7 import java.util.HashSet; 8 import java.util.Locale; 9 10 import bloom.KCountArray7MTA; 11 import fileIO.ByteFile; 12 import fileIO.FileFormat; 13 import fileIO.ReadWrite; 14 import fileIO.TextFile; 15 import shared.Parse; 16 import shared.Parser; 17 import shared.PreParser; 18 import shared.Shared; 19 import shared.Timer; 20 import shared.Tools; 21 import shared.TrimRead; 22 import stream.ConcurrentReadInputStream; 23 import stream.FastaReadInputStream; 24 import stream.Read; 25 import stream.SamLine; 26 import stream.SamReadStreamer; 27 import stream.SamStreamer; 28 import structures.ListNum; 29 30 /** 31 * Calls variants from one or more sam or bam files. 32 * 33 * @author Brian Bushnell 34 * @date December 18, 2016 35 * 36 */ 37 public class CallVariants2 { 38 39 /*--------------------------------------------------------------*/ 40 /*---------------- Initialization ----------------*/ 41 /*--------------------------------------------------------------*/ 42 43 /** 44 * Code entrance from the command line. 45 * @param args Command line arguments 46 */ main(String[] args)47 public static void main(String[] args){ 48 //Start a timer immediately upon code entrance. 49 Timer t=new Timer(); 50 51 //Create an instance of this class 52 CallVariants2 x=new CallVariants2(args); 53 54 //Run the object 55 x.process(t); 56 57 //Close the print stream if it was redirected 58 Shared.closeStream(x.outstream); 59 } 60 61 /** 62 * Constructor. 63 * @param args Command line arguments 64 */ CallVariants2(String[] args)65 public CallVariants2(String[] args){ 66 67 {//Preparse block for help, config files, and outstream 68 PreParser pp=new PreParser(args, getClass(), false); 69 args=pp.args; 70 outstream=pp.outstream; 71 } 72 73 SamLine.PARSE_0=false; 74 // SamLine.PARSE_2=false; 75 // SamLine.PARSE_5=false; 76 // SamLine.PARSE_6=false; 77 // SamLine.PARSE_7=false; 78 SamLine.PARSE_8=false; 79 // SamLine.PARSE_10=false; 80 // SamLine.PARSE_OPTIONAL=false; 81 SamLine.PARSE_OPTIONAL_MD_ONLY=true; //I only need the MD tag.. 82 83 SamLine.RNAME_AS_BYTES=false; 84 85 //Set shared static variables 86 ReadWrite.USE_PIGZ=ReadWrite.USE_UNPIGZ=true; 87 ReadWrite.MAX_ZIP_THREADS=Shared.threads(); 88 ReadWrite.USE_BGZIP=true; 89 90 //Create a parser object 91 Parser parser=new Parser(); 92 parser.qtrimLeft=qtrimLeft; 93 parser.qtrimRight=qtrimRight; 94 parser.trimq=trimq; 95 Shared.TRIM_READ_COMMENTS=Shared.TRIM_RNAME=true; 96 97 samFilter.includeUnmapped=false; 98 samFilter.includeSupplimentary=false; 99 samFilter.includeDuplicate=false; 100 samFilter.includeNonPrimary=false; 101 samFilter.includeQfail=false; 102 samFilter.minMapq=4; 103 String atomic="auto"; 104 105 //Parse each argument 106 for(int i=0; i<args.length; i++){ 107 String arg=args[i]; 108 109 //Break arguments into their constituent parts, in the form of "a=b" 110 String[] split=arg.split("="); 111 String a=split[0].toLowerCase(); 112 String b=split.length>1 ? split[1] : null; 113 114 if(a.equals("verbose")){ 115 verbose=Parse.parseBoolean(b); 116 }else if(a.equals("multi") || a.equals("multisample")){ 117 boolean multi=Parse.parseBoolean(b); 118 assert(multi) : "\nThis program is for multisample variant calling. Please use CallVariants for single-sample variant calling.\n"; 119 }else if(a.equals("ploidy")){ 120 ploidy=Integer.parseInt(b); 121 }else if(a.equals("parse_flag_goes_here")){ 122 long fake_variable=Parse.parseKMG(b); 123 //Set a variable here 124 }else if(a.equals("ss") || a.equals("samstreamer")){ 125 if(b!=null && Tools.isDigit(b.charAt(0))){ 126 useStreamer=true; 127 streamerThreads=Tools.max(1, Integer.parseInt(b)); 128 }else{ 129 useStreamer=Parse.parseBoolean(b); 130 } 131 }else if(a.equals("parsename")){ 132 SamLine.PARSE_0=Parse.parseBoolean(b); 133 }else if(a.equalsIgnoreCase("noPassDotGenotype") || a.equalsIgnoreCase("noPassDot")){ 134 Var.noPassDotGenotype=Parse.parseBoolean(b); 135 }else if(a.equalsIgnoreCase("minVarCopies")){ 136 Var.MIN_VAR_COPIES=Integer.parseInt(b); 137 }else if(a.equals("extended")){ 138 Var.extendedText=Parse.parseBoolean(b); 139 }else if(a.equals("useidentity")){ 140 Var.useIdentity=Parse.parseBoolean(b); 141 }else if(a.equals("usehomopolymer") || a.equals("homopolymer")){ 142 Var.useHomopolymer=Parse.parseBoolean(b); 143 }else if(a.equals("usepairing")){ 144 Var.usePairing=Parse.parseBoolean(b); 145 }else if(a.equals("usebias")){ 146 Var.useBias=Parse.parseBoolean(b); 147 }else if(a.equals("nscan") || a.equals("donscan")){ 148 Var.doNscan=Parse.parseBoolean(b); 149 }else if(a.equals("useedist")){ 150 Var.useEdist=Parse.parseBoolean(b); 151 }else if(a.equals("prefilter")){ 152 prefilter=Parse.parseBoolean(b); 153 }else if(a.equals("ref")){ 154 ref=b; 155 }else if(a.equals("vcf") || a.equals("vcfout") || a.equals("outvcf") || a.equals("out")){ 156 vcf=b; 157 }else if(a.equals("vcf0") || a.equals("vcfout0") || a.equals("outvcf0")){ 158 vcf0=b; 159 }else if(a.equals("invcf") || a.equals("vcfin")){ 160 vcfin=b; 161 }else if(a.equals("scorehist") || a.equals("qualhist") || a.equals("qhist") || a.equals("shist")){ 162 scoreHistFile=b; 163 }else if(a.equals("border")){ 164 border=Integer.parseInt(b); 165 }else if(a.equals("sample") || a.equals("samplename")){ 166 assert(b!=null) : "Bad parameter: "+arg; 167 if(new File(b).exists()){sampleNames.add(b);} 168 else{ 169 for(String s : b.split(",")){sampleNames.add(s);} 170 } 171 } 172 173 else if(a.equals("ca3") || a.equals("32bit")){ 174 Scaffold.setCA3(Parse.parseBoolean(b)); 175 }else if(a.equals("atomic")){ 176 atomic=b; 177 }else if(a.equals("strandedcov") || a.equals("trackstrand")){ 178 Scaffold.setTrackStrand(Parse.parseBoolean(b)); 179 } 180 181 else if(a.equals("realign")){ 182 realign=Parse.parseBoolean(b); 183 }else if(a.equals("unclip")){ 184 unclip=Parse.parseBoolean(b); 185 }else if(a.equals("realignrows") || a.equals("rerows")){ 186 Realigner.defaultMaxrows=Integer.parseInt(b); 187 }else if(a.equals("realigncols") || a.equals("recols")){ 188 Realigner.defaultColumns=Integer.parseInt(b); 189 }else if(a.equals("realignpadding") || a.equals("repadding") || a.equals("padding")){ 190 Realigner.defaultPadding=Integer.parseInt(b); 191 }else if(a.equals("msa")){ 192 Realigner.defaultMsaType=b; 193 } 194 195 else if(samFilter.parse(arg, a, b)){ 196 //do nothing 197 } 198 199 else if(a.equalsIgnoreCase("countNearbyVars")){ 200 countNearbyVars=Parse.parseBoolean(b); 201 } 202 203 else if(a.equals("in") || a.equals("in1") || a.equals("in2")){ 204 assert(b!=null) : "Bad parameter: "+arg; 205 if(new File(b).exists()){in.add(b);} 206 else{ 207 for(String s : b.split(",")){in.add(s);} 208 } 209 }else if(a.equals("list")){ 210 for(String line : TextFile.toStringLines(b)){ 211 in.add(line); 212 } 213 }else if(a.equals("clearfilters")){ 214 if(Parse.parseBoolean(b)){ 215 varFilter.clear(); 216 samFilter.clear(); 217 } 218 }else if(varFilter.parse(a, b, arg)){ 219 //do nothing 220 }else if(parser.parse(arg, a, b)){//Parse standard flags in the parser 221 //do nothing 222 }else if(arg.indexOf('=')<0 && (new File(arg).exists() || arg.indexOf(',')>0)){ 223 if(new File(arg).exists()){ 224 if(FileFormat.isSamOrBamFile(arg)){ 225 in.add(arg); 226 }else if(FileFormat.isFastaFile(arg) && (ref==null || ref.equals(arg))){ 227 ref=arg; 228 }else{ 229 assert(false) : "Unknown parameter "+arg; 230 outstream.println("Warning: Unknown parameter "+arg); 231 } 232 }else{ 233 for(String s : arg.split(",")){ 234 if(FileFormat.isSamOrBamFile(s)){ 235 in.add(s); 236 }else{ 237 assert(false) : "Unknown parameter "+arg+" part "+s; 238 outstream.println("Warning: Unknown parameter "+arg+" part "+s); 239 } 240 } 241 } 242 }else{ 243 outstream.println("Unknown parameter "+args[i]); 244 assert(false) : "Unknown parameter "+args[i]; 245 } 246 } 247 248 if("auto".equalsIgnoreCase(atomic)){Scaffold.setCA3A(Shared.threads()>8);} 249 else{Scaffold.setCA3A(Parse.parseBoolean(atomic));} 250 251 if(ploidy<1){System.err.println("WARNING: ploidy not set; assuming ploidy=1."); ploidy=1;} 252 samFilter.setSamtoolsFilter(); 253 254 {//Process parser fields 255 Parser.processQuality(); 256 257 maxReads=parser.maxReads; 258 overwrite=parser.overwrite; 259 260 extin=parser.extin; 261 extout=parser.extout; 262 263 qtrimLeft=parser.qtrimLeft; 264 qtrimRight=parser.qtrimRight; 265 trimq=parser.trimq; 266 trimE=parser.trimE(); 267 268 trimWhitespace=Shared.TRIM_READ_COMMENTS; 269 } 270 if(vcf==null){Scaffold.setTrackStrand(false);} 271 272 assert(FastaReadInputStream.settingsOK()); 273 274 ploidyArray=new long[ploidy+1]; 275 276 //Ensure there is an input file 277 if(in.isEmpty()){throw new RuntimeException("Error - at least one input file is required.");} 278 279 //Adjust the number of threads for input file reading 280 if(!ByteFile.FORCE_MODE_BF1 && !ByteFile.FORCE_MODE_BF2 && Shared.threads()>2){ 281 ByteFile.FORCE_MODE_BF2=true; 282 } 283 284 //Ensure output files can be written 285 if(!Tools.testOutputFiles(overwrite, false, false, vcf)){ 286 throw new RuntimeException("\n\noverwrite="+overwrite+"; Can't write to output file "+vcf+"\n"); 287 } 288 289 //Ensure input files can be read 290 if(!Tools.testInputFiles(false, true, in.toArray(new String[0]))){ 291 throw new RuntimeException("\nCan't read some input files.\n"); 292 } 293 294 if(vcfin!=null && !Tools.testInputFiles(false, true, vcfin.split(","))){ 295 throw new RuntimeException("\nCan't read vcfin: "+vcfin+"\n"); 296 } 297 298 //Create input FileFormat objects 299 for(String s : in){ 300 FileFormat ff=FileFormat.testInput(s, FileFormat.SAM, extin, true, false); 301 ffin.add(ff); 302 } 303 304 fixSampleNames(); 305 assert(sampleNames.size()==in.size()) : "Number of sample names and file names must match."; 306 307 assert(ref!=null) : "Please specify a reference fasta."; 308 } 309 loadForcedVCF(String fnames)310 private VarMap loadForcedVCF(String fnames){ 311 if(fnames==null){return null;} 312 313 Timer t2=new Timer(outstream, true); 314 VarMap varMap=new VarMap(scafMap); 315 String[] array=(fnames.indexOf(',')>=0 ? fnames.split(",") : new String[] {fnames}); 316 for(String fname : array){ 317 FileFormat ff=FileFormat.testInput(fname, FileFormat.VCF, null, true, false); 318 VarMap varMap2=VcfLoader.loadFile(ff, scafMap, false, false); 319 320 for(Var v : varMap2){ 321 v.clear(); 322 v.setForced(true); 323 varMap.addUnsynchronized(v); 324 } 325 } 326 327 t2.stop("Vars: \t"+varMap.size()+"\nTime: "); 328 return varMap; 329 } 330 fixSampleNames()331 private void fixSampleNames(){ 332 if(sampleNames.size()!=0){assert(sampleNames.size()==in.size()) : "Different number of input files ("+in.size()+") and sample names ("+sampleNames.size()+")";} 333 if(sampleNames.size()==0){ 334 HashMap<String, Integer> map=new HashMap<String, Integer>(); 335 for(String s : in){ 336 String core=ReadWrite.stripToCore(s); 337 if(map.containsKey(core)){ 338 int x=map.get(core)+1; 339 map.put(core, x); 340 sampleNames.add(core+"_copy_"+x); 341 }else{ 342 map.put(core, 1); 343 sampleNames.add(core); 344 } 345 } 346 } 347 348 // assert(false) : sampleNames; 349 assert(sampleNames.size()==in.size()) : "Different number of input files ("+in.size()+") and sample names ("+sampleNames.size()+")"; 350 351 HashSet<String> set=new HashSet<String>(); 352 for(String s : sampleNames){ 353 assert(!set.contains(s)) : "Duplicate sample name "+s; 354 set.add(s); 355 } 356 } 357 358 /*--------------------------------------------------------------*/ 359 /*---------------- Outer Methods ----------------*/ 360 /*--------------------------------------------------------------*/ 361 loadReference()362 private void loadReference(){ 363 if(loadedRef){return;} 364 assert(ref!=null); 365 scafMap=ScafMap.loadReference(ref, scafMap, samFilter, true); 366 if(realign){Realigner.map=scafMap;} 367 loadedRef=true; 368 } 369 370 /** Create read streams and process all data */ process(Timer t)371 public void process(Timer t){ 372 373 //Turn off read validation in the input threads to increase speed 374 final boolean vic=Read.VALIDATE_IN_CONSTRUCTOR; 375 Read.VALIDATE_IN_CONSTRUCTOR=Shared.threads()<4; 376 377 Timer t2=new Timer(); 378 379 if(ref!=null){ 380 loadReference(); 381 } 382 383 forcedVars2=new VarMap(scafMap); 384 if(vcfin!=null){ 385 forcedVars1=loadForcedVCF(vcfin); 386 for(Var v : forcedVars1){ 387 forcedVars2.addUnsynchronized(v.clone()); 388 } 389 } 390 391 ArrayList<Sample> samples=new ArrayList<Sample>(ffin.size()); 392 393 for(int i=0; i<ffin.size(); i++){ 394 FileFormat ff=ffin.get(i); 395 String sname=sampleNames.get(i); 396 Sample sample=new Sample(ff, sname); 397 samples.add(sample); 398 } 399 400 t2.start("Calculating which variants pass filters."); 401 402 long loadedVars=0; 403 long varsProcessed0=0; 404 for(Sample sample : samples){ 405 loadedVars+=sample.process1(forcedVars1, forcedVars2); 406 varsProcessed0+=sample.varsProcessed; 407 sample.clear(); 408 scafMap.clearCoverage(); 409 } 410 forcedVars1=null; 411 412 t2.stop(loadedVars+" variants passed filters."); 413 414 t2.start("Processing second pass."); 415 416 long readsProcessed=0; 417 long basesProcessed=0; 418 long pairedInSequencingReadsProcessed=0; 419 long properlyPairedReadsProcessed=0; 420 long trimmedBasesProcessed=0; 421 long realignmentsAttempted=0; 422 long realignmentsSucceeded=0; 423 long realignmentsImproved=0; 424 long realignmentsRetained=0; 425 long varsPrefiltered=0; 426 long varsProcessed=0; 427 428 for(Sample sample : samples){ 429 sample.process2(forcedVars2); 430 431 if(sample.vcfName!=null){ 432 VcfWriter vw=new VcfWriter(sample.varMap, varFilter, sample.readsProcessed-sample.readsDiscarded, 433 sample.pairedInSequencingReadsProcessed, sample.properlyPairedReadsProcessed, 434 sample.trimmedBasesProcessed, ref, trimWhitespace, sample.name); 435 vw.writeVcfFile(sample.vcfName); 436 } 437 438 readsProcessed+=sample.readsProcessed; 439 basesProcessed+=sample.basesProcessed; 440 pairedInSequencingReadsProcessed+=sample.pairedInSequencingReadsProcessed; 441 properlyPairedReadsProcessed+=sample.properlyPairedReadsProcessed; 442 trimmedBasesProcessed+=sample.trimmedBasesProcessed; 443 realignmentsAttempted+=sample.realignmentsAttempted; 444 realignmentsSucceeded+=sample.realignmentsSucceeded; 445 realignmentsImproved+=sample.realignmentsImproved; 446 realignmentsRetained+=sample.realignmentsRetained; 447 varsPrefiltered+=sample.varsPrefiltered; 448 varsProcessed+=sample.varsProcessed; 449 450 sample.clear(); 451 scafMap.clearCoverage(); 452 } 453 454 455 t2.start("Finished second pass."); 456 457 long[] types=forcedVars2.countTypes(); 458 459 if(vcf!=null){ 460 t2.start("Writing output."); 461 MergeSamples merger=new MergeSamples(); 462 merger.filter=varFilter; 463 merger.mergeSamples(samples, scafMap, vcf, scoreHistFile); 464 t2.stop("Time: "); 465 } 466 467 //Reset read validation 468 Read.VALIDATE_IN_CONSTRUCTOR=vic; 469 470 //Report timing and results 471 { 472 t.stop(); 473 474 long size=scafMap.lengthSum(); 475 long a=varsProcessed0, b=loadedVars, c=varsPrefiltered, d=varsProcessed; 476 double amult=100.0/a; 477 double bmult=100.0/b; 478 outstream.println(); 479 if(prefilter){ 480 outstream.println(c+" of "+d+" events were screened by the prefilter ("+String.format(Locale.ROOT, "%.4f%%", c*100.0/d)+")."); 481 } 482 outstream.println(b+" of "+a+" variants passed filters ("+String.format(Locale.ROOT, "%.4f%%", b*amult)+")."); 483 outstream.println(); 484 outstream.println("Substitutions: \t"+types[Var.SUB]+String.format(Locale.ROOT, "\t%.1f%%", types[Var.SUB]*bmult)); 485 outstream.println("Deletions: \t"+types[Var.DEL]+String.format(Locale.ROOT, "\t%.1f%%", types[Var.DEL]*bmult)); 486 outstream.println("Insertions: \t"+types[Var.INS]+String.format(Locale.ROOT, "\t%.1f%%", types[Var.INS]*bmult)); 487 outstream.println("Variation Rate:\t"+(b==0 ? 0 : 1)+"/"+(size/Tools.max(1,b))+"\n"); 488 489 if(realign){ 490 outstream.println("Realignments: \t"+realignmentsAttempted); 491 outstream.println("Successes: \t"+realignmentsSucceeded); 492 outstream.println("Improvements: \t"+realignmentsImproved); 493 outstream.println("Retained: \t"+realignmentsRetained); 494 outstream.println(); 495 } 496 497 outstream.println(Tools.timeReadsBasesProcessed(t, readsProcessed, basesProcessed, 8)); 498 } 499 500 //Throw an exception of there was an error in a thread 501 if(errorStateOverall){ 502 throw new RuntimeException(getClass().getName()+" terminated in an error state; the output may be corrupt."); 503 } 504 } 505 506 /*--------------------------------------------------------------*/ 507 /*---------------- Inner Methods ----------------*/ 508 /*--------------------------------------------------------------*/ 509 510 /*--------------------------------------------------------------*/ 511 /*---------------- Inner Classes ----------------*/ 512 /*--------------------------------------------------------------*/ 513 514 class Sample{ 515 516 public Sample(FileFormat ff_, String sname_){ 517 ff=ff_; 518 name=sname_; 519 vcfName=vcf0==null ? null : vcf0.replaceFirst("%", name); 520 } 521 522 /** Find all variants that pass filters for this sample and add them to the shared map */ 523 public long process1(VarMap forcedVarsIn, VarMap forcedVarsOut) { 524 525 Timer t2=new Timer(); 526 outstream.println("Processing sample "+name+"."); 527 528 final KCountArray7MTA kca; 529 if(prefilter){ 530 t2.start("Loading the prefilter."); 531 kca=prefilter(varFilter.minAlleleDepth); 532 double used=(100.0*kca.cellsUsed())/kca.cells; 533 outstream.println("Added "+varsProcessed+" events to prefilter; approximately "+(long)(kca.estimateUniqueKmers(2))+" were unique."); 534 outstream.println(String.format(Locale.ROOT, "The prefilter is %.2f%% full.", used)); 535 varsProcessed=0; 536 t2.stop("Time: "); 537 outstream.println(); 538 }else{ 539 kca=null; 540 } 541 542 t2.start("Loading variants."); 543 544 assert(varMap==null); 545 varMap=new VarMap(scafMap); 546 547 if(forcedVarsIn!=null && forcedVarsIn.size()>0){ 548 for(Var v : forcedVarsIn){ 549 varMap.addUnsynchronized(v.clone()); 550 } 551 } 552 553 processInput(ff, kca, forcedVarsIn, true); 554 final double properPairRate=properlyPairedReadsProcessed/(double)Tools.max(1, readsProcessed-readsDiscarded); 555 final double pairedInSequencingRate=pairedInSequencingReadsProcessed/(double)Tools.max(1, readsProcessed-readsDiscarded); 556 final double totalQualityAvg=totalQualitySum/(double)Tools.max(1, trimmedBasesProcessed); 557 final double totalMapqAvg=totalMapqSum/(double)Tools.max(1, readsProcessed-readsDiscarded); 558 final double readLengthAvg=trimmedBasesProcessed/(double)Tools.max(1, readsProcessed-readsDiscarded); 559 // System.err.println(properlyPairedReadsProcessed+", "+readsProcessed+", "+readsDiscarded); 560 varMap.ploidy=ploidy; 561 varMap.properPairRate=properPairRate; 562 varMap.pairedInSequencingRate=pairedInSequencingRate; 563 varMap.totalQualityAvg=totalQualityAvg; 564 varMap.totalMapqAvg=totalMapqAvg; 565 varMap.readLengthAvg=readLengthAvg; 566 t2.stop("Time: "); 567 outstream.println(); 568 569 // assert(false) : filter.toString(properPairRate, ploidy); 570 571 long initialCount=varMap.size(); 572 t2.start("Processing variants."); 573 final long[] types=processVariants(); 574 t2.stop("Time: "); 575 outstream.println(); 576 577 if(countNearbyVars){ 578 t2.start("Counting nearby variants."); 579 int x=varMap.countNearbyVars(varFilter); 580 if(x>0 && varFilter.failNearby){ 581 for(Var v : varMap.toArray(false)){ 582 if(!v.forced() && v.nearbyVarCount>varFilter.maxNearbyCount){ 583 varMap.removeUnsynchronized(v); 584 } 585 } 586 } 587 t2.stop("Time: "); 588 outstream.println(); 589 } 590 591 long added=0; 592 if(forcedVarsOut!=null){ 593 for(Var v : varMap){ 594 if(!forcedVarsOut.containsKey(v)){ 595 forcedVarsOut.addUnsynchronized(v.clone().clear().setForced(true)); 596 added++; 597 } 598 } 599 } 600 // for(int i=0; i<=VarMap.MASK; i++){ 601 // synchronized(sharedVarMap.maps[i]){ 602 // initialSharedCount+=sharedVarMap.maps[i].size(); 603 // sharedVarMap.maps[i].putAll(varMap.maps[i]); 604 // finalSharedCount+=sharedVarMap.maps[i].size(); 605 // } 606 // } 607 return added; 608 } 609 process2(VarMap forcedVars)610 public long process2(VarMap forcedVars) { 611 Timer t2=new Timer(); 612 outstream.println("Processing sample "+name+"."); 613 614 t2.start("Loading variants."); 615 616 assert(varMap==null); 617 varMap=new VarMap(scafMap); 618 619 if(forcedVars!=null && forcedVars.size()>0){ 620 for(Var v : forcedVars){ 621 varMap.addUnsynchronized(v.clone().clear().setForced(true)); 622 } 623 } 624 625 processInput(ff, null, forcedVars, true); 626 final double properPairRate=properlyPairedReadsProcessed/(double)Tools.max(1, readsProcessed-readsDiscarded); 627 final double pairedInSequencingRate=pairedInSequencingReadsProcessed/(double)Tools.max(1, readsProcessed-readsDiscarded); 628 final double totalQualityAvg=totalQualitySum/(double)Tools.max(1, trimmedBasesProcessed); 629 final double totalMapqAvg=totalMapqSum/(double)Tools.max(1, readsProcessed-readsDiscarded); 630 final double readLengthAvg=trimmedBasesProcessed/(double)Tools.max(1, readsProcessed-readsDiscarded); 631 // System.err.println(properlyPairedReadsProcessed+", "+readsProcessed+", "+readsDiscarded); 632 varMap.ploidy=ploidy; 633 varMap.properPairRate=properPairRate; 634 varMap.pairedInSequencingRate=pairedInSequencingRate; 635 varMap.totalQualityAvg=totalQualityAvg; 636 varMap.totalMapqAvg=totalMapqAvg; 637 varMap.readLengthAvg=readLengthAvg; 638 t2.stop("Time: "); 639 outstream.println(); 640 641 // assert(false) : filter.toString(properPairRate, ploidy); 642 643 long initialCount=varMap.size(); 644 t2.start("Processing variants."); 645 final long[] types=processVariants(); 646 // final long[] types=addSharedVariants(sharedVarMap); 647 varMap.calcCoverage(scafMap); 648 t2.stop("Time: "); 649 outstream.println(); 650 651 long added=0; 652 assert(forcedVars!=null); 653 if(forcedVars!=null){ 654 for(Var v : varMap){ 655 Var old=forcedVars.get(v); 656 assert(old!=null) : v; 657 if(old!=null){ 658 old.add(v); 659 }else{ 660 added++; 661 forcedVars.addUnsynchronized(v); 662 } 663 } 664 } 665 return added; 666 // long initialSharedCount=0, finalSharedCount=0; 667 // for(int i=0; i<=VarMap.MASK; i++){ 668 // synchronized(sharedVarMap.maps[i]){ 669 // initialSharedCount+=sharedVarMap.maps[i].size(); 670 // sharedVarMap.maps[i].putAll(varMap.maps[i]); 671 // finalSharedCount+=sharedVarMap.maps[i].size(); 672 // } 673 // } 674 // return finalSharedCount-initialSharedCount; 675 } 676 677 /*--------------------------------------------------------------*/ 678 prefilter(int minReads)679 private KCountArray7MTA prefilter(int minReads){ 680 int cbits=2; 681 while((1L<<cbits)-1<minReads){ 682 cbits*=2; 683 } 684 685 long mem=Shared.memAvailable(4); 686 long prebits=mem; //1 bit per byte; 1/8th of the memory 687 688 long precells=prebits/cbits; 689 if(precells<100000){ //Not enough memory - no point. 690 return null; 691 } 692 693 KCountArray7MTA kca=new KCountArray7MTA(precells, cbits, 0, 2, null, minReads); 694 695 if(ref==null){ 696 ScafMap.loadSamHeader(ff, scafMap); 697 } 698 699 final SamReadStreamer ss; 700 //Create a read input stream 701 final ConcurrentReadInputStream cris; 702 if(useStreamer){ 703 cris=null; 704 ss=new SamReadStreamer(ff, streamerThreads, false, maxReads); 705 ss.start(); 706 if(verbose){outstream.println("Started streamer");} 707 }else{ 708 ss=null; 709 cris=ConcurrentReadInputStream.getReadInputStream(maxReads, false, ff, null); 710 cris.start(); //Start the stream 711 if(verbose){outstream.println("Started cris");} 712 } 713 714 final int threads=Shared.threads(); 715 716 //Fill a list with ProcessThreads 717 ArrayList<ProcessThread> alpt=new ArrayList<ProcessThread>(threads); 718 for(int i=0; i<threads; i++){ 719 alpt.add(new ProcessThread(cris, ss, i, kca, null, true, false)); 720 } 721 722 //Start the threads 723 for(ProcessThread pt : alpt){ 724 pt.start(); 725 } 726 727 //Wait for completion of all threads 728 boolean success=true; 729 for(ProcessThread pt : alpt){ 730 731 //Wait until this thread has terminated 732 while(pt.getState()!=Thread.State.TERMINATED){ 733 try { 734 //Attempt a join operation 735 pt.join(); 736 } catch (InterruptedException e) { 737 //Potentially handle this, if it is expected to occur 738 e.printStackTrace(); 739 } 740 } 741 varsProcessed+=pt.varsProcessedT; 742 743 //Accumulate per-thread statistics 744 success&=pt.success; 745 } 746 747 if(forcedVars1!=null && forcedVars1.size()>0){//For forced vars from an input VCF 748 for(Var v : forcedVars1){ 749 final long key=v.toKey(); 750 kca.incrementAndReturnUnincremented(key, minReads); 751 } 752 } 753 754 //Track whether any threads failed 755 if(!success){errorState=true;} 756 757 kca.shutdown(); 758 return kca; 759 } 760 761 /** Create read streams and process all data */ processInput(FileFormat ff, KCountArray7MTA kca, VarMap forcedVarsIn, boolean calcCoverage)762 void processInput(FileFormat ff, KCountArray7MTA kca, VarMap forcedVarsIn, boolean calcCoverage){ 763 assert(ff.samOrBam()) : ff.name(); 764 765 if(ref==null){ 766 ScafMap.loadSamHeader(ff, scafMap); 767 } 768 769 final SamReadStreamer ss; 770 //Create a read input stream 771 final ConcurrentReadInputStream cris; 772 if(useStreamer){ 773 cris=null; 774 ss=new SamReadStreamer(ff, streamerThreads, false, maxReads); 775 ss.start(); 776 if(verbose){outstream.println("Started streamer");} 777 }else{ 778 ss=null; 779 cris=ConcurrentReadInputStream.getReadInputStream(maxReads, false, ff, null); 780 cris.start(); //Start the stream 781 if(verbose){outstream.println("Started cris");} 782 } 783 784 //Process the reads in separate threads 785 spawnThreads(cris, ss, kca, forcedVarsIn, calcCoverage); 786 787 if(verbose){outstream.println("Finished; closing streams.");} 788 789 //Close the read streams 790 errorState|=ReadWrite.closeStreams(cris); 791 } 792 processVariants()793 private long[] processVariants(){ 794 return varMap.processVariantsMT(varFilter, scoreArray, ploidyArray, avgQualityArray, maxQualityArray, ADArray, AFArray); 795 } 796 797 // private long[] addSharedVariants(VarMap sharedVarMap){ 798 // return varMap.addSharedVariantsST(varFilter, sharedVarMap); 799 // } 800 801 /** Spawn process threads */ spawnThreads(final ConcurrentReadInputStream cris, final SamReadStreamer ss, final KCountArray7MTA kca, final VarMap forced, final boolean calcCoverage)802 private void spawnThreads(final ConcurrentReadInputStream cris, final SamReadStreamer ss, 803 final KCountArray7MTA kca, final VarMap forced, final boolean calcCoverage){ 804 805 //Do anything necessary prior to processing 806 if(calcCoverage){ 807 scafMap.clearCoverage(); 808 } 809 810 //Determine how many threads may be used 811 final int threads=Shared.threads(); 812 813 //Fill a list with ProcessThreads 814 ArrayList<ProcessThread> alpt=new ArrayList<ProcessThread>(threads); 815 for(int i=0; i<threads; i++){ 816 alpt.add(new ProcessThread(cris, ss, i, kca, forced, false, calcCoverage)); 817 } 818 819 //Start the threads 820 for(ProcessThread pt : alpt){ 821 pt.start(); 822 } 823 824 //Wait for completion of all threads 825 boolean success=true; 826 for(ProcessThread pt : alpt){ 827 828 //Wait until this thread has terminated 829 while(pt.getState()!=Thread.State.TERMINATED){ 830 try { 831 //Attempt a join operation 832 pt.join(); 833 } catch (InterruptedException e) { 834 //Potentially handle this, if it is expected to occur 835 e.printStackTrace(); 836 } 837 } 838 839 //Accumulate per-thread statistics 840 readsProcessed+=pt.readsProcessedT; 841 basesProcessed+=pt.basesProcessedT; 842 trimmedBasesProcessed+=pt.trimmedBasesProcessedT; 843 readsDiscarded+=pt.readsDiscardedT; 844 pairedInSequencingReadsProcessed+=pt.pairedInSequencingReadsProcessedT; 845 properlyPairedReadsProcessed+=pt.properlyPairedReadsProcessedT; 846 varsPrefiltered+=pt.prefilteredT; 847 varsProcessed+=pt.varsProcessedT; 848 totalQualitySum+=pt.totalQualitySumT; 849 totalMapqSum+=pt.totalMapqSumT; 850 success&=pt.success; 851 if(pt.realigner!=null){ 852 realignmentsAttempted+=pt.realigner.realignmentsAttempted; 853 realignmentsImproved+=pt.realigner.realignmentsImproved; 854 realignmentsSucceeded+=pt.realigner.realignmentsSucceeded; 855 realignmentsRetained+=pt.realigner.realignmentsRetained; 856 } 857 } 858 859 //Track whether any threads failed 860 if(!success){errorState=true;} 861 } 862 dumpVars(HashMap<Var, Var> mapT)863 private int dumpVars(HashMap<Var, Var> mapT){ 864 int added=varMap.dumpVars(mapT); 865 assert(mapT.size()==0); 866 return added; 867 } 868 fixVars(Read r, SamLine sl)869 public int fixVars(Read r, SamLine sl){ 870 assert(false); 871 return -1;//fixVars(r, sl, varMap, scafMap); 872 } 873 clear()874 private void clear(){ 875 readsProcessed=0; 876 basesProcessed=0; 877 trimmedBasesProcessed=0; 878 readsDiscarded=0; 879 pairedInSequencingReadsProcessed=0; 880 properlyPairedReadsProcessed=0; 881 varsPrefiltered=0; 882 varsProcessed=0; 883 totalQualitySum=0; 884 totalMapqSum=0; 885 886 realignmentsAttempted=0; 887 realignmentsImproved=0; 888 realignmentsSucceeded=0; 889 realignmentsRetained=0; 890 891 varMap=null; 892 // varMap.clear(); 893 894 //errorState=false; 895 } 896 897 /*--------------------------------------------------------------*/ 898 899 final FileFormat ff; 900 final String name; 901 final String vcfName; 902 903 /** Number of reads processed */ 904 protected long readsProcessed=0; 905 /** Number of bases processed */ 906 protected long basesProcessed=0; 907 /** Number of trimmed, mapped bases processed */ 908 protected long trimmedBasesProcessed=0; 909 /** Number of reads discarded */ 910 protected long readsDiscarded=0; 911 /** Number of paired reads processed by this thread, whether or not they mapped as pairs */ 912 protected long pairedInSequencingReadsProcessed=0; 913 /** Number of properly paired reads processed */ 914 protected long properlyPairedReadsProcessed=0; 915 /** Number of vars ignored via prefilter */ 916 protected long varsPrefiltered=0; 917 /** Number of vars processed */ 918 protected long varsProcessed=0; 919 920 /** Sum of trimmed, mapped base qualities */ 921 protected long totalQualitySum=0; 922 /** Sum of mapqs */ 923 protected long totalMapqSum=0; 924 925 protected long realignmentsAttempted=0; 926 protected long realignmentsImproved=0; 927 protected long realignmentsSucceeded=0; 928 protected long realignmentsRetained=0; 929 930 public VarMap varMap; 931 932 boolean errorState=false; 933 934 935 936 937 /*--------------------------------------------------------------*/ 938 939 /** This class is static to prevent accidental writing to shared variables. 940 * It is safe to remove the static modifier. */ 941 private class ProcessThread extends Thread { 942 943 //Constructor ProcessThread(final ConcurrentReadInputStream cris_, final SamReadStreamer ss_, final int tid_, final KCountArray7MTA kca_, final VarMap forced_, final boolean prefilterOnly_, final boolean calcCoverage_)944 ProcessThread(final ConcurrentReadInputStream cris_, final SamReadStreamer ss_, final int tid_, 945 final KCountArray7MTA kca_, final VarMap forced_, final boolean prefilterOnly_, 946 final boolean calcCoverage_){ 947 cris=cris_; 948 ss=ss_; 949 tid=tid_; 950 kca=kca_; 951 prefilterOnly=prefilterOnly_; 952 realigner=(realign ? new Realigner() : null); 953 forced=forced_; 954 calcCoverage=calcCoverage_; 955 } 956 957 //Called by start() 958 @Override run()959 public void run(){ 960 //Do anything necessary prior to processing 961 962 //Process the reads 963 if(cris==null){ 964 processInner_ss(); 965 }else{ 966 processInner_cris(); 967 } 968 969 //Do anything necessary after processing 970 if(!varMapT.isEmpty()){ 971 dumpVars(varMapT); 972 } 973 assert(varMapT.isEmpty()); 974 975 //Indicate successful exit status 976 success=true; 977 } 978 979 /** Iterate through the reads */ processInner_cris()980 void processInner_cris(){ 981 982 //Grab the first ListNum of reads 983 ListNum<Read> ln=cris.nextList(); 984 //Grab the actual read list from the ListNum 985 ArrayList<Read> reads=(ln!=null ? ln.list : null); 986 987 //As long as there is a nonempty read list... 988 while(ln!=null && reads!=null && reads.size()>0){//ln!=null prevents a compiler potential null access warning 989 // if(verbose){outstream.println("Fetched "+reads.size()+" reads.");} //Disabled due to non-static access 990 991 //Loop through each read in the list 992 for(int idx=0; idx<reads.size(); idx++){ 993 final Read r=reads.get(idx); 994 assert(r.mate==null); 995 996 if(!r.validated()){r.validate(true);} 997 998 //Track the initial length for statistics 999 final int initialLength=r.length(); 1000 1001 //Increment counters 1002 readsProcessedT++; 1003 basesProcessedT+=initialLength; 1004 1005 boolean b=processRead(r); 1006 1007 if(!b){ 1008 readsDiscardedT++; 1009 } 1010 } 1011 1012 //Notify the input stream that the list was used 1013 cris.returnList(ln); 1014 // if(verbose){outstream.println("Returned a list.");} //Disabled due to non-static access 1015 1016 //Fetch a new list 1017 ln=cris.nextList(); 1018 reads=(ln!=null ? ln.list : null); 1019 } 1020 1021 //Notify the input stream that the final list was used 1022 if(ln!=null){ 1023 cris.returnList(ln.id, ln.list==null || ln.list.isEmpty()); 1024 } 1025 } 1026 1027 /** Iterate through the reads */ processInner_ss()1028 void processInner_ss(){ 1029 1030 //Grab the actual read list from the ListNum 1031 ListNum<Read> ln=ss.nextList(); 1032 1033 //As long as there is a nonempty read list... 1034 while(ln!=null && ln.size()>0){ 1035 ArrayList<Read> reads=ln.list; 1036 // if(verbose){outstream.println("Fetched "+reads.size()+" reads.");} //Disabled due to non-static access 1037 1038 //Loop through each read in the list 1039 for(int idx=0; idx<reads.size(); idx++){ 1040 final Read r=reads.get(idx); 1041 assert(r.mate==null); 1042 1043 if(!r.validated()){r.validate(true);} 1044 1045 //Track the initial length for statistics 1046 final int initialLength=r.length(); 1047 1048 //Increment counters 1049 readsProcessedT++; 1050 basesProcessedT+=initialLength; 1051 1052 boolean b=processRead(r); 1053 if(!b){ 1054 readsDiscardedT++; 1055 } 1056 } 1057 1058 ln=ss.nextList(); 1059 } 1060 } 1061 1062 /** 1063 * Process a read. 1064 * @param r Read 1 1065 * @return True if the reads should be kept, false if they should be discarded. 1066 */ processRead(final Read r)1067 boolean processRead(final Read r){ 1068 if(r.bases==null || r.length()<=1){return false;} 1069 final SamLine sl=r.samline; 1070 1071 // final SamLine oldSL=new SamLine(sl); 1072 // final Read oldRead=r.clone(); 1073 1074 if(samFilter!=null && !samFilter.passesFilter(sl)){return false;} 1075 if(sl.properPair()){properlyPairedReadsProcessedT++;} 1076 if(sl.hasMate()){pairedInSequencingReadsProcessedT++;} 1077 final Scaffold scaf=scafMap.getScaffold(sl); 1078 final int scafnum=scaf.number; 1079 1080 // r.toLongMatchString(false); //Not necessary since scoring can be done on short match string 1081 if(realign){ 1082 realigner.realign(r, sl, scaf, unclip); 1083 } 1084 // System.err.println(sl); 1085 // System.err.println(new String(r.match)); 1086 1087 int leftTrimAmount=border, rightTrimAmount=border; 1088 if(qtrimLeft || qtrimRight){ 1089 long packed=TrimRead.testOptimal(r.bases, r.quality, trimE); 1090 if(qtrimLeft){leftTrimAmount=Tools.max(leftTrimAmount, (int)((packed>>32)&0xFFFFFFFFL));} 1091 if(qtrimRight){rightTrimAmount=Tools.max(rightTrimAmount, (int)((packed)&0xFFFFFFFFL));} 1092 } 1093 1094 int trimmed=(leftTrimAmount<1 && rightTrimAmount<1 ? 0 : TrimRead.trimReadWithMatch(r, sl, leftTrimAmount, rightTrimAmount, 0, scaf.length, false)); 1095 if(trimmed<0){return false;}//In this case the whole read should be trimmed 1096 int extra=(qtrimLeft || qtrimRight) ? trimmed/2 : Tools.min(border, trimmed/2); 1097 // System.err.println(sl); 1098 // System.err.println(new String(r.match)); 1099 // System.err.println(); 1100 1101 ArrayList<Var> vars=null; 1102 // try { 1103 vars = Var.toVars(r, sl, callNs, scafnum); 1104 // } catch (Throwable e) { 1105 // // TODO Auto-generated catch block 1106 // System.err.println("Bad line:"); 1107 // System.err.println(oldRead.toString()); 1108 // System.err.println(r.toString()); 1109 // System.err.println(oldSL.toString()); 1110 // System.err.println(sl.toString()); 1111 // System.err.println("\n"); 1112 // } 1113 1114 if(prefilterOnly){ 1115 if(vars==null){return true;} 1116 for(Var v : vars){ 1117 long key=v.toKey(); 1118 kca.increment(key); 1119 } 1120 }else{ 1121 trimmedBasesProcessedT+=r.length(); 1122 totalQualitySumT+=Tools.sum(r.quality); 1123 totalMapqSumT+=sl.mapq; 1124 if(calcCoverage){scaf.add(sl);} 1125 if(vars==null){return true;} 1126 1127 for(Var v : vars){//Vars in each read 1128 if((forced!=null && forced.containsKey(v)) || kca==null || kca.read(v.toKey())>=varFilter.minAlleleDepth){ 1129 v.endDistMax+=extra; 1130 v.endDistSum+=extra; 1131 1132 Var old=varMapT.get(v); 1133 if(old==null){varMapT.put(v, v);} 1134 else{old.add(v);} 1135 }else{ 1136 prefilteredT++; 1137 } 1138 } 1139 if(varMapT.size()>vmtSizeLimit){ 1140 dumpVars(varMapT); 1141 } 1142 } 1143 varsProcessedT+=vars.size(); 1144 return true; 1145 } 1146 1147 private final KCountArray7MTA kca; 1148 private final boolean prefilterOnly; 1149 private final VarMap forced; 1150 1151 HashMap<Var, Var> varMapT=new HashMap<Var, Var>(); 1152 1153 /** Number of vars blocked by the prefilter */ 1154 protected long prefilteredT=0; 1155 /** Number of vars processed */ 1156 protected long varsProcessedT=0; 1157 1158 /** Sum of trimmed, mapped base qualities */ 1159 protected long totalQualitySumT=0; 1160 /** Sum of mapqs */ 1161 protected long totalMapqSumT=0; 1162 1163 /** Number of reads processed by this thread */ 1164 protected long readsProcessedT=0; 1165 /** Number of bases processed by this thread */ 1166 protected long basesProcessedT=0; 1167 /** Number of trimmed, mapped bases processed. */ 1168 protected long trimmedBasesProcessedT=0; 1169 /** Number of reads discarded by this thread */ 1170 protected long readsDiscardedT=0; 1171 /** Number of paired reads processed by this thread, whether or not they mapped as pairs */ 1172 protected long pairedInSequencingReadsProcessedT=0; 1173 /** Number of properly paired reads processed by this thread */ 1174 protected long properlyPairedReadsProcessedT=0; 1175 1176 /** True only if this thread has completed successfully */ 1177 boolean success=false; 1178 1179 /** Shared input stream */ 1180 private final ConcurrentReadInputStream cris; 1181 /** Optional SamReadStreamer for high throughput */ 1182 private final SamReadStreamer ss; 1183 /** For realigning reads */ 1184 final Realigner realigner; 1185 1186 final boolean calcCoverage; 1187 1188 /** Thread ID */ 1189 final int tid; 1190 } 1191 } 1192 1193 public static int fixVars(Read r, VarMap varMap, ScafMap scafMap){ 1194 return CallVariants.fixVars(r, varMap, scafMap); 1195 } 1196 1197 public static void unfixVars(Read r){ 1198 CallVariants.unfixVars(r); 1199 } 1200 1201 public static int fixVars(Read r, SamLine sl, VarMap varMap, ScafMap scafMap){ 1202 return CallVariants.fixVars(r, sl, varMap, scafMap); 1203 } 1204 1205 /*--------------------------------------------------------------*/ 1206 /*---------------- Fields ----------------*/ 1207 /*--------------------------------------------------------------*/ 1208 1209 /** Primary input file path */ 1210 private ArrayList<String> in=new ArrayList<String>(); 1211 1212 /** VCF output file path */ 1213 private String vcf=null; 1214 1215 /** VCF input file path for forced variants */ 1216 private String vcfin=null; 1217 1218 /** Individual vcf files */ 1219 private String vcf0="individual_%.vcf.gz"; 1220 1221 private String scoreHistFile=null; 1222 1223 /** Override input file extension */ 1224 private String extin=null; 1225 /** Override output file extension */ 1226 private String extout=null; 1227 /** A fasta file. */ 1228 private String ref=null; 1229 1230 private boolean loadedRef=false; 1231 1232 private boolean qtrimLeft=false; 1233 private boolean qtrimRight=true; 1234 private float trimq=10; 1235 private final float trimE; 1236 1237 /*--------------------------------------------------------------*/ 1238 1239 public ScafMap scafMap=new ScafMap(); 1240 1241 public VarMap forcedVars1=null; 1242 public VarMap forcedVars2=null; 1243 1244 /** Quit after processing this many input reads; -1 means no limit */ 1245 private long maxReads=-1; 1246 1247 public int ploidy=-1; 1248 1249 public int border=5; 1250 1251 public boolean realign=false; 1252 public boolean unclip=false; 1253 1254 public boolean prefilter=false; 1255 1256 /* 1257 * These cover junk due to artifacts, misassemblies, or structural variants, 1258 * which generally result in a rainbow of adjacent SNPs. 1259 * Some fields are in VarFilter. 1260 */ 1261 public boolean countNearbyVars=true; 1262 1263 /*--------------------------------------------------------------*/ 1264 /*---------------- Final Fields ----------------*/ 1265 /*--------------------------------------------------------------*/ 1266 1267 /** Primary input file */ 1268 private final ArrayList<FileFormat> ffin=new ArrayList<FileFormat>(); 1269 1270 /** Sample names */ 1271 private final ArrayList<String> sampleNames=new ArrayList<String>(); 1272 1273 public final VarFilter varFilter=new VarFilter(); 1274 public final SamFilter samFilter=new SamFilter(); 1275 public final long[][] scoreArray=new long[8][200]; 1276 public final long[] ploidyArray; 1277 public final long[][] avgQualityArray=new long[8][100]; 1278 public final long[] maxQualityArray=new long[100]; 1279 public final long[][] ADArray=new long[2][7]; 1280 public final double[] AFArray=new double[7]; 1281 1282 /*--------------------------------------------------------------*/ 1283 /*---------------- Static Fields ----------------*/ 1284 /*--------------------------------------------------------------*/ 1285 1286 private static int vmtSizeLimit=10000; 1287 1288 static boolean callNs=false; 1289 static boolean trimWhitespace=true; 1290 1291 static boolean useStreamer=true; 1292 static int streamerThreads=SamStreamer.DEFAULT_THREADS; 1293 1294 /*--------------------------------------------------------------*/ 1295 /*---------------- Common Fields ----------------*/ 1296 /*--------------------------------------------------------------*/ 1297 1298 /** Print status messages to this output stream */ 1299 private PrintStream outstream=System.err; 1300 /** Print verbose messages */ 1301 public static boolean verbose=false; 1302 /** True if an error was encountered */ 1303 public boolean errorStateOverall=false; 1304 /** Overwrite existing output files */ 1305 private boolean overwrite=false; 1306 1307 } 1308