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 Feb 15, 2010 021 * Author: Andreas Prlic 022 * 023 */ 024 025package org.biojava.nbio.structure.align.model; 026 027import org.biojava.nbio.structure.*; 028import org.biojava.nbio.structure.align.ce.CeMain; 029import org.biojava.nbio.structure.align.ce.CeSideChainMain; 030import org.biojava.nbio.structure.align.fatcat.FatCatFlexible; 031import org.biojava.nbio.structure.align.seq.SmithWaterman3Daligner; 032import org.biojava.nbio.structure.align.util.AFPAlignmentDisplay; 033import org.biojava.nbio.structure.jama.Matrix; 034 035import java.io.StringWriter; 036import java.util.List; 037 038/** A class to convert the data in an AfpChain object to various String outputs. 039 * 040 * @author Andreas Prlic 041 * 042 */ 043public class AfpChainWriter 044{ 045 046 public static final String newline = System.getProperty("line.separator"); 047 048 private static int LINELENGTH = 70; 049 050 public static String toFatCat(AFPChain afpChain, Atom[] ca1, Atom[] ca2) 051 { 052 053 boolean printLegend = true; 054 boolean longHeader = true; 055 boolean showHTML = false; 056 boolean showAlignmentBlock = false; 057 058 return toFatCatCore(afpChain, ca1, ca2, printLegend, longHeader, showHTML, showAlignmentBlock); 059 } 060 061 public static String toScoresList(AFPChain afpChain){ 062 063 // see sippl On distance and similarity in fold space 2008 bioinformatics 064 065 StringWriter writer = new StringWriter(); 066 067 if ( afpChain.getAlgorithmName().startsWith("CE")) { 068 writer.append("Z-score " ); 069 writer.append(String.format("%.2f", afpChain.getProbability())); 070 writer.append(newline); 071 } 072 073 074 writer.append("Sab (nr. equivalent residues): " ); 075 writer.append(String.valueOf(afpChain.getNrEQR())).append(""); 076 writer.append(newline); 077 078 writer.append("Dab (distance between folds a,b): "); 079 int dab = afpChain.getCa1Length()+afpChain.getCa2Length() - 2 * afpChain.getNrEQR(); 080 writer.append(String.valueOf(dab)).append(""); 081 writer.append(newline); 082 083 writer.append("sab (relative similarity): "); 084 double sab = 2 * afpChain.getNrEQR() / (double)( afpChain.getCa1Length() + afpChain.getCa2Length()); 085 writer.append(String.valueOf(sab)).append(""); 086 writer.append(newline); 087 088 writer.append("cab (coverage a): "); 089 double cab = afpChain.getNrEQR() / (double) afpChain.getCa1Length(); 090 writer.append(String.valueOf(cab)).append(""); 091 writer.append(newline); 092 093 writer.append("cba (coverage b): "); 094 double cba = afpChain.getNrEQR() / (double) afpChain.getCa2Length(); 095 writer.append(String.valueOf(cba)).append(""); 096 writer.append(newline); 097 098 writer.append("seq similarity: "); 099 writer.append(String.valueOf(afpChain.getSimilarity())).append(""); 100 writer.append(newline); 101 102 writer.append("TM-score: "); 103 writer.append(String.valueOf(afpChain.getTMScore())).append(""); 104 writer.append(newline); 105 106 return writer.toString(); 107 } 108 109 /** 110 * Output in FatCatCore format 111 * 112 * <p>Note that if a circular permutation has occured the residue numbers may 113 * be innaccurate. 114 * 115 * @param afpChain 116 * @param ca1 117 * @param ca2 118 * @param printLegend 119 * @param longHeader 120 * @param showHTML 121 * @param showAlignmentBlock 122 * @return 123 */ 124 public static String toFatCatCore( 125 AFPChain afpChain, 126 Atom[] ca1, 127 Atom[] ca2, 128 boolean printLegend, boolean longHeader, boolean showHTML, boolean showAlignmentBlock){ 129 130 //TODO The sequence numbers are inaccurate if a !afpChain.isSequential() 131 132 String name1 = afpChain.getName1(); 133 String name2 = afpChain.getName2(); 134 int ca1Length = afpChain.getCa1Length(); 135 int ca2Length = afpChain.getCa2Length(); 136 137 int blockNum = afpChain.getBlockNum(); 138 int totalLenIni = afpChain.getTotalLenIni(); 139 double totalRmsdIni = afpChain.getTotalRmsdIni(); 140 int optLength = afpChain.getOptLength(); 141 double totalRmsdOpt = afpChain.getTotalRmsdOpt(); 142 double chainRmsd = afpChain.getChainRmsd(); 143 double alignScore = afpChain.getAlignScore(); 144 int alnLength = afpChain.getAlnLength(); 145 int gapLen = afpChain.getGapLen(); 146 List<AFP> afpSet = afpChain.getAfpSet(); 147 148 double similarity = afpChain.getSimilarity(); 149 double identity = afpChain.getIdentity(); 150 151 if (similarity <0 || identity < 0){ 152 afpChain.calcSimilarity(); 153 similarity = afpChain.getSimilarity(); 154 identity = afpChain.getIdentity(); 155 } 156 157 158 159 String algorithmName = afpChain.getAlgorithmName(); 160 //String version = afpChain.getVersion(); 161 162 double probability = afpChain.getProbability(); 163 164 165 int afpNum = afpSet.size(); 166 167 int[] blockGap = afpChain.getBlockGap(); 168 169 170 double[] blockScore = afpChain.getBlockScore(); 171 double[] blockRmsd = afpChain.getBlockRmsd(); 172 int[] blockSize = afpChain.getBlockSize(); 173 174 175 int alnbeg1 = afpChain.getAlnbeg1(); 176 int alnbeg2 = afpChain.getAlnbeg2(); 177 178 char[] alnseq1 = afpChain.getAlnseq1(); 179 char[] alnseq2 = afpChain.getAlnseq2(); 180 char[] alnsymb = afpChain.getAlnsymb(); 181 182 // == end of extractation of data values from afpChain 183 //////////////////////////////// 184 185 StringBuffer txt = new StringBuffer(); 186 187 if ( longHeader) { 188 txt.append(String.format("Align %s.pdb %d with %s.pdb %d", name1, ca1Length, name2, ca2Length)); 189 } 190 else { 191 txt.append(String.format("Align %s.pdb Length1: %d with %s.pdb Length2: %d", name1, ca1Length, name2, ca2Length)); 192 } 193 txt.append(newline); 194 if ( afpChain.isShortAlign()){ 195 txt.append("Short match"); 196 return txt.toString(); 197 } 198 //txt.append(String.format("raw-score: %.2f norm.-score: %.2f ", alignScore, normAlignScore)); 199 200 if ( longHeader ) { 201 txt.append(String.format( "Twists %d ini-len %d ini-rmsd %.2f opt-equ %d opt-rmsd %.2f chain-rmsd %.2f Score %.2f align-len %d gaps %d (%.2f%%)", 202 blockNum - 1, totalLenIni, totalRmsdIni, optLength, totalRmsdOpt, chainRmsd, alignScore, 203 alnLength, gapLen, (100.0 * gapLen/alnLength)) ); 204 txt.append(newline); 205 206 } else { 207 208 if ( ! longHeader) 209 printScore(txt,algorithmName,probability,longHeader); 210 211 printScoresInLines(afpChain, blockNum, optLength, totalRmsdOpt, alignScore, alnLength, gapLen, identity, similarity,txt); 212 } 213 214 215 //txt.append(String.format("P-value %.2e Afp-num %d Identity %.2f%% Similarity %.2f%% norm.-score: %.2f"+newline, probability, afpNum, identity * 100, similarity * 100, normAlignScore)); 216 217 if ( longHeader) { 218 printScore(txt,algorithmName,probability,longHeader); 219 220 txt.append(String.format("Afp-num %d Identity %.2f%% Similarity %.2f%%", afpNum, identity * 100, similarity * 100)); 221 txt.append(newline); 222 } 223 224 int i; 225 double gap; 226 227 if ( longHeader ){ 228 int fragLen = 8 ; // FatCatParameters.DEFAULT_FRAGLEN; 229 for(i = 0; i < blockNum; i ++) { 230 gap = blockGap[i] /( (double)blockGap[i] + fragLen * blockSize[i]); 231 txt.append(String.format( "Block %2d afp %2d score %5.2f rmsd %5.2f gap %d (%.2f%%)", 232 i, blockSize[i], blockScore[i], blockRmsd[i], blockGap[i], gap)); 233 txt.append(newline); 234 } 235 } 236 237 int linelen = 70; 238 String a; 239 String b; 240 String c; 241 242 243 int t = 0; 244 int ap = alnbeg1; 245 int bp = alnbeg2; 246 int k, len; 247 248 //System.out.println(alnseq1.length + " " + alnseq1.toString()); 249 250 while((alnLength - t) > 0) { 251 if(alnLength - t > linelen) len = linelen; 252 else len = alnLength - t; 253 254 if ( ap >= ca1.length) 255 break; 256 if ( bp >= ca2.length) 257 break; 258 259 String pdb1 = ca1[ap].getGroup().getResidueNumber().toString(); 260 String pdb2 = ca2[bp].getGroup().getResidueNumber().toString(); 261 262 263 //System.err.println("t,len:"+t+":"+len); 264 String lseq1 = new String(alnseq1).substring(t,t+len); 265 String lseq2 = new String(alnseq2).substring(t,t+len); 266 String lsymb = new String(alnsymb).substring(t,t+len); 267 268 //System.err.println("B:" + b); 269 270 271 // check conservation and color accordingly, if requested by user. 272 if ( showHTML ) { 273 a = ""; 274 b = ""; 275 c = ""; 276 277 // <span class=\"m\">|</span> ... Structurally equivalent and identical residues 278 // <span class=\"sm\">:</span> ... Structurally equivalent and similar residues 279 // <span class=\"qg\">.</span> ... Structurally equivalent, but not similar residues. 280 281 for (int pos = 0 ; pos < lseq1.length() ; pos ++){ 282 char c1 = lseq1.charAt(pos); 283 char c2 = lseq2.charAt(pos); 284 char cl = lsymb.charAt(pos); 285 int block = -1 ; 286 if ( cl != ' ') { 287 try { 288 block = Integer.parseInt(String.valueOf(cl)); 289 } catch (Exception e){ 290 // 291 } 292 } 293 if ( cl != ' ' ){ 294 295 if ( showAlignmentBlock && block > -1 ) { 296 a += "<span class=\"alignmentBlock1"+block+"\">" + c1 + "</span>"; 297 b += "<span class=\"alignmentBlock2"+block+"\">" + c2 + "</span>"; 298 c += "<span class=\"m\">" + cl + "</span>"; 299 } else { 300 a += getPrefix(c1, c2, 0, block, false).toString() + c1 + "</span>"; 301 b += getPrefix(c1, c2, 1, block, false).toString() + c2 + "</span>"; 302 c += "<span class=\"m\">" + cl + "</span>"; 303 } 304 305 } else if ( c1 != '-' && c2 != '-') { 306 307 a += "<span class=\"sm\">" + c1 + "</span>"; 308 b += "<span class=\"sm\">" + c2 + "</span>"; 309 c += "<span class=\"sm\">" + cl + "</span>"; 310 311 312 } else { 313 314 a += "<span class=\"qg\">" + c1 + "</span>"; 315 b += "<span class=\"qg\">" + c2 + "</span>"; 316 c += "<span class=\"qg\">" + cl + "</span>"; 317 318 } 319 320 if(c1 != '-') ap ++; 321 if(c2 != '-') bp ++; 322 } 323 324 325 } else { 326 327 a = lseq1; 328 b = lseq2; 329 c = lsymb; 330 } 331 332 txt.append(newline); 333 if ( longHeader ) 334 txt.append(String.format("%14s", " ")); 335 else 336 txt.append(String.format("%14s", " ")); 337 338 if ( longHeader ) { 339 for(k = 10; k <= len; k += 10) 340 txt.append(" . :"); 341 if(k <= len + 5) txt.append(" ."); 342 343 } else { 344 345 for(k = 10; k <= len; k += 10) 346 txt.append("----+----|"); 347 if(k <= len + 5) txt.append("----+"); 348 349 350 } 351 352 353 354 txt.append(newline); 355 txt.append(String.format("Chain 1:%5s %s"+newline +"%14s%s"+newline+"Chain 2:%5s %s", 356 pdb1, a, " ", c, pdb2, b)); 357 358 txt.append(newline); 359 360 if ( ! showHTML){ 361 for(k = 0; k < len; k ++) { 362 if(a.charAt(k) != '-') ap ++; 363 if(b.charAt(k) != '-') bp ++; 364 } 365 } 366 t += len; 367 368 369 370 } 371 txt.append(newline); 372 if ( printLegend ){ 373 if ( algorithmName.equalsIgnoreCase(CeMain.algorithmName) || 374 algorithmName.equalsIgnoreCase(SmithWaterman3Daligner.algorithmName)){ 375 txt.append("Note: positions are from PDB; | means alignment of identical amino acids, : of similar amino acids "); 376 377 } else { 378 txt.append("Note: positions are from PDB; the numbers between alignments are block index"); 379 } 380 txt.append(newline); 381 382 } 383 return txt.toString(); 384 385 } 386 387 public static void printScoresInLines(AFPChain afpChain, int blockNum, int optLength, double totalRmsdOpt, double alignScore, 388 int alnLength, int gapLen, double identity, double similarity, StringBuffer txt) 389 { 390 if ( blockNum - 1 > 0) { 391 txt.append(String.format( "Twists %d ", blockNum -1 )); 392 txt.append(newline); 393 } 394 395 txt.append(String.format("Equ: %d ", optLength)); 396 txt.append(newline); 397 txt.append(String.format("RMSD: %.2f ", totalRmsdOpt)); 398 txt.append(newline); 399 txt.append(String.format("Score: %.2f ", alignScore)); 400 txt.append(newline); 401 txt.append(String.format("Align-len: %d ", alnLength)); 402 txt.append(newline); 403 txt.append(String.format("Gaps: %d (%.2f%%)", 404 gapLen, (100.0 * gapLen/alnLength)) ); 405 txt.append(newline); 406 if ( afpChain.getTMScore() >= 0) { 407 txt.append(String.format("TM-score: %.2f",afpChain.getTMScore())); 408 txt.append(newline); 409 } 410 txt.append(newline); 411 txt.append(String.format("Identity: %.2f%% ", identity * 100 )); 412 txt.append(newline); 413 txt.append(String.format("Similarity: %.2f%%", similarity * 100)); 414 txt.append(newline); 415 } 416 417 private static void printScore(StringBuffer txt, 418 String algorithmName, 419 double probability, 420 boolean longHeader) 421 { 422 if ( algorithmName.equalsIgnoreCase(CeMain.algorithmName) || algorithmName.equalsIgnoreCase(CeSideChainMain.algorithmName) ){ 423 txt.append(String.format("Z-score %.2f ", probability)); 424 if ( ! longHeader) 425 txt.append(newline); 426 } else if ( algorithmName.equalsIgnoreCase(SmithWaterman3Daligner.algorithmName)) { 427 428 } else { 429 if ( longHeader ){ 430 txt.append(String.format("P-value %.2e ",probability)); 431 } else { 432 txt.append(String.format("P-value: %.2e ",probability)); 433 txt.append(newline); 434 } 435 } 436 437 438 439 } 440 441 /** 442 * Prints the afpChain as a nicely formatted alignment, including alignment 443 * statistics, the aligned sequences themselves, and information about the 444 * superposition. 445 * @param afpChain 446 * @param ca1 447 * @param ca2 448 * @return a String representation as it is used on the RCSB PDB web site for display. 449 */ 450 public static String toWebSiteDisplay(AFPChain afpChain, Atom[] ca1, Atom[] ca2 ){ 451 boolean showAlignmentBlock = true; 452 return toWebSiteDisplay(afpChain, ca1, ca2, showAlignmentBlock); 453 } 454 455 /** 456 * Prints the afpChain as a nicely formatted alignment, including alignment 457 * statistics, the aligned sequences themselves, and information about the 458 * superposition. 459 * @param afpChain 460 * @param ca1 461 * @param ca2 462 * 463 * @return a String representation as it is used on the RCSB PDB web site for display. 464 */ 465 public static String toWebSiteDisplay(AFPChain afpChain, Atom[] ca1, Atom[] ca2, boolean showAlignmentBlock){ 466 467 boolean printLegend = true; 468 boolean longHeader = true; 469 boolean showHTML = true; 470 471 if ( afpChain.getAlgorithmName().equalsIgnoreCase(FatCatFlexible.algorithmName)) { 472 473 474 String msg = toFatCatCore(afpChain,ca1,ca2,printLegend,longHeader,showHTML, showAlignmentBlock); 475 476 return msg; 477 } 478 479 boolean showSeq = true; 480 481 AFPAlignmentDisplay.getAlign(afpChain, ca1, ca2, showSeq); 482 483 484 // String msg= toFatCatCore(afpChain,ca1,ca2, printLegend,longHeader); 485 // 486 487 488 String msg = toPrettyAlignment(afpChain, ca1, ca2, showHTML, showAlignmentBlock); 489 490 491 msg = msg + newline + 492 " <span class=\"m\">|</span> ... Structurally equivalent and identical residues " + newline + 493 " <span class=\"sm\">:</span> ... Structurally equivalent and similar residues " + newline + 494 " <span class=\"qg\">.</span> ... Structurally equivalent, but not similar residues. " + newline; 495 496 msg += newline; 497 msg += " To calculate the coordinates of chain 2 aligned on chain 1 apply the following transformation: "; 498 msg += newline; 499 msg += newline; 500 msg += toRotMat(afpChain); 501 return msg; 502 503 504 } 505 506 public static String toPrettyAlignment(AFPChain afpChain, Atom[] ca1, Atom[] ca2, boolean showHTML, boolean showAlignmentBlock) { 507 String name1 = afpChain.getName1(); 508 String name2 = afpChain.getName2(); 509 int ca1Length = afpChain.getCa1Length(); 510 int ca2Length = afpChain.getCa2Length(); 511 512 int blockNum = afpChain.getBlockNum(); 513 514 515 int optLength = afpChain.getOptLength(); 516 double totalRmsdOpt = afpChain.getTotalRmsdOpt(); 517 518 double alignScore = afpChain.getAlignScore(); 519 int alnLength = afpChain.getAlnLength(); 520 int gapLen = afpChain.getGapLen(); 521 522 523 double similarity = afpChain.getSimilarity(); 524 double identity = afpChain.getIdentity(); 525 526 if (similarity <0 || identity < 0){ 527 afpChain.calcSimilarity(); 528 similarity = afpChain.getSimilarity(); 529 identity = afpChain.getIdentity(); 530 } 531 532 533 String algorithmName = afpChain.getAlgorithmName(); 534 //String version = afpChain.getVersion(); 535 536 double probability = afpChain.getProbability(); 537 538 539 // == end of extractation of data values from afpChain 540 541 StringBuffer txt = new StringBuffer(); 542 543 txt.append(String.format("Align %s.pdb Length1: %d with %s.pdb Length2: %d", name1, ca1Length, name2, ca2Length)); 544 545 txt.append(newline); 546 547 if ( afpChain.isShortAlign()){ 548 txt.append("Short match"); 549 return txt.toString(); 550 } 551 552 printScore(txt, algorithmName, probability, false); 553 printScoresInLines(afpChain, blockNum, optLength, totalRmsdOpt, alignScore, alnLength, gapLen,identity, similarity, txt); 554 txt.append(newline); 555 556 int[] optLen = afpChain.getOptLen(); 557 int[][][] optAln = afpChain.getOptAln(); 558 559 560 int i, j,p1, p2; 561 562 int k; 563 int p1b = 0; 564 int p2b = 0; 565 566 int len = 0; 567 StringWriter alnseq1 = new StringWriter(); 568 StringWriter alnseq2 = new StringWriter(); 569 StringWriter alnsymb = new StringWriter(); 570 StringWriter header1 = new StringWriter(); 571 StringWriter footer1 = new StringWriter(); 572 StringWriter header2 = new StringWriter(); 573 StringWriter footer2 = new StringWriter(); 574 StringWriter block = new StringWriter(); 575 576 int aligPos = -1; 577 for(i = 0; i < blockNum; i ++) { 578 579 for(j = 0; j < optLen[i]; j ++) { 580 581 p1 = optAln[i][0][j]; 582 p2 = optAln[i][1][j]; 583 aligPos++; 584 585 // System.out.println(p1 + " " + p2 + " " + footer2.toString()); 586 587 if ( len == 0){ 588 //the first position of sequence in alignment 589 formatStartingText(p1,p2,header1,header2,footer1,footer2,ca1,ca2); 590 } else { 591 // check for gapped region 592 int lmax = (p1 - p1b - 1)>(p2 - p2b - 1)?(p1 - p1b - 1):(p2 - p2b - 1); 593 for(k = 0; k < lmax; k ++) { 594 595 596 formatGappedRegion(ca1, ca2, txt, p1, p2, k, p1b, p2b, alnseq1, alnseq2, alnsymb, header1, footer1, header2, 597 footer2, block,len, showHTML); 598 len++; 599 doLenCheck(len,txt,header1,header2,alnseq1,alnsymb,alnseq2,footer1, footer2,block, showHTML) ; 600 } 601 } 602 603 // ALIGNED REGION 604 // System.out.println(len + " >" + header1.toString() +"< "); 605 // System.out.println(len + " >" + header2.toString() +"< "); 606 // System.out.println(len + " >" + alnseq1.toString() +"< "); 607 // System.out.println(len + " >" + alnsymb.toString() +"< "); 608 // System.out.println(len + " >" + alnseq2.toString() +"< "); 609 // System.out.println(len + " >" + footer1.toString() +"< "); 610 formatAlignedRegion(afpChain, ca1, ca2, p1, p2, alnseq1, alnseq2, alnsymb, header1, footer1, header2, footer2, block,len, aligPos, showHTML, showAlignmentBlock); 611 // System.out.println(len + " >" + header1.toString() +"< "); 612 // System.out.println(len + " >" + header2.toString() +"< "); 613 // System.out.println(len + " >" + alnseq1.toString() +"< "); 614 // System.out.println(len + " >" + alnsymb.toString() +"< "); 615 // System.out.println(len + " >" + alnseq2.toString() +"< "); 616 // System.out.println(len + " >" + footer1.toString() +"< "); 617 618 len++; 619 620 doLenCheck(len,txt,header1,header2,alnseq1,alnsymb,alnseq2,footer1, footer2,block, showHTML) ; 621 622 p1b = p1; 623 p2b = p2; 624 625 //header1.append(newline); 626 //header2.append(newline); 627 628 } 629 630 } 631 632 alnLength = len; 633 634 doLenCheck(LINELENGTH,txt,header1,header2,alnseq1,alnsymb,alnseq2,footer1, footer2,block, showHTML); 635 return txt.toString(); 636 } 637 638 /** 639 * Prints the alignment in the simplest form: a list of aligned residues. 640 * Format is one line per residue pair, tab delimited: 641 * <ul><li>1. PDB number. Includes insertion code</li> 642 * <li>1. Chain.</li> 643 * <li>1. Amino Acid. Three letter code.</li> 644 * <li>2. PDB number.</li> 645 * <li>2. Chain.</li> 646 * <li>2. Amino Acid.</li> 647 * </ul> 648 * example: 649 * <code>152 A ALA 161S A VAL</code> 650 * <p>Note that this format loses information about blocks. 651 * @param afpChain 652 * @param ca1 653 * @param ca2 654 * @return a String representation of the aligned pairs. 655 */ 656 public static String toAlignedPairs(AFPChain afpChain, Atom[] ca1, Atom[] ca2) { 657 StringWriter pairs = new StringWriter(); 658 659 //Write structure names & PDB codes 660 pairs.append("#Struct1:\t"); 661 pairs.append(afpChain.getName1()); 662 pairs.append("\n"); 663 pairs.append("#Struct2:\t"); 664 pairs.append(afpChain.getName2()); 665 pairs.append("\n"); 666 667 //Write optimally aligned pairs 668 pairs.append("#Num1\tChain1\tAA1\tNum2\tChain2\tAA2\n"); 669 int[][][] optAln = afpChain.getOptAln(); 670 int[] blockLen = afpChain.getOptLen(); 671 for( int block=0;block<afpChain.getBlockNum(); block++) { 672 for(int i=0;i<blockLen[block];i++) { 673 Atom atom1 = ca1[ optAln[block][0][i] ]; 674 Atom atom2 = ca2[ optAln[block][1][i] ]; 675 676 pairs.append(atom1.getGroup().getResidueNumber().toString()); 677 pairs.append('\t'); 678 pairs.append(atom1.getGroup().getChain().getName()); 679 pairs.append('\t'); 680 pairs.append(atom1.getGroup().getPDBName()); 681 pairs.append('\t'); 682 pairs.append(atom2.getGroup().getResidueNumber().toString()); 683 pairs.append('\t'); 684 pairs.append(atom2.getGroup().getChain().getName()); 685 pairs.append('\t'); 686 pairs.append(atom2.getGroup().getPDBName()); 687 pairs.append('\n'); 688 } 689 } 690 691 return pairs.toString(); 692 } 693 694 private static void formatGappedRegion(Atom[] ca1, Atom[] ca2, StringBuffer txt, int p1, int p2, int k, int p1b, int p2b, 695 StringWriter alnseq1, StringWriter alnseq2, StringWriter alnsymb, StringWriter header1, StringWriter footer1, 696 StringWriter header2, StringWriter footer2, StringWriter block, int len, boolean formatHTML) { 697 698 // DEAL WITH GAPS 699 int tmppos = (p1 - p1b - 1); 700 block.append("g"); 701 702 int pos1=p1b+1+k ; 703 char oneletter1 = ' '; 704 try { 705 oneletter1 = getOneLetter(ca1[pos1].getGroup()); 706 } catch (Exception e){} 707 int pos2=p2b+1+k; 708 char oneletter2 = ' '; 709 try { 710 oneletter2 = getOneLetter(ca2[pos2].getGroup()); 711 } catch (Exception e){} 712 713 714 if(k >= tmppos) { 715 //alnseq1[len] = '-'; 716 if ( formatHTML){ 717 alnseq1.append("<span class=\"qg\">-</span>"); 718 header1.append(" "); 719 header2.append(" "); 720 721 722 } else { 723 alnseq1.append('-'); 724 header1.append(" "); 725 header2.append(" "); 726 } 727 728 } 729 else { 730 if ( formatHTML){ 731 alnseq1.append(getPrefix(oneletter1,oneletter2,0,-1, false)); 732 } 733 alnseq1.append(oneletter1); 734 if (formatHTML){ 735 alnseq1.append("</span>"); 736 } 737 formatPosition(pos1,ca1, len, header1, header2); 738 739 } 740 741 if(k >= (p2 - p2b - 1)) { 742 //alnseq2[len] = '-'; 743 if ( formatHTML){ 744 alnseq2.append("<span class=\"qg\">-</span>"); 745 footer1.append(" "); 746 footer2.append(" "); 747 } else { 748 alnseq2.append('-'); 749 footer1.append(" "); 750 footer2.append(" "); 751 } 752 753 } 754 else { 755 if ( formatHTML){ 756 alnseq2.append(getPrefix(oneletter1,oneletter2,1, -1, false)); 757 } 758 alnseq2.append(oneletter2); 759 if (formatHTML){ 760 alnseq2.append("</span>"); 761 } 762 formatPosition(pos2, ca2, len, footer1, footer2); 763 764 } 765 //alnsymb[len ++] = ' '; 766 alnsymb.append(' '); 767 768 } 769 770 771 772 private static CharSequence getPrefix(char oneletter1, char oneletter2, 773 int i, int blockNr, boolean showAlignmentBlock) { 774 775 if ( oneletter1 == '-' || oneletter2 == '-' ) { 776 // a gap in the alignment. 777 // label as mismatch 778 return "<span class=\"qg\">"; 779 } 780 781 // an aligned position 782 783 if ( showAlignmentBlock && blockNr > -1){ 784 return "<span class=\"alignmentBlock"+(i+1)+(blockNr+1)+"\">"; 785 } 786 787 // we return the "default" sequence alignment view... 788 789 if ( oneletter1 == oneletter2) 790 return "<span class=\"m\">"; 791 792 double score = AFPAlignmentDisplay.aaScore(oneletter1,oneletter2); 793 if ( score > 0 ) 794 return "<span class=\"sm\">"; 795 796 // not similar 797 return "<span class=\"qg\">"; 798 } 799 800 private static void formatPosition(int pos1, Atom[] ca, int len, StringWriter header1, StringWriter header2) 801 { 802 int linePos = len % LINELENGTH; 803 804 if ( header1.getBuffer().length() < linePos) { 805 // fill up the buffer, we are probably shortly after the start... 806 for ( int i = header1.getBuffer().length() ; i< linePos ; i++){ 807 header1.append(" "); 808 } 809 } 810 811 812 813 Atom a = ca[pos1]; 814 Group g = a.getGroup(); 815 816 ResidueNumber residueNumber = g.getResidueNumber(); 817 pos1 = residueNumber.getSeqNum(); 818 boolean hasInsertionCode = false; 819 if ( residueNumber.getInsCode() != null) { 820 hasInsertionCode = true; 821 } 822 823 if ( (pos1 %10 == 0) && ( ! hasInsertionCode)) { 824 CharSequence display = getPDBPos(a); 825 826 boolean ignoreH1 = false; 827 828 // make sure we don't have a problem with the left boundary... 829 if ( header1.getBuffer().length()-1 > linePos) { 830 ignoreH1 = true; 831 //System.out.println("Ignore h1: " + len + " " + header1.getBuffer().length() + " linePos: " + linePos +" >" + header1.toString() +"<"); 832 } 833 //System.out.println(len + " p1:" + tmp + " = " + pos1 + " " + " " + display + " " + ignoreH1); 834 if ( ! ignoreH1) { 835 header1.append(String.format("%-13s",display )); 836 header2.append("|"); 837 } else { 838 header2.append("|"); 839 } 840 841 } else if ( hasInsertionCode){ 842 Character insCode = g.getResidueNumber().getInsCode(); 843 if ( insCode != null) 844 header2.append(insCode); 845 else { 846 header2.append("!"); 847 } 848 } else if ( ((pos1) %5 ) == 0 && len > 5) { 849 header2.append("."); 850 } else { 851 if ( len > 0) 852 header2.append(" "); 853 } 854 855 } 856 857 858 859 private static void formatAlignedRegion(AFPChain afpChain, Atom[] ca1, Atom[] ca2, int p1, int p2, 860 StringWriter alnseq1, StringWriter alnseq2, 861 StringWriter alnsymb, StringWriter header1, StringWriter footer1, StringWriter header2, 862 StringWriter footer2, StringWriter block, int len, int aligPos, 863 boolean showHTML, boolean showAlignmentBlock) 864 { 865 char c1; 866 char c2; 867 if (( p1 < ca1.length) && (p2< ca2.length)){ 868 c1= getOneLetter(ca1[p1].getGroup()); 869 c2 = getOneLetter(ca2[p2].getGroup()); 870 } else { 871 c1 = 'X'; 872 c2 = 'X'; 873 } 874 875 int blockPos = -1; 876 if ( afpChain.getBlockNum() > 0) { 877 blockPos = AFPAlignmentDisplay.getBlockNrForAlignPos(afpChain, aligPos); 878 } 879 880 881 882 double score = AFPAlignmentDisplay.aaScore(c1,c2); 883 884 if ( showHTML) { 885 alnseq1.append(getPrefix(c1,c2, 0, blockPos, showAlignmentBlock)); 886 alnseq2.append(getPrefix(c1,c2, 1, blockPos, showAlignmentBlock)); 887 } 888 889 alnseq1.append(c1); 890 alnseq2.append(c2); 891 892 if ( showHTML){ 893 alnseq1.append("</span>"); 894 alnseq2.append("</span>"); 895 } 896 897 if ( c1 == c2){ 898 if ( showHTML){ 899 900 alnsymb.append("<span class=\"m\">|</span>"); 901 902 } else { 903 alnsymb.append('|'); 904 } 905 //alnsymb[len ++] = '|'; 906 } else { 907 908 909 if ( score > 1) { 910 if ( showHTML){ 911 alnsymb.append( "<span class=\"sm\">:</span>"); 912 } else { 913 alnsymb.append( ':'); 914 } 915 } 916 else { 917 if ( showHTML) 918 alnsymb.append( "<span class=\"qg\">.</span>"); 919 else 920 alnsymb.append( '.'); 921 } 922 } 923 924 if ( p1 < ca1.length) 925 formatPosition(p1, ca1,len, header1, header2); 926 927 if ( p2 < ca2.length) 928 formatPosition(p2,ca2,len, footer1, footer2); 929 930 } 931 932 private static void formatStartingText(int p1, int p2, StringWriter header1, StringWriter header2, StringWriter footer1, 933 StringWriter footer2, Atom[] ca1, Atom[] ca2) 934 { 935 936 header1.append(String.format("%-13s", getPDBPos(ca1[p1]))); 937 header2.append("|"); 938 footer1.append(String.format("%-13s", getPDBPos(ca2[p2]))); 939 footer2.append("|"); 940 941 942 } 943 944 private static boolean doLenCheck(int len, StringBuffer txt, StringWriter header1, StringWriter header2, StringWriter alnseq1, 945 StringWriter alnsymb, StringWriter alnseq2, StringWriter footer1, StringWriter footer2, StringWriter block, boolean formatHTML) 946 { 947 948 if ( len % LINELENGTH == 0) { 949 950 //txt.append("|"); 951 txt.append(header1); 952 //txt.append("|"); 953 txt.append(newline); 954 //txt.append("|"); 955 txt.append(header2); 956 //txt.append("|"); 957 txt.append(newline); 958 //txt.append("|"); 959 txt.append(alnseq1); 960 //txt.append("|"); 961 txt.append(newline); 962 963 //txt.append("|"); 964 txt.append(alnsymb); 965 // txt.append(newline); 966 // txt.append(block); 967 //txt.append("|"); 968 txt.append(newline); 969 //txt.append("|"); 970 txt.append(alnseq2); 971 //txt.append("|"); 972 txt.append(newline); 973 //txt.append("|"); 974 txt.append(footer2); 975 //txt.append("|"); 976 txt.append(newline); 977 //txt.append("|"); 978 txt.append(footer1); 979 //txt.append("|"); 980 txt.append(newline); 981 txt.append(newline); 982 txt.append(newline); 983 984 if (formatHTML ) { 985 986 int len1 = alnseq1.getBuffer().length(); 987 int len2 = alnseq2.getBuffer().length(); 988 int lens = alnsymb.getBuffer().length(); 989 alnseq1.getBuffer().replace(0, len1, ""); 990 alnseq2.getBuffer().replace(0, len2, ""); 991 alnsymb.getBuffer().replace(0, lens, ""); 992 993 994 995 header1.getBuffer().replace(0, LINELENGTH, ""); 996 header2.getBuffer().replace(0, LINELENGTH , ""); 997 footer1.getBuffer().replace(0, LINELENGTH, ""); 998 footer2.getBuffer().replace(0, LINELENGTH, ""); 999 block.getBuffer().replace(0, LINELENGTH, ""); 1000 } else { 1001 alnseq1.getBuffer().replace(0, LINELENGTH, ""); 1002 alnseq2.getBuffer().replace(0, LINELENGTH, ""); 1003 alnsymb.getBuffer().replace(0, LINELENGTH, ""); 1004 header1.getBuffer().replace(0, LINELENGTH, ""); 1005 header2.getBuffer().replace(0, LINELENGTH , ""); 1006 footer1.getBuffer().replace(0, LINELENGTH, ""); 1007 footer2.getBuffer().replace(0, LINELENGTH, ""); 1008 block.getBuffer().replace(0, LINELENGTH, ""); 1009 } 1010 StringBuffer buf = header1.getBuffer(); 1011 for ( int i=0;i<buf.length();i++){ 1012 char c = buf.charAt(i); 1013 if ( c != ' '){ 1014 buf.setCharAt(i, ' '); 1015 } 1016 } 1017 buf = footer1.getBuffer(); 1018 for ( int i=0;i<buf.length();i++){ 1019 char c = buf.charAt(i); 1020 if ( c != ' '){ 1021 buf.setCharAt(i, ' '); 1022 } 1023 } 1024 1025 return true; 1026 } 1027 1028 return false; 1029 1030 1031 } 1032 1033 private static CharSequence getPDBPos(Atom atom) 1034 { 1035 1036 Group g = atom.getGroup(); 1037 if ( g!= null){ 1038 Chain c = g.getChain(); 1039 if (c != null){ 1040 return g.getResidueNumber().toString()+":" + c.getName() ; 1041 //return g.getPDBCode()+":" + c.getName() + "." + getOneLetter(g) ; 1042 } 1043 } 1044 return "!"; 1045 } 1046 1047 private static char getOneLetter(Group g){ 1048 1049 1050 if (g==null) return StructureTools.UNKNOWN_GROUP_LABEL; 1051 1052 1053 return StructureTools.get1LetterCode(g.getPDBName()); 1054 1055 1056 } 1057 1058 1059 public static String toDBSearchResult(AFPChain afpChain) 1060 { 1061 StringBuffer str = new StringBuffer(); 1062 1063 str.append(afpChain.getName1()); 1064 str.append("\t"); 1065 str.append(afpChain.getName2()); 1066 str.append("\t"); 1067 str.append(String.format("%.2f",afpChain.getAlignScore())); 1068 str.append("\t"); 1069 if ( afpChain.getAlgorithmName().equalsIgnoreCase(CeMain.algorithmName)){ 1070 str.append(String.format("%.2f",afpChain.getProbability())); 1071 } else { 1072 str.append(String.format("%.2e",afpChain.getProbability())); 1073 } 1074 str.append("\t"); 1075 str.append(String.format("%.2f",afpChain.getTotalRmsdOpt())); 1076 str.append("\t"); 1077 str.append(afpChain.getCa1Length()); 1078 str.append("\t"); 1079 str.append(afpChain.getCa2Length()); 1080 str.append("\t"); 1081 str.append(afpChain.getCoverage1()); 1082 str.append("\t"); 1083 str.append(afpChain.getCoverage2()); 1084 str.append("\t"); 1085 str.append(String.format("%.2f",afpChain.getIdentity())); 1086 str.append("\t"); 1087 str.append(afpChain.getDescription2()); 1088 str.append("\t"); 1089 str.append(newline); 1090 1091 return str.toString(); 1092 } 1093 1094 public static String toRotMat(AFPChain afpChain) 1095 { 1096 1097 Matrix[] blockRotationMatrix = afpChain.getBlockRotationMatrix(); 1098 int blockNum = afpChain.getBlockNum(); 1099 Atom[] blockShiftVector = afpChain.getBlockShiftVector(); 1100 1101 StringBuffer txt = new StringBuffer(); 1102 1103 if ( blockRotationMatrix == null || blockRotationMatrix.length < 1) 1104 return ""; 1105 1106 1107 for ( int blockNr = 0 ; blockNr < blockNum ; blockNr++){ 1108 Matrix m = blockRotationMatrix[blockNr]; 1109 Atom shift = blockShiftVector[blockNr]; 1110 if ( blockNum > 1) { 1111 txt.append("Operations for block " ); 1112 txt.append(blockNr); 1113 txt.append(newline); 1114 } 1115 1116 String origString = "orig"; 1117 if ( blockNr > 0) 1118 origString = String.valueOf(blockNr); 1119 1120 1121 txt.append(String.format(" X"+(blockNr+1)+" = (%9.6f)*X"+ origString +" + (%9.6f)*Y"+ origString +" + (%9.6f)*Z"+ origString +" + (%12.6f)",m.get(0,0),m.get(1,0), m.get(2,0), shift.getX())); 1122 txt.append( newline); 1123 txt.append(String.format(" Y"+(blockNr+1)+" = (%9.6f)*X"+ origString +" + (%9.6f)*Y"+ origString +" + (%9.6f)*Z"+ origString +" + (%12.6f)",m.get(0,1),m.get(1,1), m.get(2,1), shift.getY())); 1124 txt.append( newline); 1125 txt.append(String.format(" Z"+(blockNr+1)+" = (%9.6f)*X"+ origString +" + (%9.6f)*Y"+ origString +" + (%9.6f)*Z"+ origString +" + (%12.6f)",m.get(0,2),m.get(1,2), m.get(2,2), shift.getZ())); 1126 txt.append(newline); 1127 } 1128 return txt.toString(); 1129 } 1130 1131 public static String toCE(AFPChain afpChain, Atom[] ca1, Atom[] ca2) 1132 { 1133 1134 1135 1136 String name1 = afpChain.getName1(); 1137 String name2 = afpChain.getName2(); 1138 1139 int optLength = afpChain.getOptLength(); 1140 double totalRmsdOpt = afpChain.getTotalRmsdOpt(); 1141 1142 int alnLength = afpChain.getAlnLength(); 1143 int gapLen = afpChain.getGapLen(); 1144 1145 1146 double similarity = afpChain.getSimilarity(); 1147 double identity = afpChain.getIdentity(); 1148 if (similarity <0 || identity <0 ){ 1149 afpChain.calcSimilarity(); 1150 similarity = afpChain.getSimilarity(); 1151 identity = afpChain.getIdentity(); 1152 } 1153 1154 1155 1156 double probability = afpChain.getProbability(); 1157 1158 1159 int alnbeg1 = afpChain.getAlnbeg1(); 1160 int alnbeg2 = afpChain.getAlnbeg2(); 1161 1162 char[] alnseq1 = afpChain.getAlnseq1(); 1163 char[] alnseq2 = afpChain.getAlnseq2(); 1164 1165 1166 long calculationTime = afpChain.getCalculationTime(); 1167 1168 // == end of extractation of data values from afpChain 1169 1170 1171 1172 StringBuffer txt = new StringBuffer(); 1173 1174 txt.append("Chain 1: "); 1175 txt.append(name1); 1176 txt.append(" (Size="); 1177 txt.append(ca1.length); 1178 txt.append(")"); 1179 txt.append(newline); 1180 txt.append("Chain 2: "); 1181 txt.append(name2); 1182 txt.append(" (Size="); 1183 txt.append(ca2.length); 1184 txt.append(")"); 1185 txt.append(newline); 1186 txt.append(newline); 1187 txt.append(String.format("Alignment length = %d Rmsd = %.2fA Z-Score = %.1f",optLength,totalRmsdOpt,probability)); 1188 txt.append(String.format(" Gaps = %d(%.1f%%) CPU = %d ms. Sequence identities = %.1f%%",gapLen,( gapLen*100.0/optLength),calculationTime,identity*100)); 1189 1190 int linelen = 70; 1191 String a; 1192 String b; 1193 1194 1195 1196 int t = 0; 1197 int ap = alnbeg1; 1198 int bp = alnbeg2; 1199 int k, len; 1200 1201 while((alnLength - t) > 0) { 1202 if(alnLength - t > linelen) len = linelen; 1203 else len = alnLength - t; 1204 1205 1206 //System.err.println("t,len:"+t+":"+len); 1207 a = new String(alnseq1).substring(t,t+len); 1208 b = new String(alnseq2).substring(t,t+len); 1209 1210 //System.err.println("B:" + b); 1211 1212 /* 1213 txt.append(newline); 1214 txt.append(String.format("%14s", " ")); 1215 1216 for(k = 10; k <= len; k += 10) 1217 txt.append(" . :"); 1218 if(k <= len + 5) txt.append(" ."); 1219 */ 1220 1221 //String pdb1 = ca1[ap].getParent().getPDBCode(); 1222 //String pdb2 = ca2[bp].getParent().getPDBCode(); 1223 txt.append(newline); 1224 txt.append(String.format("Chain 1:%5s %s"+newline+"Chain 2:%5s %s", 1225 (ap+1), a, (bp+1), b)); 1226 txt.append(newline); 1227 for(k = 0; k < len; k ++) { 1228 if(a.charAt(k) != '-') ap ++; 1229 if(b.charAt(k) != '-') bp ++; 1230 } 1231 t += len; 1232 1233 } 1234 txt.append(newline); 1235 1236 txt.append(toRotMat(afpChain)); 1237 1238 return txt.toString(); 1239 1240 1241 } 1242 1243 1244 1245 1246 1247 1248}