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