1 package align2;
2 
3 import java.io.File;
4 import java.util.ArrayList;
5 import java.util.Locale;
6 
7 import bloom.BloomFilter;
8 import dna.ChromosomeArray;
9 import dna.Data;
10 import fileIO.ReadWrite;
11 import jgi.CoveragePileup;
12 import shared.Shared;
13 import shared.Timer;
14 import shared.Tools;
15 import stream.FastaReadInputStream;
16 import stream.ReadStreamWriter;
17 import stream.SamLine;
18 
19 /**
20  *
21  * @author Brian Bushnell
22  * @date Dec 22, 2012
23  *
24  */
25 public final class BBMap extends AbstractMapper {
26 
27 
main(String[] args)28 	public static void main(String[] args){
29 		Timer t=new Timer();
30 		BBMap mapper=new BBMap(args);
31 		args=Tools.condenseStrict(args);
32 		if(!INDEX_LOADED){mapper.loadIndex();}
33 		if(Data.scaffoldPrefixes){mapper.processAmbig2();}
34 		mapper.testSpeed(args);
35 		ReadWrite.waitForWritingToFinish();
36 		t.stop();
37 		outstream.println("\nTotal time:     \t"+t);
38 		clearStatics();
39 	}
40 
BBMap(String[] args)41 	public BBMap(String[] args){
42 		super(args);
43 	}
44 
45 	@Override
setDefaults()46 	public void setDefaults(){
47 		ReadWrite.USE_PIGZ=ReadWrite.USE_UNPIGZ=false;
48 		ReadWrite.USE_BGZIP=ReadWrite.USE_UNBGZIP=true;
49 		ReadWrite.PREFER_BGZIP=true;
50 		ReadWrite.ZIPLEVEL=2;
51 		MAKE_MATCH_STRING=true;
52 		keylen=13;
53 
54 		MINIMUM_ALIGNMENT_SCORE_RATIO=0.56f;
55 
56 		keyDensity=1.9f;//2.3f;
57 		maxKeyDensity=3f;//4f;
58 		minKeyDensity=1.5f;//1.8f;
59 		maxDesiredKeys=15;
60 
61 		SLOW_ALIGN_PADDING=4;
62 		SLOW_RESCUE_PADDING=4+SLOW_ALIGN_PADDING;
63 		TIP_SEARCH_DIST=100;
64 
65 		MSA_TYPE="MultiStateAligner11ts";
66 		MAX_SITESCORES_TO_PRINT=5;
67 		PRINT_SECONDARY_ALIGNMENTS=false;
68 		AbstractIndex.MIN_APPROX_HITS_TO_KEEP=1;
69 	}
70 
71 	@Override
preparse(String[] args)72 	public String[] preparse(String[] args){
73 		if(fast){
74 			ArrayList<String> list=new ArrayList<String>();
75 			list.add("tipsearch="+TIP_SEARCH_DIST/5);
76 			list.add("maxindel=80");
77 			list.add("minhits=2");
78 			list.add("bwr=0.18");
79 			list.add("bw=40");
80 			list.add("minratio=0.65");
81 			list.add("midpad=150");
82 			list.add("minscaf=50");
83 			list.add("quickmatch=t");
84 			list.add("rescuemismatches=15");
85 			list.add("rescuedist=800");
86 			list.add("maxsites=3");
87 			list.add("maxsites2=100");
88 //			list.add("k=13");
89 
90 			//TODO:  Make these adjustable.
91 //			MIN_TRIM_SITES_TO_RETAIN_SINGLE
92 //			MIN_TRIM_SITES_TO_RETAIN_PAIRED
93 //			MAX_TRIM_SITES_TO_RETAIN
94 			//TODO:  Make trimLists adjustable via an offset or multiplier
95 
96 			BBIndex.setFractionToExclude(BBIndex.FRACTION_GENOME_TO_EXCLUDE*1.25f);
97 
98 			for(String s : args){if(s!=null){list.add(s);}}
99 			args=list.toArray(new String[list.size()]);
100 
101 			keyDensity*=0.9f;
102 			maxKeyDensity*=0.9f;
103 			minKeyDensity*=0.9f;
104 		}else if(vslow){
105 			ArrayList<String> list=new ArrayList<String>();
106 			list.add("tipsearch="+(TIP_SEARCH_DIST*3)/2);
107 			list.add("minhits=1");
108 			list.add("minratio=0.25");
109 			list.add("rescuemismatches=50");
110 			list.add("rescuedist=3000");
111 
112 			BBIndex.setFractionToExclude(0);
113 
114 			for(String s : args){if(s!=null){list.add(s);}}
115 			args=list.toArray(new String[list.size()]);
116 
117 			SLOW_ALIGN_PADDING=SLOW_ALIGN_PADDING*2+2;
118 			SLOW_RESCUE_PADDING=SLOW_RESCUE_PADDING*2+2;
119 
120 			AbstractIndex.SLOW=true;
121 			AbstractIndex.VSLOW=true;
122 			keyDensity*=2.5f;
123 			maxKeyDensity*=2.5f;
124 			minKeyDensity*=2.5f;
125 		}else if(slow){
126 			ArrayList<String> list=new ArrayList<String>();
127 			list.add("tipsearch="+(TIP_SEARCH_DIST*3)/2);
128 //			list.add("maxindel=80");
129 			list.add("minhits=1");
130 //			list.add("bwr=0.18");
131 //			list.add("bw=40");
132 			list.add("minratio=0.45");
133 //			list.add("midpad=150");
134 //			list.add("minscaf=50");
135 //			list.add("k=13");
136 
137 			BBIndex.setFractionToExclude(BBIndex.FRACTION_GENOME_TO_EXCLUDE*0.4f);
138 
139 			for(String s : args){if(s!=null){list.add(s);}}
140 			args=list.toArray(new String[list.size()]);
141 
142 			AbstractIndex.SLOW=true;
143 			keyDensity*=1.2f;
144 			maxKeyDensity*=1.2f;
145 			minKeyDensity*=1.2f;
146 		}
147 
148 		if(excludeFraction>=0){
149 			BBIndex.setFractionToExclude(excludeFraction);
150 		}
151 		return args;
152 	}
153 
154 	@Override
postparse(String[] args)155 	void postparse(String[] args){
156 
157 		if(MSA.bandwidthRatio>0 && MSA.bandwidthRatio<.2){
158 			SLOW_ALIGN_PADDING=Tools.min(SLOW_ALIGN_PADDING, 3);
159 			SLOW_RESCUE_PADDING=Tools.min(SLOW_RESCUE_PADDING, 6);
160 		}
161 
162 		if(maxIndel1>-1){
163 			TIP_SEARCH_DIST=Tools.min(TIP_SEARCH_DIST, maxIndel1);
164 			BBIndex.MAX_INDEL=maxIndel1;
165 		}
166 		if(maxIndel2>-1){
167 			BBIndex.MAX_INDEL2=maxIndel2;
168 		}
169 
170 		if(minApproxHits>-1){
171 			BBIndex.MIN_APPROX_HITS_TO_KEEP=minApproxHits;
172 		}
173 
174 		if(expectedSites>-1){
175 			BBMapThread.setExpectedSites(expectedSites);
176 			outstream.println("Set EXPECTED_SITES to "+expectedSites);
177 		}
178 
179 		if(fractionGenomeToExclude>=0){
180 			BBIndex.setFractionToExclude(fractionGenomeToExclude);
181 		}
182 
183 		{
184 			final String a=(args.length>0 ? args[0] : null);
185 			final String b=(args.length>1 ? args[1] : null);
186 			if(in1==null && a!=null && a.indexOf('=')<0 && (a.startsWith("stdin") || new File(a).exists())){in1=a;}
187 			if(in2==null && b!=null && b.indexOf('=')<0 && new File(b).exists()){in2=b;}
188 			if(ERROR_ON_NO_OUTPUT && !OUTPUT_READS && in1!=null){throw new RuntimeException("Error: no output file, and ERROR_ON_NO_OUTPUT="+ERROR_ON_NO_OUTPUT);}
189 		}
190 
191 		assert(synthReadlen<BBMapThread.ALIGN_ROWS);
192 
193 		if(MSA.bandwidth>0){
194 			int halfwidth=MSA.bandwidth/2;
195 			TIP_SEARCH_DIST=Tools.min(TIP_SEARCH_DIST, halfwidth/2);
196 			BBIndex.MAX_INDEL=Tools.min(BBIndex.MAX_INDEL, halfwidth/2);
197 			BBIndex.MAX_INDEL2=Tools.min(BBIndex.MAX_INDEL2, halfwidth);
198 			SLOW_ALIGN_PADDING=Tools.min(SLOW_ALIGN_PADDING, halfwidth/4);
199 			SLOW_RESCUE_PADDING=Tools.min(SLOW_RESCUE_PADDING, halfwidth/4);
200 		}
201 
202 		if(PRINT_SECONDARY_ALIGNMENTS){
203 			REMOVE_DUPLICATE_BEST_ALIGNMENTS=false;
204 			BBIndex.QUIT_AFTER_TWO_PERFECTS=false;
205 		}
206 
207 		if(in1!=null){
208 			if(ambigMode==AMBIG_BEST){
209 				REMOVE_DUPLICATE_BEST_ALIGNMENTS=false;
210 				if(!PRINT_SECONDARY_ALIGNMENTS){BBIndex.QUIT_AFTER_TWO_PERFECTS=true;}
211 				outstream.println("Retaining first best site only for ambiguous mappings.");
212 			}else if(ambigMode==AMBIG_ALL){
213 				PRINT_SECONDARY_ALIGNMENTS=ReadStreamWriter.OUTPUT_SAM_SECONDARY_ALIGNMENTS=true;
214 				REMOVE_DUPLICATE_BEST_ALIGNMENTS=false;
215 				BBIndex.QUIT_AFTER_TWO_PERFECTS=false;
216 				SamLine.MAKE_NH_TAG=true;
217 				ambiguousAll=true;
218 				outstream.println("Retaining all best sites for ambiguous mappings.");
219 			}else if(ambigMode==AMBIG_RANDOM){
220 				REMOVE_DUPLICATE_BEST_ALIGNMENTS=false;
221 				BBIndex.QUIT_AFTER_TWO_PERFECTS=false;
222 				ambiguousRandom=true;
223 				outstream.println("Choosing a site randomly for ambiguous mappings.");
224 			}else if(ambigMode==AMBIG_TOSS){
225 				REMOVE_DUPLICATE_BEST_ALIGNMENTS=true;
226 				BBIndex.QUIT_AFTER_TWO_PERFECTS=true;
227 				outstream.println("Ambiguously mapped reads will be considered unmapped.");
228 			}else{
229 				throw new RuntimeException("Unknown ambiguous mapping mode: "+ambigMode);
230 			}
231 		}
232 
233 	}
234 
235 	@Override
setup()236 	public void setup(){
237 
238 		assert(!useRandomReads || maxReads>0 || (in1!=null && in1.equals("sequential"))) : "Please specify number of reads to use.";
239 
240 		if(minid!=-1){
241 			MINIMUM_ALIGNMENT_SCORE_RATIO=MSA.minIdToMinRatio(minid, MSA_TYPE);
242 			outstream.println("Set MINIMUM_ALIGNMENT_SCORE_RATIO to "+String.format(Locale.ROOT, "%.3f",MINIMUM_ALIGNMENT_SCORE_RATIO));
243 		}
244 
245 		if(!setxs){SamLine.MAKE_XS_TAG=(SamLine.INTRON_LIMIT<1000000000);}
246 		if(setxs && !setintron){SamLine.INTRON_LIMIT=10;}
247 
248 		if(outFile==null && outFile2==null && outFileM==null && outFileM2==null && outFileU==null && outFileU2==null
249 				&& outFileB==null && outFileB2==null && splitterOutputs==null && BBSplitter.streamTable==null){
250 			outstream.println("No output file.");
251 			OUTPUT_READS=false;
252 		}else{
253 			OUTPUT_READS=true;
254 			if(bamscript!=null){
255 				BBSplitter.makeBamScript(bamscript, splitterOutputs, outFile, outFile2, outFileM, outFileM2, outFileU, outFileU2, outFileB, outFileB2);
256 			}
257 		}
258 //		assert(false) : bamscript+", "+BBSplitter.streamTable+", "+OUTPUT_READS;
259 
260 
261 
262 		FastaReadInputStream.MIN_READ_LEN=Tools.max(keylen+2, FastaReadInputStream.MIN_READ_LEN);
263 		assert(FastaReadInputStream.settingsOK());
264 
265 		if(build<0){throw new RuntimeException("Must specify a build number, e.g. build=1");}
266 		else{Data.GENOME_BUILD=build;}
267 
268 		if(blacklist!=null && blacklist.size()>0){
269 			Timer t=new Timer();
270 			t.start();
271 			for(String s : blacklist){
272 				Blacklist.addToBlacklist(s);
273 			}
274 			t.stop();
275 			outstream.println("Created blacklist:\t"+t);
276 			t.start();
277 		}
278 
279 		if(ziplevel!=-1){ReadWrite.ZIPLEVEL=ziplevel;}
280 		if(reference!=null){RefToIndex.makeIndex(reference, build, outstream, keylen);}
281 	}
282 
283 
284 	@Override
processAmbig2()285 	void processAmbig2(){
286 		assert(Data.scaffoldPrefixes) : "Only process this block if there are multiple references.";
287 		if(BBSplitter.AMBIGUOUS2_MODE==BBSplitter.AMBIGUOUS2_SPLIT){
288 			REMOVE_DUPLICATE_BEST_ALIGNMENTS=false;
289 			BBIndex.QUIT_AFTER_TWO_PERFECTS=false;
290 			outstream.println("Reads that map to multiple references will be written to special output streams.");
291 		}else if(BBSplitter.AMBIGUOUS2_MODE==BBSplitter.AMBIGUOUS2_FIRST){
292 			REMOVE_DUPLICATE_BEST_ALIGNMENTS=false;
293 			BBIndex.QUIT_AFTER_TWO_PERFECTS=false;
294 			outstream.println("Reads that map to multiple references will be written to the first reference's stream only.");
295 		}else if(BBSplitter.AMBIGUOUS2_MODE==BBSplitter.AMBIGUOUS2_TOSS){
296 			BBIndex.QUIT_AFTER_TWO_PERFECTS=true;
297 			outstream.println("Reads that map to multiple references will be considered unmapped.");
298 		}else if(BBSplitter.AMBIGUOUS2_MODE==BBSplitter.AMBIGUOUS2_RANDOM){
299 			REMOVE_DUPLICATE_BEST_ALIGNMENTS=false;
300 			BBIndex.QUIT_AFTER_TWO_PERFECTS=false;
301 			outstream.println("Reads that map to multiple references will be written to a random stream.");
302 		}else if(BBSplitter.AMBIGUOUS2_MODE==BBSplitter.AMBIGUOUS2_ALL){
303 			REMOVE_DUPLICATE_BEST_ALIGNMENTS=false;
304 			BBIndex.QUIT_AFTER_TWO_PERFECTS=false;
305 			outstream.println("Reads that map to multiple references will be written to all relevant output streams.");
306 		}else{
307 			BBSplitter.AMBIGUOUS2_MODE=BBSplitter.AMBIGUOUS2_FIRST;
308 		}
309 	}
310 
311 	@Override
loadIndex()312 	void loadIndex(){
313 		Timer t=new Timer(outstream, true);
314 
315 		if(build>-1){
316 			Data.setGenome(build);
317 			AbstractIndex.MINCHROM=1;
318 			AbstractIndex.MAXCHROM=Data.numChroms;
319 			if(minChrom<0){minChrom=1;}
320 			if(maxChrom<0 || maxChrom>Data.numChroms){maxChrom=Data.numChroms;}
321 			outstream.println("Set genome to "+Data.GENOME_BUILD);
322 
323 			if(RefToIndex.AUTO_CHROMBITS){
324 				int maxLength=Tools.max(Data.chromLengths);
325 				RefToIndex.chrombits=Integer.numberOfLeadingZeros(maxLength)-1;
326 				RefToIndex.chrombits=Tools.min(RefToIndex.chrombits, 16);
327 			}
328 			if(RefToIndex.chrombits!=-1){
329 				BBIndex.setChromBits(RefToIndex.chrombits);
330 				if(verbose_stats>0){outstream.println("Set CHROMBITS to "+RefToIndex.chrombits);}
331 			}
332 		}
333 
334 		assert(minChrom>=AbstractIndex.MINCHROM && maxChrom<=AbstractIndex.MAXCHROM) :
335 			minChrom+", "+maxChrom+", "+AbstractIndex.MINCHROM+", "+AbstractIndex.MAXCHROM;
336 		AbstractIndex.MINCHROM=minChrom;
337 		AbstractIndex.MAXCHROM=maxChrom;
338 
339 		if(targetGenomeSize>0){
340 			long bases=Data.numDefinedBases;
341 			long x=Tools.max(1, Math.round(0.25f+bases*1d/targetGenomeSize));
342 			BBMapThread.setExpectedSites((int)x);
343 			outstream.println("Set EXPECTED_SITES to "+x);
344 		}
345 
346 		assert(!(PERFECTMODE && SEMIPERFECTMODE));
347 		if(PERFECTMODE){setPerfectMode();}
348 		if(SEMIPERFECTMODE){setSemiperfectMode();}
349 
350 		//Optional section for discrete timing of chrom array loading
351 		if(SLOW_ALIGN || AbstractIndex.USE_EXTENDED_SCORE || useRandomReads || MAKE_MATCH_STRING){
352 			outstream.println();
353 			if(INDEX_LOADED){
354 				//do nothing
355 			}else if(RefToIndex.chromlist==null){
356 				Data.loadChromosomes(minChrom, maxChrom);
357 			}else{
358 				assert(RefToIndex.chromlist.size()==maxChrom-minChrom+1) : RefToIndex.chromlist.size();
359 				for(ChromosomeArray cha : RefToIndex.chromlist){
360 					Data.chromosomePlusMatrix[cha.chromosome]=cha;
361 				}
362 			}
363 			if(Shared.TRIM_RNAME){Data.trimScaffoldNames();}
364 			t.stop();
365 			outstream.println("Loaded Reference:\t"+t);
366 			t.start();
367 		}
368 		RefToIndex.chromlist=null;
369 
370 		t.start();
371 		BBIndex.loadIndex(minChrom, maxChrom, keylen, !RefToIndex.NODISK, RefToIndex.NODISK);
372 
373 		{
374 			long len=Data.numDefinedBases;
375 			if(len<300000000){
376 				BBIndex.MAX_HITS_REDUCTION2+=1;
377 				BBIndex.MAXIMUM_MAX_HITS_REDUCTION+=1;
378 				if(len<30000000){
379 					BBIndex.setFractionToExclude(BBIndex.FRACTION_GENOME_TO_EXCLUDE*0.5f);
380 					BBIndex.MAXIMUM_MAX_HITS_REDUCTION+=1;
381 					BBIndex.HIT_REDUCTION_DIV=Tools.max(BBIndex.HIT_REDUCTION_DIV-1, 3);
382 				}else if(len<100000000){
383 					BBIndex.setFractionToExclude(BBIndex.FRACTION_GENOME_TO_EXCLUDE*0.6f);
384 				}else{
385 					BBIndex.setFractionToExclude(BBIndex.FRACTION_GENOME_TO_EXCLUDE*0.75f);
386 				}
387 			}
388 		}
389 
390 		t.stop();
391 		outstream.println("Generated Index:\t"+t);
392 		t.start();
393 
394 		if(!SLOW_ALIGN && !AbstractIndex.USE_EXTENDED_SCORE && !useRandomReads && !MAKE_MATCH_STRING){
395 			for(int chrom=minChrom; chrom<=maxChrom; chrom++){
396 				Data.unload(chrom, true);
397 			}
398 		}
399 
400 		if(ReadWrite.countActiveThreads()>0){
401 			ReadWrite.waitForWritingToFinish();
402 			t.stop();
403 			outstream.println("Finished Writing:\t"+t);
404 			t.start();
405 		}
406 
407 		if(coverageBinned!=null || coverageBase!=null || coverageHist!=null || coverageStats!=null || coverageRPKM!=null || normcov!=null || normcovOverall!=null || calcCov){
408 			String[] cvargs=("covhist="+coverageHist+"\tcovstats="+coverageStats+"\tbasecov="+coverageBase+"\tbincov="+coverageBinned+"\tphyscov="+coveragePhysical+
409 					"\t32bit="+cov32bit+"\tnzo="+covNzo+"\ttwocolumn="+covTwocolumn+"\tsecondary="+PRINT_SECONDARY_ALIGNMENTS+"\tcovminscaf="+coverageMinScaf+
410 					"\tksb="+covKsb+"\tbinsize="+covBinSize+"\tk="+covK+"\tstartcov="+covStartOnly+"\tstopcov="+covStopOnly+"\tstrandedcov="+covStranded+"\trpkm="+coverageRPKM+
411 					"\tnormcov="+normcov+"\tnormcovo="+normcovOverall+(in1==null ? "" : "\tin1="+in1)+(in2==null ? "" : "\tin2="+in2)+
412 					(covSetbs ? ("\tbitset="+covBitset+"\tarrays="+covArrays) : "")).split("\t");
413 			pileup=new CoveragePileup(cvargs);
414 			pileup.createDataStructures();
415 			pileup.loadScaffoldsFromIndex(minChrom, maxChrom);
416 		}
417 
418 		if(!forceanalyze && (in1==null || maxReads==0)){return;}
419 
420 		BBIndex.analyzeIndex(minChrom, maxChrom, BBIndex.FRACTION_GENOME_TO_EXCLUDE, keylen);
421 
422 		t.stop("Analyzed Index:   ");
423 		t.start();
424 
425 		if(makeBloomFilter){
426 			String serialPath=RefToIndex.bloomLoc(build);
427 			File serialFile=new File(serialPath);
428 //			System.err.println(serialPath+", "+serialFile.exists()+", "+bloomSerial+", "+RefToIndex.NODISK);
429 			if(bloomSerial && !RefToIndex.NODISK && serialFile.exists()){
430 				bloomFilter=ReadWrite.read(BloomFilter.class, RefToIndex.bloomLoc(build), true);
431 				t.stop("Loaded Bloom Filter: ");
432 			}else{
433 				if(bloomSerial){System.out.println("Could not read "+serialPath+", generating filter from reference.");}
434 				bloomFilter=new BloomFilter(true, bloomFilterK, bloomFilterK, 1, bloomFilterHashes, bloomFilterMinHits, true);
435 				t.stop("Made Bloom Filter: ");
436 				if(bloomSerial && !RefToIndex.NODISK && !RefToIndex.FORCE_READ_ONLY){
437 //					 && serialFile.canWrite()
438 					try {
439 						ReadWrite.writeObjectInThread(bloomFilter, serialPath, true);
440 						outstream.println("Writing Bloom Filter.");
441 					} catch (Throwable e) {
442 						e.printStackTrace();
443 						outstream.println("Can't Write Bloom Filter.");
444 					}
445 				}
446 			}
447 			outstream.println(bloomFilter.filter.toShortString());
448 			t.start();
449 		}
450 //		assert(false) : makeBloomFilter;
451 //		assert(false) : RefToIndex.chrombits+", "+AbstractIndex.CHROMS_PER_BLOCK;
452 	}
453 
454 	@Override
testSpeed(String[] args)455 	public void testSpeed(String[] args){
456 
457 		if(in1==null || maxReads==0){
458 			outstream.println("No reads to process; quitting.");
459 			return;
460 		}
461 
462 		Timer t=new Timer();
463 
464 		final boolean paired=openStreams(t, args);
465 		if(paired){BBIndex.QUIT_AFTER_TWO_PERFECTS=false;}
466 
467 		t.start();
468 
469 		if(Shared.USE_JNI){
470 			final int threads=Shared.threads();
471 			adjustThreadsforMemory(105);
472 			if(Shared.threads()<threads*0.9){
473 				outstream.println("Disabling JNI due to low system memory.");
474 				Shared.USE_JNI=false;
475 				Shared.setThreads(threads);
476 			}
477 		}
478 		if(!Shared.USE_JNI){
479 			adjustThreadsforMemory(65);
480 		}
481 
482 		AbstractMapThread.CALC_STATISTICS=CALC_STATISTICS;
483 		AbstractMapThread[] mtts=new AbstractMapThread[Shared.threads()];
484 		for(int i=0; i<mtts.length; i++){
485 			try {
486 				mtts[i]=new BBMapThread(cris, keylen,
487 						pileup, SLOW_ALIGN, CORRECT_THRESH, minChrom,
488 						maxChrom, keyDensity, maxKeyDensity, minKeyDensity, maxDesiredKeys, REMOVE_DUPLICATE_BEST_ALIGNMENTS,
489 						SAVE_AMBIGUOUS_XY, MINIMUM_ALIGNMENT_SCORE_RATIO, TRIM_LIST, MAKE_MATCH_STRING, QUICK_MATCH_STRINGS, rosA, rosM, rosU, rosB,
490 						SLOW_ALIGN_PADDING, SLOW_RESCUE_PADDING, OUTPUT_MAPPED_ONLY, DONT_OUTPUT_BLACKLISTED_READS, MAX_SITESCORES_TO_PRINT, PRINT_SECONDARY_ALIGNMENTS,
491 						REQUIRE_CORRECT_STRANDS_PAIRS, SAME_STRAND_PAIRS, KILL_BAD_PAIRS, rcompMate,
492 						PERFECTMODE, SEMIPERFECTMODE, FORBID_SELF_MAPPING, TIP_SEARCH_DIST,
493 						ambiguousRandom, ambiguousAll, KFILTER, MIN_IDFILTER, qtrimLeft, qtrimRight, untrim, TRIM_QUALITY, minTrimLength,
494 						LOCAL_ALIGN, RESCUE, STRICT_MAX_INDEL, MSA_TYPE, bloomFilter);
495 			} catch (Throwable e) {
496 				e.printStackTrace();
497 				abort(mtts, "Aborting due to prior error when making thread "+i+".");
498 			}
499 			mtts[i].idmodulo=idmodulo;
500 			if(verbose){
501 				mtts[i].verbose=verbose;
502 				mtts[i].index().verbose=verbose;
503 			}
504 		}
505 
506 		cris.start(); //4567
507 		outstream.println("Processing reads in "+(paired ? "paired" : "single")+"-ended mode.");
508 		outstream.println("Started read stream.");
509 
510 		/* The threads are started after initialization to prevent resource competition between initialization and mapping */
511 		for(int i=0; i<mtts.length; i++){mtts[i].start();}
512 		outstream.println("Started "+mtts.length+" mapping thread"+(mtts.length==1 ? "" : "s")+".");
513 
514 		final int broken=shutDownThreads(mtts, false);
515 
516 		if(printStats){outstream.println("\n\n   ------------------   Results   ------------------   ");}
517 		closeStreams(cris, rosA, rosM, rosU, rosB);
518 		outstream.println();
519 		if(printSettings){printSettings(keylen);}
520 
521 		printOutput(mtts, t, keylen, paired, false, pileup, scafNzo, sortStats, statsOutputFile);
522 		if(broken>0 || errorState){throw new RuntimeException("BBMap terminated in an error state; the output may be corrupt.");}
523 	}
524 
525 	@Override
setSemiperfectMode()526 	void setSemiperfectMode() {
527 		assert(SEMIPERFECTMODE);
528 		if(SEMIPERFECTMODE){
529 			TRIM_LIST=false;
530 			keyDensity/=2;
531 			maxKeyDensity/=2;
532 			minKeyDensity=1.1f;
533 			maxDesiredKeys/=2;
534 			MINIMUM_ALIGNMENT_SCORE_RATIO=0.45f;
535 			BBIndex.setSemiperfectMode();
536 		}
537 	}
538 
539 	@Override
setPerfectMode()540 	void setPerfectMode() {
541 		assert(PERFECTMODE);
542 		if(PERFECTMODE){
543 			TRIM_LIST=false;
544 			keyDensity/=2;
545 			maxKeyDensity/=2;
546 			minKeyDensity=1.1f;
547 			maxDesiredKeys/=2;
548 			MINIMUM_ALIGNMENT_SCORE_RATIO=1.0f;
549 			BBIndex.setPerfectMode();
550 		}
551 	}
552 
553 
554 	@Override
printSettings(int k)555 	void printSettings(int k){
556 
557 		printSettings0(k, BBIndex.MAX_INDEL, MINIMUM_ALIGNMENT_SCORE_RATIO);
558 
559 		if(verbose_stats>=2){
560 			outstream.println("Key Density:          \t"+keyDensity+" ("+minKeyDensity+" ~ "+maxKeyDensity+")");
561 			outstream.println("Max keys:             \t"+maxDesiredKeys);
562 
563 			outstream.println("Block Subsections:     \t"+BBIndex.CHROMS_PER_BLOCK);
564 			outstream.println("Fraction To Remove:    \t"+String.format(Locale.ROOT, "%.4f", (BBIndex.REMOVE_FREQUENT_GENOME_FRACTION ? BBIndex.FRACTION_GENOME_TO_EXCLUDE : 0)));
565 			//		sysout.println("ADD_SCORE_Z:           \t"+Index4.ADD_SCORE_Z);
566 			outstream.println("Hits To Keep:          \t"+BBIndex.MIN_APPROX_HITS_TO_KEEP);
567 		}
568 
569 		if(verbose_stats>=3){
570 			outstream.println("Remove Clumpy:         \t"+BBIndex.REMOVE_CLUMPY);
571 			if(BBIndex.REMOVE_CLUMPY){
572 				outstream.println("CLUMPY_MAX_DIST:       \t"+BBIndex.CLUMPY_MAX_DIST);
573 				outstream.println("CLUMPY_MIN_LENGTH:     \t"+BBIndex.CLUMPY_MIN_LENGTH_INDEX);
574 				outstream.println("CLUMPY_FRACTION:       \t"+BBIndex.CLUMPY_FRACTION);
575 			}
576 			outstream.println("Remove Long Lists:     \t"+BBIndex.TRIM_LONG_HIT_LISTS);
577 			if(BBIndex.TRIM_LONG_HIT_LISTS){
578 				outstream.println("HIT_FRACTION_TO_RETAIN:\t"+BBIndex.HIT_FRACTION_TO_RETAIN);
579 			}
580 			outstream.println("Trim By Greedy:        \t"+BBIndex.TRIM_BY_GREEDY);
581 			outstream.println("Trim By Total Sites:   \t"+BBIndex.TRIM_BY_TOTAL_SITE_COUNT);
582 			if(BBIndex.TRIM_BY_TOTAL_SITE_COUNT){
583 				outstream.println("MAX_AVG_SITES:         \t"+BBIndex.MAX_AVERAGE_LIST_TO_SEARCH);
584 				outstream.println("MAX_AVG_SITES_2:       \t"+BBIndex.MAX_AVERAGE_LIST_TO_SEARCH2);
585 				outstream.println("MAX_SHORTEST_SITE:     \t"+BBIndex.MAX_SHORTEST_LIST_TO_SEARCH);
586 			}
587 			outstream.println("Index Min Score:       \t"+BBIndex.MIN_SCORE_MULT);
588 
589 			outstream.println("Dynamic Trim:          \t"+BBIndex.DYNAMICALLY_TRIM_LOW_SCORES);
590 			if(BBIndex.DYNAMICALLY_TRIM_LOW_SCORES){
591 				outstream.println("DYNAMIC_SCORE_THRESH:  \t"+BBIndex.DYNAMIC_SCORE_THRESH);
592 			}
593 		}
594 
595 	}
596 
597 }
598