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.cluster; 022 023import java.util.ArrayList; 024import java.util.List; 025 026import org.biojava.nbio.core.exceptions.CompoundNotFoundException; 027import org.biojava.nbio.structure.Structure; 028import org.biojava.nbio.structure.StructureException; 029import org.biojava.nbio.structure.symmetry.core.Stoichiometry; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033/** 034 * The SubunitClusterer takes as input a collection of {@link Subunit} and 035 * returns a collection of {@link SubunitCluster}. 036 * 037 * @author Aleix Lafita 038 * @since 5.0.0 039 * 040 */ 041public class SubunitClusterer { 042 043 private static final Logger logger = LoggerFactory 044 .getLogger(SubunitClusterer.class); 045 046 /** Prevent instantiation **/ 047 private SubunitClusterer() { 048 } 049 050 public static Stoichiometry cluster(Structure structure, 051 SubunitClustererParameters params) { 052 List<Subunit> subunits = SubunitExtractor.extractSubunits(structure, 053 params.getAbsoluteMinimumSequenceLength(), 054 params.getMinimumSequenceLengthFraction(), 055 params.getMinimumSequenceLength()); 056 return cluster(subunits, params); 057 } 058 059 public static Stoichiometry cluster(List<Subunit> subunits, 060 SubunitClustererParameters params) { 061 062 // The collection of clusters to return 063 List<SubunitCluster> clusters = new ArrayList<SubunitCluster>(); 064 065 if (subunits.size() == 0) 066 return new Stoichiometry(clusters); 067 068 // First generate a new cluster for each Subunit 069 for (Subunit s : subunits) 070 clusters.add(new SubunitCluster(s)); 071 072 if (params.getClustererMethod() == SubunitClustererMethod.SEQUENCE || 073 params.getClustererMethod() == SubunitClustererMethod.SEQUENCE_STRUCTURE) { 074 // Now merge clusters by SEQUENCE 075 for (int c1 = 0; c1 < clusters.size(); c1++) { 076 for (int c2 = clusters.size() - 1; c2 > c1; c2--) { 077 try { 078 if (clusters.get(c1).mergeSequence(clusters.get(c2), params)) { 079 clusters.remove(c2); 080 } 081 082 } catch (CompoundNotFoundException e) { 083 logger.warn("Could not merge by Sequence. {}", 084 e.getMessage()); 085 } 086 } 087 } 088 } 089 090 if (params.getClustererMethod() == SubunitClustererMethod.STRUCTURE || 091 params.getClustererMethod() == SubunitClustererMethod.SEQUENCE_STRUCTURE) { 092 // Now merge clusters by STRUCTURE 093 for (int c1 = 0; c1 < clusters.size(); c1++) { 094 for (int c2 = clusters.size() - 1; c2 > c1; c2--) { 095 try { 096 if (clusters.get(c1).mergeStructure(clusters.get(c2), params)) { 097 clusters.remove(c2); 098 } 099 } catch (StructureException e) { 100 logger.warn("Could not merge by Structure. {}", e.getMessage()); 101 } 102 } 103 } 104 } 105 106 if (params.isInternalSymmetry()) { 107 // Now divide clusters by their INTERNAL SYMMETRY 108 for (int c = 0; c < clusters.size(); c++) { 109 try { 110 clusters.get(c).divideInternally(params); 111 } catch (StructureException e) { 112 logger.warn("Error analyzing internal symmetry. {}", 113 e.getMessage()); 114 } 115 } 116 117 // After internal symmetry merge again by structural similarity 118 // Use case: C8 propeller with 3 chains with 3+3+2 repeats each 119 for (int c1 = 0; c1 < clusters.size(); c1++) { 120 for (int c2 = clusters.size() - 1; c2 > c1; c2--) { 121 try { 122 if (clusters.get(c1).mergeStructure(clusters.get(c2), params)) 123 clusters.remove(c2); 124 } catch (StructureException e) { 125 logger.warn("Could not merge by Structure. {}", 126 e.getMessage()); 127 } 128 } 129 } 130 } 131 132 return new Stoichiometry(clusters); 133 } 134}