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