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 */ 021 022package org.biojava.nbio.structure.symmetry.core; 023 024import java.util.ArrayList; 025import java.util.List; 026 027/** 028 * 029 * @author Peter 030 */ 031public class HelixLayers { 032 private List<Helix> helices = new ArrayList<Helix>(); 033 private double symmetryDeviation = 0; 034 035 public int size() { 036 return helices.size(); 037 } 038 039 public void addHelix(Helix helix) { 040 helices.add(helix); 041 } 042 043 public Helix getHelix(int index) { 044 return helices.get(index); 045 } 046 047 /* 048 * Returns Helix with lowest twist angle 049 */ 050 public Helix getByLowestAngle() { 051 double angle = Double.MAX_VALUE; 052 Helix lowest = null; 053 for (Helix helix: helices) { 054 if (helix.getAngle() < angle) { 055 angle = helix.getAngle(); 056 lowest = helix; 057 } 058 } 059 return lowest; 060 } 061 062 /* 063 * Returns Helix with largest number of intermolecular contacts 064 * between repeat units 065 */ 066 public Helix getByLargestContacts() { 067 double contacts = 0; 068 Helix largest = null; 069 for (Helix helix: helices) { 070 if (helix.getContacts() > contacts) { 071 contacts = helix.getContacts(); 072 largest = helix; 073 } 074 } 075 return largest; 076 } 077 078 /* 079 * Returns Helix that has the largest number of contacts, besides 080 * the Helix with the lowest twist angle 081 */ 082 public Helix getByLargestContactsNotLowestAngle() { 083 double contacts = 0; 084 Helix lowest = getByLowestAngle(); 085 // TODO why are there helices with almost identical helix parameters?? 086 double angle = lowest.getAngle() + 0.05; 087 Helix largest = null; 088 for (Helix helix: helices) { 089 if (helix == lowest) { 090 continue; 091 } 092 if (helix.getContacts() > contacts && helix.getAngle() > angle) { 093 contacts = helix.getContacts(); 094 largest = helix; 095 } 096 } 097 if (largest == null) { 098 return lowest; 099 } 100 return largest; 101 } 102 103 /** 104 * Returns QuatSymmetryScores averaged over all rotations 105 * (except the first rotation, which is the unit operation E) 106 * @return mean scores average over rotations 107 */ 108 public QuatSymmetryScores getScores() { 109 QuatSymmetryScores scores = new QuatSymmetryScores(); 110 111 double[] values = new double[helices.size()]; 112 113 // minRmsd 114 for (int i = 0; i < helices.size(); i++) { 115 values[i] = helices.get(i).getScores().getMinRmsd(); 116 } 117 scores.setMinRmsd(minScores(values)); 118 119 // maxRmsd 120 for (int i = 0; i < helices.size(); i++) { 121 values[i] = helices.get(i).getScores().getMaxRmsd(); 122 } 123 scores.setMaxRmsd(maxScores(values)); 124 125 // Rmsd 126 for (int i = 0; i < helices.size(); i++) { 127 values[i] = helices.get(i).getScores().getRmsd(); 128 } 129 scores.setRmsd(averageScores(values)); 130 131 // minTm 132 for (int i = 0; i < helices.size(); i++) { 133 values[i] = helices.get(i).getScores().getMinTm(); 134 } 135 scores.setMinTm(minScores(values)); 136 137 // maxTm 138 for (int i = 0; i < helices.size(); i++) { 139 values[i] = helices.get(i).getScores().getMaxTm(); 140 } 141 scores.setMaxTm(maxScores(values)); 142 143 // Tm 144 for (int i = 0; i < helices.size(); i++) { 145 values[i] = helices.get(i).getScores().getTm(); 146 } 147 scores.setTm(averageScores(values)); 148 149 // Rmsd subunit centers 150 for (int i = 0; i < helices.size(); i++) { 151 values[i] = helices.get(i).getScores().getRmsdCenters(); 152 } 153 scores.setRmsdCenters(averageScores(values)); 154 155 // TmIntra 156 for (int i = 0; i < helices.size(); i++) { 157 values[i] = helices.get(i).getScores().getTmIntra(); 158 } 159 scores.setTmIntra(averageScores(values)); 160 161 // RmsdIntra 162 for (int i = 0; i < helices.size(); i++) { 163 values[i] = helices.get(i).getScores().getRmsdIntra(); 164 } 165 scores.setRmsdIntra(averageScores(values)); 166 167 // SymDeviation 168 scores.setSymDeviation(symmetryDeviation); 169 170 return scores; 171 } 172 173 /** 174 * @param symmetryDeviation the symmetryDeviation to set 175 */ 176 public void setSymmetryDeviation(double symmetryDeviation) { 177 this.symmetryDeviation = symmetryDeviation; 178 } 179 180 private double averageScores(double[] scores) { 181 double sum = 0; 182 for (double s: scores) { 183 sum += s; 184 } 185 return sum/scores.length; 186 } 187 188 private double minScores(double[] scores) { 189 double score = Double.MAX_VALUE; 190 for (double s: scores) { 191 score = Math.min(score, s); 192 } 193 return score; 194 } 195 196 private double maxScores(double[] scores) { 197 double score = Double.MIN_VALUE; 198 for (double s: scores) { 199 score = Math.max(score, s); 200 } 201 return score; 202 } 203 204 public void clear() { 205 helices.clear(); 206 } 207 208 @Override 209 public String toString() { 210 StringBuilder sb = new StringBuilder(); 211 sb.append("Helices: ").append(size()).append("\n"); 212 for (Helix s: helices) { 213 sb.append(s.toString()).append("\n"); 214 } 215 return sb.toString(); 216 } 217 218 219 220}