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 javax.vecmath.AxisAngle4d;
025import javax.vecmath.Matrix4d;
026import java.util.ArrayList;
027import java.util.Iterator;
028import java.util.List;
029
030/**
031 *
032 * @author Peter
033 */
034public class Helix {
035        private QuatSymmetryScores scores = new QuatSymmetryScores();
036        private List<Integer> permutation;
037        private List<List<Integer>> repeatUnits;
038        private Matrix4d transformation;
039        private double rise;
040        private int nStart;
041        private int fold;
042        private int contacts;
043
044        /**
045         * @return the scores
046         */
047        public QuatSymmetryScores getScores() {
048                return scores;
049        }
050
051        /**
052         * @param scores the scores to set
053         */
054        public void setScores(QuatSymmetryScores scores) {
055                this.scores = scores;
056        }
057
058        /**
059         * @return the permutation
060         */
061        public List<Integer> getPermutation() {
062                return permutation;
063        }
064
065        /**
066         * @param permutation the permutation to set
067         */
068        public void setPermutation(List<Integer> permutation) {
069                this.permutation = permutation;
070        }
071
072        public List<List<Integer>> getRepeatUnits() {
073                return repeatUnits;
074        }
075
076        public void setRepeatUnits(List<List<Integer>> repeatUnits) {
077                this.repeatUnits = repeatUnits;
078        }
079
080        /**
081         * @return the transformation
082         */
083        public Matrix4d getTransformation() {
084                return transformation;
085        }
086
087        /**
088         * @param transformation the transformation to set
089         */
090        public void setTransformation(Matrix4d transformation) {
091                this.transformation = transformation;
092        }
093
094        public double getRise() {
095                return rise;
096        }
097
098        public void setRise(double rise) {
099                this.rise = rise;
100        }
101
102        /**
103         * Returns the pitch angle of the helix
104         * @return
105         */
106        public double getAngle() {
107                return getAxisAngle().angle;
108        }
109
110        /**
111         * Returns the AxisAngle of the helix transformation
112         * @return
113         */
114        public AxisAngle4d getAxisAngle() {
115                AxisAngle4d axis = new AxisAngle4d();
116                axis.set(this.transformation);
117                return axis;
118        }
119
120        public int getnStart() {
121                return nStart;
122        }
123
124        public void setnStart(int nStart) {
125                this.nStart = nStart;
126        }
127
128        /**
129         * @return the fold
130         */
131        public int getFold() {
132                return fold;
133        }
134
135        /**
136         * @param fold the fold to set
137         */
138        public void setFold(int fold) {
139                this.fold = fold;
140        }
141
142        public int getContacts() {
143                return contacts;
144        }
145
146        public void setContacts(int contacts) {
147                this.contacts = contacts;
148        }
149
150        @Override
151        public String toString() {
152                StringBuilder sb = new StringBuilder();
153                sb.append("Permutation   : " + getPermutation() + "\n");
154                sb.append("Repeat units  : " + getRepeatUnits() + "\n");
155                sb.append("Rise          : " + getRise() + "\n");
156                sb.append("Angle         : " + Math.toDegrees(getAngle()) +"\n");
157                sb.append("Fold          : " + getFold() + "\n");
158                return sb.toString();
159        }
160
161        public List<List<Integer>> getLayerLines() {
162                List<List<Integer>> layerLines = new ArrayList<>();
163
164                createLineSegments(permutation, layerLines);
165
166//              System.out.println("Line segments: " + layerLines.size());
167//              for (List<Integer> lineSegment: layerLines) {
168//                      System.out.println(lineSegment);
169//              }
170
171                int count = layerLines.size();
172
173                // iteratively join line segments
174                do {
175                        count = layerLines.size();
176                        joinLineSegments(layerLines);
177                        // after joining line segments, get rid of the empty line segments left behind
178                        trimEmptyLineSegments(layerLines);
179
180//                      System.out.println("Line segments: " + count);
181//                      for (List<Integer> lineSegment: layerLines) {
182//                              System.out.println(lineSegment);
183//                      }
184                } while (layerLines.size() < count);
185
186                return layerLines;
187        }
188
189        private static void createLineSegments(List<Integer> permutation,
190                        List<List<Integer>> layerLines) {
191                for (int i = 0; i < permutation.size(); i++) {
192                        if (permutation.get(i) != -1 ) {
193                                List<Integer> lineSegment = new ArrayList<>();
194                                lineSegment.add(i);
195                                lineSegment.add(permutation.get(i));
196                                layerLines.add(lineSegment);
197                        }
198                }
199        }
200
201        private static void joinLineSegments(List<List<Integer>> layerLines) {
202                for (int i = 0; i < layerLines.size()-1; i++) {
203                        List<Integer> lineSegmentI = layerLines.get(i);
204                        if (! lineSegmentI.isEmpty()) {
205                                for (int j = i + 1; j < layerLines.size(); j++) {
206                                        List<Integer> lineSegmentJ = layerLines.get(j);
207                                        if (! lineSegmentJ.isEmpty()) {
208                                                if (lineSegmentI.get(lineSegmentI.size()-1).equals(lineSegmentJ.get(0))) {
209//                                                      System.out.println("join right: " + lineSegmentI + " - " + lineSegmentJ);
210                                                        lineSegmentI.addAll(lineSegmentJ.subList(1,  lineSegmentJ.size()));
211//                                                      System.out.println("joned segment: " + lineSegmentI);
212                                                        lineSegmentJ.clear();
213                                                } else if ((lineSegmentI.get(0).equals(lineSegmentJ.get(lineSegmentJ.size()-1)))) {
214                                                        lineSegmentI.addAll(0, lineSegmentJ.subList(0,  lineSegmentJ.size()-1));
215//                                                      System.out.println("join left: " + lineSegmentJ + " - " + lineSegmentI);
216//                                                      System.out.println("joned segment: " + lineSegmentI);
217                                                        lineSegmentJ.clear();
218                                                }
219                                        }
220                                }
221                        }
222                }
223        }
224
225        private static void trimEmptyLineSegments(List<List<Integer>> layerLines) {
226                for (Iterator<List<Integer>> iter = layerLines.iterator(); iter.hasNext();) {
227                        if (iter.next().isEmpty()) {
228                                iter.remove();
229                        }
230                }
231        }
232}