jpayne@68: package icecream; jpayne@68: jpayne@68: import java.io.PrintStream; jpayne@68: import java.util.ArrayList; jpayne@68: import java.util.Arrays; jpayne@68: import java.util.Random; jpayne@68: import java.util.concurrent.atomic.AtomicLong; jpayne@68: jpayne@68: import dna.AminoAcid; jpayne@68: import fileIO.ByteFile; jpayne@68: import fileIO.ByteStreamWriter; 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 stream.SamLine; jpayne@68: import structures.ByteBuilder; jpayne@68: import structures.IntList; jpayne@68: import structures.ListNum; jpayne@68: jpayne@68: /** jpayne@68: * Generates chimeric PacBio reads containing inverted repeats jpayne@68: * due to missing adapters. jpayne@68: * jpayne@68: * @author Brian Bushnell jpayne@68: * @date June 8, 2019 jpayne@68: * jpayne@68: */ jpayne@68: public class IceCreamMaker { 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: IceCreamMaker x=new IceCreamMaker(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 IceCreamMaker(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: //Set shared static variables prior to parsing jpayne@68: ReadWrite.USE_PIGZ=ReadWrite.USE_UNPIGZ=true; jpayne@68: ReadWrite.MAX_ZIP_THREADS=Shared.threads(); jpayne@68: FASTQ.TEST_INTERLEAVED=FASTQ.FORCE_INTERLEAVED=false; jpayne@68: Shared.FAKE_QUAL=8; jpayne@68: // Shared.FASTA_WRAP=511; jpayne@68: SamLine.SET_FROM_OK=true; jpayne@68: jpayne@68: {//Parse the arguments jpayne@68: final Parser parser=parse(args); jpayne@68: Parser.processQuality(); jpayne@68: jpayne@68: maxReads=parser.maxReads; jpayne@68: overwrite=ReadStats.overwrite=parser.overwrite; jpayne@68: append=ReadStats.append=parser.append; jpayne@68: jpayne@68: in1=parser.in1; jpayne@68: extin=parser.extin; jpayne@68: jpayne@68: out1=parser.out1; jpayne@68: qfout1=parser.qfout1; jpayne@68: extout=parser.extout; jpayne@68: } jpayne@68: jpayne@68: validateParams(); jpayne@68: fixExtensions(); //Add or remove .gz or .bz2 as needed jpayne@68: checkFileExistence(); //Ensure files can be read and written jpayne@68: checkStatics(); //Adjust file-related static fields as needed for this program jpayne@68: jpayne@68: //Create output FileFormat objects jpayne@68: ffout1=FileFormat.testOutput(out1, FileFormat.FASTQ, extout, true, overwrite, append, false); jpayne@68: jpayne@68: //Create input FileFormat objects jpayne@68: ffin1=FileFormat.testInput(in1, FileFormat.FASTQ, extin, true, true); jpayne@68: jpayne@68: ffIdHist=FileFormat.testOutput(outIdHist, FileFormat.TXT, null, false, overwrite, append, false); jpayne@68: jpayne@68: insThresh=insFraction; jpayne@68: delThresh=delFraction+insThresh; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Initialization Helpers ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Parse arguments from the command line */ jpayne@68: private Parser parse(String[] args){ jpayne@68: jpayne@68: //Create a parser object jpayne@68: Parser parser=new Parser(); jpayne@68: jpayne@68: //Set any necessary Parser defaults here jpayne@68: //parser.foo=bar; 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: } jpayne@68: jpayne@68: else if(a.equals("idhist")){ jpayne@68: outIdHist=b; jpayne@68: } jpayne@68: jpayne@68: else if(a.equals("minlength") || a.equals("minlen")){ jpayne@68: minMoleculeLength=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("maxlength") || a.equals("maxlen")){ jpayne@68: maxMoleculeLength=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("length") || a.equals("len")){ jpayne@68: minMoleculeLength=maxMoleculeLength=Parse.parseIntKMG(b); jpayne@68: } jpayne@68: jpayne@68: else if(a.equals("minmovie") || a.equals("minmov")){ jpayne@68: minMovie=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("maxmovie") || a.equals("maxmov")){ jpayne@68: maxMovie=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("movie") || a.equals("mov")){ jpayne@68: minMovie=maxMovie=Parse.parseIntKMG(b); jpayne@68: } jpayne@68: jpayne@68: else if(a.equals("missingrate") || a.equals("missing")){ jpayne@68: missingRate=Double.parseDouble(b); jpayne@68: assert(missingRate<=1); jpayne@68: }else if(a.equals("hiddenrate") || a.equals("hidden")){ jpayne@68: hiddenRate=Double.parseDouble(b); jpayne@68: assert(hiddenRate<=1); jpayne@68: }else if(a.equals("bothends")){ jpayne@68: allowBothEndsBad=Parse.parseBoolean(b); jpayne@68: assert(false) : "TODO"; jpayne@68: } jpayne@68: jpayne@68: else if(a.equals("gc")){ jpayne@68: genomeGC=(float)Double.parseDouble(b); jpayne@68: assert(genomeGC>=0 && genomeGC<=1); jpayne@68: }else if(a.equals("genomesize")){ jpayne@68: genomeSize=Parse.parseKMG(b); jpayne@68: }else if(a.equals("addns") || a.equals("ns")){ jpayne@68: addNs=Parse.parseBoolean(b); jpayne@68: }else if(a.equals("seed")){ jpayne@68: seed=Long.parseLong(b); jpayne@68: }else if(a.equals("zmws") || a.equals("maxzmws") || a.equals("reads")){ jpayne@68: maxZMWs=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("ccs")){ jpayne@68: makeCCS=Parse.parseBoolean(b); jpayne@68: } jpayne@68: jpayne@68: else if(a.equals("invertedrepeatrate") || a.equals("invertrepeatrate") || a.equals("irrate")){ jpayne@68: invertedRepeatRate=Double.parseDouble(b); jpayne@68: assert(invertedRepeatRate>=0); jpayne@68: }else if(a.equals("invertedrepeatminlen") || a.equals("invertrepeatminlen") || a.equals("irminlen")){ jpayne@68: invertedRepeatMinLength=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("invertedrepeatmaxlen") || a.equals("invertrepeatmaxlen") || a.equals("irmaxlen")){ jpayne@68: invertedRepeatMaxLength=Parse.parseIntKMG(b); jpayne@68: }else if(a.equals("invertedrepeatlen") || a.equals("invertrepeatlen") || a.equals("irlen")){ jpayne@68: invertedRepeatMinLength=invertedRepeatMaxLength=Parse.parseIntKMG(b); jpayne@68: } jpayne@68: jpayne@68: else if(a.equals("miner") || a.equals("minerrorrate")){ jpayne@68: minErrorRate=(float)Double.parseDouble(b); jpayne@68: assert(minErrorRate>=0 && minErrorRate<=1); jpayne@68: }else if(a.equals("maxer") || a.equals("maxerrorrate")){ jpayne@68: maxErrorRate=(float)Double.parseDouble(b); jpayne@68: assert(maxErrorRate>=0 && maxErrorRate<=1); jpayne@68: }else if(a.equals("er") || a.equals("errorrate")){ jpayne@68: minErrorRate=maxErrorRate=(float)Double.parseDouble(b); jpayne@68: assert(minErrorRate>=0 && minErrorRate<=1); jpayne@68: } jpayne@68: jpayne@68: else if(a.equals("minid") || a.equals("minidentity")){ jpayne@68: maxErrorRate=1-(float)Double.parseDouble(b); jpayne@68: assert(maxErrorRate>=0 && maxErrorRate<=1); jpayne@68: }else if(a.equals("maxid") || a.equals("maxidentity")){ jpayne@68: minErrorRate=1-(float)Double.parseDouble(b); jpayne@68: assert(minErrorRate>=0 && minErrorRate<=1); jpayne@68: }else if(a.equals("id") || a.equals("identity")){ jpayne@68: minErrorRate=maxErrorRate=1-(float)Double.parseDouble(b); jpayne@68: assert(minErrorRate>=0 && minErrorRate<=1); jpayne@68: }else if(a.equals("adderrors")){ jpayne@68: addErrors=Parse.parseBoolean(b); jpayne@68: }else if(a.equals("ref")){ jpayne@68: parser.in1=b; jpayne@68: } jpayne@68: 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: return parser; jpayne@68: } jpayne@68: jpayne@68: /** Add or remove .gz or .bz2 as needed */ jpayne@68: private void fixExtensions(){ jpayne@68: in1=Tools.fixExtension(in1); jpayne@68: } jpayne@68: jpayne@68: /** Ensure files can be read and written */ jpayne@68: private void checkFileExistence(){ jpayne@68: //Ensure output files can be written jpayne@68: if(!Tools.testOutputFiles(overwrite, append, false, out1, outIdHist)){ jpayne@68: throw new RuntimeException("\n\noverwrite="+overwrite+"; Can't write to output file "+out1+"\n"); jpayne@68: } jpayne@68: jpayne@68: //Ensure input files can be read jpayne@68: if(!Tools.testInputFiles(false, true, in1)){ 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, out1, outIdHist)){ jpayne@68: throw new RuntimeException("\nSome file names were specified multiple times.\n"); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: /** Adjust file-related static fields as needed for this program */ jpayne@68: private static void checkStatics(){ 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: assert(FastaReadInputStream.settingsOK()); jpayne@68: } jpayne@68: jpayne@68: /** Ensure parameter ranges are within bounds and required parameters are set */ jpayne@68: private boolean validateParams(){ jpayne@68: assert(minMoleculeLength>0 && minMoleculeLength<=maxMoleculeLength) : minMoleculeLength+", "+maxMoleculeLength; jpayne@68: assert(minMovie>0 && minMovie<=maxMovie) : minMovie+", "+maxMovie; jpayne@68: jpayne@68: assert(missingRate>=0 && missingRate<=1) : missingRate; jpayne@68: assert(hiddenRate>=0 && hiddenRate<=1) : hiddenRate; jpayne@68: assert(genomeGC>=0 && genomeGC<=1) : genomeGC; jpayne@68: assert(in1!=null || genomeSize>maxMoleculeLength) : genomeSize; jpayne@68: assert(in1!=null || invertedRepeatMaxLength*20) : "zmsw="+maxZMWs+"; please set to a positive number."; jpayne@68: jpayne@68: assert(invertedRepeatRate>=0) : invertedRepeatRate; jpayne@68: assert(invertedRepeatMinLength>0 && invertedRepeatMinLength<=invertedRepeatMaxLength) : invertedRepeatMinLength+", "+invertedRepeatMaxLength; jpayne@68: jpayne@68: assert(minErrorRate>=0 && minErrorRate<=maxErrorRate) : minErrorRate+", "+maxErrorRate; jpayne@68: return true; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Outer Methods ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Create read streams and process all data */ jpayne@68: void process(Timer t){ jpayne@68: jpayne@68: //Turn off read validation in the input threads to increase speed jpayne@68: final boolean vic=Read.VALIDATE_IN_CONSTRUCTOR; jpayne@68: Read.VALIDATE_IN_CONSTRUCTOR=true; jpayne@68: jpayne@68: //Create a read input stream jpayne@68: final ConcurrentReadInputStream cris=makeCris(); jpayne@68: jpayne@68: //Optionally create a read output stream jpayne@68: final ConcurrentReadOutputStream ros=makeCros(false); jpayne@68: jpayne@68: //Reset counters jpayne@68: readsProcessed=readsOut=0; jpayne@68: basesProcessed=basesOut=0; jpayne@68: jpayne@68: Random randy=Shared.threadLocalRandom(seed); jpayne@68: if(cris==null){ jpayne@68: ref=genSynthGenome(randy); jpayne@68: }else{ jpayne@68: ref=loadData(cris, randy); jpayne@68: } jpayne@68: jpayne@68: if(invertedRepeatRate>0){ jpayne@68: addInvertedRepeats(ref, randy); jpayne@68: } jpayne@68: jpayne@68: //Process the reads in separate threads jpayne@68: spawnThreads(cris, ros); jpayne@68: jpayne@68: if(verbose){outstream.println("Finished; closing streams.");} jpayne@68: jpayne@68: //Write anything that was accumulated by ReadStats jpayne@68: errorState|=ReadStats.writeAll(); jpayne@68: //Close the read streams jpayne@68: errorState|=ReadWrite.closeStreams(cris, ros); jpayne@68: jpayne@68: writeIdHist(); jpayne@68: jpayne@68: //Reset read validation jpayne@68: Read.VALIDATE_IN_CONSTRUCTOR=vic; jpayne@68: jpayne@68: //Report timing and results jpayne@68: t.stop(); jpayne@68: outstream.println(Tools.timeReadsBasesProcessed(t, readsOut, basesOut, 8)); jpayne@68: // outstream.println(Tools.readsBasesOut(readsProcessed, basesProcessed, readsOut, basesOut, 8, false)); 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: private void writeIdHist(){ jpayne@68: if(ffIdHist==null){return;} jpayne@68: ByteStreamWriter bsw=new ByteStreamWriter(ffIdHist); jpayne@68: bsw.start(); jpayne@68: bsw.print("#Identity\tCount\n".getBytes()); jpayne@68: for(int i=0; i alpt=new ArrayList(threads); jpayne@68: for(int i=0; i alpt){ jpayne@68: jpayne@68: //Wait for completion of all threads jpayne@68: boolean success=true; jpayne@68: for(ProcessThread pt : alpt){ jpayne@68: jpayne@68: //Wait until this thread has terminated jpayne@68: while(pt.getState()!=Thread.State.TERMINATED){ jpayne@68: try { jpayne@68: //Attempt a join operation jpayne@68: pt.join(); jpayne@68: } catch (InterruptedException e) { jpayne@68: //Potentially handle this, if it is expected to occur jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: //Accumulate per-thread statistics jpayne@68: readsOut+=pt.readsOutT; jpayne@68: basesOut+=pt.basesOutT; jpayne@68: Tools.add(idHist, pt.idHistT); jpayne@68: jpayne@68: success&=pt.success; jpayne@68: } jpayne@68: jpayne@68: //Track whether any threads failed jpayne@68: if(!success){errorState=true;} jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Inner Methods ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: private byte randomBase(Random randy) { jpayne@68: float rGC=randy.nextFloat(); jpayne@68: if(rGC>=genomeGC){//AT jpayne@68: return (byte)(randy.nextBoolean() ? 'A' : 'T'); jpayne@68: }else{//GC jpayne@68: return (byte)(randy.nextBoolean() ? 'G' : 'C'); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: private static int randomLength(int min, int max, Random randy) { jpayne@68: if(min==max){return min;} jpayne@68: int range=max-min+1; jpayne@68: int x=min+Tools.min(randy.nextInt(range), randy.nextInt(range)); jpayne@68: // System.err.println(x+", "+min+", "+max); jpayne@68: // new Exception().printStackTrace(); jpayne@68: // System.err.println(randy.getClass()); jpayne@68: // System.err.println(randy.nextLong()); jpayne@68: return x; jpayne@68: } jpayne@68: jpayne@68: private static float randomRate(float min, float max, Random randy) { jpayne@68: if(min==max){return min;} jpayne@68: float range=max-min; jpayne@68: // float a=(randy.nextFloat()+randy.nextFloat()); jpayne@68: float b=(randy.nextFloat()+randy.nextFloat()); jpayne@68: float c=(1.6f*randy.nextFloat()+0.4f*randy.nextFloat()); jpayne@68: float x=min+range*0.5f*Tools.min(b, c); jpayne@68: // assert(false) : "x="+x+", a="+a+", b="+b+", c="+c+", min="+min+", max="+max; jpayne@68: // System.err.println(x+", "+min+", "+max); jpayne@68: return x; jpayne@68: } jpayne@68: jpayne@68: private byte[] genSynthGenome(Random randy){ jpayne@68: assert(genomeSize<=MAX_GENOME_LENGTH) : genomeSize; jpayne@68: byte[] array=new byte[(int)genomeSize]; jpayne@68: for(int i=0; i ln=cris.nextList(); jpayne@68: jpayne@68: //As long as there is a nonempty read list... jpayne@68: while(ln!=null && ln.size()>0){ jpayne@68: // if(verbose){outstream.println("Fetched "+reads.size()+" reads.");} //Disabled due to non-static access jpayne@68: jpayne@68: for(Read r : ln){ jpayne@68: jpayne@68: // System.err.println("Fetched read len="+r.length());//123 jpayne@68: jpayne@68: //Increment counters jpayne@68: readsProcessed+=r.pairCount(); jpayne@68: basesProcessed+=r.pairLength(); jpayne@68: jpayne@68: jpayne@68: jpayne@68: // System.err.println("Filter: addNs="+addNs+", (r.length()>maxMoleculeLength && (invertedRepeatRate<=0 || r.length()>2*invertedRepeatMaxLength);//123 jpayne@68: jpayne@68: //Filter disabled; it causes short sequences to be ignored. jpayne@68: //Optional filter criteria jpayne@68: // if(!addNs || (r.length()>maxMoleculeLength && (invertedRepeatRate<=0 || r.length()>2*invertedRepeatMaxLength))){ jpayne@68: final byte[] bases=r.bases; jpayne@68: jpayne@68: if(addNs){ jpayne@68: if(bb.length()>0){bb.append('N');} jpayne@68: }else{ jpayne@68: for(int i=0; i=MAX_GENOME_LENGTH){ jpayne@68: cris.returnList(ln.id, true); jpayne@68: // System.err.println("Returning partial "+bb.length);//123 jpayne@68: return bb.toBytes(); jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: // } jpayne@68: } jpayne@68: jpayne@68: //Notify the input stream that the list was used jpayne@68: cris.returnList(ln); jpayne@68: // if(verbose){outstream.println("Returned a list.");} //Disabled due to non-static access jpayne@68: jpayne@68: //Fetch a new list jpayne@68: ln=cris.nextList(); jpayne@68: } jpayne@68: jpayne@68: //Notify the input stream that the final list was used jpayne@68: if(ln!=null){ jpayne@68: cris.returnList(ln.id, ln.list==null || ln.list.isEmpty()); jpayne@68: } jpayne@68: jpayne@68: // System.err.println("Returning full "+bb.length);//123 jpayne@68: return bb.toBytes(); jpayne@68: } jpayne@68: jpayne@68: private void addInvertedRepeats(byte[] bases, Random randy){ jpayne@68: jpayne@68: long added=0; jpayne@68: long toAdd=(long) (bases.length*invertedRepeatRate); jpayne@68: while(added reads=generateList((int)toGenerate, generated); jpayne@68: jpayne@68: //Output reads to the output stream jpayne@68: if(ros!=null){ros.add(reads, 0);} jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: /** Generate the next list of reads */ jpayne@68: private ArrayList generateList(int toGenerate, long nextID){ jpayne@68: jpayne@68: //Grab the actual read list from the ListNum jpayne@68: final ArrayList reads=new ArrayList(toGenerate); jpayne@68: jpayne@68: //Loop through each read in the list jpayne@68: for(int i=0; i zmw=generateZMW(nextID); jpayne@68: if(zmw==null){ jpayne@68: i--; jpayne@68: nextID--; jpayne@68: }else{reads.addAll(zmw);} jpayne@68: } jpayne@68: jpayne@68: return reads; jpayne@68: } jpayne@68: jpayne@68: private ReadBuilder median(ArrayList list){ jpayne@68: if(list.size()<3){return null;} jpayne@68: IntList lengths=new IntList(list.size()-2); jpayne@68: jpayne@68: for(int i=1; i generateZMW(final long nextID){ jpayne@68: jpayne@68: final int movieLength=randomLength(minMovie, maxMovie, randy); jpayne@68: final float errorRate=randomRate(minErrorRate, maxErrorRate, randy); jpayne@68: jpayne@68: ArrayList baseCalls=baseCallAllPasses(movieLength, errorRate, nextID); jpayne@68: if(baseCalls==null){ jpayne@68: // System.err.println(movieLength+", "+errorRate+", "+nextID);//123 jpayne@68: return null; jpayne@68: } jpayne@68: jpayne@68: final boolean missing=randy.nextFloat() temp=new ArrayList(); jpayne@68: jpayne@68: ReadBuilder current=null; jpayne@68: for(int i=0; i1); jpayne@68: assert(current.missing>0); jpayne@68: temp.add(current); jpayne@68: current=null; jpayne@68: }else{ jpayne@68: if(current!=null){temp.add(current);} jpayne@68: current=rb; jpayne@68: } jpayne@68: } jpayne@68: if(current!=null){temp.add(current);} jpayne@68: baseCalls=temp; jpayne@68: } jpayne@68: jpayne@68: if(makeCCS){ jpayne@68: ReadBuilder median=median(baseCalls); jpayne@68: if(median==null){return null;} jpayne@68: baseCalls.clear(); jpayne@68: baseCalls.add(median); jpayne@68: }else if(hiddenRate>0){ jpayne@68: ArrayList temp=new ArrayList(); jpayne@68: jpayne@68: ReadBuilder current=null; jpayne@68: for(int i=0; i0); jpayne@68: assert(current.subreads>1); jpayne@68: }else{ jpayne@68: if(current!=null){temp.add(current);} jpayne@68: current=rb; jpayne@68: assert(current.adapters==0); jpayne@68: } jpayne@68: } jpayne@68: if(current!=null){temp.add(current);} jpayne@68: baseCalls=temp; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: ArrayList reads=new ArrayList(); jpayne@68: for(ReadBuilder rb : baseCalls){ jpayne@68: Read r=rb.toRead(); jpayne@68: readsOutT+=r.pairCount(); jpayne@68: basesOutT+=r.length(); jpayne@68: reads.add(r); jpayne@68: } jpayne@68: jpayne@68: idHistT[(int)((1-errorRate)*(ID_BINS-1)+0.5f)]++; jpayne@68: return reads; jpayne@68: } jpayne@68: jpayne@68: private ArrayList baseCallAllPasses(final int movieLength, final float errorRate, long zmw){ jpayne@68: byte[] frag=null; jpayne@68: jpayne@68: for(int i=0; i<10 && frag==null; i++){//retry several times jpayne@68: frag=fetchBases(ref); jpayne@68: } jpayne@68: jpayne@68: if(frag==null){ jpayne@68: // System.err.println("Failed baseCallAllPasses("+movieLength+", "+errorRate+", "+zmw);//123 jpayne@68: return null; jpayne@68: } jpayne@68: jpayne@68: ArrayList list=new ArrayList(); jpayne@68: int movieRemaining=movieLength; jpayne@68: int moviePos=0; jpayne@68: assert(frag.length>0) : frag.length; jpayne@68: int start=randy.nextInt(frag.length); jpayne@68: while(movieRemaining>0){ jpayne@68: ReadBuilder rb=baseCallOnePass(frag, errorRate, start, moviePos, movieRemaining, zmw); jpayne@68: list.add(rb); jpayne@68: start=0; jpayne@68: int elapsed=rb.length()+adapterLen; jpayne@68: moviePos+=elapsed; jpayne@68: movieRemaining-=elapsed; jpayne@68: AminoAcid.reverseComplementBasesInPlace(frag); jpayne@68: } jpayne@68: return list; jpayne@68: } jpayne@68: jpayne@68: /** Call bases for one pass */ jpayne@68: private ReadBuilder baseCallOnePass(final byte[] frag, final float errorRate, final int start, final int movieStart, int movieRemaining, long zmw){ jpayne@68: final float mult=1/(1-errorRate); jpayne@68: ByteBuilder bb=new ByteBuilder(); jpayne@68: int fpos=start; jpayne@68: for(; fpos0; fpos++){ jpayne@68: float f=randy.nextFloat(); jpayne@68: byte b=frag[fpos]; jpayne@68: if(f>=errorRate){ jpayne@68: bb.append(b); jpayne@68: movieRemaining--; jpayne@68: }else{ jpayne@68: f=mult*(1-f); jpayne@68: if(f=source.length ? 0 : randy.nextInt(source.length-len); jpayne@68: int stop=Tools.min(start+len, source.length); jpayne@68: jpayne@68: // System.err.println("fetchBases(len="+len+", slen="+source.length+", start="+start+", stop="+stop);//123 jpayne@68: jpayne@68: for(int i=start; i