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 * Created on Aug 3, 2007
021 *
022 */
023
024package org.biojava.nbio.structure.gui;
025
026import org.biojava.nbio.structure.Structure;
027import org.biojava.nbio.structure.align.StrucAligParameters;
028import org.biojava.nbio.structure.align.StructurePairAligner;
029import org.biojava.nbio.structure.align.pairwise.AlternativeAlignment;
030import org.biojava.nbio.structure.align.pairwise.FragmentPair;
031import org.biojava.nbio.structure.gui.util.color.*;
032import org.biojava.nbio.structure.gui.util.color.LinearColorInterpolator.InterpolationDirection;
033import org.biojava.nbio.structure.io.PDBFileReader;
034import org.biojava.nbio.structure.jama.Matrix;
035
036import javax.swing.*;
037import javax.swing.event.ChangeEvent;
038import javax.swing.event.ChangeListener;
039import java.awt.*;
040import java.awt.color.ColorSpace;
041import java.awt.event.ActionEvent;
042import java.awt.event.ActionListener;
043import java.awt.event.WindowAdapter;
044import java.awt.event.WindowEvent;
045import java.util.Map;
046import java.util.SortedMap;
047import java.util.TreeMap;
048
049
050/** A JPanel that can display the underlying distance matrix
051 * data of the protein structure alignment algorithm. It adds a
052 * JSlider to a JMatrixPanel.
053 *
054 * see also JMatrixPanel.
055 *
056 */
057public class ScaleableMatrixPanel
058extends JPanel
059implements ChangeListener, ActionListener {
060
061        /**
062         *
063         */
064        private static final long serialVersionUID = -8082261434322968652L;
065
066        protected JMatrixPanel mPanel;
067        protected JSlider slider;
068        protected JScrollPane scroll;
069        protected JComboBox coloring;
070
071        protected Map<String,ContinuousColorMapper> gradients;
072
073        protected static final int SLIDER_STEPS = 8; // Number of minor ticks per unit scaled
074
075
076        public static void main(String[] args){
077
078                PDBFileReader pdbr = new PDBFileReader();
079                pdbr.setPath("/tmp/");
080
081
082                //String pdb1 = "1crl";
083                //String pdb2 = "1ede";
084
085                String pdb1 = "1buz";
086                String pdb2 = "1ali";
087
088                //String pdb1 = "5pti";
089                //String pdb2 = "5pti";
090
091                // NO NEED TO DO CHANGE ANYTHING BELOW HERE...
092
093                StructurePairAligner sc = new StructurePairAligner();
094                StrucAligParameters params = new StrucAligParameters();
095                params.setMaxIter(1);
096                sc.setParams(params);
097
098                // step1 : read molecules
099                try {
100                        Structure s1 = pdbr.getStructureById(pdb1);
101                        Structure s2 = pdbr.getStructureById(pdb2);
102
103                        System.out.println("aligning " + pdb1 + " vs. " + pdb2);
104                        System.out.println(s1);
105                        System.out.println();
106                        System.out.println(s2);
107                        // step 2 : do the calculations
108                        sc.align(s1,s2);
109
110
111                        ScaleableMatrixPanel smp = new ScaleableMatrixPanel();
112                        JFrame frame = new JFrame();
113                        frame.addWindowListener(new WindowAdapter(){
114                                @Override
115                                public void windowClosing(WindowEvent e){
116                                        JFrame f = (JFrame) e.getSource();
117                                        f.setVisible(false);
118                                        f.dispose();
119                                }
120
121
122
123                        });
124
125                        smp.setMatrix(sc.getDistMat());
126                        smp.setFragmentPairs(sc.getFragmentPairs());
127                        smp.setAlternativeAligs(sc.getAlignments());
128
129                        for (int i = 0; i < sc.getAlignments().length; i++) {
130                                AlternativeAlignment aa =sc.getAlignments()[i];
131                                System.out.println(aa);
132
133                        }
134
135                        frame.getContentPane().add(smp);
136
137                        frame.pack();
138                        frame.setVisible(true);
139
140                } catch (Exception e) {
141                        e.printStackTrace();
142                }
143
144        }
145
146        public ScaleableMatrixPanel(){
147
148                mPanel   = new JMatrixPanel();
149                Box vBox = Box.createVerticalBox();
150
151                Box gradientBox = Box.createHorizontalBox();
152                vBox.add(gradientBox);
153                gradientBox.add(new JLabel("Coloring:"));
154                gradients = createGradients(); //sets gradients
155                //Set first gradient
156                this.setCellColor(gradients.values().iterator().next());
157
158                coloring = new JComboBox(gradients.keySet().toArray(new String[] {}));
159                coloring.setRenderer(new GradientRenderer());
160                coloring.addActionListener(this);
161                coloring.setMaximumSize(new Dimension(1000,30));
162                gradientBox.add(coloring);
163
164                int RES_MIN  = 0*SLIDER_STEPS;
165                int RES_MAX  = 8*SLIDER_STEPS;
166                int RES_INIT = 1*SLIDER_STEPS;
167
168                slider = new JSlider(JSlider.HORIZONTAL, RES_MIN,RES_MAX,RES_INIT);
169                slider.setInverted(false);
170                slider.setPaintTicks(true);
171                //slider.setMinorTickSpacing(1);
172                slider.setMajorTickSpacing(SLIDER_STEPS);
173                slider.setSnapToTicks(false);
174                slider.setPaintLabels(false);
175                slider.setPaintTrack(true);
176                //slider.setLabelTable(slider.createStandardLabels(SLIDER_STEPS));
177                slider.addChangeListener(this);
178                slider.setPreferredSize(new Dimension(100,slider.getPreferredSize().height));
179
180                vBox.add(slider);
181
182                scroll = new JScrollPane(mPanel);
183                scroll.getHorizontalScrollBar().setUnitIncrement(60);
184                scroll.getVerticalScrollBar().setUnitIncrement(60);
185                scroll.getHorizontalScrollBar().setBlockIncrement(60);
186                scroll.getVerticalScrollBar().setBlockIncrement(60);
187                vBox.add(scroll);
188                this.setPreferredSize(new Dimension(400,400));
189                this.add(vBox);
190
191
192                mPanel.setLayout(new BoxLayout(mPanel,BoxLayout.Y_AXIS));
193                this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
194
195        }
196
197
198
199
200        protected static Map<String,ContinuousColorMapper> createGradients() {
201                SortedMap<String,ContinuousColorMapper> gradients = new TreeMap<String,ContinuousColorMapper>();
202
203                int i = 0; //prepend number, since sorted alphabetically
204                ColorSpace hsv = HSVColorSpace.getHSVColorSpace();
205                LinearColorInterpolator interp;
206                GradientMapper gradient;
207
208                /*
209                DefaultMatrixMapper defaultMapper = new DefaultMatrixMapper(10., .9f);
210                gradients.put((++i)+". Default", defaultMapper);
211                defaultMapper = new DefaultMatrixMapper(5., .9f);
212                gradients.put((++i)+". Sensitive", defaultMapper);
213
214
215                gradients.put((++i)+". Rainbow", GradientMapper.getGradientMapper(GradientMapper.RAINBOW_INTENSITY_GRADIENT, 0, 10));
216                gradients.put((++i)+". Rainbow", GradientMapper.getGradientMapper(GradientMapper.RAINBOW_INTENSITY_GRADIENT, 10, 0));
217                */
218
219
220                interp = new LinearColorInterpolator(hsv);
221                interp.setInterpolationDirection(0, InterpolationDirection.INNER);
222                gradient = new GradientMapper(Color.green, Color.black, hsv);
223                gradient.put( -50., new Color(hsv,new float[] {0f, .9f, 0f},1f));
224                gradient.put( 10., new Color(hsv,new float[] {1f, .9f, 1f},1f));
225                gradient.setInterpolator(interp);
226
227                gradients.put((++i)+". -50 to 10", gradient);
228
229
230
231                // Mimic DefaultMapper
232                interp = new LinearColorInterpolator(hsv);
233                interp.setInterpolationDirection(0, InterpolationDirection.INNER);
234                gradient = new GradientMapper(Color.green, Color.black, hsv);
235                gradient.put( 0., new Color(hsv,new float[] {1f, .9f, 1f},1f));
236                gradient.put(10., new Color(hsv,new float[] {0f, .9f, 0f},1f));
237                gradient.setInterpolator(interp);
238
239                gradients.put((++i)+". Default", gradient);
240
241                // Sensitive DefaultMapper
242                interp = new LinearColorInterpolator(hsv);
243                interp.setInterpolationDirection(0, InterpolationDirection.INNER);
244                gradient = new GradientMapper(Color.green, Color.black, hsv);
245                gradient.put( 0., new Color(hsv,new float[] {1f, .9f, 1f},1f));
246                gradient.put( 5., new Color(hsv,new float[] {0f, .9f, 0f},1f));
247                gradient.setInterpolator(interp);
248
249                gradients.put((++i)+". Sensitive", gradient);
250
251                // color [0,1]import java.awt.Color;
252
253                interp = new LinearColorInterpolator(hsv);
254                interp.setInterpolationDirection(0, InterpolationDirection.INNER);
255                gradient = new GradientMapper(Color.green, Color.black, hsv);
256                gradient.put( 0., new Color(hsv,new float[] {1f, .9f, 1f},1f));
257                gradient.put( 1., new Color(hsv,new float[] {.2f, .9f, 1f},1f));
258                gradient.put( 1+1e-6, Color.white);
259                gradient.put(5., Color.black);
260                gradient.setInterpolator(interp);
261
262                gradients.put((++i)+". Emphasize low", gradient);
263
264
265                interp = new LinearColorInterpolator(hsv);
266                interp.setInterpolationDirection(0, InterpolationDirection.INNER);
267                gradient = new GradientMapper(Color.green, Color.black, hsv);
268                gradient.put( 0., new Color(hsv,new float[] {0f, .9f, 0f},1f));
269                gradient.put( 100., new Color(hsv,new float[] {1f, .9f, 1f},1f));
270                gradient.setInterpolator(interp);
271
272                gradients.put((++i)+". 0 to 100", gradient);
273
274                // log color
275                interp = new LinearColorInterpolator(hsv);
276                interp.setInterpolationDirection(0, InterpolationDirection.INNER);
277                gradient = new GradientMapper(Color.red, Color.black, hsv);
278                gradient.put( 0., new Color(hsv,new float[] {1f, .9f, 1f},1f));
279                gradient.put( 10., new Color(hsv,new float[] {0f, .9f, 0f},1f));
280                gradient.setInterpolator(interp);
281
282                ContinuousColorMapper logGradient = new LogColorMapper(gradient,2);
283                gradients.put((++i)+". Logorithmic", logGradient);
284
285                // sqrt color
286                interp = new LinearColorInterpolator(hsv);
287                interp.setInterpolationDirection(0, InterpolationDirection.INNER);
288                gradient = new GradientMapper(Color.red, Color.black, hsv);
289                gradient.put( 0., new Color(hsv,new float[] {1f, .9f, 1f},1f));
290                gradient.put( 4., new Color(hsv,new float[] {0f, .9f, 0f},1f));
291                gradient.setInterpolator(interp);
292
293                ContinuousColorMapper sqrtGradient = new SqrtColorMapper(gradient);
294                gradients.put((++i)+". Square Root", sqrtGradient);
295
296                GradientMapper black = new GradientMapper(Color.BLACK, Color.BLACK);
297                gradients.put((++i)+". Black", black);
298
299                return gradients;
300        }
301
302        @Override
303        public void stateChanged(ChangeEvent e) {
304
305                JSlider source = (JSlider)e.getSource();
306
307                if ( source.getValueIsAdjusting()) {
308                        //return;
309                }
310
311                //System.out.println("Changed scale to "+source.getValue());
312                mPanel.setScale((float)source.getValue()/SLIDER_STEPS);
313
314                scroll.repaint();
315                scroll.updateUI();
316        }
317
318        public Matrix getMatrix() {
319                return mPanel.getMatrix();
320        }
321
322        public void setMatrix(Matrix matrix) {
323                mPanel.setMatrix(matrix);
324
325
326        }
327
328        public JMatrixPanel getMatrixPanel(){
329                return mPanel;
330        }
331
332        public FragmentPair[] getFragmentPairs(){
333                return mPanel.getFragmentPairs();
334        }
335        public void setFragmentPairs(FragmentPair[] pairs){
336                mPanel.setFragmentPairs(pairs);
337        }
338
339        public AlternativeAlignment[] getAlternativeAligs() {
340                return mPanel.getAlternativeAligs();
341        }
342
343
344
345        public void setAlternativeAligs(AlternativeAlignment[] aligs) {
346                mPanel.setAlternativeAligs(aligs);
347        }
348
349        public int getSelectedAlignmentPos() {
350                return mPanel.getSelectedAlignmentPos();
351        }
352
353        public void setSelectedAlignmentPos(int selectedAlignmentPos) {
354                mPanel.setSelectedAlignmentPos(selectedAlignmentPos);
355        }
356
357        /**
358         * @return the color mapping of the JMatrixPanel
359         */
360        public ContinuousColorMapper getCellColor() {
361                return mPanel.getCellColor();
362        }
363
364        /**
365         * @param cellColor the color mapping of the JMatrixPanel
366         */
367        public void setCellColor(ContinuousColorMapper cellColor) {
368                mPanel.setCellColor(cellColor);
369        }
370
371        /**
372         * A renderer for the the gradient dropdown menu at the top of scaleableMatrixPanes.
373         * Knows how to draw a gradient and nicely label it.
374         *
375         * @author Spencer Bliven
376         *
377         */
378        protected class GradientRenderer extends JPanel
379        implements ListCellRenderer {
380
381                private static final long serialVersionUID = -2000575579184232365L;
382                private int min,max;
383                JLabel title;
384                JPanel gradientContainer;
385
386                public GradientRenderer() {
387                        this.setPreferredSize(new Dimension(100,25));
388                        this.setLayout(new BorderLayout());
389                        this.min = -1;
390                        this.max = 10;
391
392                        JPanel gradientBounds = new JPanel();
393                        gradientBounds.setLayout(new BorderLayout());
394                        //gradientBounds.setBorder(BorderFactory.createLineBorder(Color.GRAY));
395                        gradientBounds.add(new JLabel(Integer.toString(min)),BorderLayout.WEST);
396
397                        gradientContainer = new JPanel();
398                        gradientContainer.setLayout(new BorderLayout());
399                        gradientContainer.setOpaque(false);
400                        gradientContainer.add(new JLabel("<No gradient>"),BorderLayout.CENTER);
401                        //gradientContainer.setMinimumSize(new Dimension(50,20));
402                        //gradientContainer.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
403                        //gradientBounds.setPreferredSize(new Dimension(200,25));
404                        gradientBounds.add(gradientContainer,BorderLayout.CENTER);
405                        gradientBounds.setOpaque(false);
406
407                        gradientBounds.add(new JLabel(Integer.toString(max)),BorderLayout.EAST);
408
409                        this.add(gradientBounds, BorderLayout.EAST);
410
411                        this.title = new JLabel("No gradient");
412                        //this.title.setOpaque(true);
413                        this.title.setHorizontalAlignment(JLabel.CENTER);
414                        this.title.setVerticalAlignment(JLabel.CENTER);
415                        this.add(this.title,BorderLayout.CENTER);
416                }
417
418                /*
419                 * This method finds the image and text corresponding
420                 * to the selected value and returns the label, set up
421                 * to display the text and image.
422                 */
423                @Override
424                public Component getListCellRendererComponent(
425                                JList list,
426                                Object value,
427                                int index,
428                                boolean isSelected,
429                                boolean cellHasFocus) {
430                        //Get the selected index. (The index param isn't
431                        //always valid, so just use the value.)
432                        String gradientLabel = (String)value;
433
434                        if (isSelected) {
435                                setBackground(list.getSelectionBackground());
436                                setForeground(list.getSelectionForeground());
437                        } else {
438                                setBackground(list.getBackground());
439                                setForeground(list.getForeground());
440                        }
441
442                        //Set the icon and text.  If icon was null, say so.
443                        GradientPanel gradPanel = new GradientPanel(gradients.get(gradientLabel),min,max);
444                        gradPanel.setPreferredSize(new Dimension(100,20));
445                        //gradPanel.setBorder(BorderFactory.createLineBorder(Color.cyan));
446                        gradientContainer.removeAll();
447                        gradientContainer.add(gradPanel,BorderLayout.CENTER);
448
449                        title.setText(gradientLabel);
450
451                        this.validate();
452
453                        return this;
454                }
455        }
456
457        /**
458         * @param e
459         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
460         */
461        @Override
462        public void actionPerformed(ActionEvent e) {
463                JComboBox cb = (JComboBox)e.getSource(); // == coloring
464                String gradientName = (String)cb.getSelectedItem();
465                ContinuousColorMapper gradient = gradients.get(gradientName);
466                assert(gradient != null);
467                this.setCellColor(gradient);
468                this.repaint();
469        }
470
471
472}