/* * Copyright (c) 2010 The Regents of the University of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.. */ package sequencing; import jaligner.Alignment; import jaligner.Sequence; import jaligner.SmithWatermanGotoh; import jaligner.matrix.MatrixLoader; import java.util.ArrayList; import javax.swing.JPanel; import sequencing.TraceExtract.AlignedABI; import sequencing.TraceExtract.ResultType; /** * * @author jcanderson_Home */ public class Analyzer { public Analyzer(ArrayList<ABITrace> abis, String sequ) { //Initiate data String oldsequ = sequ.toUpperCase(); sequ = oldsequ; traces= new ArrayList<TraceExtract>(); contigs = new ArrayList<TraceExtract>(); _abis = abis; for(ABITrace abi : abis) { TraceExtract te = new TraceExtract(abi); traces.add(te); contigs.add(te); } int[] partQualities = new int[sequ.length()]; short[] partScores = new short[sequ.length()]; finalTarget = new TraceExtract(sequ, partQualities, partScores); } public ResultType go() { //Do the analysis: //Take all the traces and let them assemble without bias of the target sequence assemblyContig(); //Remove all the contigs that don't align to the target sequence and reorient the good ones pruneOutDuds(); //Call each base as correct, wrong, or ambiguous (data stored in the baseScores array as 1, 0, or -1 alignToTarget(); //Realign all the abis for(AlignedABI abi: finalTarget.getABIList()) { abi.realign(finalTarget.getSeq()); } return finalTarget.getResult(); } public void launchReport() { //Instantiate the gui on the final target new InteractiveReport(finalTarget, "Chris Anderson", "Best sample ever", finalTarget.getResult().toString()).showReport(); } //returns the JPanel instead of displaying it immediately, which is done in launchReport() public JPanel returnReport() { return new InteractiveReport(finalTarget, "Chris Anderson", "Best sample ever", finalTarget.getResult().toString()).getPanel(); } /** * The contigs going into this are already confirmed to be good matches * to the target and have been oriented in the right direction. This * transfers the best quality score to the quality array. */ private void alignToTarget() { for(TraceExtract atrace : contigs) { Alignment Falign = swAlign(atrace.getSeq(), finalTarget.getSeq()); //Modify the target sequence and qualities to include any gaps char[] seqy = Falign.getSequence2(); for(int i=0; i<seqy.length; i++) { if(seqy[i]!='-') { continue; } finalTarget.addGap(Falign.getStart2()+i, 10); atrace.noteDeletion(Falign.getStart1() + i); } //Modify the target sequence and qualities to include any deletions seqy = Falign.getSequence1(); for(int i=0; i<seqy.length; i++) { if(seqy[i]!='-') { continue; } finalTarget.noteDeletion(Falign.getStart2() + i); atrace.addGap(Falign.getStart1() + i, 10); } //With all the gaps fixed, merge them Falign = swAlign(atrace.getSeq(), finalTarget.getSeq()); int start = Falign.getStart1(); int end = Falign.getLength() + start; int partStart = Falign.getStart2(); int partOffset = start - partStart; TraceExtract result = TraceExtract.merge(atrace, finalTarget, start, partStart, true); finalTarget = result; // System.out.println("\n\nSequence: "); // System.out.println(result.getSeq()); // int[] quals = result.getQualities(); // // System.out.println("\n\nQualities: "); // for(int i=0; i < quals.length; i++) { // System.out.print(quals[i]); // } System.out.println("\n\nBaseCalls: "); short[] calls = result.getBaseScores(); for(int i=0; i < calls.length; i++) { System.out.print(calls[i]); } System.out.println("\n\nI have x many abis: " + result.getABIList().size()); } // System.out.println("finalTarget seq: " + finalTarget.getSeq()); } /** * Takes all the qualified Strings and gets them to assemble into one contig (if possible) * @param traces */ private void assemblyContig() { //Create a second copy of the array to avoid concurrency errors ArrayList<TraceExtract> backupArray = new ArrayList<TraceExtract>(); for(TraceExtract str : contigs) { backupArray.add(str); } //Iterate through all the contigs and merge them into one contig (if possible) while(alignAndMerge(contigs.get(0), TraceExtract.revcomp(contigs.get(0)))); } /** * Aligns a TraceExtract contig to the target sequence * @param atrace */ private void pruneOutDuds() { //Copy the ArrayList ArrayList<TraceExtract> listy = new ArrayList<TraceExtract>(); for(TraceExtract atrace : contigs) { TraceExtract rctrace = TraceExtract.revcomp(atrace); Alignment Falign = swAlign(atrace.getSeq(), finalTarget.getSeq()); Alignment Ralign = swAlign(rctrace.getSeq(), finalTarget.getSeq()); float fscore = Falign.getScoreWithNoTerminalGaps(); float rscore = Ralign.getScoreWithNoTerminalGaps(); if(Math.max(fscore, rscore) > 200) { if(fscore>rscore) { listy.add(atrace); } else { listy.add(rctrace); } } } contigs = listy; } /** * Align two TraceExtracts and merge them into a contig. This is called iteratively * to force all the abis to assemble into contigs (ideally 1, but will make more if there * isn't homology between them). * @param first * @param firstrc * @return */ private boolean alignAndMerge(TraceExtract first, TraceExtract firstrc) { if(contigs.size()<2) { return false; } boolean bestRC=false; //if the best Match for or rev int bestMatch=0; //Index in contigs of best match float bestScore=0; //Score of the best match Alignment bestAlign = null; //The alignment for the best match //For each string after the first see which is the best for(int j=1; j<contigs.size(); j++) { String second = contigs.get(j).getSeq(); Alignment Falign = swAlign(first.getSeq(), second); Alignment Ralign = swAlign(firstrc.getSeq(), second); Alignment betterAlign = Falign; boolean isRC = false; //If the alignment is better as rev comp, set that parameter float fscore = Falign.getScoreWithNoTerminalGaps(); float rscore = Ralign.getScoreWithNoTerminalGaps(); if(fscore<rscore){ isRC=true; betterAlign = Ralign; } float myscore = Math.max(fscore, rscore); // System.out.println(isRC + " " + fscore + " " +rscore + " " +myscore); //If this is the best alignment of the first datapoint to the others in the array, set that if(myscore>bestScore) { bestScore = myscore; bestRC = isRC; bestMatch = j; bestAlign = betterAlign; } } if(bestScore<200) { return false; } //Based on best choice, reorient first seq to be in right order TraceExtract reorient = first; if(bestRC) { reorient = firstrc; } //Do the merge, remove the two that were aligned and put in the new merge TraceExtract newone = TraceExtract.merge(reorient, contigs.get(bestMatch), bestAlign.getStart1(), bestAlign.getStart2(), false); // System.out.println(newone.getSeq()); contigs.remove(bestMatch); contigs.remove(0); contigs.add(newone); return true; } public static Alignment swAlign(String first, String test){ Sequence s1=new Sequence(first); Sequence s2=new Sequence(test); try{ Alignment alignment = SmithWatermanGotoh.align(s1, s2, MatrixLoader.load("IDENTITY_1"), 100f, 50f); //System.out.println ( alignment.getSummary() ); //System.out.println ( new Pair().format(alignment) ); alignment.getScoreWithNoTerminalGaps(); return alignment; } catch (Exception e) { System.out.println("Failed running example: " + e.getMessage()); } return null; } private String revcomp(String in){ String ret=""; for(int i=in.length()-1; i>=0; i--){ char nuc=in.charAt(i); switch(nuc){ case 'A': ret+='T'; break; case 'G': ret+='C'; break; case 'C': ret+='G'; break; case 'T': ret+='A'; break; case 'N': ret+='N'; break; } } return ret; } /////////////////////////////////////////////////////////////////// //// private variables //// public static final double MIN_QUALITY=6; public static final int MIN_AVERAGE_QUALITY=25; private ArrayList<TraceExtract> traces; private ArrayList<TraceExtract> contigs; private ArrayList<ABITrace> _abis; private TraceExtract finalTarget; private Result _result; public static enum Result { PERFECT, PERFECT_PARTIAL, MUTATIONS } }