jpayne@68: package sketch; jpayne@68: jpayne@68: import java.io.File; jpayne@68: import java.io.PrintStream; jpayne@68: import java.util.ArrayList; jpayne@68: import java.util.Arrays; jpayne@68: import java.util.Locale; jpayne@68: import java.util.Random; jpayne@68: jpayne@68: import dna.AminoAcid; jpayne@68: import fileIO.ByteFile; jpayne@68: import fileIO.FileFormat; jpayne@68: import fileIO.ReadWrite; jpayne@68: import shared.Parse; jpayne@68: import shared.Parser; jpayne@68: import shared.PreParser; jpayne@68: import shared.ReadStats; jpayne@68: import shared.Shared; jpayne@68: import shared.Timer; jpayne@68: import shared.Tools; jpayne@68: import stream.ConcurrentReadInputStream; jpayne@68: import stream.ConcurrentReadOutputStream; jpayne@68: import stream.FASTQ; jpayne@68: import stream.FastaReadInputStream; jpayne@68: import stream.Read; jpayne@68: import structures.IntMap; jpayne@68: import structures.ListNum; jpayne@68: jpayne@68: /** jpayne@68: * jpayne@68: * @author Brian Bushnell jpayne@68: * @date July 30, 2018 jpayne@68: * jpayne@68: */ jpayne@68: public class KmerLimit2 extends SketchObject { jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Initialization ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** jpayne@68: * Code entrance from the command line. jpayne@68: * @param args Command line arguments jpayne@68: */ jpayne@68: public static void main(String[] args){ jpayne@68: //Start a timer immediately upon code entrance. jpayne@68: Timer t=new Timer(); jpayne@68: jpayne@68: //Create an instance of this class jpayne@68: KmerLimit2 x=new KmerLimit2(args); jpayne@68: jpayne@68: //Run the object jpayne@68: x.process(t); jpayne@68: jpayne@68: //Close the print stream if it was redirected jpayne@68: Shared.closeStream(x.outstream); jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * Constructor. jpayne@68: * @param args Command line arguments jpayne@68: */ jpayne@68: public KmerLimit2(String[] args){ jpayne@68: jpayne@68: {//Preparse block for help, config files, and outstream jpayne@68: PreParser pp=new PreParser(args, getClass(), false); jpayne@68: args=pp.args; jpayne@68: outstream=pp.outstream; jpayne@68: } jpayne@68: jpayne@68: boolean setInterleaved=false; //Whether interleaved was explicitly set. jpayne@68: jpayne@68: //Set shared static variables jpayne@68: ReadWrite.USE_PIGZ=ReadWrite.USE_UNPIGZ=true; jpayne@68: ReadWrite.MAX_ZIP_THREADS=Shared.threads(); jpayne@68: SketchObject.setKeyFraction(0.1); jpayne@68: defaultParams.minEntropy=0; jpayne@68: defaultParams.minProb=0.2f; jpayne@68: jpayne@68: boolean setHeapSize=false; jpayne@68: int heapSize_=8091; jpayne@68: long targetKmers_=0; jpayne@68: int k_=32; jpayne@68: int minCount_=1; jpayne@68: jpayne@68: //Create a parser object jpayne@68: Parser parser=new Parser(); jpayne@68: parser.overwrite=true; jpayne@68: jpayne@68: //Parse each argument jpayne@68: for(int i=0; i1 ? split[1] : null; jpayne@68: if(b!=null && b.equalsIgnoreCase("null")){b=null;} jpayne@68: jpayne@68: if(a.equals("verbose")){ jpayne@68: verbose=Parse.parseBoolean(b); jpayne@68: }else if(a.equals("ordered")){ jpayne@68: ordered=Parse.parseBoolean(b); jpayne@68: }else if(a.equals("size") || a.equals("heapsize")){ jpayne@68: heapSize_=Parse.parseIntKMG(b); jpayne@68: setHeapSize=true; jpayne@68: }else if(a.equals("kmers") || a.equals("target") || a.equals("limit")){ jpayne@68: targetKmers_=Parse.parseKMG(b); jpayne@68: }else if(a.equals("mincount")){ jpayne@68: minCount_=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("maxexpandedlength") || a.equals("maxlength") || a.equals("maxlen")){ jpayne@68: maxExpandedLength=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("seed")){ jpayne@68: seed=Parse.parseKMG(b); jpayne@68: }else if(a.equals("trials")){ jpayne@68: trials=Parse.parseIntKMG(b); jpayne@68: }else if(parseSketchFlags(arg, a, b)){ jpayne@68: parser.parse(arg, a, b); jpayne@68: }else if(defaultParams.parse(arg, a, b)){ jpayne@68: parser.parse(arg, a, b); jpayne@68: }else if(a.equals("parse_flag_goes_here")){ jpayne@68: long fake_variable=Parse.parseKMG(b); jpayne@68: //Set a variable here jpayne@68: }else if(parser.parse(arg, a, b)){//Parse standard flags in the parser jpayne@68: //do nothing jpayne@68: }else{ jpayne@68: outstream.println("Unknown parameter "+args[i]); jpayne@68: assert(false) : "Unknown parameter "+args[i]; jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: if(!setHeapSize && minCount_>1){heapSize_=32000;} jpayne@68: heapSize=heapSize_; jpayne@68: targetKmers=targetKmers_; jpayne@68: k=k_; jpayne@68: minCount=minCount_; jpayne@68: assert(targetKmers>0) : "Must set a kmer limit."; jpayne@68: assert(heapSize>0) : "Heap size must be positive."; jpayne@68: assert(k>0 && k<=32) : "0-1){ jpayne@68: out2=out1.replace("#", "2"); jpayne@68: out1=out1.replace("#", "1"); jpayne@68: } jpayne@68: jpayne@68: //Adjust interleaved detection based on the number of input files jpayne@68: if(in2!=null){ jpayne@68: if(FASTQ.FORCE_INTERLEAVED){outstream.println("Reset INTERLEAVED to false because paired input files were specified.");} jpayne@68: FASTQ.FORCE_INTERLEAVED=FASTQ.TEST_INTERLEAVED=false; jpayne@68: } jpayne@68: jpayne@68: assert(FastaReadInputStream.settingsOK()); jpayne@68: jpayne@68: //Ensure there is an input file jpayne@68: if(in1==null){throw new RuntimeException("Error - at least one input file is required.");} jpayne@68: jpayne@68: //Adjust the number of threads for input file reading jpayne@68: if(!ByteFile.FORCE_MODE_BF1 && !ByteFile.FORCE_MODE_BF2 && Shared.threads()>2){ jpayne@68: ByteFile.FORCE_MODE_BF2=true; jpayne@68: } jpayne@68: jpayne@68: //Ensure out2 is not set without out1 jpayne@68: if(out1==null && out2!=null){throw new RuntimeException("Error - cannot define out2 without defining out1.");} jpayne@68: jpayne@68: //Adjust interleaved settings based on number of output files jpayne@68: if(!setInterleaved){ jpayne@68: assert(in1!=null && (out1!=null || out2==null)) : "\nin1="+in1+"\nin2="+in2+"\nout1="+out1+"\nout2="+out2+"\n"; jpayne@68: if(in2!=null){ //If there are 2 input streams. jpayne@68: FASTQ.FORCE_INTERLEAVED=FASTQ.TEST_INTERLEAVED=false; jpayne@68: outstream.println("Set INTERLEAVED to "+FASTQ.FORCE_INTERLEAVED); jpayne@68: }else{ //There is one input stream. jpayne@68: if(out2!=null){ jpayne@68: FASTQ.FORCE_INTERLEAVED=true; jpayne@68: FASTQ.TEST_INTERLEAVED=false; jpayne@68: outstream.println("Set INTERLEAVED to "+FASTQ.FORCE_INTERLEAVED); jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: //Ensure output files can be written jpayne@68: if(!Tools.testOutputFiles(overwrite, append, false, out1, out2)){ jpayne@68: outstream.println((out1==null)+", "+(out2==null)+", "+out1+", "+out2); jpayne@68: throw new RuntimeException("\n\noverwrite="+overwrite+"; Can't write to output files "+out1+", "+out2+"\n"); jpayne@68: } jpayne@68: jpayne@68: //Ensure input files can be read jpayne@68: if(!Tools.testInputFiles(false, true, in1, in2)){ jpayne@68: throw new RuntimeException("\nCan't read some input files.\n"); jpayne@68: } jpayne@68: jpayne@68: //Ensure that no file was specified multiple times jpayne@68: if(!Tools.testForDuplicateFiles(true, in1, in2, out1, out2)){ jpayne@68: throw new RuntimeException("\nSome file names were specified multiple times.\n"); jpayne@68: } jpayne@68: jpayne@68: //Create output FileFormat objects jpayne@68: ffout1=FileFormat.testOutput(out1, FileFormat.FASTQ, extout, true, overwrite, append, ordered); jpayne@68: ffout2=FileFormat.testOutput(out2, FileFormat.FASTQ, extout, true, overwrite, append, ordered); jpayne@68: jpayne@68: //Create input FileFormat objects jpayne@68: ffin1=FileFormat.testInput(in1, FileFormat.FASTQ, extin, true, true); jpayne@68: ffin2=FileFormat.testInput(in2, FileFormat.FASTQ, extin, true, true); jpayne@68: jpayne@68: minProb=defaultParams.minProb; jpayne@68: minQual=defaultParams.minQual; jpayne@68: jpayne@68: shift=2*k; jpayne@68: shift2=shift-2; jpayne@68: mask=(shift>63 ? -1L : ~((-1L)< args=new ArrayList(); jpayne@68: // args.add("in="+in1); jpayne@68: // if(in2!=null){args.add("in2="+in2);} jpayne@68: // args.add("out="+out1); jpayne@68: // if(out2!=null){args.add("out2="+out2);} jpayne@68: // args.add("ordered="+ordered); jpayne@68: // args.add("ow="+(overwrite ? "t" : "f")); jpayne@68: // if(targetRate<1){args.add("samplerate="+targetRateS);} jpayne@68: // args.add("loglogout"); jpayne@68: // args.add("loglogk="+k); jpayne@68: // args.add("loglogminprob="+minProb); jpayne@68: // BBDukF.main(args.toArray(new String[0])); jpayne@68: jpayne@68: // Sketch sk=new Sketch(sharedHeap, true, true, null); jpayne@68: // outstream.println(sk.genomeSizeEstimate()); jpayne@68: spawnThreads2(targetRate); jpayne@68: t.stop(); jpayne@68: outstream.println(Tools.timeReadsBasesProcessed(t, readsProcessed, basesProcessed, 8)); jpayne@68: jpayne@68: outstream.println(Tools.readsBasesOut(readsProcessed, basesProcessed, readsOut, basesOut, 8, false)); jpayne@68: String kstring=Tools.padKM(sharedHeap.genomeSizeEstimate(minCount), 8); jpayne@68: outstream.println("Unique Kmers Out: "+kstring); jpayne@68: jpayne@68: //Throw an exception of there was an error in a thread jpayne@68: if(errorState){ jpayne@68: throw new RuntimeException(getClass().getName()+" terminated in an error state; the output may be corrupt."); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: /** Spawn process threads */ jpayne@68: private void spawnThreads0(){ jpayne@68: jpayne@68: //Create a read input stream jpayne@68: final ConcurrentReadInputStream cris; jpayne@68: { jpayne@68: cris=ConcurrentReadInputStream.getReadInputStream(maxReads, true, ffin1, ffin2, qfin1, qfin2); jpayne@68: cris.start(); //Start the stream jpayne@68: if(verbose){outstream.println("Started cris");} jpayne@68: } jpayne@68: paired=cris.paired(); jpayne@68: if(!ffin1.samOrBam()){outstream.println("Input is being processed as "+(paired ? "paired" : "unpaired"));} jpayne@68: jpayne@68: //Determine how many threads may be used jpayne@68: final int threads=Tools.min(10, Shared.threads()); jpayne@68: jpayne@68: //Fill a list with ProcessThreads jpayne@68: ArrayList alpt=new ArrayList(threads); jpayne@68: for(int i=0; i alpt=new ArrayList(threads); jpayne@68: for(int i=0; imax){break;} jpayne@68: } jpayne@68: if(len>=sketch0.length()){return sketch0;} jpayne@68: jpayne@68: long[] keys=Arrays.copyOf(sketch0.keys, len); jpayne@68: int[] counts=Arrays.copyOf(sketch0.keyCounts, len); jpayne@68: jpayne@68: // long[] array_, int[] counts_, int taxID_, long imgID_, long gSizeBases_, long gSizeKmers_, long gSequences_, double probCorrect_, jpayne@68: // String taxName_, String name0_, String fname_, ArrayList meta_ jpayne@68: jpayne@68: Sketch sk=new Sketch(keys, counts, null, null, null, -1, -1, jpayne@68: sketch0.genomeSizeBases, sketch0.genomeSizeKmers, sketch0.genomeSequences, sketch0.probCorrect, jpayne@68: null, null, null, null); jpayne@68: jpayne@68: return sk; jpayne@68: } jpayne@68: jpayne@68: public static long calcTargetReads(Sketch sketch, long targetKmers, int minCount, int trials, long seed){ jpayne@68: final int[] counts0=sketch.keyCounts; jpayne@68: final int[] counts=Arrays.copyOf(counts0, counts0.length); jpayne@68: final long size=sketch.genomeSizeEstimate(minCount); jpayne@68: final long reads=sketch.genomeSequences; jpayne@68: final double targetKmerFraction=targetKmers/(double)size; jpayne@68: if(targetKmerFraction>=1){return reads;} jpayne@68: jpayne@68: final int targetKeys=(int)(targetKmerFraction*counts.length); jpayne@68: final long countSum=Tools.sum(counts0); jpayne@68: assert(countSum=0) : minCount; jpayne@68: // int rounds=0; jpayne@68: // int valid=0; jpayne@68: // for(int x : counts){ jpayne@68: // if(x>=minCount){valid++;} jpayne@68: // } jpayne@68: // jpayne@68: // int len=counts.length; jpayne@68: // System.err.println(targetKeys+", "+counts.length+", "+valid+", "+len+", "+rounds+", "+Tools.sum(counts)+", "+Arrays.toString(counts)); jpayne@68: // for(; valid>targetKeys; rounds++){ jpayne@68: // int pos=randy.nextInt(len); jpayne@68: //// assert(counts[pos]>0) : pos+"/"+len+": "+targetKeys+", "+counts.length+", "+valid+", "+len+", "+rounds+", "+Arrays.toString(counts); jpayne@68: // if(counts[pos]==minCount){valid--;} jpayne@68: // counts[pos]--; jpayne@68: // if(counts[pos]==0){ jpayne@68: // len--;//shrink the array jpayne@68: // System.err.println("len="+len+", counts[len]="+counts[len]); jpayne@68: // System.err.println("pos="+pos+", counts[pos]="+counts[pos]); jpayne@68: // counts[pos]=counts[len];//move the last element to the empty slot jpayne@68: // counts[len]=0; jpayne@68: // if(pos!=len && len>0){ jpayne@68: // assert(counts[pos]>0) : pos+"/"+len+": "+targetKeys+", "+counts.length+", "+valid+", "+len+", "+rounds+", "+Arrays.toString(counts); jpayne@68: // } jpayne@68: // } jpayne@68: // System.err.println(len+", "+pos+": "+Arrays.toString(counts)); jpayne@68: // } jpayne@68: // jpayne@68: // System.err.println(targetKeys+", "+counts.length+", "+valid+", "+len+", "+rounds+", "+Tools.sum(counts)); jpayne@68: // jpayne@68: // return rounds; jpayne@68: // } jpayne@68: jpayne@68: //This can be done faster with bins. jpayne@68: //Each bin contains all kmers with count x. When a bin is hit, one kmer moves to the next bin lower. jpayne@68: //Alternately, expand the array into one physical kmer per count. Store the current counts in an IntMap. Remove key each time. jpayne@68: public static long reduceRounds(final int[] counts0, final int[] counts, final int minCount, final int targetKeys, final Random randy){ jpayne@68: assert(minCount>=0) : minCount; jpayne@68: long rounds=0; jpayne@68: int valid=0; jpayne@68: for(int x : counts){ jpayne@68: if(x>=minCount){valid++;} jpayne@68: } jpayne@68: jpayne@68: int len=counts.length; jpayne@68: final long sum0=Tools.sum(counts); jpayne@68: long sum=sum0; jpayne@68: // System.err.println(targetKeys+", "+counts.length+", "+valid+", "+len+", "+rounds+", "+Tools.sum(counts)+", "+Arrays.toString(counts)); jpayne@68: for(; valid>targetKeys; rounds++){ jpayne@68: long posNum=(Long.MAX_VALUE&randy.nextLong())%sum; jpayne@68: long sum2=0; jpayne@68: int pos=0; jpayne@68: jpayne@68: for(int i=0; i0){ jpayne@68: sum2+=x; jpayne@68: if(sum2>=posNum){ jpayne@68: pos=i; jpayne@68: break; jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: // for(int i=0; i0){ jpayne@68: // sum2+=x; jpayne@68: // if(sum2>=posNum){ jpayne@68: // pos=i; jpayne@68: // break; jpayne@68: // } jpayne@68: // } jpayne@68: // } jpayne@68: jpayne@68: sum--; jpayne@68: jpayne@68: assert(counts[pos]>0) : pos+"/"+len+": "+targetKeys+", "+counts.length+", "+valid+", "+len+", "+rounds+", "+Arrays.toString(counts); jpayne@68: if(counts[pos]==minCount){valid--;} jpayne@68: counts[pos]--; jpayne@68: if(counts[pos]==0){ jpayne@68: len--;//shrink the array jpayne@68: } jpayne@68: // System.err.println(len+", "+pos+": "+Arrays.toString(counts)); jpayne@68: } jpayne@68: jpayne@68: // System.err.println(targetKeys+", "+counts.length+", "+valid+", "+len+", "+rounds+", "+Tools.sum(counts)); jpayne@68: jpayne@68: return rounds; jpayne@68: } jpayne@68: jpayne@68: //This can be done faster with bins. jpayne@68: //Each bin contains all kmers with count x. When a bin is hit, one kmer moves to the next bin lower. jpayne@68: //Alternately, expand the array into one physical kmer per count. Store the current counts in an IntMap. Remove key each time. jpayne@68: public static long reduceRoundsIM(final int[] counts0, final int[] expanded, final int minCount, final int targetKeys, final Random randy, final IntMap map){ jpayne@68: assert(minCount>=0) : minCount; jpayne@68: long rounds=0; jpayne@68: int valid=0; jpayne@68: map.clear(); jpayne@68: for(int i=0, k=0; i=minCount){valid++;} jpayne@68: map.put(i, x); jpayne@68: for(int j=0; jtargetKeys; rounds++){ jpayne@68: final int pos=randy.nextInt(len); jpayne@68: final int key=expanded[pos]; jpayne@68: final int x=map.get(key); jpayne@68: assert(x>0); jpayne@68: jpayne@68: jpayne@68: if(x==minCount){valid--;} jpayne@68: map.put(key, x-1); jpayne@68: jpayne@68: len--;//shrink the array jpayne@68: // System.err.println("len="+len+", counts[len]="+counts[len]); jpayne@68: // System.err.println("pos="+pos+", counts[pos]="+counts[pos]); jpayne@68: expanded[pos]=expanded[len];//move the last element to the empty slot jpayne@68: expanded[len]=0; jpayne@68: jpayne@68: // System.err.println(len+", "+pos+": "+Arrays.toString(counts)); jpayne@68: } jpayne@68: jpayne@68: // System.err.println(targetKeys+", "+counts.length+", "+valid+", "+len+", "+rounds+", "+Tools.sum(counts)); jpayne@68: jpayne@68: return rounds; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Inner Classes ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** This class is static to prevent accidental writing to shared variables. jpayne@68: * It is safe to remove the static modifier. */ jpayne@68: private class ProcessThread extends Thread { jpayne@68: jpayne@68: //Constructor jpayne@68: ProcessThread(final ConcurrentReadInputStream cris_, final ConcurrentReadOutputStream ros_, final int tid_, final int size){ jpayne@68: cris=cris_; jpayne@68: ros=ros_; jpayne@68: tid=tid_; jpayne@68: localHeap=new SketchHeap(size, 0, true); jpayne@68: } jpayne@68: jpayne@68: //Called by start() jpayne@68: @Override jpayne@68: public void run(){ jpayne@68: //Do anything necessary prior to processing jpayne@68: jpayne@68: //Process the reads jpayne@68: processInner(); jpayne@68: jpayne@68: //Do anything necessary after processing jpayne@68: dumpHeap(); jpayne@68: jpayne@68: //Indicate successful exit status jpayne@68: success=true; jpayne@68: } jpayne@68: jpayne@68: /** Iterate through the reads */ jpayne@68: void processInner(){ jpayne@68: jpayne@68: //Grab the first ListNum of reads jpayne@68: ListNum ln=cris.nextList(); jpayne@68: //Grab the actual read list from the ListNum jpayne@68: ArrayList reads=(ln!=null ? ln.list : null); jpayne@68: jpayne@68: //Check to ensure pairing is as expected jpayne@68: if(reads!=null && !reads.isEmpty()){ jpayne@68: Read r=reads.get(0); jpayne@68: // assert(ffin1.samOrBam() || (r.mate!=null)==cris.paired()); //Disabled due to non-static access jpayne@68: } jpayne@68: jpayne@68: //As long as there is a nonempty read list... jpayne@68: while(ln!=null && reads!=null && reads.size()>0){//ln!=null prevents a compiler potential null access warning jpayne@68: // if(verbose){outstream.println("Fetched "+reads.size()+" reads.");} //Disabled due to non-static access jpayne@68: jpayne@68: //Loop through each read in the list jpayne@68: for(int idx=0; idx>>2)|(x2<=k){ jpayne@68: localHeap.genomeSizeKmers++; jpayne@68: final long hashcode=hash(kmer, rkmer); jpayne@68: if(hashcode>min){localHeap.add(hashcode);} jpayne@68: } jpayne@68: } jpayne@68: }else{ jpayne@68: float prob=1; jpayne@68: for(int i=0; i=0) : Arrays.toString(quals)+"\n"+minProb+", "+minQual; jpayne@68: prob=prob*align2.QualityTools.PROB_CORRECT[q]; jpayne@68: if(len>k){ jpayne@68: byte oldq=quals[i-k]; jpayne@68: prob=prob*align2.QualityTools.PROB_CORRECT_INVERSE[oldq]; jpayne@68: } jpayne@68: if(x<0 || q>>2)|(x2<=k && prob>=minProb){ jpayne@68: localHeap.genomeSizeKmers++; jpayne@68: localHeap.probSum+=prob; jpayne@68: final long hashcode=hash(kmer, rkmer); jpayne@68: if(hashcode>min){localHeap.checkAndAdd(hashcode);} jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: private void dumpHeap(){ jpayne@68: synchronized(sharedHeap){ jpayne@68: sharedHeap.add(localHeap); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: /** Number of reads processed by this thread */ jpayne@68: protected long readsProcessedT=0; jpayne@68: /** Number of bases processed by this thread */ jpayne@68: protected long basesProcessedT=0; jpayne@68: jpayne@68: /** Number of reads retained by this thread */ jpayne@68: protected long readsOutT=0; jpayne@68: /** Number of bases retained by this thread */ jpayne@68: protected long basesOutT=0; jpayne@68: jpayne@68: /** True only if this thread has completed successfully */ jpayne@68: boolean success=false; jpayne@68: jpayne@68: /** Shared input stream */ jpayne@68: private final ConcurrentReadInputStream cris; jpayne@68: /** Shared output stream */ jpayne@68: private final ConcurrentReadOutputStream ros; jpayne@68: /** Thread ID */ jpayne@68: final int tid; jpayne@68: jpayne@68: final SketchHeap localHeap; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Fields ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Primary input file path */ jpayne@68: private String in1=null; jpayne@68: /** Secondary input file path */ jpayne@68: private String in2=null; jpayne@68: jpayne@68: private String qfin1=null; jpayne@68: private String qfin2=null; jpayne@68: jpayne@68: /** Primary output file path */ jpayne@68: private String out1=null; jpayne@68: /** Secondary output file path */ jpayne@68: private String out2=null; jpayne@68: jpayne@68: private String qfout1=null; jpayne@68: private String qfout2=null; jpayne@68: jpayne@68: /** Override input file extension */ jpayne@68: private String extin=null; jpayne@68: /** Override output file extension */ jpayne@68: private String extout=null; jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Number of reads processed */ jpayne@68: protected long readsProcessed=0; jpayne@68: /** Number of bases processed */ jpayne@68: protected long basesProcessed=0; jpayne@68: jpayne@68: /** Number of reads retained */ jpayne@68: protected long readsOut=0; jpayne@68: /** Number of bases retained */ jpayne@68: protected long basesOut=0; jpayne@68: jpayne@68: /** Quit after processing this many input reads; -1 means no limit */ jpayne@68: private long maxReads=-1; jpayne@68: jpayne@68: private boolean paired=false; jpayne@68: private int trials=25; jpayne@68: private long seed=-1; jpayne@68: private int maxExpandedLength=50000000; jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Final Fields ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Primary input file */ jpayne@68: private final FileFormat ffin1; jpayne@68: /** Secondary input file */ jpayne@68: private final FileFormat ffin2; jpayne@68: jpayne@68: /** Primary output file */ jpayne@68: private final FileFormat ffout1; jpayne@68: /** Secondary output file */ jpayne@68: private final FileFormat ffout2; jpayne@68: jpayne@68: private final SketchHeap sharedHeap; jpayne@68: private final int heapSize; jpayne@68: private final long targetKmers; jpayne@68: private final int minCount; jpayne@68: jpayne@68: final int shift; jpayne@68: final int shift2; jpayne@68: final long mask; jpayne@68: jpayne@68: final float minProb; jpayne@68: final byte minQual; jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Common Fields ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Print status messages to this output stream */ jpayne@68: private PrintStream outstream=System.err; jpayne@68: /** Print verbose messages */ jpayne@68: public static boolean verbose=false; jpayne@68: /** True if an error was encountered */ jpayne@68: public boolean errorState=false; jpayne@68: /** Overwrite existing output files */ jpayne@68: private boolean overwrite=true; jpayne@68: /** Append to existing output files */ jpayne@68: private boolean append=false; jpayne@68: /** Reads are output in input order (not enabled) */ jpayne@68: private boolean ordered=true; jpayne@68: jpayne@68: }