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 */ 021package org.biojava.nbio.structure.secstruc; 022 023import java.util.Locale; 024 025import org.biojava.nbio.structure.Atom; 026import org.biojava.nbio.structure.Group; 027import org.biojava.nbio.structure.StructureTools; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031/** 032 * This class extends the basic container for secondary structure annotation, 033 * including all the information used in the DSSP algorithm. 034 * 035 * @author Andreas Prlic 036 * @author Aleix Lafita 037 * 038 */ 039public class SecStrucState extends SecStrucInfo { 040 041 private static final long serialVersionUID = -5549430890272724340L; 042 043 private static final Logger logger = LoggerFactory 044 .getLogger(SecStrucState.class); 045 046 private double phi; 047 private double psi; 048 private double omega; 049 private float kappa; 050 051 private HBond accept1; // from CO of partner to NH of this 052 private HBond accept2; // this is the donor of accept partner 053 private HBond donor1; // from CO of this to NH of partner 054 private HBond donor2; // this is the acceptor of donor partner 055 056 // Symbols: starting '>', ending '<', or both 'X'. 057 // Number means bracketed n-turn residue without h-bond 058 private char[] turn; 059 private boolean bend; 060 061 private BetaBridge bridge1; 062 private BetaBridge bridge2; 063 064 public SecStrucState(Group g, String ass, SecStrucType t) { 065 super(g, ass, t); 066 067 phi = 360; 068 psi = 360; 069 omega = 360; 070 071 accept1 = new HBond(); 072 accept2 = new HBond(); 073 donor1 = new HBond(); 074 donor2 = new HBond(); 075 076 bridge1 = null; 077 bridge2 = null; 078 079 turn = new char[3]; 080 turn[0] = ' '; 081 turn[1] = ' '; 082 turn[2] = ' '; 083 084 bend = false; 085 kappa = 360; 086 } 087 088 public boolean isBend() { 089 return bend; 090 } 091 092 public void setBend(boolean bend) { 093 this.bend = bend; 094 } 095 096 public float getKappa() { 097 return kappa; 098 } 099 100 public void setKappa(float kappa) { 101 this.kappa = kappa; 102 } 103 104 public char[] getTurn() { 105 return turn; 106 } 107 108 /** 109 * Set the turn column corresponding to 3,4 or 5 helix patterns. If starting 110 * > or ending < was set and the opposite is being set, the value will be 111 * converted to X. If a number was set, it will be overwritten by the new 112 * character. 113 * 114 * @param c 115 * character in the column 116 * @param t 117 * turn of the helix {3,4,5} 118 */ 119 public void setTurn(char c, int t) { 120 if (turn[t - 3] == 'X') 121 return; 122 else if (turn[t - 3] == '<' && c == '>' || turn[t - 3] == '>' 123 && c == '<') { 124 turn[t - 3] = 'X'; 125 } else if (turn[t - 3] == '<' || turn[t - 3] == '>') 126 return; 127 else 128 turn[t - 3] = c; 129 } 130 131 public HBond getAccept1() { 132 return accept1; 133 } 134 135 public void setAccept1(HBond accept1) { 136 this.accept1 = accept1; 137 } 138 139 public HBond getAccept2() { 140 return accept2; 141 } 142 143 public void setAccept2(HBond accept2) { 144 this.accept2 = accept2; 145 } 146 147 public HBond getDonor1() { 148 return donor1; 149 } 150 151 public void setDonor1(HBond donor1) { 152 this.donor1 = donor1; 153 } 154 155 public HBond getDonor2() { 156 return donor2; 157 } 158 159 public void setDonor2(HBond donor2) { 160 this.donor2 = donor2; 161 } 162 163 public double getPhi() { 164 return phi; 165 } 166 167 public void setPhi(double phi) { 168 this.phi = phi; 169 } 170 171 public double getPsi() { 172 return psi; 173 } 174 175 public void setPsi(double psi) { 176 this.psi = psi; 177 } 178 179 public double getOmega() { 180 return omega; 181 } 182 183 public void setOmega(double omega) { 184 this.omega = omega; 185 } 186 187 public BetaBridge getBridge1() { 188 return bridge1; 189 } 190 191 public BetaBridge getBridge2() { 192 return bridge2; 193 } 194 195 /** 196 * Adds a Bridge to the residue. Each residue can only store two bridges. If 197 * the residue contains already two Bridges, the Bridge will not be added 198 * and the method returns false. 199 * 200 * @param bridge 201 * @return false if the Bridge was not added, true otherwise 202 */ 203 public boolean addBridge(BetaBridge bridge) { 204 if (bridge1 == null) { 205 bridge1 = bridge; 206 return true; 207 } else if (bridge1.equals(bridge)) { 208 return true; 209 } else if (bridge2 == null) { 210 bridge2 = bridge; 211 return true; 212 } else if (bridge2.equals(bridge)) { 213 return true; 214 } else { //no space left, cannot add the bridge 215 logger.info("Residue forms more than 2 beta Bridges, " 216 + "DSSP output might differ in Bridges column."); 217 return false; 218 } 219 } 220 221 public void setBridge1(BetaBridge bridge1) { 222 this.bridge1 = bridge1; 223 } 224 225 public void setBridge2(BetaBridge bridge2) { 226 this.bridge2 = bridge2; 227 } 228 229 public String printDSSPline(int index) { 230 231 StringBuffer buf = new StringBuffer(); 232 233 // # 234 if (index < 9) 235 buf.append(" "); 236 else if (index < 99) 237 buf.append(" "); 238 else if (index < 999) 239 buf.append(" "); 240 else 241 buf.append(" "); 242 buf.append(index + 1); 243 244 // RESIDUE 245 int resnum = parent.getResidueNumber().getSeqNum(); 246 if (resnum < 10) 247 buf.append(" "); 248 else if (resnum < 100) 249 buf.append(" "); 250 else 251 buf.append(" "); 252 buf.append(resnum); 253 Character insCode = parent.getResidueNumber().getInsCode(); 254 if (insCode != null) 255 buf.append(insCode); 256 else 257 buf.append(" "); 258 buf.append(parent.getChainId()); 259 if (parent.getChainId().length() == 1) 260 buf.append(" "); 261 262 // AA 263 char aaLetter = StructureTools.get1LetterCode(parent.getPDBName()); 264 buf.append(aaLetter).append(" "); 265 266 // STRUCTURE 267 buf.append(type).append(" "); 268 269 for (int t = 0; t < 3; t++) { 270 buf.append(turn[t]); 271 } 272 273 buf.append(" "); 274 275 if (isBend()) 276 buf.append('S'); 277 else 278 buf.append(" "); 279 280 buf.append(" "); 281 282 int bp1 = 0; 283 if (bridge1 != null) { 284 if (bridge1.partner1 != index) 285 bp1 = bridge1.partner1 + 1; 286 else 287 bp1 = bridge1.partner2 + 1; 288 } 289 // TODO a clever way to do this? 290 if (bp1 < 10) 291 buf.append(" ").append(bp1); 292 else if (bp1 < 100) 293 buf.append(" ").append(bp1); 294 else if (bp1 < 1000) 295 buf.append(" ").append(bp1); 296 else 297 buf.append(bp1); 298 299 int bp2 = 0; 300 if (bridge2 != null) { 301 if (bridge2.partner1 != index) 302 bp2 = bridge2.partner1 + 1; 303 else 304 bp2 = bridge2.partner2 + 1; 305 } 306 if (bp2 < 10) 307 buf.append(" ").append(bp2); 308 else if (bp2 < 100) 309 buf.append(" ").append(bp2); 310 else if (bp2 < 1000) 311 buf.append(" ").append(bp2); 312 else 313 buf.append(bp2); 314 315 // beta-sheet label TODO 316 buf.append(" "); 317 318 // ACC TODO 319 buf.append(" "); 320 321 // N-H-->O 322 int p1 = accept1.getPartner(); 323 double e1 = (accept1.getEnergy() / 1000.0); 324 if (e1 < 0.0) 325 p1 -= index; 326 buf.append(String.format(Locale.US, "%6d,%4.1f", p1, e1)); 327 328 // O-->H-N 329 int p2 = donor1.getPartner(); 330 double e2 = (donor1.getEnergy() / 1000.0); 331 if (e2 < 0.0) 332 p2 -= index; 333 buf.append(String.format(Locale.US, "%6d,%4.1f", p2, e2)); 334 335 // N-H-->O 336 int p3 = accept2.getPartner(); 337 double e3 = (accept2.getEnergy() / 1000.0); 338 if (e3 < 0.0) 339 p3 -= index; 340 buf.append(String.format(Locale.US, "%6d,%4.1f", p3, e3)); 341 342 // O-->H-N 343 int p4 = donor2.getPartner(); 344 double e4 = (donor2.getEnergy() / 1000.0); 345 if (e4 < 0.0) 346 p4 -= index; 347 buf.append(String.format(Locale.US, "%6d,%4.1f", p4, e4)); 348 349 // TCO TODO 350 buf.append(" "); 351 352 // KAPPA 353 buf.append(String.format(Locale.US, "%6.1f", kappa)); 354 355 // ALPHA TODO 356 buf.append(" "); 357 358 // PHI PSI 359 buf.append(String.format(Locale.US, "%6.1f %6.1f ", phi, psi)); 360 361 // X-CA Y-CA Z-CA 362 Atom ca = parent.getAtom("CA"); 363 buf.append(String.format(Locale.US, "%6.1f %6.1f %6.1f", ca.getX(), ca.getY(), 364 ca.getZ())); 365 366 return buf.toString(); 367 } 368 369}