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.align.StrucAligParameters;
027import org.biojava.nbio.structure.align.pairwise.AlternativeAlignment;
028import org.biojava.nbio.structure.align.pairwise.FragmentPair;
029import org.biojava.nbio.structure.gui.util.color.ContinuousColorMapper;
030import org.biojava.nbio.structure.gui.util.color.DefaultMatrixMapper;
031import org.biojava.nbio.structure.jama.Matrix;
032
033import javax.swing.*;
034import java.awt.*;
035import java.awt.image.BufferedImage;
036
037
038/** a JPanel that can display a difference of distance matrix and paths that have been
039 * taken for the alignment
040 *
041 * <p>Note: This panel displays the transpose of its underlying matrix.
042 * Thus its width will be the same as {@link Matrix#getRowDimension()} and its
043 * height the same as {@link Matrix#getColumnDimension()}. This stems from the
044 * unfortunate ordering of {@link Matrix#get(int, int)} parameters as (row, col),
045 * which is opposite from the normal (x,y) order used when displaying graphics.
046 *
047 * @author Andreas Prlic
048 *
049 */
050public class JMatrixPanel extends JPanel{
051
052        /**
053         *
054         */
055        private static final long serialVersionUID = -1720879395453257846L;
056        BufferedImage _bufImage;
057        Matrix matrix;
058        ContinuousColorMapper cellColor; //Maps matrix elements to a color
059        float scale;
060
061        FragmentPair[] fragmentPairs;
062        AlternativeAlignment[] aligs;
063        int selectedAlignmentPos;
064
065        final static BasicStroke stroke = new BasicStroke(2.0f);
066        StrucAligParameters params;
067
068        public JMatrixPanel(){
069                scale = 1;
070                cellColor = new DefaultMatrixMapper(10, 0.9f);
071                //saturation = 0.9f;
072                //scalevalue = 10;
073                selectedAlignmentPos = -1;
074                matrix = new Matrix(0,0);
075                params = new StrucAligParameters();
076        }
077
078        public int getSelectedAlignmentPos() {
079                return selectedAlignmentPos;
080        }
081
082        public void setSelectedAlignmentPos(int selectedAlignmentPos) {
083                this.selectedAlignmentPos = selectedAlignmentPos;
084        }
085
086        public AlternativeAlignment[] getAlternativeAligs() {
087                return aligs;
088        }
089
090        public void setAlternativeAligs(AlternativeAlignment[] aligs) {
091                this.aligs = aligs;
092        }
093
094
095
096        public FragmentPair[] getFragmentPairs() {
097                return fragmentPairs;
098        }
099
100        public void setFragmentPairs(FragmentPair[] fragmentPairs) {
101                this.fragmentPairs = fragmentPairs;
102        }
103
104        public float getScale() {
105                return scale;
106        }
107
108        public void setPreferredSize(){
109
110                int prefW = Math.round(matrix.getRowDimension() * scale);
111                int prefH = Math.round(matrix.getColumnDimension() * scale);
112
113                this.setPreferredSize(new Dimension(prefW,prefH));
114
115        }
116
117        public void setScale(float scale) {
118
119                if ( scale == this.scale)
120                        return;
121                //System.out.println("setting scale " + scale + "current width " + getWidth() + " " + getHeight());
122
123                this.scale = scale;
124
125                setPreferredSize();
126
127                this.repaint();
128
129        }
130
131        public Matrix getMatrix() {
132                return matrix;
133        }
134
135        /** sets the distance matrix to be displayed
136         *
137         * @param matrix
138         */
139        public void setMatrix(Matrix matrix) {
140                this.matrix = matrix;
141                setPreferredSize();
142        }
143
144        @Override
145        public void paintComponent(Graphics g){
146
147                //super.paintComponent(g);
148
149                Graphics2D g2 = (Graphics2D)g;
150                if ( _bufImage == null){
151
152                        int w = getWidth();
153                        int h = getHeight();
154                        _bufImage = (BufferedImage) createImage(w,h);
155                        //Graphics gc = _bufImage.createGraphics();
156                        //gc.setColor(Color.blue);
157                        //gc.fillRect(0,0,w,h);
158
159                }
160
161
162                g2.drawImage(_bufImage,null,0,0);
163                drawDistances(g);
164
165                drawPairs(g);
166
167                if ( scale >= 4) {
168                        drawBoxes(g);
169                }
170        }
171
172        /** draw alternative alignments
173         *
174         * @param g
175         */
176        public void drawPairs(Graphics g){
177
178                if ( aligs == null)
179                        return;
180
181                int nr = aligs.length;
182
183                Graphics2D g2D = (Graphics2D)g;
184                Stroke oldStroke = g2D.getStroke();
185                g2D.setStroke(stroke);
186
187                Color color;
188                float hue;
189
190                int width = Math.round(scale);
191                int w2 = width / 2 ;
192
193                for (int i = 0; i < aligs.length; i++) {
194                        AlternativeAlignment a = aligs[i];
195                        int[] idx1 = a.getIdx1();
196                        int[] idx2 = a.getIdx2();
197                        int xold = -1;
198                        int yold = -1;
199                        boolean start = true;
200
201                        if ( (selectedAlignmentPos != -1 ) &&
202                                        ( selectedAlignmentPos == i)){
203                                color = Color.white;
204                        } else {
205
206                                hue = i * (1/ (float)nr);
207                                color = Color.getHSBColor(hue,1.0f,1.0f);
208                        }
209                        g.setColor(color);
210
211                        for (int j = 0; j < idx1.length; j++) {
212                                int x1 = Math.round(idx1[j]*scale) ;
213                                int y1 = Math.round(idx2[j]*scale) ;
214                                if ( ! start){
215                                        //g.drawLine(xold+1,yold,x1+1,y1);
216
217                                        //g2D.draw(new Line2D.Double(xold,yold,x1,y1));
218                                        g.fillRect(xold,yold,2,2);
219                                } else {
220                                        g.fillRect(x1,y1, w2, w2);
221                                        start =false;
222                                }
223                                xold = x1;
224                                yold = y1;
225                        }
226
227                        if ( ! start)
228                                g.fillRect(xold,yold,w2,w2);
229
230
231                }
232
233                g2D.setStroke(oldStroke);
234        }
235
236
237        /** draw high scoring fragments that are used for the initial alignment seed
238         * selection
239         *
240         * @param g
241         */
242        public void drawBoxes(Graphics g){
243                if ( fragmentPairs == null )
244                        return;
245
246                g.setColor(Color.yellow);
247
248
249                for (int i = 0; i < fragmentPairs.length; i++) {
250                        FragmentPair fp =fragmentPairs[i];
251                        int xp = fp.getPos1();
252                        int yp = fp.getPos2();
253
254                        int width = Math.round(scale);
255
256                        g.drawRect(Math.round(xp*scale),Math.round(yp*scale),width, width);
257
258                }
259        }
260
261
262        /**
263         * For each element in matrix, draw it as a colored square or pixel.
264         *
265         * The color of a matrix element with value x is specified as
266         *   - H: 1-x/scalevalue
267         *   - S: saturation
268         *   - B: 1-x/scalevalue
269         * @param g1
270         */
271        public void drawDistances(Graphics g1){
272                Graphics2D g = (Graphics2D)g1;
273
274                int c = matrix.getRowDimension();
275                int d = matrix.getColumnDimension();
276
277                float scale = getScale();
278                int width = Math.round(scale);
279
280                for (int i = 0; i < c; i++) {
281                        int ipaint = Math.round(i*scale);
282
283                        for (int j = 0; j < d; j++) {
284                                double val = matrix.get(i,j);
285
286                                int jpaint = Math.round(j*scale);
287
288                                Color color = cellColor.getColor(val);
289                                g.setColor(color);
290
291                                g.fillRect(ipaint,jpaint,width,width);
292                        }
293
294                }
295
296        }
297
298        /**
299         * @return the color mapping of the JMatrixPanel
300         */
301        public ContinuousColorMapper getCellColor() {
302                return cellColor;
303        }
304
305        /**
306         * @param cellColor the color mapping of the JMatrixPanel to set
307         */
308        public void setCellColor(ContinuousColorMapper cellColor) {
309                this.cellColor = cellColor;
310        }
311
312
313
314}