/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * * Created on Jan 29, 2006 * */ package org.biojava.nbio.structure.align.pairwise; import org.biojava.nbio.structure.align.helper.AligMatEl; import org.biojava.nbio.structure.align.helper.GapArray; import org.biojava.nbio.structure.align.helper.IndexPair; import java.util.ArrayList; import java.util.List; /** a class to perform Gotoh algorithm * * @author Andreas Prlic (Java), Peter Lackner (original C code) * @since 10:56:53 AM * @version %I% %G% */ public class Gotoh { public static int ALIGFACTOR = 1000; // constant to shift floats to ints Alignable a; int k,openPen,elgPen,rowDim,colDim,openVal,elgVal; AligMatEl currentCell; GapArray currentGap; public Gotoh(Alignable alignable) { super(); a = alignable; align(); } private void align() { rowDim = a.getRows()+1; colDim = a.getCols()+1; openPen = Math.round(ALIGFACTOR * a.getGapOpenCol()); elgPen = Math.round(ALIGFACTOR * a.getGapExtCol()); GapArray[] gapCol = new GapArray[colDim]; GapArray[] gapRow = new GapArray[rowDim]; // init the arrays for ( int i = 0 ; i< colDim;i++){ gapCol[i] = new GapArray(); } for ( int j = 0 ; j< rowDim;j++){ gapRow[j] = new GapArray(); } currentGap = new GapArray(); AligMatEl[][]aligmat = a.getAligMat(); int lastValue = aligmat[rowDim-1][colDim-1].getValue(); // first cell aligmat[0][0].setValue(0); gapCol[0].setValue(0); gapCol[0].setIndex(0); gapRow[0].setValue(0); gapRow[0].setIndex(0); // set row 0 margin for(int j=1;j<colDim;j++) { aligmat[0][j].setValue(0); gapCol[j].setValue(-(openPen+elgPen)); gapCol[j].setIndex(0); } for(int rowCounter=1;rowCounter<rowDim;rowCounter++){ // set column 0 margin aligmat[rowCounter][0].setValue(0); gapRow[rowCounter].setValue(-(openPen+elgPen)); gapRow[rowCounter].setIndex(0); for(int colCounter=1;colCounter<colDim;colCounter++) { currentCell = aligmat[rowCounter][colCounter]; // no gap currentCell.setValue( aligmat[rowCounter-1][colCounter-1].getValue() + currentCell.getValue()); currentCell.setRow((short)(rowCounter-1)); currentCell.setCol((short)(colCounter-1)); // scan column j for gap, gap in seqB openVal = aligmat[rowCounter-1][colCounter].getValue() - (openPen+elgPen); elgVal = gapCol[colCounter].getValue()-elgPen; currentGap = new GapArray(); if ( openVal >= elgVal){ currentGap.setValue(openVal); currentGap.setIndex(rowCounter-1); } else { currentGap.setValue(elgVal); currentGap.setIndex(gapCol[colCounter].index); } gapCol[colCounter] = currentGap; if (currentGap.getValue() > currentCell.getValue()){ if ( currentGap.getIndex() >= rowDim) System.err.println("col gap at" + rowCounter + " " + colCounter + " to " + currentGap.getIndex()); currentCell.setValue( currentGap.getValue()); currentCell.setRow((short)currentGap.getIndex()); currentCell.setCol((short)colCounter); } // scan row i for gap, gap in row openVal = aligmat[rowCounter][colCounter-1].getValue()-(openPen+elgPen); elgVal = gapRow[rowCounter].getValue() - elgPen; currentGap = new GapArray(); if (openVal >= elgVal){ currentGap.setValue(openVal); currentGap.setIndex(colCounter-1); } else { currentGap.setValue(elgVal); currentGap.setIndex(gapRow[rowCounter].getIndex()); } gapRow[rowCounter] = currentGap; if ( currentGap.getValue() > currentCell.getValue() ) { if ( currentGap.getIndex() >= colDim) System.err.println("row gap at" + rowCounter + " " + colCounter + " to " + currentGap.getIndex()); currentCell.setValue(currentGap.getValue()); currentCell.setRow((short)rowCounter); currentCell.setCol((short)currentGap.getIndex()); } aligmat[rowCounter][colCounter]=currentCell; } } // last cell in alignment matrix // do not penalize end gaps int rowCount = rowDim -1; int colCount = colDim -1; currentCell = aligmat[rowCount][colCount]; // no gap currentCell.setValue(aligmat[rowCount-1][colCount-1].getValue() + lastValue); currentCell.setRow((short)(rowCount-1)); currentCell.setCol((short)(colCount-1)); // scan last column j for gap, gap in seqB // do not penalyze gaps for (int k=1;k<=rowCount;k++) { int val = aligmat[rowCount-k][colCount].getValue(); if ( val>currentCell.getValue()){ currentCell.setValue(val); //System.out.println("setting row to " + (rowCount ) ); currentCell.setRow((short)(rowCount-k )); currentCell.setCol((short)(colCount )); } } // scan row i for gap, gap in SeqA // do not penalyze gaps for (int k=1;k<=colCount;k++) { int val = aligmat[rowCount][colCount-k].getValue(); if ( val > currentCell.getValue()){ currentCell.setValue(val); currentCell.setRow((short) (rowCount ) ); currentCell.setCol((short)(colCount-k )); } } a.setScore(aligmat[rowDim-1][colDim-1].getValue() / (float)ALIGFACTOR); setPath(); } private void setPath(){ // dmyersturnbull: TODO fix exception handling and logging int n; IndexPair[] backId = new IndexPair[a.getRows()+1+a.getCols()+1]; List<IndexPair> path = new ArrayList<IndexPair>(); backId[0] = new IndexPair((short)(a.getRows()),(short)(a.getCols())); // backtrace, get backId indices, the indices in diagonal store in path int pathsize = 0; AligMatEl[][] aligmat = a.getAligMat(); n=1; while ( (backId[n-1].getRow()>=1) && (backId[n-1].getCol()>=1) ) { // get backtrace index int x = backId[n-1].getRow(); int y = backId[n-1].getCol(); try { AligMatEl el = null ; try { el =aligmat[x][y]; } catch(Exception e){ e.printStackTrace(); for (int f=0; f< n;f++){ System.out.println(backId[f]); } } if ( el == null) System.out.println("el = null! x:"+ x + " y " + y); backId[n] = el; } catch (Exception e){ e.printStackTrace(); System.out.println("x " + x); System.out.println("y " + y); System.out.println(backId[n-2]); System.exit(0); } // get diagonal indeces into path if (((backId[n-1].getRow() - backId[n].getRow()) == 1) && (( backId[n-1].getCol() - backId[n].getCol()) == 1)) { path.add(backId[n-1]); pathsize++; } n++; } // path is reverse order.. // switch order IndexPair[] newpath = new IndexPair[pathsize]; for (int i = 0 ; i < pathsize; i++){ IndexPair o = path.get(pathsize-1-i); IndexPair np = new IndexPair((short)(o.getRow()-1),(short)(o.getCol()-1)); newpath[i] = np; } a.setPath(newpath); a.setPathSize(pathsize); } }