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.symmetry.jmolScript;
022
023import org.biojava.nbio.structure.symmetry.axis.AxisAligner;
024import org.biojava.nbio.structure.symmetry.axis.HelixAxisAligner;
025import org.biojava.nbio.structure.symmetry.axis.RotationAxisAligner;
026
027import javax.vecmath.Color4f;
028import javax.vecmath.Matrix4d;
029import javax.vecmath.Tuple3d;
030
031import java.util.List;
032import java.util.Map;
033import java.util.Map.Entry;
034
035public abstract class JmolSymmetryScriptGenerator {
036
037        /**
038         * Returns an instance of a JmolSymmetryScriptGenerator, based on the symmetry of a structure (factory method)
039         * @param axisAligner
040         * @param rotationGroup
041         * @return instance of JmolSymmetryScriptGenerator
042         */
043        public static JmolSymmetryScriptGenerator getInstance(AxisAligner axisAligner, String name) {
044                String symmetry = axisAligner.getSymmetry();
045
046                if (symmetry.equals("C1")) {
047                        return new JmolSymmetryScriptGeneratorC1((RotationAxisAligner)axisAligner, name);
048                } else if (symmetry.startsWith("C")) {
049                        return new JmolSymmetryScriptGeneratorCn((RotationAxisAligner)axisAligner, name);
050                } else if (symmetry.startsWith("D")) {
051                        return new JmolSymmetryScriptGeneratorDn((RotationAxisAligner)axisAligner, name);
052                } else if (symmetry.equals("T")) {
053                        return new JmolSymmetryScriptGeneratorT((RotationAxisAligner)axisAligner, name);
054                } else if (symmetry.equals("O")) {
055                        return new JmolSymmetryScriptGeneratorO((RotationAxisAligner)axisAligner, name);
056                } else if (symmetry.equals("I")) {
057                        return new JmolSymmetryScriptGeneratorI((RotationAxisAligner)axisAligner, name);
058                } else if (symmetry.equals("H")) {
059                        return new JmolSymmetryScriptGeneratorH((HelixAxisAligner)axisAligner, name);
060                }
061
062                return null;
063        }
064        /**
065         * Returns the Jmol zoom to fit polyhedron and symmetry axes. This zoom
066         * level should be used so that the polyhedron and symmetry axes are not cutoff.
067         * @return
068         */
069        abstract public int getZoom();
070
071        /**
072         * Returns a Jmol script to set the default orientation for a structure
073         * @return Jmol script
074         */
075        public abstract String getDefaultOrientation();
076
077        /**
078         * Returns the number of orientations available for this structure
079         * @return number of orientations
080         */
081        public abstract int getOrientationCount();
082
083        /**
084         * Returns a Jmol script that sets a specific orientation
085         * @param index orientation index
086         * @return Jmol script
087         */
088        public abstract String getOrientation(int index);
089
090        /**
091         * Returns a Jmol script that sets a specific orientation instantaneously
092         * @param index orientation index
093         * @return Jmol script
094         */
095        public String getInstantaneousOrientation(int index){
096                String s = getOrientation(index);
097                return s.replaceAll("moveto 4", "moveto 0");
098        }
099
100        /**
101         * Returns a Jmol script that sets a specific orientation and zoom
102         * to draw either axes or polyhedron
103         * @param index orientation index
104         * @return Jmol script
105         */
106        public abstract String getOrientationWithZoom(int index);
107
108        /**
109         * Returns the name of a specific orientation
110         * @param index orientation index
111         * @return name of orientation
112         */
113        public abstract String getOrientationName(int index);
114
115        /**
116         * Returns transformation matrix to orient structure
117         * @return transformation matrix
118         */
119        public abstract Matrix4d getTransformation();
120
121        /** Sets a default Jmol script used for coloring. This method is
122         * used in local symmetry cases to color those subunits that are
123         * not related by symmetry.
124         * @param colorScript
125         */
126        public abstract void setDefaultColoring(String colorScript);
127
128        /**
129         * Sets the type of bioassembly to be colored. If set to true,
130         * it will generate a Jmol script for a bioassembly generated
131         * by Jmol on the fly. If set to false, it will generate Jmol script for
132         * a bioassembly file read by Jmol.
133         */
134        public abstract void setOnTheFly(boolean onTheFly);
135
136        /**
137         * Returns a Jmol script that draws an invisible polyhedron around a structure.
138         * Use showPolyhedron() and hidePolyhedron() to toggle visibility.
139         * @return Jmol script
140         */
141        public abstract String drawPolyhedron();
142
143        public abstract String hidePolyhedron();
144
145        public abstract String showPolyhedron();
146
147        /**
148         * Returns a Jmol script that draws symmetry or inertia axes for a structure.
149         * Use showAxes() and hideAxes() to toggle visibility.
150         * @return Jmol script
151         */
152        public abstract String drawAxes();
153
154        /**
155         * Returns a Jmol script to hide axes
156         * @return Jmol script
157         */
158        public abstract String hideAxes();
159
160        /**
161         * Returns a Jmol script to show axes
162         * @return Jmol script
163         */
164        public abstract String showAxes();
165
166        /**
167         * Returns a Jmol script that displays a symmetry polyhedron and symmetry axes
168         * and then loop through different orientations
169         * @return Jmol script
170         */
171        public abstract String playOrientations();
172
173        /**
174         * Returns a Jmol script that colors the subunits of a structure by different colors
175         * @return
176         */
177        public abstract String colorBySubunit();
178
179        /**
180         * Returns a Jmol script that colors subunits by their sequence cluster ids.
181         * @return Jmol script
182         */
183        public abstract String colorBySequenceCluster();
184
185        /**
186         * Returns a Jmol script that colors subunits to highlight the symmetry within a structure
187         * @return Jmol script
188         */
189        public abstract String colorBySymmetry();
190
191        protected static String getJmolColorScript(Map<Color4f, List<String>> map) {
192                StringBuilder s = new StringBuilder();
193                s.append("color cartoons none;");
194                for (Entry<Color4f, List<String>> entry: map.entrySet()) {
195                        s.append("color{");
196                        List<String> ids = entry.getValue();
197                        for (int i = 0; i < ids.size(); i++) {
198                                s.append(":");
199                                s.append(ids.get(i));
200                                if (i < ids.size() -1 ) {
201                                        s.append("|");
202                                }
203                        }
204                        s.append("}");
205                        s.append(getJmolColor(entry.getKey()));
206                        s.append(";");
207                }
208                return s.toString();
209        }
210
211        protected static String getJmolColor(Color4f color) {
212                String hex = Integer.toHexString((color.get().getRGB() & 0xffffff) | 0x1000000).substring(1);
213                return " [x" + hex + "]";
214        }
215
216        protected static String getJmolPoint(Tuple3d point) {
217                StringBuilder s = new StringBuilder();
218                s.append("{");
219                s.append(fDot2(point.x));
220                s.append(",");
221                s.append(fDot2(point.y));
222                s.append(",");
223                s.append(fDot2(point.z));
224                s.append("}");
225                return s.toString();
226        }
227
228        protected static String f1Dot2(float number) {
229                return String.format("%1.2f", number);
230        }
231
232        protected static String fDot2(double number) {
233                return String.format("%.2f", number);
234        }
235
236        /**
237         * Returns a lower precision floating point number for Jmol
238         * @param f
239         * @return
240         */
241        protected static float jMolFloat(double f) {
242                return (float)f;
243        }
244
245        protected static String getJmolLigandScript() {
246                return "select ligand;wireframe 0.16;spacefill 23%;color cpk;";
247        }
248
249}