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