1+ /*
2+ * BioJava development code
3+ *
4+ * This code may be freely distributed and modified under the
5+ * terms of the GNU Lesser General Public Licence. This should
6+ * be distributed with the code. If you do not have a copy,
7+ * see:
8+ *
9+ * http://www.gnu.org/copyleft/lesser.html
10+ *
11+ * Copyright for this code is held jointly by the individual
12+ * authors. These should be listed in @author doc comments.
13+ *
14+ * For more information on the BioJava project and its aims,
15+ * or to join the biojava-l mailing list, visit the home page
16+ * at:
17+ *
18+ * http://www.biojava.org/
19+ *
20+ */
21+
122package org .biojava .bio .structure .quaternary ;
223
324import java .util .ArrayList ;
425import java .util .Arrays ;
26+ import java .util .Collections ;
27+ import java .util .Comparator ;
528import java .util .List ;
629
730import org .biojava .bio .structure .Atom ;
1538import org .biojava .bio .structure .io .mmcif .model .PdbxStructOperList ;
1639import org .biojava .bio .structure .jama .Matrix ;
1740
18-
19-
20- /** Reconstructs the quaternary structure of a protein from an asymmetric unit
41+ /**
42+ * Reconstructs the quaternary structure of a protein from an asymmetric unit
2143 *
2244 * @author Peter Rose
2345 * @author Andreas Prlic
2446 *
2547 */
2648public class BiologicalAssemblyBuilder {
49+ private OperatorResolver operatorResolver ;
50+ private List <PdbxStructAssemblyGen > psags ;
2751
28- OperatorResolver operatorResolver ;
29-
30- String asymId ;
31-
32- PdbxStructAssembly psa ;
33- List <PdbxStructAssemblyGen > psags ;
34- //List<PdbxStructOperList> operators;
52+ private List <ModelTransformationMatrix > modelTransformations ;
3553
36- List <ModelTransformationMatrix > modelTransformations ;
37-
38- //List<String> asymIds;
3954 public BiologicalAssemblyBuilder (){
4055 init ();
4156 }
4257
43- private void init (){
44- operatorResolver = new OperatorResolver ();
45- modelTransformations = new ArrayList <ModelTransformationMatrix >(1 );
46-
47- }
48-
49-
50-
51-
5258 public Structure rebuildQuaternaryStructure (Structure asymUnit , List <ModelTransformationMatrix > transformations ){
53-
59+ // ensure that new chains are build in the same order as they appear in the asymmetric unit
60+ orderTransformationsByChainId (asymUnit , transformations );
61+
5462 Structure s = asymUnit .clone ();
5563 List <Chain > transformedChains = new ArrayList <Chain >();
5664 s .setChains (transformedChains );
57- //System.out.print("rebuilding " + s.getPDBCode() + " ");
58- //for (Chain c : s.getChains()) {
59- //System.out.print(c.getChainID());
60- //if ( c.getInternalChainID() != null) {
61- //System.out.print("("+c.getInternalChainID()+")");
62- //}
63-
64- //}
65-
66- //asymUnit.getPDBHeader().setBioUnitTranformations(transformations);
67-
6865
69- //double[] tmpcoords = new double[3];
7066 for (ModelTransformationMatrix max : transformations ){
71- boolean foundChain = false ;
72- for ( Chain c : asymUnit .getChains ()){
73-
67+ for (Chain c : asymUnit .getChains ()){
68+
7469 String intChainID = c .getInternalChainID ();
7570 if ( intChainID == null ) {
7671 //System.err.println("no internal chain ID found, using " + c.getChainID() + " ( while looking for " + max.ndbChainId+")");
7772 intChainID = c .getChainID ();
7873 }
7974
80- if ( max .ndbChainId .equals (intChainID )){
81-
82- /*System.out.println("transforming " + max.ndbChainId + " " + c.getChainID());
83- System.out.println(max );
84- System.out.println();
85- */
86- foundChain = true ;
87- Chain newChain = (Chain )c .clone ();
75+ if (max .getChainId ().equals (intChainID )){
76+ Chain chain = (Chain )c .clone ();
8877 Matrix m = max .getMatrix ();
89- //m = m.transpose();
9078 double [] vector = max .getVector ();
9179 Atom v = new AtomImpl ();
9280 v .setCoords (vector );
93- for ( Group g :newChain .getAtomGroups ()) {
94- for ( Atom a : g .getAtoms ()) {
95- //max.transformPoint(a.getCoords(), tmpcoords);
96- //a.setX(tmpcoords[0]);
97- //a.setY(tmpcoords[1]);
98- //a.setZ(tmpcoords[2]);
99- Calc .rotate (a , m );
100- Calc .shift (a , v );
101- }
81+ for (Group g : chain .getAtomGroups ()) {
82+ Calc .rotate (g , m );
83+ Calc .shift (g , v );
10284 }
10385
104-
105- addCheckChainModel (s ,newChain );
106-
86+ int modelNumber = Integer .parseInt (max .getId ());
87+ addChainAndModel (s , chain , modelNumber );
10788 }
10889 }
109- if (! foundChain ){
110- //System.err.println("could not transform chain: " + max.ndbChainId);
111- }
11290 }
11391
114- //s.setChains(transformedChains);
11592 s .setBiologicalAssembly (true );
11693 return s ;
117-
118-
11994 }
120-
121-
122- private void addCheckChainModel (Structure s , Chain newChain ) {
123- for ( int i = 0 ; i < s .nrModels () ; i ++){
124- List <Chain > model = s .getModel (i );
125- boolean found = false ;
126- for ( Chain c : model ){
127- if ( c .getChainID ().equals (newChain .getChainID ())) {
128- found = true ;
129- break ;
95+
96+ /**
97+ * Orders model transformations by chain ids in the same order as in the asymmetric unit
98+ * @param asymUnit
99+ * @param transformations
100+ */
101+ private void orderTransformationsByChainId (Structure asymUnit , List <ModelTransformationMatrix > transformations ) {
102+ final List <String > chainIds = getChainIds (asymUnit );
103+ Collections .sort (transformations , new Comparator <ModelTransformationMatrix >() {
104+ public int compare (ModelTransformationMatrix t1 , ModelTransformationMatrix t2 ) {
105+ // set sort order only if the two ids are identical
106+ if (t1 .getId ().equals (t2 .getId ())) {
107+ return chainIds .indexOf (t1 .getChainId ()) - chainIds .indexOf (t2 .getChainId ());
130108 }
109+ return 0 ;
110+ }
111+ });
112+ }
113+
114+ /**
115+ * Returns a list of chain ids in the order they are specified in the ATOM
116+ * records in the asymmetric unit
117+ * @param asymUnit
118+ * @return
119+ */
120+ private List <String > getChainIds (Structure asymUnit ) {
121+ List <String > chainIds = new ArrayList <String >();
122+ for ( Chain c : asymUnit .getChains ()){
123+ String intChainID = c .getInternalChainID ();
124+ if ( intChainID == null ) {
125+ //System.err.println("no internal chain ID found, using " + c.getChainID() + " ( while looking for " + max.ndbChainId+")");
126+ intChainID = c .getChainID ();
131127 }
132- if ( ! found ){
133-
134- model .add (newChain );
135- return ;
136- }
137-
128+ chainIds .add (intChainID );
129+ }
130+ return chainIds ;
131+ }
132+
133+ private void addChainAndModel (Structure s , Chain newChain , int modelCount ) {
134+ if (modelCount == 0 ) {
135+ s .addChain (newChain );
136+ } else if (modelCount > s .nrModels ()) {
137+ List <Chain > newModel = new ArrayList <Chain >();
138+ newModel .add (newChain );
139+ s .addModel (newModel );
140+ } else {
141+ s .addChain (newChain , modelCount -1 );
138142 }
139-
140- // all existing models contain already a chain with the same ID. add a new model
141- List <Chain > newModel = new ArrayList <Chain >();
142- newModel .add (newChain );
143- s .addModel (newModel );
144-
145-
146143 }
147144
148145 /**
@@ -153,26 +150,20 @@ private void addCheckChainModel(Structure s, Chain newChain) {
153150 * @return list of transformation matrices to generate macromolecular assembly
154151 */
155152 public ArrayList <ModelTransformationMatrix > getBioUnitTransformationList (PdbxStructAssembly psa , List <PdbxStructAssemblyGen > psags , List <PdbxStructOperList > operators ) {
156-
157153 //System.out.println("Rebuilding " + psa.getDetails() + " | " + psa.getOligomeric_details() + " | " + psa.getOligomeric_count());
158154 //System.out.println(psag);
159155 init ();
160- this .psa =psa ;
161156 this .psags = psags ;
162157
163- //this.operators = operators;
164-
165- asymId = psa .getId ();
158+ psa .getId ();
166159
167160 for (PdbxStructOperList oper : operators ){
168161 ModelTransformationMatrix transform = new ModelTransformationMatrix ();
169- transform .id = oper .getId ();
162+ transform .setId ( oper .getId () );
170163 transform .setTransformationMatrix (oper .getMatrix (), oper .getVector ());
171164 modelTransformations .add (transform );
172165 }
173166
174- ///
175-
176167 ArrayList <ModelTransformationMatrix > transformations = getBioUnitTransformationsListUnaryOperators (psa .getId ());
177168 transformations .addAll (getBioUnitTransformationsListBinaryOperators (psa .getId ()));
178169 transformations .trimToSize ();
@@ -193,7 +184,6 @@ private ArrayList<ModelTransformationMatrix> getBioUnitTransformationsListBinary
193184
194185 operatorResolver .parseOperatorExpressionString (psag .getOper_expression ());
195186
196-
197187 // apply binary operators to the specified chains
198188 // Example 1M4X: generates all products of transformation matrices (1-60)(61-88)
199189 for (String chainId : asymIds ) {
@@ -202,36 +192,29 @@ private ArrayList<ModelTransformationMatrix> getBioUnitTransformationsListBinary
202192 ModelTransformationMatrix original1 = getModelTransformationMatrix (operator .getElement1 ());
203193 ModelTransformationMatrix original2 = getModelTransformationMatrix (operator .getElement2 ());
204194 ModelTransformationMatrix transform = ModelTransformationMatrix .multiply4square_x_4square2 (original1 , original2 );
205- transform .ndbChainId = chainId ;
206- transform .id = original1 .id + "x" + original2 .id ;
195+ transform .setChainId ( chainId ) ;
196+ transform .setId ( original1 .getId () + "x" + original2 .getId ()) ;
207197 transformations .add (transform );
208198 }
209199 }
210-
211200 }
212201
213202 }
214203
215- // apply binary operators to the specified chains
216- // Example 1M4X: generates all products of transformation matrices (1-60)(61-88)
217-
218- //System.out.println("BioUnitTrasnformListBinaryOperators " + assemblyId + " " + transformations.size());
219204 return transformations ;
220205 }
221206
222207 private ModelTransformationMatrix getModelTransformationMatrix (String operator ) {
223208 for (ModelTransformationMatrix transform : modelTransformations ) {
224- if (transform .id .equals (operator )) {
209+ if (transform .getId () .equals (operator )) {
225210 return transform ;
226211 }
227212 }
228213 System .err .println ("Could not find modelTransformationmatrix for " + operator );
229214 return new ModelTransformationMatrix ();
230215 }
231216
232- private ArrayList <ModelTransformationMatrix > getBioUnitTransformationsListUnaryOperators (String assemblyId ) {
233-
234-
217+ private ArrayList <ModelTransformationMatrix > getBioUnitTransformationsListUnaryOperators (String assemblyId ) {
235218 ArrayList <ModelTransformationMatrix > transformations = new ArrayList <ModelTransformationMatrix >();
236219
237220
@@ -249,14 +232,19 @@ private ArrayList<ModelTransformationMatrix> getBioUnitTransformationsListUnaryO
249232 //System.out.println("transforming " + chainId + " " + operator);
250233 ModelTransformationMatrix original = getModelTransformationMatrix (operator );
251234 ModelTransformationMatrix transform = new ModelTransformationMatrix (original );
252- transform .ndbChainId = chainId ;
253- transform .id = operator ;
235+ transform .setChainId ( chainId ) ;
236+ transform .setId ( operator ) ;
254237 transformations .add (transform );
255238 }
256239 }
257240 }
258241 }
259- //System.out.println("BioUnitTrasnformListUnary " + assemblyId + " " + transformations.size());
242+
260243 return transformations ;
261244 }
245+
246+ private void init (){
247+ operatorResolver = new OperatorResolver ();
248+ modelTransformations = new ArrayList <ModelTransformationMatrix >(1 );
249+ }
262250}
0 commit comments