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 2013-05-23 021 * 022 */ 023package org.biojava.nbio.structure.symmetry.core; 024 025import org.biojava.nbio.structure.Structure; 026import org.biojava.nbio.structure.cluster.Subunit; 027import org.biojava.nbio.structure.cluster.SubunitCluster; 028 029import java.util.ArrayList; 030import java.util.Collections; 031import java.util.List; 032 033/** 034 * Holds the results of quaternary symmetry perception obtained with 035 * {@link QuatSymmetryDetector}. 036 * 037 * @author Peter Rose 038 * @author Aleix Lafita 039 * 040 */ 041public class QuatSymmetryResults { 042 043 // Optional: the query Structure, if any 044 private Structure structure; 045 046 // Information about the clustering process 047 private Stoichiometry stoichiometry; 048 private boolean local = false; 049 050 // Cached properties 051 private List<SubunitCluster> clusters; 052 private List<Subunit> subunits; 053 054 // Information about the symmetry 055 private SymmetryPerceptionMethod method; 056 private HelixLayers helixLayers; 057 private RotationGroup rotationGroup = new RotationGroup(); 058 059 // TODO we should unify rotational and roto-translational results 060 061 /** 062 * Constructor for rotational symmetries. 063 * 064 * @param stoichiometry 065 * Stoichiometry used to calculate symmetry 066 * @param rotationGroup 067 * @param method 068 */ 069 public QuatSymmetryResults(Stoichiometry stoichiometry, 070 RotationGroup rotationGroup, SymmetryPerceptionMethod method) { 071 072 this.stoichiometry = stoichiometry; 073 this.clusters = stoichiometry.getClusters(); 074 075 subunits = new ArrayList<Subunit>(); 076 for (SubunitCluster c : clusters) { 077 subunits.addAll(c.getSubunits()); 078 } 079 080 this.rotationGroup = rotationGroup; 081 this.method = method; 082 } 083 084 /** 085 * Constructor for roto-translational symmetries. 086 * 087 * @param stoichiometry 088 * Stoichiometry used to calculate symmetry 089 * @param helixLayers 090 * @param method 091 */ 092 public QuatSymmetryResults(Stoichiometry stoichiometry, 093 HelixLayers helixLayers, SymmetryPerceptionMethod method) { 094 095 this.stoichiometry = stoichiometry; 096 this.clusters = stoichiometry.getClusters(); 097 098 subunits = new ArrayList<Subunit>(); 099 for (SubunitCluster c : clusters) { 100 subunits.addAll(c.getSubunits()); 101 } 102 103 this.helixLayers = helixLayers; 104 this.method = method; 105 } 106 107 /** 108 * Determine if this symmetry result is a subset of the other Symmetry result. 109 * Checks the following conditions: 110 * - 'Other' includes all subunits of 'this'. 111 * - 'Other' has the same or higher order than 'this'. 112 * 113 * Special treatment for the helical symmetry: 114 * - 'Other' includes all subunits of 'this'. 115 * - 'this' may be Cn, as well as H 116 * 117 * Note that isSupersededBy establishes a partial order, i.e. for some 118 * symmetries A and B, neither A.isSupersededBy(B) nor B.isSupersededBy(A) 119 * may be true. 120 * 121 * @param other 122 * QuatSymmetryResults 123 * 124 * @return true if other supersedes this, false otherwise 125 */ 126 127 public boolean isSupersededBy(QuatSymmetryResults other) { 128 if(other.getSymmetry().startsWith("H")) { 129 if(this.getSymmetry().startsWith("C") || this.getSymmetry().startsWith("H")) { 130 if (other.subunits.containsAll(this.subunits)) { 131 return true; 132 } 133 } 134 return false; 135 } 136 137 if (this.getSymmetry().startsWith("H")) { 138 return false; 139 } 140 141 if (this.rotationGroup.getOrder() <= other.rotationGroup.getOrder() && 142 other.subunits.containsAll(this.subunits)) { 143 return true; 144 } 145 return false; 146 } 147 148 /** 149 * Returns the List of SubunitCluster used to calculate symmetry. 150 * 151 * @return an unmodifiable view of the original List 152 */ 153 public List<SubunitCluster> getSubunitClusters() { 154 return Collections.unmodifiableList(clusters); 155 } 156 157 /** 158 * Returns the List of Subunits used to calculate symmetry. 159 * 160 * @return an unmodifiable view of the List 161 */ 162 public List<Subunit> getSubunits() { 163 return Collections.unmodifiableList(subunits); 164 } 165 166 /** 167 * Return the number of Subunits involved in the symmetry. 168 * 169 * @return the number of Subunits 170 */ 171 public int getSubunitCount() { 172 return subunits.size(); 173 } 174 175 /** 176 * @return rotation group (point group) information representing rotational 177 * quaternary symmetry. 178 */ 179 public RotationGroup getRotationGroup() { 180 return rotationGroup; 181 } 182 183 /** 184 * @return helix layers (layer lines) as a list of helices that describe a 185 * helical structure. 186 */ 187 public HelixLayers getHelixLayers() { 188 return helixLayers; 189 } 190 191 /** 192 * @return the method used for symmetry perception. 193 */ 194 public SymmetryPerceptionMethod getMethod() { 195 return method; 196 } 197 198 /** 199 * @return the symmetry group symbol. For point groups returns the point 200 * group symbol and for helical symmetry returns "H". 201 */ 202 public String getSymmetry() { 203 if (helixLayers != null && helixLayers.size() > 0) { 204 return "H"; 205 } else if (rotationGroup != null && rotationGroup.getOrder() > 0) { 206 return rotationGroup.getPointGroup(); 207 } 208 return ""; 209 } 210 211 /** 212 * @return the quaternary scores as an object 213 */ 214 public QuatSymmetryScores getScores() { 215 if (helixLayers != null && helixLayers.size() > 0) { 216 return helixLayers.getScores(); 217 } else if (rotationGroup != null && rotationGroup.getOrder() > 0) { 218 return rotationGroup.getScores(); 219 } 220 return new QuatSymmetryScores(); 221 } 222 223 public Stoichiometry getStoichiometry() { 224 return stoichiometry; 225 } 226 227 public boolean isPseudoStoichiometric() { 228 return stoichiometry.isPseudoStoichiometric(); 229 } 230 231 /** 232 * A local result means that only a subset of the original Subunits was used 233 * for symmetry determination. 234 * 235 * @return true if local result, false otherwise 236 */ 237 public boolean isLocal() { 238 return local; 239 } 240 241 /** 242 * A local result means that only a subset of the original Subunits was used 243 * for symmetry determination. 244 * 245 * @param local 246 * true if local result, false otherwise 247 */ 248 void setLocal(boolean local) { 249 this.local = local; 250 } 251 252 public Structure getStructure() { 253 return structure; 254 } 255 256 public void setStructure(Structure structure) { 257 this.structure = structure; 258 } 259 260 @Override 261 public String toString() { 262 return "QuatSymmetryResults [stoichiometry: " + getStoichiometry() 263 + ", symmetry: " + getSymmetry() + ", pseudo-stoichiometric: " 264 + isPseudoStoichiometric() + ", local: " + local + ", method: " 265 + method + "]"; 266 } 267 268}