comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/opt/bbmap-39.01-1/current/prok/MergeRibo.java @ 68:5028fdace37b

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 16:23:26 -0400
parents
children
comparison
equal deleted inserted replaced
67:0e9998148a16 68:5028fdace37b
1 package prok;
2
3 import java.io.File;
4 import java.io.PrintStream;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.HashMap;
9 import java.util.Map.Entry;
10 import java.util.concurrent.ConcurrentLinkedQueue;
11
12 import aligner.SingleStateAlignerFlat2;
13 import consensus.BaseGraph;
14 import fileIO.ByteFile;
15 import fileIO.FileFormat;
16 import fileIO.ReadWrite;
17 import shared.Parse;
18 import shared.Parser;
19 import shared.PreParser;
20 import shared.ReadStats;
21 import shared.Shared;
22 import shared.Timer;
23 import shared.Tools;
24 import stream.ConcurrentReadInputStream;
25 import stream.ConcurrentReadOutputStream;
26 import stream.FASTQ;
27 import stream.FastaReadInputStream;
28 import stream.Read;
29 import structures.IntHashSet;
30 import structures.ListNum;
31 import tax.GiToTaxid;
32 import template.Accumulator;
33 import template.ThreadWaiter;
34
35 /**
36 * Picks one ribosomal (16S) sequence per taxID.
37 *
38 * @author Brian Bushnell
39 * @date November 19, 2015
40 *
41 */
42 public class MergeRibo implements Accumulator<MergeRibo.ProcessThread> {
43
44 /*--------------------------------------------------------------*/
45 /*---------------- Initialization ----------------*/
46 /*--------------------------------------------------------------*/
47
48 /**
49 * Code entrance from the command line.
50 * @param args Command line arguments
51 */
52 public static void main(String[] args){
53 //Start a timer immediately upon code entrance.
54 Timer t=new Timer();
55
56 //Create an instance of this class
57 MergeRibo x=new MergeRibo(args);
58
59 //Run the object
60 x.process(t);
61
62 //Close the print stream if it was redirected
63 Shared.closeStream(x.outstream);
64 }
65
66 /**
67 * Constructor.
68 * @param args Command line arguments
69 */
70 public MergeRibo(String[] args){
71
72 {//Preparse block for help, config files, and outstream
73 PreParser pp=new PreParser(args, getClass(), false);
74 args=pp.args;
75 outstream=pp.outstream;
76 }
77
78 //Set shared static variables prior to parsing
79 ReadWrite.USE_PIGZ=ReadWrite.USE_UNPIGZ=true;
80 ReadWrite.MAX_ZIP_THREADS=Shared.threads();
81 // Shared.capBufferLen(40);//This does not help; the slowness comes from unevenness in list length during pickBest.
82 //To fix it, long lists should be sorted to be first.
83
84 BaseGraph.MAF_sub=0.251f;
85 BaseGraph.MAF_del=0.0f;
86 BaseGraph.MAF_ins=0.0f;
87 BaseGraph.MAF_noref=0.0f;
88 BaseGraph.trimDepthFraction=0.3f;
89 BaseGraph.trimNs=true;
90
91 {//Parse the arguments
92 final Parser parser=parse(args);
93 Parser.processQuality();
94
95 maxReads=parser.maxReads;
96 overwrite=ReadStats.overwrite=parser.overwrite;
97 append=ReadStats.append=parser.append;
98
99 extin=parser.extin;
100
101 out1=parser.out1;
102 extout=parser.extout;
103 }
104
105 validateParams();
106 adjustInterleaving(); //Make sure interleaving agrees with number of input and output files
107 checkFileExistence(); //Ensure files can be read and written
108 checkStatics(); //Adjust file-related static fields as needed for this program
109
110 //Create output FileFormat objects
111 ffout1=FileFormat.testOutput(out1, FileFormat.FASTA, extout, true, overwrite, append, ordered);
112
113 //Create input FileFormat objects
114 ffin=new ArrayList<FileFormat>(in.size());
115 ffalt=FileFormat.testInput(alt, FileFormat.FASTA, extin, true, true);
116 for(String s : in){
117 FileFormat ff=FileFormat.testInput(s, FileFormat.FASTA, extin, true, true);
118 ffin.add(ff);
119 }
120
121 //Determine how many threads may be used
122 threads=Shared.threads();
123 }
124
125 /*--------------------------------------------------------------*/
126 /*---------------- Initialization Helpers ----------------*/
127 /*--------------------------------------------------------------*/
128
129 /** Parse arguments from the command line */
130 private Parser parse(String[] args){
131
132 //Create a parser object
133 Parser parser=new Parser();
134
135 //Set any necessary Parser defaults here
136 //parser.foo=bar;
137
138 //Parse each argument
139 for(int i=0; i<args.length; i++){
140 String arg=args[i];
141
142 //Break arguments into their constituent parts, in the form of "a=b"
143 String[] split=arg.split("=");
144 String a=split[0].toLowerCase();
145 String b=split.length>1 ? split[1] : null;
146 if(b!=null && b.equalsIgnoreCase("null")){b=null;}
147
148 if(a.equals("verbose")){
149 verbose=Parse.parseBoolean(b);
150 }else if(a.equals("ordered")){
151 ordered=Parse.parseBoolean(b);
152 }else if(a.equals("consensus")){
153 useConsensus=Parse.parseBoolean(b);
154 }else if(a.equals("best")){
155 useConsensus=!Parse.parseBoolean(b);
156 }else if(a.equals("fast")){
157 fast=Parse.parseBoolean(b);
158 }else if(a.equals("minid")){
159 minID=Float.parseFloat(b);
160 }else if(a.equals("maxns")){
161 maxns=Integer.parseInt(b);
162 }else if(a.equals("minlen")){
163 minlen=Integer.parseInt(b);
164 }else if(a.equals("maxlen")){
165 maxlen=Integer.parseInt(b);
166 }else if(a.equals("in")){
167 Tools.addFiles(b, in);
168 }else if(a.equals("alt")){
169 alt=b;
170 }else if(a.equalsIgnoreCase("process16S") || a.equalsIgnoreCase("16S")){
171 process16S=Parse.parseBoolean(b);
172 process18S=!process16S;
173 }else if(a.equalsIgnoreCase("process18S") || a.equalsIgnoreCase("18S")){
174 process18S=Parse.parseBoolean(b);
175 process16S=!process18S;
176 }else if(a.equals("parse_flag_goes_here")){
177 long fake_variable=Parse.parseKMG(b);
178 //Set a variable here
179 }else if(parser.parse(arg, a, b)){//Parse standard flags in the parser
180 //do nothing
181 }else if(b==null && new File(arg).exists()){
182 in.add(arg);
183 }else{
184 outstream.println("Unknown parameter "+args[i]);
185 assert(false) : "Unknown parameter "+args[i];
186 }
187 }
188 assert(!in.isEmpty()) : "No input file.";
189 return parser;
190 }
191
192 /** Ensure files can be read and written */
193 private void checkFileExistence(){
194 //Ensure output files can be written
195 if(!Tools.testOutputFiles(overwrite, append, false, out1)){
196 outstream.println((out1==null)+", "+out1);
197 throw new RuntimeException("\n\noverwrite="+overwrite+"; Can't write to output files "+out1+"\n");
198 }
199
200 //Ensure input files can be read
201 if(!Tools.testInputFiles(false, true, in)){
202 throw new RuntimeException("\nCan't read some input files.\n");
203 }
204
205 // //Ensure that no file was specified multiple times
206 // if(!Tools.testForDuplicateFiles(true, out1, in.toArray(new String[0]))){
207 // throw new RuntimeException("\nSome file names were specified multiple times.\n");
208 // }
209 }
210
211 /** Make sure interleaving agrees with number of input and output files */
212 private void adjustInterleaving(){
213 FASTQ.FORCE_INTERLEAVED=FASTQ.TEST_INTERLEAVED=false;
214 }
215
216 /** Adjust file-related static fields as needed for this program */
217 private static void checkStatics(){
218 //Adjust the number of threads for input file reading
219 if(!ByteFile.FORCE_MODE_BF1 && !ByteFile.FORCE_MODE_BF2 && Shared.threads()>2){
220 ByteFile.FORCE_MODE_BF2=true;
221 }
222
223 assert(FastaReadInputStream.settingsOK());
224 }
225
226 /** Ensure parameter ranges are within bounds and required parameters are set */
227 private boolean validateParams(){
228 // assert(minfoo>0 && minfoo<=maxfoo) : minfoo+", "+maxfoo;
229 // assert(false) : "TODO";
230 assert(process16S || process18S) : "16S or 18S must be selected.";
231 assert(!process16S || !process18S) : "16S or 18S are both selected; only one may be active.";
232 return true;
233 }
234
235 /*--------------------------------------------------------------*/
236 /*---------------- Outer Methods ----------------*/
237 /*--------------------------------------------------------------*/
238
239 /** Create read streams and process all data */
240 void process(Timer t){
241
242 if(process16S){
243 Read[] data=ProkObject.loadConsensusSequenceType("16S", true, true);
244 consensus16S=data[0].bases;
245 if(verbose){System.err.println("process16S: Loaded 16S consensus, length "+consensus16S.length+": "+new String(consensus16S));}
246 }
247 if(process18S){
248 Read[] data=ProkObject.loadConsensusSequenceType("18S", true, true);
249 consensus18S=data[0].bases;
250 if(verbose){System.err.println("process18S: Loaded 18S consensus, length "+consensus18S.length+": "+new String(consensus18S));}
251 }
252
253 //Turn off read validation in the input threads to increase speed
254 final boolean vic=Read.VALIDATE_IN_CONSTRUCTOR;
255 Read.VALIDATE_IN_CONSTRUCTOR=Shared.threads()<4;
256
257 //Reset counters
258 readsProcessed=readsOut=0;
259 basesProcessed=basesOut=0;
260
261 //Align everything to global consensus
262 for(FileFormat ff : ffin) {
263 //Create a read input stream
264 final ConcurrentReadInputStream cris=makeCris(ff);
265
266 //Process the reads in separate threads
267 spawnThreads(cris, false);
268 errorState|=ReadWrite.closeStream(cris);
269 }
270
271 if(ffalt!=null){
272 //Create a read input stream
273 final ConcurrentReadInputStream cris=makeCris(ffalt);
274
275 //Process the reads in separate threads
276 spawnThreads(cris, true);
277 errorState|=ReadWrite.closeStream(cris);
278 }
279
280 // queue=new ConcurrentLinkedQueue<ArrayList<Ribo>>();
281 // for(Entry<Integer, ArrayList<Ribo>> e : listMap.entrySet()){
282 // queue.add(e.getValue());
283 // }
284 // listMap=null;
285 queue=makeQueue();
286
287 //Run a second pass to pick the best SSU per taxID
288 spawnThreads(null, false);
289
290 //Do anything necessary after processing
291 if(ffout1!=null){
292 //Optionally create a read output stream
293 final ConcurrentReadOutputStream ros=makeCros();
294 long num=0;
295 for(Ribo ribo : bestList){
296 Read r=ribo.r;
297 readsOut++;
298 basesOut+=r.length();
299 ArrayList<Read> list=new ArrayList<Read>(1);
300 list.add(r);
301 ros.add(list, num);
302 num++;
303 }
304 //Close the read streams
305 errorState|=ReadWrite.closeStream(ros);
306 }
307
308 if(verbose){outstream.println("Finished; closing streams.");}
309
310 //Write anything that was accumulated by ReadStats
311 errorState|=ReadStats.writeAll();
312
313 //Reset read validation
314 Read.VALIDATE_IN_CONSTRUCTOR=vic;
315
316 //Report timing and results
317 t.stop();
318 outstream.println(Tools.timeReadsBasesProcessed(t, readsProcessed, basesProcessed, 8));
319 outstream.println(Tools.readsBasesOut(readsProcessed, basesProcessed, readsOut, basesOut, 8, false));
320
321 //Throw an exception of there was an error in a thread
322 if(errorState){
323 throw new RuntimeException(getClass().getName()+" terminated in an error state; the output may be corrupt.");
324 }
325 }
326
327 private ConcurrentLinkedQueue<ArrayList<Ribo>> makeQueue(){
328 ArrayList<ArrayList<Ribo>> listList=new ArrayList<ArrayList<Ribo>>(listMap.size());
329 for(Entry<Integer, ArrayList<Ribo>> e : listMap.entrySet()){
330 listList.add(e.getValue());
331 }
332 listMap=null;
333 Collections.sort(listList, new ListComparator());
334 assert(listList.isEmpty() || listList.get(0).size()>=listList.get(listList.size()-1).size());
335 ConcurrentLinkedQueue<ArrayList<Ribo>> q=new ConcurrentLinkedQueue<ArrayList<Ribo>>();
336 for(ArrayList<Ribo> x : listList){
337 q.add(x);
338 }
339 return q;
340 }
341
342 private ConcurrentReadInputStream makeCris(FileFormat ff){
343 ConcurrentReadInputStream cris=ConcurrentReadInputStream.getReadInputStream(maxReads, true, ff, null);
344 cris.start(); //Start the stream
345 if(verbose){outstream.println("Started cris");}
346 boolean paired=cris.paired();
347 assert(!paired) : "This should not be paired input.";
348 return cris;
349 }
350
351 private ConcurrentReadOutputStream makeCros(){
352 if(ffout1==null){return null;}
353
354 //Select output buffer size based on whether it needs to be ordered
355 final int buff=(ordered ? Tools.mid(16, 128, (Shared.threads()*2)/3) : 8);
356
357 final ConcurrentReadOutputStream ros=ConcurrentReadOutputStream.getStream(ffout1, null, buff, null, false);
358 ros.start(); //Start the stream
359 return ros;
360 }
361
362 /*--------------------------------------------------------------*/
363 /*---------------- Thread Management ----------------*/
364 /*--------------------------------------------------------------*/
365
366 /** Spawn process threads */
367 private void spawnThreads(final ConcurrentReadInputStream cris, boolean altData){
368
369 //Do anything necessary prior to processing
370
371 //Fill a list with ProcessThreads
372 if(verbose){System.err.println("Spawning "+threads+" threads.");}
373 ArrayList<ProcessThread> alpt=new ArrayList<ProcessThread>(threads);
374 for(int i=0; i<threads; i++){
375 alpt.add(new ProcessThread(cris, i, altData));
376 }
377
378 //Start the threads and wait for them to finish
379 boolean success=ThreadWaiter.startAndWait(alpt, this);
380 if(verbose){System.err.println("Threads finished with success="+success+".");}
381 errorState&=!success;
382 }
383
384 @Override
385 public final void accumulate(ProcessThread pt){
386 readsProcessed+=pt.readsProcessedT;
387 basesProcessed+=pt.basesProcessedT;
388 errorState|=(!pt.success);
389 }
390
391 @Override
392 public final boolean success(){return !errorState;}
393
394 /*--------------------------------------------------------------*/
395 /*---------------- Inner Methods ----------------*/
396 /*--------------------------------------------------------------*/
397
398 /*--------------------------------------------------------------*/
399 /*---------------- Inner Classes ----------------*/
400 /*--------------------------------------------------------------*/
401
402 /** This class is static to prevent accidental writing to shared variables.
403 * It is safe to remove the static modifier. */
404 class ProcessThread extends Thread {
405
406 //Constructor
407 ProcessThread(final ConcurrentReadInputStream cris_, final int tid_, boolean alt_){
408 cris=cris_;
409 tid=tid_;
410 processInput=(cris!=null);
411 altData=alt_;
412 }
413
414 //Called by start()
415 @Override
416 public void run(){
417 //Do anything necessary prior to processing
418
419 if(processInput){
420 //Process the reads
421 processInner();
422 }else{
423 pickBest();
424 }
425
426 //Do anything necessary after processing
427
428 //Indicate successful exit status
429 success=true;
430 }
431
432 /** Iterate through the reads */
433 void processInner(){
434 if(verbose && tid==0){System.err.println("processInner() for tid="+tid);}
435
436 //Grab the first ListNum of reads
437 ListNum<Read> ln=cris.nextList();
438
439 //Check to ensure pairing is as expected
440 if(ln!=null && !ln.isEmpty()){
441 Read r=ln.get(0);
442 // assert(ffin1.samOrBam() || (r.mate!=null)==cris.paired()); //Disabled due to non-static access
443 }
444
445 //As long as there is a nonempty read list...
446 while(ln!=null && ln.size()>0){
447 // if(verbose){outstream.println("Fetched "+reads.size()+" reads.");} //Disabled due to non-static access
448
449 processInput(ln);
450
451 //Notify the input stream that the list was used
452 cris.returnList(ln);
453 // if(verbose){outstream.println("Returned a list.");} //Disabled due to non-static access
454
455 //Fetch a new list
456 ln=cris.nextList();
457 }
458
459 //Notify the input stream that the final list was used
460 if(ln!=null){
461 cris.returnList(ln.id, ln.list==null || ln.list.isEmpty());
462 }
463 }
464
465 void processInput(ListNum<Read> ln){
466 if(verbose && tid==0){System.err.println("processInput() for tid="+tid);}
467
468 //Grab the actual read list from the ListNum
469 final ArrayList<Read> reads=ln.list;
470
471 //Loop through each read in the list
472 for(int idx=0; idx<reads.size(); idx++){
473 final Read r1=reads.get(idx);
474
475 //Validate reads in worker threads
476 if(!r1.validated()){r1.validate(true);}
477
478 //Track the initial length for statistics
479 final int initialLength1=r1.length();
480
481 //Increment counters
482 readsProcessedT++;
483 basesProcessedT+=initialLength1;
484
485 processRead(r1);
486 }
487 }
488
489 void pickBest(){
490 if(verbose && tid==0){System.err.println("pickBest() for tid="+tid);}
491 for(ArrayList<Ribo> list=queue.poll(); list!=null; list=queue.poll()){
492 Ribo best=pickBest(list);
493 list.clear();
494 synchronized(bestList){
495 bestList.add(best);
496 }
497 }
498 }
499
500 Ribo pickBest(ArrayList<Ribo> list){
501 if(verbose && tid==0){System.err.println("pickBest(list[="+list.size()+"]) for tid="+tid);}
502 assert(list!=null && list.size()>0);
503 if(list.size()==1){return list.get(0);}
504 Collections.sort(list);
505 Collections.reverse(list);
506 assert(list.get(0).product>=list.get(1).product);
507 if(list.size()<3 || fast){return list.get(0);}
508
509 Ribo base=list.get(0);
510 int pad=Tools.max(10, (1600-base.r.length()));
511 BaseGraph bg=new BaseGraph(base.r.name(), base.r.bases, base.r.quality, base.r.numericID, pad);
512 for(Ribo r : list){
513 bg.alignAndGenerateMatch(r.r, ssa);
514 }
515 Read consensus=bg.traverse();
516 Ribo best;
517 if(useConsensus){
518 best=new Ribo(consensus, base.tid, 1);
519 }else{
520 for(Ribo r : list){
521 float id=align(r.r.bases, consensus.bases);
522 r.identity=id;
523 r.product=score(r.length(), r.identity);
524 }
525 Collections.sort(list);
526 Collections.reverse(list);
527 assert(list.get(0).product>=list.get(1).product);
528 best=list.get(0);
529 }
530 return best;
531 }
532
533 /**
534 * Process a read or a read pair.
535 * @return True if the reads should be kept, false if they should be discarded.
536 */
537 void processRead(final Read r){
538 if(verbose && tid==0){System.err.println("processRead()");}
539 if(r.length()<minlen || r.length()>maxlen){return;}
540 if(maxns>=0 && r.countNocalls()>maxns){return;}
541 Integer key=GiToTaxid.parseTaxidNumber(r.id, '|');
542 if(verbose && tid==0){System.err.println("key="+key);}
543 if(key==null || key==-1 || (altData && seenTaxID.contains(key))){return;}
544 float id=align(r);
545 if(id<minID){return;}
546 Ribo ribo=new Ribo(r, key, id);
547
548 synchronized(listMap){
549 ArrayList<Ribo> list=listMap.get(key);
550 if(list==null){
551 list=new ArrayList<Ribo>(8);
552 listMap.put(key, list);
553 }
554 list.add(ribo);
555 if(!altData){seenTaxID.add(key);}
556 }
557 }
558
559 float align(Read r){
560 float a=(process16S ? align(r.bases, consensus16S) : 0);
561 float b=(process18S ? align(r.bases, consensus18S) : 0);
562 if(verbose && tid==0){System.err.println("Aligned; a="+a+", b="+b);}
563 return Tools.max(a, b);
564 }
565
566 float align(byte[] query, byte[] ref){
567 int a=0, b=ref.length-1;
568 int[] max=ssa.fillUnlimited(query, ref, a, b, -9999);
569 if(max==null){return 0;}
570
571 final int rows=max[0];
572 final int maxCol=max[1];
573 final int maxState=max[2];
574 final float id=ssa.tracebackIdentity(query, ref, a, b, rows, maxCol, maxState, null);
575 return id;
576 }
577
578 SingleStateAlignerFlat2 ssa=new SingleStateAlignerFlat2();
579
580 /** Number of reads processed by this thread */
581 protected long readsProcessedT=0;
582 /** Number of bases processed by this thread */
583 protected long basesProcessedT=0;
584
585 /** True only if this thread has completed successfully */
586 boolean success=false;
587
588 /** Shared input stream */
589 private final ConcurrentReadInputStream cris;
590 /** Thread ID */
591 final int tid;
592
593 //Run mode
594 final boolean processInput;
595 final boolean altData;
596 }
597
598 private class Ribo implements Comparable<Ribo>{
599 Ribo(Read r_, int tid_, float identity_){
600 r=r_;
601 tid=tid_;
602 identity=identity_;
603 product=score(r.length(), identity);
604 }
605
606 @Override
607 public int compareTo(Ribo b) {
608 if(b.product>product){return -1;}
609 else if(b.product<product){return 1;}
610 else if(b.r.length()>r.length()){return -1;}
611 else if(b.r.length()<r.length()){return 1;}
612 return 0;
613 }
614
615 int length(){return r.length();}
616
617 Read r;
618 int tid;
619 float identity;
620 float product;
621 }
622
623 private class ListComparator implements Comparator<ArrayList<Ribo>> {
624
625 @Override
626 public int compare(ArrayList<Ribo> a, ArrayList<Ribo> b) {
627 return a.size()>b.size() ? -1 : a.size()<b.size() ? 1 : 0;
628 }
629
630 }
631
632 private float lengthMult(int len){
633 int idealLength=idealLength();
634 int max=Tools.max(len, idealLength, 1);
635 int min=Tools.min(len, idealLength);
636 return min/(float)max;
637 }
638
639 private float score(int len, float identity){
640 return lengthMult(len)*identity;
641 }
642
643 /*--------------------------------------------------------------*/
644 /*---------------- Fields ----------------*/
645 /*--------------------------------------------------------------*/
646
647 /** Primary input file path */
648 private ArrayList<String> in=new ArrayList<String>();
649
650 /** Alternate input file path */
651 private String alt=null;
652
653 /** Primary output file path */
654 private String out1=null;
655
656 /** Override input file extension */
657 private String extin=null;
658 /** Override output file extension */
659 private String extout=null;
660
661 ArrayList<Ribo> bestList=new ArrayList<Ribo>();
662 HashMap<Integer, ArrayList<Ribo>> listMap=new HashMap<Integer, ArrayList<Ribo>>(100000);
663 ConcurrentLinkedQueue<ArrayList<Ribo>> queue;
664
665
666 IntHashSet seenTaxID=new IntHashSet(1000000);
667
668 byte[] consensus16S;
669 byte[] consensus18S;
670
671 int idealLength(){
672 if(process16S){return consensus16S.length;}
673 return consensus18S.length;
674 }
675
676 boolean useConsensus=false;
677 boolean fast=false;
678 int maxns=-1;
679 int minlen=1;
680 int maxlen=4000;
681
682 /*--------------------------------------------------------------*/
683
684 /** Number of reads processed */
685 protected long readsProcessed=0;
686 /** Number of bases processed */
687 protected long basesProcessed=0;
688
689 /** Number of reads retained */
690 protected long readsOut=0;
691 /** Number of bases retained */
692 protected long basesOut=0;
693
694 /** Quit after processing this many input reads; -1 means no limit */
695 private long maxReads=-1;
696
697 private float minID=0.62f;
698
699 private boolean process16S=true;
700 private boolean process18S=false;
701
702 /*--------------------------------------------------------------*/
703 /*---------------- Final Fields ----------------*/
704 /*--------------------------------------------------------------*/
705
706 /** Primary input file */
707 private final ArrayList<FileFormat> ffin;
708 private final FileFormat ffalt;
709
710 /** Primary output file */
711 private final FileFormat ffout1;
712
713 final int threads;
714
715 /*--------------------------------------------------------------*/
716 /*---------------- Common Fields ----------------*/
717 /*--------------------------------------------------------------*/
718
719 /** Print status messages to this output stream */
720 private PrintStream outstream=System.err;
721 /** Print verbose messages */
722 public static boolean verbose=false;
723 /** True if an error was encountered */
724 public boolean errorState=false;
725 /** Overwrite existing output files */
726 private boolean overwrite=false;
727 /** Append to existing output files */
728 private boolean append=false;
729 /** Reads are output in input order */
730 private boolean ordered=false;
731
732 }