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(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 private 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 507 508 private static String toPrettyAlignment(AFPChain afpChain, Atom[] ca1, Atom[] ca2, boolean showHTML, boolean showAlignmentBlock) { 509 String name1 = afpChain.getName1(); 510 String name2 = afpChain.getName2(); 511 int ca1Length = afpChain.getCa1Length(); 512 int ca2Length = afpChain.getCa2Length(); 513 514 int blockNum = afpChain.getBlockNum(); 515 516 517 int optLength = afpChain.getOptLength(); 518 double totalRmsdOpt = afpChain.getTotalRmsdOpt(); 519 520 double alignScore = afpChain.getAlignScore(); 521 int alnLength = afpChain.getAlnLength(); 522 int gapLen = afpChain.getGapLen(); 523 524 525 double similarity = afpChain.getSimilarity(); 526 double identity = afpChain.getIdentity(); 527 528 if (similarity <0 || identity < 0){ 529 afpChain.calcSimilarity(); 530 similarity = afpChain.getSimilarity(); 531 identity = afpChain.getIdentity(); 532 } 533 534 535 String algorithmName = afpChain.getAlgorithmName(); 536 //String version = afpChain.getVersion(); 537 538 double probability = afpChain.getProbability(); 539 540 541 // == end of extractation of data values from afpChain 542 543 StringBuffer txt = new StringBuffer(); 544 545 txt.append(String.format("Align %s.pdb Length1: %d with %s.pdb Length2: %d", name1, ca1Length, name2, ca2Length)); 546 547 txt.append(newline); 548 549 if ( afpChain.isShortAlign()){ 550 txt.append("Short match"); 551 return txt.toString(); 552 } 553 554 printScore(txt, algorithmName, probability, false); 555 printScoresInLines(afpChain, blockNum, optLength, totalRmsdOpt, alignScore, alnLength, gapLen,identity, similarity, txt); 556 txt.append(newline); 557 558 int[] optLen = afpChain.getOptLen(); 559 int[][][] optAln = afpChain.getOptAln(); 560 561 562 int i, j,p1, p2; 563 564 int k; 565 int p1b = 0; 566 int p2b = 0; 567 568 int len = 0; 569 StringWriter alnseq1 = new StringWriter(); 570 StringWriter alnseq2 = new StringWriter(); 571 StringWriter alnsymb = new StringWriter(); 572 StringWriter header1 = new StringWriter(); 573 StringWriter footer1 = new StringWriter(); 574 StringWriter header2 = new StringWriter(); 575 StringWriter footer2 = new StringWriter(); 576 StringWriter block = new StringWriter(); 577 578 int aligPos = -1; 579 for(i = 0; i < blockNum; i ++) { 580 581 for(j = 0; j < optLen[i]; j ++) { 582 583 p1 = optAln[i][0][j]; 584 p2 = optAln[i][1][j]; 585 aligPos++; 586 587 // System.out.println(p1 + " " + p2 + " " + footer2.toString()); 588 589 if ( len == 0){ 590 //the first position of sequence in alignment 591 formatStartingText(p1,p2,header1,header2,footer1,footer2,ca1,ca2); 592 } else { 593 // check for gapped region 594 int lmax = (p1 - p1b - 1)>(p2 - p2b - 1)?(p1 - p1b - 1):(p2 - p2b - 1); 595 for(k = 0; k < lmax; k ++) { 596 597 598 formatGappedRegion(ca1, ca2, txt, p1, p2, k, p1b, p2b, alnseq1, alnseq2, alnsymb, header1, footer1, header2, 599 footer2, block,len, showHTML); 600 len++; 601 doLenCheck(len,txt,header1,header2,alnseq1,alnsymb,alnseq2,footer1, footer2,block, showHTML) ; 602 } 603 } 604 605 // ALIGNED REGION 606 // System.out.println(len + " >" + header1.toString() +"< "); 607 // System.out.println(len + " >" + header2.toString() +"< "); 608 // System.out.println(len + " >" + alnseq1.toString() +"< "); 609 // System.out.println(len + " >" + alnsymb.toString() +"< "); 610 // System.out.println(len + " >" + alnseq2.toString() +"< "); 611 // System.out.println(len + " >" + footer1.toString() +"< "); 612 formatAlignedRegion(afpChain, ca1, ca2, p1, p2, alnseq1, alnseq2, alnsymb, header1, footer1, header2, footer2, block,len, aligPos, showHTML, showAlignmentBlock); 613 // System.out.println(len + " >" + header1.toString() +"< "); 614 // System.out.println(len + " >" + header2.toString() +"< "); 615 // System.out.println(len + " >" + alnseq1.toString() +"< "); 616 // System.out.println(len + " >" + alnsymb.toString() +"< "); 617 // System.out.println(len + " >" + alnseq2.toString() +"< "); 618 // System.out.println(len + " >" + footer1.toString() +"< "); 619 620 len++; 621 622 doLenCheck(len,txt,header1,header2,alnseq1,alnsymb,alnseq2,footer1, footer2,block, showHTML) ; 623 624 p1b = p1; 625 p2b = p2; 626 627 //header1.append(newline); 628 //header2.append(newline); 629 630 } 631 632 } 633 634 alnLength = len; 635 636 doLenCheck(LINELENGTH,txt,header1,header2,alnseq1,alnsymb,alnseq2,footer1, footer2,block, showHTML); 637 return txt.toString(); 638 } 639 640 /** 641 * Prints the alignment in the simplest form: a list of aligned residues. 642 * Format is one line per residue pair, tab delimited: 643 * <ul><li>1. PDB number. Includes insertion code</li> 644 * <li>1. Chain.</li> 645 * <li>1. Amino Acid. Three letter code.</li> 646 * <li>2. PDB number.</li> 647 * <li>2. Chain.</li> 648 * <li>2. Amino Acid.</li> 649 * </ul> 650 * example: 651 * <code>152 A ALA 161S A VAL</code> 652 * <p>Note that this format loses information about blocks. 653 * @param afpChain 654 * @param ca1 655 * @param ca2 656 * @return a String representation of the aligned pairs. 657 */ 658 public static String toAlignedPairs(AFPChain afpChain, Atom[] ca1, Atom[] ca2) { 659 StringWriter pairs = new StringWriter(); 660 661 //Write structure names & PDB codes 662 pairs.append("#Struct1:\t"); 663 pairs.append(afpChain.getName1()); 664 pairs.append("\n"); 665 pairs.append("#Struct2:\t"); 666 pairs.append(afpChain.getName2()); 667 pairs.append("\n"); 668 669 //Write optimally aligned pairs 670 pairs.append("#Num1\tChain1\tAA1\tNum2\tChain2\tAA2\n"); 671 int[][][] optAln = afpChain.getOptAln(); 672 int[] blockLen = afpChain.getOptLen(); 673 for( int block=0;block<afpChain.getBlockNum(); block++) { 674 for(int i=0;i<blockLen[block];i++) { 675 Atom atom1 = ca1[ optAln[block][0][i] ]; 676 Atom atom2 = ca2[ optAln[block][1][i] ]; 677 678 pairs.append(atom1.getGroup().getResidueNumber().toString()); 679 pairs.append('\t'); 680 pairs.append(atom1.getGroup().getChain().getChainID()); 681 pairs.append('\t'); 682 pairs.append(atom1.getGroup().getPDBName()); 683 pairs.append('\t'); 684 pairs.append(atom2.getGroup().getResidueNumber().toString()); 685 pairs.append('\t'); 686 pairs.append(atom2.getGroup().getChain().getChainID()); 687 pairs.append('\t'); 688 pairs.append(atom2.getGroup().getPDBName()); 689 pairs.append('\n'); 690 } 691 } 692 693 return pairs.toString(); 694 } 695 696 private static void formatGappedRegion(Atom[] ca1, Atom[] ca2, StringBuffer txt, int p1, int p2, int k, int p1b, int p2b, 697 StringWriter alnseq1, StringWriter alnseq2, StringWriter alnsymb, StringWriter header1, StringWriter footer1, 698 StringWriter header2, StringWriter footer2, StringWriter block, int len, boolean formatHTML) { 699 700 // DEAL WITH GAPS 701 int tmppos = (p1 - p1b - 1); 702 block.append("g"); 703 704 int pos1=p1b+1+k ; 705 char oneletter1 = ' '; 706 try { 707 oneletter1 = getOneLetter(ca1[pos1].getGroup()); 708 } catch (Exception e){} 709 int pos2=p2b+1+k; 710 char oneletter2 = ' '; 711 try { 712 oneletter2 = getOneLetter(ca2[pos2].getGroup()); 713 } catch (Exception e){} 714 715 716 if(k >= tmppos) { 717 //alnseq1[len] = '-'; 718 if ( formatHTML){ 719 alnseq1.append("<span class=\"qg\">-</span>"); 720 header1.append(" "); 721 header2.append(" "); 722 723 724 } else { 725 alnseq1.append('-'); 726 header1.append(" "); 727 header2.append(" "); 728 } 729 730 } 731 else { 732 if ( formatHTML){ 733 alnseq1.append(getPrefix(oneletter1,oneletter2,0,-1, false)); 734 } 735 alnseq1.append(oneletter1); 736 if (formatHTML){ 737 alnseq1.append("</span>"); 738 } 739 formatPosition(pos1,ca1, len, header1, header2); 740 741 } 742 743 if(k >= (p2 - p2b - 1)) { 744 //alnseq2[len] = '-'; 745 if ( formatHTML){ 746 alnseq2.append("<span class=\"qg\">-</span>"); 747 footer1.append(" "); 748 footer2.append(" "); 749 } else { 750 alnseq2.append('-'); 751 footer1.append(" "); 752 footer2.append(" "); 753 } 754 755 } 756 else { 757 if ( formatHTML){ 758 alnseq2.append(getPrefix(oneletter1,oneletter2,1, -1, false)); 759 } 760 alnseq2.append(oneletter2); 761 if (formatHTML){ 762 alnseq2.append("</span>"); 763 } 764 formatPosition(pos2, ca2, len, footer1, footer2); 765 766 } 767 //alnsymb[len ++] = ' '; 768 alnsymb.append(' '); 769 770 } 771 772 773 774 private static CharSequence getPrefix(char oneletter1, char oneletter2, 775 int i, int blockNr, boolean showAlignmentBlock) { 776 777 if ( oneletter1 == '-' || oneletter2 == '-' ) { 778 // a gap in the alignment. 779 // label as mismatch 780 return "<span class=\"qg\">"; 781 } 782 783 // an aligned position 784 785 if ( showAlignmentBlock && blockNr > -1){ 786 return "<span class=\"alignmentBlock"+(i+1)+(blockNr+1)+"\">"; 787 } 788 789 // we return the "default" sequence alignment view... 790 791 if ( oneletter1 == oneletter2) 792 return "<span class=\"m\">"; 793 794 double score = AFPAlignmentDisplay.aaScore(oneletter1,oneletter2); 795 if ( score > 0 ) 796 return "<span class=\"sm\">"; 797 798 // not similar 799 return "<span class=\"qg\">"; 800 } 801 802 private static void formatPosition(int pos1, Atom[] ca, int len, StringWriter header1, StringWriter header2) 803 { 804 int linePos = len % LINELENGTH; 805 806 if ( header1.getBuffer().length() < linePos) { 807 // fill up the buffer, we are probably shortly after the start... 808 for ( int i = header1.getBuffer().length() ; i< linePos ; i++){ 809 header1.append(" "); 810 } 811 } 812 813 814 815 Atom a = ca[pos1]; 816 Group g = a.getGroup(); 817 818 ResidueNumber residueNumber = g.getResidueNumber(); 819 pos1 = residueNumber.getSeqNum(); 820 boolean hasInsertionCode = false; 821 if ( residueNumber.getInsCode() != null) { 822 hasInsertionCode = true; 823 } 824 825 if ( (pos1 %10 == 0) && ( ! hasInsertionCode)) { 826 CharSequence display = getPDBPos(a); 827 828 boolean ignoreH1 = false; 829 830 // make sure we don't have a problem with the left boundary... 831 if ( header1.getBuffer().length()-1 > linePos) { 832 ignoreH1 = true; 833 //System.out.println("Ignore h1: " + len + " " + header1.getBuffer().length() + " linePos: " + linePos +" >" + header1.toString() +"<"); 834 } 835 //System.out.println(len + " p1:" + tmp + " = " + pos1 + " " + " " + display + " " + ignoreH1); 836 if ( ! ignoreH1) { 837 header1.append(String.format("%-13s",display )); 838 header2.append("|"); 839 } else { 840 header2.append("|"); 841 } 842 843 } else if ( hasInsertionCode){ 844 Character insCode = g.getResidueNumber().getInsCode(); 845 if ( insCode != null) 846 header2.append(insCode); 847 else { 848 header2.append("!"); 849 } 850 } else if ( ((pos1) %5 ) == 0 && len > 5) { 851 header2.append("."); 852 } else { 853 if ( len > 0) 854 header2.append(" "); 855 } 856 857 } 858 859 860 861 private static void formatAlignedRegion(AFPChain afpChain, Atom[] ca1, Atom[] ca2, int p1, int p2, 862 StringWriter alnseq1, StringWriter alnseq2, 863 StringWriter alnsymb, StringWriter header1, StringWriter footer1, StringWriter header2, 864 StringWriter footer2, StringWriter block, int len, int aligPos, 865 boolean showHTML, boolean showAlignmentBlock) 866 { 867 char c1; 868 char c2; 869 if (( p1 < ca1.length) && (p2< ca2.length)){ 870 c1= getOneLetter(ca1[p1].getGroup()); 871 c2 = getOneLetter(ca2[p2].getGroup()); 872 } else { 873 c1 = 'X'; 874 c2 = 'X'; 875 } 876 877 int blockPos = -1; 878 if ( afpChain.getBlockNum() > 0) { 879 blockPos = AFPAlignmentDisplay.getBlockNrForAlignPos(afpChain, aligPos); 880 } 881 882 883 884 double score = AFPAlignmentDisplay.aaScore(c1,c2); 885 886 if ( showHTML) { 887 alnseq1.append(getPrefix(c1,c2, 0, blockPos, showAlignmentBlock)); 888 alnseq2.append(getPrefix(c1,c2, 1, blockPos, showAlignmentBlock)); 889 } 890 891 alnseq1.append(c1); 892 alnseq2.append(c2); 893 894 if ( showHTML){ 895 alnseq1.append("</span>"); 896 alnseq2.append("</span>"); 897 } 898 899 if ( c1 == c2){ 900 if ( showHTML){ 901 902 alnsymb.append("<span class=\"m\">|</span>"); 903 904 } else { 905 alnsymb.append('|'); 906 } 907 //alnsymb[len ++] = '|'; 908 } else { 909 910 911 if ( score > 1) { 912 if ( showHTML){ 913 alnsymb.append( "<span class=\"sm\">:</span>"); 914 } else { 915 alnsymb.append( ':'); 916 } 917 } 918 else { 919 if ( showHTML) 920 alnsymb.append( "<span class=\"qg\">.</span>"); 921 else 922 alnsymb.append( '.'); 923 } 924 } 925 926 if ( p1 < ca1.length) 927 formatPosition(p1, ca1,len, header1, header2); 928 929 if ( p2 < ca2.length) 930 formatPosition(p2,ca2,len, footer1, footer2); 931 932 } 933 934 private static void formatStartingText(int p1, int p2, StringWriter header1, StringWriter header2, StringWriter footer1, 935 StringWriter footer2, Atom[] ca1, Atom[] ca2) 936 { 937 938 header1.append(String.format("%-13s", getPDBPos(ca1[p1]))); 939 header2.append("|"); 940 footer1.append(String.format("%-13s", getPDBPos(ca2[p2]))); 941 footer2.append("|"); 942 943 944 } 945 946 private static boolean doLenCheck(int len, StringBuffer txt, StringWriter header1, StringWriter header2, StringWriter alnseq1, 947 StringWriter alnsymb, StringWriter alnseq2, StringWriter footer1, StringWriter footer2, StringWriter block, boolean formatHTML) 948 { 949 950 if ( len % LINELENGTH == 0) { 951 952 //txt.append("|"); 953 txt.append(header1); 954 //txt.append("|"); 955 txt.append(newline); 956 //txt.append("|"); 957 txt.append(header2); 958 //txt.append("|"); 959 txt.append(newline); 960 //txt.append("|"); 961 txt.append(alnseq1); 962 //txt.append("|"); 963 txt.append(newline); 964 965 //txt.append("|"); 966 txt.append(alnsymb); 967 // txt.append(newline); 968 // txt.append(block); 969 //txt.append("|"); 970 txt.append(newline); 971 //txt.append("|"); 972 txt.append(alnseq2); 973 //txt.append("|"); 974 txt.append(newline); 975 //txt.append("|"); 976 txt.append(footer2); 977 //txt.append("|"); 978 txt.append(newline); 979 //txt.append("|"); 980 txt.append(footer1); 981 //txt.append("|"); 982 txt.append(newline); 983 txt.append(newline); 984 txt.append(newline); 985 986 if (formatHTML ) { 987 988 int len1 = alnseq1.getBuffer().length(); 989 int len2 = alnseq2.getBuffer().length(); 990 int lens = alnsymb.getBuffer().length(); 991 alnseq1.getBuffer().replace(0, len1, ""); 992 alnseq2.getBuffer().replace(0, len2, ""); 993 alnsymb.getBuffer().replace(0, lens, ""); 994 995 996 997 header1.getBuffer().replace(0, LINELENGTH, ""); 998 header2.getBuffer().replace(0, LINELENGTH , ""); 999 footer1.getBuffer().replace(0, LINELENGTH, ""); 1000 footer2.getBuffer().replace(0, LINELENGTH, ""); 1001 block.getBuffer().replace(0, LINELENGTH, ""); 1002 } else { 1003 alnseq1.getBuffer().replace(0, LINELENGTH, ""); 1004 alnseq2.getBuffer().replace(0, LINELENGTH, ""); 1005 alnsymb.getBuffer().replace(0, LINELENGTH, ""); 1006 header1.getBuffer().replace(0, LINELENGTH, ""); 1007 header2.getBuffer().replace(0, LINELENGTH , ""); 1008 footer1.getBuffer().replace(0, LINELENGTH, ""); 1009 footer2.getBuffer().replace(0, LINELENGTH, ""); 1010 block.getBuffer().replace(0, LINELENGTH, ""); 1011 } 1012 StringBuffer buf = header1.getBuffer(); 1013 for ( int i=0;i<buf.length();i++){ 1014 char c = buf.charAt(i); 1015 if ( c != ' '){ 1016 buf.setCharAt(i, ' '); 1017 } 1018 } 1019 buf = footer1.getBuffer(); 1020 for ( int i=0;i<buf.length();i++){ 1021 char c = buf.charAt(i); 1022 if ( c != ' '){ 1023 buf.setCharAt(i, ' '); 1024 } 1025 } 1026 1027 return true; 1028 } 1029 1030 return false; 1031 1032 1033 } 1034 1035 private static CharSequence getPDBPos(Atom atom) 1036 { 1037 1038 Group g = atom.getGroup(); 1039 if ( g!= null){ 1040 Chain c = g.getChain(); 1041 if (c != null){ 1042 return g.getResidueNumber().toString()+":" + c.getChainID() ; 1043 //return g.getPDBCode()+":" + c.getName() + "." + getOneLetter(g) ; 1044 } 1045 } 1046 return "!"; 1047 } 1048 1049 private static char getOneLetter(Group g){ 1050 1051 1052 if (g==null) return StructureTools.UNKNOWN_GROUP_LABEL; 1053 1054 1055 return StructureTools.get1LetterCode(g.getPDBName()); 1056 1057 1058 } 1059 1060 1061 public static String toDBSearchResult(AFPChain afpChain) 1062 { 1063 StringBuffer str = new StringBuffer(); 1064 1065 str.append(afpChain.getName1()); 1066 str.append("\t"); 1067 str.append(afpChain.getName2()); 1068 str.append("\t"); 1069 str.append(String.format("%.2f",afpChain.getAlignScore())); 1070 str.append("\t"); 1071 if ( afpChain.getAlgorithmName().equalsIgnoreCase(CeMain.algorithmName)){ 1072 str.append(String.format("%.2f",afpChain.getProbability())); 1073 } else { 1074 str.append(String.format("%.2e",afpChain.getProbability())); 1075 } 1076 str.append("\t"); 1077 str.append(String.format("%.2f",afpChain.getTotalRmsdOpt())); 1078 str.append("\t"); 1079 str.append(afpChain.getCa1Length()); 1080 str.append("\t"); 1081 str.append(afpChain.getCa2Length()); 1082 str.append("\t"); 1083 str.append(afpChain.getCoverage1()); 1084 str.append("\t"); 1085 str.append(afpChain.getCoverage2()); 1086 str.append("\t"); 1087 str.append(String.format("%.2f",afpChain.getIdentity())); 1088 str.append("\t"); 1089 str.append(afpChain.getDescription2()); 1090 str.append("\t"); 1091 str.append(newline); 1092 1093 return str.toString(); 1094 } 1095 1096 public static String toRotMat(AFPChain afpChain) 1097 { 1098 1099 Matrix[] blockRotationMatrix = afpChain.getBlockRotationMatrix(); 1100 int blockNum = afpChain.getBlockNum(); 1101 Atom[] blockShiftVector = afpChain.getBlockShiftVector(); 1102 1103 StringBuffer txt = new StringBuffer(); 1104 1105 if ( blockRotationMatrix == null || blockRotationMatrix.length < 1) 1106 return ""; 1107 1108 1109 for ( int blockNr = 0 ; blockNr < blockNum ; blockNr++){ 1110 Matrix m = blockRotationMatrix[blockNr]; 1111 Atom shift = blockShiftVector[blockNr]; 1112 if ( blockNum > 1) { 1113 txt.append("Operations for block " ); 1114 txt.append(blockNr); 1115 txt.append(newline); 1116 } 1117 1118 String origString = "orig"; 1119 if ( blockNr > 0) 1120 origString = (blockNr)+""; 1121 1122 1123 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())); 1124 txt.append( newline); 1125 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())); 1126 txt.append( newline); 1127 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())); 1128 txt.append(newline); 1129 } 1130 return txt.toString(); 1131 } 1132 1133 public static String toCE(AFPChain afpChain, Atom[] ca1, Atom[] ca2) 1134 { 1135 1136 1137 1138 String name1 = afpChain.getName1(); 1139 String name2 = afpChain.getName2(); 1140 1141 int optLength = afpChain.getOptLength(); 1142 double totalRmsdOpt = afpChain.getTotalRmsdOpt(); 1143 1144 int alnLength = afpChain.getAlnLength(); 1145 int gapLen = afpChain.getGapLen(); 1146 1147 1148 double similarity = afpChain.getSimilarity(); 1149 double identity = afpChain.getIdentity(); 1150 if (similarity <0 || identity <0 ){ 1151 afpChain.calcSimilarity(); 1152 similarity = afpChain.getSimilarity(); 1153 identity = afpChain.getIdentity(); 1154 } 1155 1156 1157 1158 double probability = afpChain.getProbability(); 1159 1160 1161 int alnbeg1 = afpChain.getAlnbeg1(); 1162 int alnbeg2 = afpChain.getAlnbeg2(); 1163 1164 char[] alnseq1 = afpChain.getAlnseq1(); 1165 char[] alnseq2 = afpChain.getAlnseq2(); 1166 1167 1168 long calculationTime = afpChain.getCalculationTime(); 1169 1170 // == end of extractation of data values from afpChain 1171 1172 1173 1174 StringBuffer txt = new StringBuffer(); 1175 1176 txt.append("Chain 1: "); 1177 txt.append(name1); 1178 txt.append(" (Size="); 1179 txt.append(ca1.length); 1180 txt.append(")"); 1181 txt.append(newline); 1182 txt.append("Chain 2: "); 1183 txt.append(name2); 1184 txt.append(" (Size="); 1185 txt.append(ca2.length); 1186 txt.append(")"); 1187 txt.append(newline); 1188 txt.append(newline); 1189 txt.append(String.format("Alignment length = %d Rmsd = %.2fA Z-Score = %.1f",optLength,totalRmsdOpt,probability)); 1190 txt.append(String.format(" Gaps = %d(%.1f%%) CPU = %d ms. Sequence identities = %.1f%%",gapLen,( gapLen*100.0/optLength),calculationTime,identity*100)); 1191 1192 int linelen = 70; 1193 String a; 1194 String b; 1195 1196 1197 1198 int t = 0; 1199 int ap = alnbeg1; 1200 int bp = alnbeg2; 1201 int k, len; 1202 1203 while((alnLength - t) > 0) { 1204 if(alnLength - t > linelen) len = linelen; 1205 else len = alnLength - t; 1206 1207 1208 //System.err.println("t,len:"+t+":"+len); 1209 a = new String(alnseq1).substring(t,t+len); 1210 b = new String(alnseq2).substring(t,t+len); 1211 1212 //System.err.println("B:" + b); 1213 1214 /* 1215 txt.append(newline); 1216 txt.append(String.format("%14s", " ")); 1217 1218 for(k = 10; k <= len; k += 10) 1219 txt.append(" . :"); 1220 if(k <= len + 5) txt.append(" ."); 1221 */ 1222 1223 //String pdb1 = ca1[ap].getParent().getPDBCode(); 1224 //String pdb2 = ca2[bp].getParent().getPDBCode(); 1225 txt.append(newline); 1226 txt.append(String.format("Chain 1:%5s %s"+newline+"Chain 2:%5s %s", 1227 (ap+1), a, (bp+1), b)); 1228 txt.append(newline); 1229 for(k = 0; k < len; k ++) { 1230 if(a.charAt(k) != '-') ap ++; 1231 if(b.charAt(k) != '-') bp ++; 1232 } 1233 t += len; 1234 1235 } 1236 txt.append(newline); 1237 1238 txt.append(toRotMat(afpChain)); 1239 1240 return txt.toString(); 1241 1242 1243 } 1244 1245 1246 1247 1248 1249 1250}