2525import java .util .List ;
2626
2727import javax .vecmath .Matrix4d ;
28+ import javax .vecmath .Point3d ;
2829
2930import org .biojava .nbio .structure .align .multiple .MultipleAlignment ;
31+ import org .biojava .nbio .structure .align .util .RotationAxis ;
3032import org .biojava .nbio .structure .symmetry .internal .CESymmParameters .SymmetryType ;
3133
3234/**
@@ -62,34 +64,93 @@ public class SymmetryAxes {
6264 /*
6365 * Implementation note: The tree is a nice explanation and a good image
6466 * for developing algorithms, but it is not constructed explicitly.
65- * Instead, we just store the axis and order for each level and reconstruct
67+ * Instead, we just store one elementary axis for each level and reconstruct
6668 * which operators apply to a particular leaf based on that leaf's index.
6769 */
70+
71+ /**
72+ * Represents an axis of symmetry
73+ * @author Spencer Bliven
74+ *
75+ */
76+ public static class Axis {
77+ private Matrix4d operator ;
78+ private int order ;
79+ private SymmetryType symmType ;
80+ private int level ;
81+
82+ public Axis (Matrix4d operator , int order , SymmetryType type ) {
83+ if (order < 2 ) {
84+ throw new IllegalArgumentException ("A symmetry axis should divide a structure in > 2 parts" );
85+ }
86+ if (type != SymmetryType .OPEN && type != SymmetryType .CLOSED ) {
87+ throw new IllegalArgumentException ("Invalid symmetry type. Only OPEN and CLOSED are allowed" );
88+ }
89+
90+ this .operator = operator ;
91+ this .order = order ;
92+ this .symmType = type ;
93+ this .level = -1 ;
94+ }
95+ /**
96+ * Get the transformation operator for this axis as an homogeneous matrix
97+ * @return the transformation operator
98+ */
99+ public Matrix4d getOperator () {
100+ return operator ;
101+ }
102+ public void setOperator (Matrix4d op ) {
103+ this .operator = op ;
104+ }
105+ /**
106+ * Get the order of this axis (closed symm) or the number of repeats
107+ * (open symm)
108+ * @return the order
109+ */
110+ public int getOrder () {
111+ return order ;
112+ }
113+ /**
114+ * @return the symmType (OPEN or CLOSED only)
115+ */
116+ public SymmetryType getSymmType () {
117+ return symmType ;
118+ }
119+
120+ /**
121+ * Get the transformation operator as a rotation axis. For open
122+ * symmetry this will have a non-zero screw component.
123+ * @return a RotationAxis for this Axis
124+ */
125+ public RotationAxis getRotationAxis () {
126+ return new RotationAxis (operator );
127+ }
128+ /**
129+ * @return The level of this axis within it's parent hierarchy, or -1 if unset
130+ */
131+ public int getLevel () {
132+ return level ;
133+ }
134+ public void setLevel (int level ) {
135+ if (level < 0 ) throw new IndexOutOfBoundsException ("Level must be positive" );
136+ this .level = level ;
137+ }
138+ }
139+
68140 /**
69141 * List of all symmetry axis. They are sorted from higher to lower
70142 * in the symmetry hierarchy, where higher means that they apply
71143 * more globally and lower means that they apply to a local region
72144 * of the higher axis division.
73- *
74- * (Operator for each level in the hierarchy)
75- */
76- private final List <Matrix4d > axes ;
77-
78- /**
79- * Degree (branching factor) for each level in the hierarchy. This should
80- * be the order of the corresponding transformation operator
81145 */
82- private final List <Integer > degrees ;
146+ private final List <Axis > axes ;
83147
84- private final List <SymmetryType > symmTypes ;
85148 /**
86149 * Constructor.
87150 * Initializes variables only.
88151 */
89152 public SymmetryAxes (){
90153 axes = new ArrayList <>();
91- degrees = new ArrayList <>();
92- symmTypes = new ArrayList <>();
93154 }
94155
95156 /**
@@ -139,16 +200,7 @@ public void addAxis(Matrix4d axis, List<List<Integer>> superposition,
139200 * @param type indicates whether the axis has OPEN or CLOSED symmetry
140201 */
141202 public void addAxis (Matrix4d axis , int order , SymmetryType type ) {
142- if (order < 2 ) {
143- throw new IllegalArgumentException ("A symmetry axis should divide a structure in > 2 parts" );
144- }
145- if (type != SymmetryType .OPEN && type != SymmetryType .CLOSED ) {
146- throw new IllegalArgumentException ("Invalid symmetry type. Only OPEN and CLOSED are allowed" );
147- }
148-
149- axes .add (axis );
150- degrees .add (order );
151- symmTypes .add (type );
203+ axes .add (new Axis (axis ,order ,type ));
152204 }
153205
154206 /**
@@ -157,17 +209,17 @@ public void addAxis(Matrix4d axis, int order, SymmetryType type) {
157209 * <P>
158210 * For instance, for a D3 case <tt>getAxisCounts(4)</tt> would return [2,0],
159211 * indicating that repeat 4 is generated by two applications of the 3-fold
160- * axis followed by 0 appications of the two-fold axis.
212+ * axis followed by 0 applications of the two-fold axis.
161213 *
162214 * @param repeat Index of the desired repeat
163215 * @return array of the same length as axes giving the number of times
164216 * to apply each axis.
165217 */
166218 private int [] getAxisCounts (int repeat ) {
167- int [] counts = new int [degrees . size ()];
219+ int [] counts = new int [getNumLevels ()];
168220
169221 for (int i = counts .length -1 ; i >= 0 ; i --) {
170- int d = degrees .get (i );
222+ int d = axes .get (i ). getOrder ( );
171223 counts [i ] = repeat % d ;
172224 repeat /= d ;
173225 }
@@ -184,7 +236,7 @@ private int[] getAxisCounts(int repeat) {
184236 private int getRepeatIndex (int [] counts ) {
185237 int repeat = 0 ;
186238 for (int i = 0 ; i < counts .length ; i ++) {
187- repeat += counts [i ]*degrees .get (i );
239+ repeat += counts [i ]*axes .get (i ). getOrder ( );
188240 }
189241 return repeat ;
190242 }
@@ -195,7 +247,7 @@ private int getRepeatIndex(int[] counts) {
195247 * @param newAxis
196248 */
197249 public void updateAxis (Integer index , Matrix4d newAxis ){
198- axes .set (index , newAxis );
250+ axes .get (index ). setOperator ( newAxis );
199251 }
200252
201253 /**
@@ -206,7 +258,11 @@ public void updateAxis(Integer index, Matrix4d newAxis){
206258 * @return axes elementary axes of symmetry.
207259 */
208260 public List <Matrix4d > getElementaryAxes (){
209- return axes ;
261+ List <Matrix4d > ops = new ArrayList <Matrix4d >(getNumLevels ());
262+ for (Axis axis : axes ) {
263+ ops .add (axis .getOperator ());
264+ }
265+ return ops ;
210266 }
211267
212268 /**
@@ -221,10 +277,11 @@ public List<Matrix4d> getElementaryAxes(){
221277 * level is invalid
222278 */
223279 public List <List <Integer >> getRepeatRelation (int level ){
280+ Axis axis = axes .get (level );
224281 int m = getNumRepeats (level +1 );//size of the children
225- int d = degrees . get ( level ); // degree of this node
282+ int d = axis . getOrder ( ); // degree of this node
226283 int n = m *d ; // number of repeats included
227- if (symmTypes . get ( level ) == SymmetryType .OPEN ) {
284+ if (axis . getSymmType ( ) == SymmetryType .OPEN ) {
228285 n -= m ; // leave off last child for open symm
229286 }
230287 List <Integer > repeats = new ArrayList <>(n );
@@ -254,7 +311,7 @@ public Matrix4d getRepeatTransform(int repeat){
254311 for (int t = counts .length -1 ; t >=0 ; t --) {
255312 if ( counts [t ] == 0 )
256313 continue ;
257- Matrix4d axis = new Matrix4d (axes .get (t ));
314+ Matrix4d axis = new Matrix4d (axes .get (t ). getOperator () );
258315 for (int i =0 ;i <counts [t ];i ++) {
259316 transform .mul (axis );
260317 }
@@ -269,9 +326,9 @@ public Matrix4d getRepeatTransform(int repeat){
269326 * degrees.
270327 * @return axes all symmetry axes of the structure.
271328 */
272- public List <Matrix4d > getSymmetryAxes (){
329+ public List <Axis > getSymmetryAxes (){
273330
274- List <Matrix4d > symmAxes = new ArrayList <Matrix4d >();
331+ List <Axis > symmAxes = new ArrayList <>();
275332
276333 Matrix4d prior = new Matrix4d ();
277334 prior .setIdentity ();
@@ -287,30 +344,34 @@ public List<Matrix4d> getSymmetryAxes(){
287344 * @param prior transformation aligning the first repeat of this axis with the first overall
288345 * @param level current level
289346 */
290- private void getSymmetryAxes (List <Matrix4d > symmAxes , Matrix4d prior , int level ) {
291- if (level >= degrees . size () ) {
347+ private void getSymmetryAxes (List <Axis > symmAxes , Matrix4d prior , int level ) {
348+ if (level >= getNumLevels () ) {
292349 return ;
293350 }
294-
295- Matrix4d elementary = axes .get (level );
351+
352+ Axis elem = axes .get (level );
353+ Matrix4d elemOp = elem .getOperator ();
296354
297355 // Current axis:
298356 // elementary maps B -> A
299357 // prior maps I -> A and J -> B
300358 // want J -> I = J -> B -> A <- I= inv(prior) * elementary * prior
301359 Matrix4d invPrior = new Matrix4d (prior );
302360 invPrior .invert ();
303- Matrix4d currAxis = new Matrix4d (prior );
304- currAxis .mul (elementary );
305- Matrix4d newPrior = new Matrix4d (currAxis );//save intermediate for later
306- currAxis .mul (invPrior );
361+ Matrix4d currAxisOp = new Matrix4d (prior );
362+ currAxisOp .mul (elemOp );
363+ Matrix4d newPrior = new Matrix4d (currAxisOp );//save intermediate for later
364+ currAxisOp .mul (invPrior );
365+ Axis currAxis = new Axis (currAxisOp ,elem .getOrder (),elem .getSymmType ());
366+ currAxis .setLevel (level );
307367 symmAxes .add (currAxis );
368+
308369 //New prior is elementary^d*prior
309370 //Remember that all degrees are at least 2
310371 getSymmetryAxes (symmAxes ,prior ,level +1 );
311372 getSymmetryAxes (symmAxes ,newPrior ,level +1 );
312- for (int d =2 ;d <degrees . get ( level );d ++) {
313- newPrior .mul (elementary );
373+ for (int d =2 ;d <elem . getOrder ( );d ++) {
374+ newPrior .mul (elemOp );
314375 getSymmetryAxes (symmAxes ,newPrior ,level +1 );
315376 }
316377 }
@@ -343,23 +404,19 @@ public int getNumRepeats() {
343404 private int getNumRepeats (int level ) {
344405 int size = 1 ;
345406 // Return 1 for illegally high level
346- if (level < degrees . size ()) {
347- for (int order : degrees .subList (level , degrees . size ())) {
348- size *= order ;
407+ if (level < getNumLevels ()) {
408+ for (Axis axis : axes .subList (level , getNumLevels ())) {
409+ size *= axis . getOrder () ;
349410 }
350411 }
351412 return size ;
352413 }
353-
354- public SymmetryType getSymmetryType (int level ) {
355- return symmTypes .get (level );
356- }
357-
358- public Matrix4d getElementaryAxis (int level ) {
414+
415+ public Axis getElementaryAxis (int level ) {
359416 return axes .get (level );
360417 }
361-
418+
362419 public int getNumLevels () {
363- return degrees .size ();
420+ return axes .size ();
364421 }
365422}
0 commit comments