001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 * Created on Jan 29, 2006 021 * 022 */ 023package org.biojava.nbio.structure.align.pairwise; 024 025 026import org.biojava.nbio.structure.align.helper.AligMatEl; 027import org.biojava.nbio.structure.align.helper.GapArray; 028import org.biojava.nbio.structure.align.helper.IndexPair; 029 030import java.util.ArrayList; 031import java.util.List; 032 033/** a class to perform Gotoh algorithm 034 * 035 * @author Andreas Prlic (Java), Peter Lackner (original C code) 036 * @since 10:56:53 AM 037 * @version %I% %G% 038 */ 039public class Gotoh { 040 public static int ALIGFACTOR = 1000; // constant to shift floats to ints 041 042 Alignable a; 043 044 int k,openPen,elgPen,rowDim,colDim,openVal,elgVal; 045 046 AligMatEl currentCell; 047 GapArray currentGap; 048 049 050 051 public Gotoh(Alignable alignable) { 052 super(); 053 a = alignable; 054 055 align(); 056 057 } 058 059 060 061 private void align() { 062 063 rowDim = a.getRows()+1; 064 colDim = a.getCols()+1; 065 066 openPen = Math.round(ALIGFACTOR * a.getGapOpenCol()); 067 elgPen = Math.round(ALIGFACTOR * a.getGapExtCol()); 068 069 GapArray[] gapCol = new GapArray[colDim]; 070 GapArray[] gapRow = new GapArray[rowDim]; 071 072 // init the arrays 073 for ( int i = 0 ; i< colDim;i++){ 074 gapCol[i] = new GapArray(); 075 } 076 for ( int j = 0 ; j< rowDim;j++){ 077 gapRow[j] = new GapArray(); 078 } 079 currentGap = new GapArray(); 080 081 AligMatEl[][]aligmat = a.getAligMat(); 082 int lastValue = aligmat[rowDim-1][colDim-1].getValue(); 083 084// first cell 085 aligmat[0][0].setValue(0); 086 gapCol[0].setValue(0); 087 gapCol[0].setIndex(0); 088 gapRow[0].setValue(0); 089 gapRow[0].setIndex(0); 090 091 // set row 0 margin 092 for(int j=1;j<colDim;j++) { 093 aligmat[0][j].setValue(0); 094 gapCol[j].setValue(-(openPen+elgPen)); 095 gapCol[j].setIndex(0); 096 } 097 098 099 for(int rowCounter=1;rowCounter<rowDim;rowCounter++){ 100 101 // set column 0 margin 102 aligmat[rowCounter][0].setValue(0); 103 gapRow[rowCounter].setValue(-(openPen+elgPen)); 104 gapRow[rowCounter].setIndex(0); 105 106 for(int colCounter=1;colCounter<colDim;colCounter++) { 107 108 currentCell = aligmat[rowCounter][colCounter]; 109 110 // no gap 111 currentCell.setValue( aligmat[rowCounter-1][colCounter-1].getValue() + currentCell.getValue()); 112 currentCell.setRow((short)(rowCounter-1)); 113 currentCell.setCol((short)(colCounter-1)); 114 115 // scan column j for gap, gap in seqB 116 openVal = aligmat[rowCounter-1][colCounter].getValue() - (openPen+elgPen); 117 elgVal = gapCol[colCounter].getValue()-elgPen; 118 119 currentGap = new GapArray(); 120 121 if ( openVal >= elgVal){ 122 currentGap.setValue(openVal); 123 currentGap.setIndex(rowCounter-1); 124 } else { 125 currentGap.setValue(elgVal); 126 currentGap.setIndex(gapCol[colCounter].index); 127 } 128 gapCol[colCounter] = currentGap; 129 130 if (currentGap.getValue() > currentCell.getValue()){ 131 if ( currentGap.getIndex() >= rowDim) 132 System.err.println("col gap at" + rowCounter + " " + colCounter + " to " + currentGap.getIndex()); 133 currentCell.setValue( currentGap.getValue()); 134 currentCell.setRow((short)currentGap.getIndex()); 135 currentCell.setCol((short)colCounter); 136 } 137 138// scan row i for gap, gap in row 139 openVal = aligmat[rowCounter][colCounter-1].getValue()-(openPen+elgPen); 140 elgVal = gapRow[rowCounter].getValue() - elgPen; 141 142 currentGap = new GapArray(); 143 144 if (openVal >= elgVal){ 145 currentGap.setValue(openVal); 146 currentGap.setIndex(colCounter-1); 147 } else { 148 currentGap.setValue(elgVal); 149 currentGap.setIndex(gapRow[rowCounter].getIndex()); 150 } 151 gapRow[rowCounter] = currentGap; 152 153 154 if ( currentGap.getValue() > currentCell.getValue() ) { 155 if ( currentGap.getIndex() >= colDim) 156 System.err.println("row gap at" + rowCounter + " " + colCounter + " to " + currentGap.getIndex()); 157 currentCell.setValue(currentGap.getValue()); 158 currentCell.setRow((short)rowCounter); 159 currentCell.setCol((short)currentGap.getIndex()); 160 } 161 162 aligmat[rowCounter][colCounter]=currentCell; 163 } 164 165 } 166 167 168 // last cell in alignment matrix 169 // do not penalize end gaps 170 int rowCount = rowDim -1; 171 int colCount = colDim -1; 172 currentCell = aligmat[rowCount][colCount]; 173 174 // no gap 175 currentCell.setValue(aligmat[rowCount-1][colCount-1].getValue() + lastValue); 176 currentCell.setRow((short)(rowCount-1)); 177 currentCell.setCol((short)(colCount-1)); 178 179 // scan last column j for gap, gap in seqB 180 // do not penalyze gaps 181 for (int k=1;k<=rowCount;k++) { 182 int val = aligmat[rowCount-k][colCount].getValue(); 183 if ( val>currentCell.getValue()){ 184 currentCell.setValue(val); 185 //System.out.println("setting row to " + (rowCount ) ); 186 currentCell.setRow((short)(rowCount-k )); 187 currentCell.setCol((short)(colCount )); 188 } 189 } 190 191 // scan row i for gap, gap in SeqA 192 // do not penalyze gaps 193 for (int k=1;k<=colCount;k++) { 194 int val = aligmat[rowCount][colCount-k].getValue(); 195 if ( val > currentCell.getValue()){ 196 currentCell.setValue(val); 197 currentCell.setRow((short) (rowCount ) ); 198 currentCell.setCol((short)(colCount-k )); 199 } 200 } 201 a.setScore(aligmat[rowDim-1][colDim-1].getValue() / (float)ALIGFACTOR); 202 setPath(); 203 204 } 205 206 private void setPath(){ 207 208 // dmyersturnbull: TODO fix exception handling and logging 209 210 int n; 211 IndexPair[] backId = new IndexPair[a.getRows()+1+a.getCols()+1]; 212 List<IndexPair> path = new ArrayList<IndexPair>(); 213 214 backId[0] = new IndexPair((short)(a.getRows()),(short)(a.getCols())); 215 216 // backtrace, get backId indices, the indices in diagonal store in path 217 218 219 int pathsize = 0; 220 221 AligMatEl[][] aligmat = a.getAligMat(); 222 223 224 n=1; 225 while ( (backId[n-1].getRow()>=1) && 226 (backId[n-1].getCol()>=1) 227 ) 228 { 229 // get backtrace index 230 int x = backId[n-1].getRow(); 231 int y = backId[n-1].getCol(); 232 233 try { 234 235 AligMatEl el = null ; 236 try { 237 el =aligmat[x][y]; 238 } catch(Exception e){ 239 240 241 e.printStackTrace(); 242 for (int f=0; f< n;f++){ 243 System.out.println(backId[f]); 244 } 245 246 } 247 248 if ( el == null) 249 System.out.println("el = null! x:"+ x + " y " + y); 250 backId[n] = el; 251 } catch (Exception e){ 252 e.printStackTrace(); 253 System.out.println("x " + x); 254 System.out.println("y " + y); 255 System.out.println(backId[n-2]); 256 System.exit(0); 257 } 258 // get diagonal indeces into path 259 if (((backId[n-1].getRow() - backId[n].getRow()) == 1) 260 && (( backId[n-1].getCol() - backId[n].getCol()) == 1)) { 261 path.add(backId[n-1]); 262 pathsize++; 263 264 } 265 n++; 266 } 267 268 // path is reverse order.. 269 // switch order 270 IndexPair[] newpath = new IndexPair[pathsize]; 271 for (int i = 0 ; i < pathsize; i++){ 272 IndexPair o = path.get(pathsize-1-i); 273 IndexPair np = new IndexPair((short)(o.getRow()-1),(short)(o.getCol()-1)); 274 newpath[i] = np; 275 } 276 277 a.setPath(newpath); 278 a.setPathSize(pathsize); 279 280 281 } 282}