001/*
002 *                    PDB web 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 *
015 * Created on Jul 28, 2009
016 * Created by ap3
017 *
018 */
019
020package org.biojava.nbio.structure.align.gui;
021
022import org.biojava.nbio.structure.Atom;
023import org.biojava.nbio.structure.StructureException;
024import org.biojava.nbio.structure.align.StructureAlignmentFactory;
025import org.biojava.nbio.structure.align.ce.CeCPMain;
026import org.biojava.nbio.structure.align.ce.CeMain;
027import org.biojava.nbio.structure.align.ce.CeParameters;
028import org.biojava.nbio.structure.align.helper.JointFragments;
029import org.biojava.nbio.structure.align.model.AFP;
030import org.biojava.nbio.structure.align.model.AFPChain;
031import org.biojava.nbio.structure.align.pairwise.AlternativeAlignment;
032import org.biojava.nbio.structure.align.util.AtomCache;
033import org.biojava.nbio.structure.gui.ScaleableMatrixPanel;
034import org.biojava.nbio.structure.jama.Matrix;
035
036import javax.swing.*;
037import java.awt.event.WindowAdapter;
038import java.awt.event.WindowEvent;
039import java.io.IOException;
040import java.util.ArrayList;
041import java.util.List;
042
043/**
044 * Displays the dot plot trace for an alignment.
045 *
046 * This class adapts ScaleableMatrixPanel, which uses code from org.biojava.nbio.structure.align.pairwise,
047 * with more BioJava-friendly methods based off AFPChains.
048 *
049 * @author Spencer Bliven
050 *
051 */
052public class DotPlotPanel extends ScaleableMatrixPanel {
053
054        private static final long serialVersionUID = -7641953255857483895L;
055
056        /**
057         *
058         * @param alignment The alignment to plot
059         * @param background [Optional]A matrix of 'background colors' over which to draw the alignment.
060         *
061         *      Originally designed as a matrix of RMSD values between AFPs, so it is colorized
062         *      accordingly from red (0) to black (>10).
063         *
064         *  If this set to null, the background is set to black.
065         */
066        public DotPlotPanel(AFPChain alignment ){
067                super();
068
069                final double defaultBackground = 100.;
070
071                // Convert the AFPChain alignment into the MatrixPanel format
072                AlternativeAlignment[] aligns = new AlternativeAlignment[alignment.getBlockNum()];
073                int alignNumber = 0;
074
075                //One alternative alignment for each block
076                int[][][] optAln = alignment.getOptAln(); // [block #][{0,1} chain index][pos]
077
078                for(;alignNumber < optAln.length;alignNumber++) {
079                        List<int[]> alignPairs = new ArrayList<int[]>();
080                        for(int pos = 0; pos<optAln[alignNumber][0].length; pos++ ) {
081                                alignPairs.add( new int[] {
082                                                optAln[alignNumber][0][pos],
083                                                optAln[alignNumber][1][pos] }
084                                );
085                        }
086                        JointFragments frag = new JointFragments();
087                        frag.setIdxlist(alignPairs);
088                        aligns[alignNumber] = new AlternativeAlignment();
089                        aligns[alignNumber].apairs_from_idxlst(frag);
090
091                }
092
093                /* TODO After the AFPSet is fixed in CeMain#filterDuplicateAFPs, maybe include this again
094                //add alignment for the AFPs
095                List<AFP> afps = alignment.getAfpSet();
096                List<int[]> alignPairs = new ArrayList<int[]>();
097                for(AFP afp : afps) {
098                        int start1 = afp.getP1();
099                        int start2 = afp.getP2();
100                        for(int i=0;i<afp.getFragLen();i++) {
101                                alignPairs.add( new int[] { start1+i, start2+i } );
102                        }
103                }
104                JointFragments frag = new JointFragments();
105                frag.setIdxlist(alignPairs);
106                aligns[alignNumber] = new AlternativeAlignment();
107                aligns[alignNumber].apairs_from_idxlst(frag);
108                */
109
110
111                /* AFP boxes are unnecessary.
112                // Calculate FragmentPairs based on alignment.
113                // These are displayed as a small box around the start of each alignment.
114                FragmentPair[] pairs = new FragmentPair[afps.size()];
115                for(int i=0;i<pairs.length;i++) {
116                        AFP afp = afps.get(i);
117                        pairs[i] = new FragmentPair(afp.getFragLen(), afp.getP1(), afp.getP2());
118                        pairs[i].setRms(afp.getRmsd());
119                }
120
121                this.setFragmentPairs(pairs);
122                */
123
124
125                // Now the alignments have been build; add it
126                this.setAlternativeAligs(aligns);
127                this.setSelectedAlignmentPos(0); //color white, not red
128
129                Matrix background = alignment.getDistanceMatrix();
130                //Fill with default black background if none given
131                if(background == null) {
132                        background = new Matrix(alignment.getCa1Length(),alignment.getCa2Length());
133                        for(int i=0;i<background.getRowDimension();i++)
134                                for(int j=0;j<background.getColumnDimension(); j++) {
135                                        background.set(i, j, defaultBackground);
136                                }
137                }
138
139                // Set parameters
140                this.setMatrix(background);
141        }
142
143        /**
144         * Helper function to create and display a JFrame with a single DotPlotPanel
145         *
146         * @param afpChain
147         * @param background
148         */
149        private static JFrame showDotPlotJFrame(AFPChain afpChain ) {
150
151                DotPlotPanel dotplot = new DotPlotPanel(afpChain);
152
153                //Create JFrame
154
155                String title = String.format("Dot plot of %s vs. %s", afpChain.getName1(),afpChain.getName2());
156
157                // Create window
158                JFrame frame = new JFrame(title);
159                frame.addWindowListener(new WindowAdapter(){
160                        @Override
161                        public void windowClosing(WindowEvent e){
162                                JFrame f = (JFrame) e.getSource();
163                                f.setVisible(false);
164                                f.dispose();
165                        }
166                });
167
168
169                frame.getContentPane().add(dotplot);
170
171                frame.pack();
172                frame.setVisible(true);
173
174                return frame;
175        }
176
177        public static void main(String[] args) {
178
179//              String name2= "1k5j.A"; //16-68,73-119
180//              String name1= "1lrh.A"; //80-127,37-79
181
182                String name1= "1iu9.A";
183                String name2= "1h0r.A";
184
185                // Hard case
186//              String name1= "1uiz.A";
187//              String name2= "1xxa.C";
188
189                AtomCache cache = new AtomCache();
190
191
192                try {
193                        CeMain ceA = (CeMain) StructureAlignmentFactory.getAlgorithm(CeMain.algorithmName);
194
195                        CeParameters params = (CeParameters) ceA.getParameters();
196                        params.setMaxGapSize(0);
197
198                        Atom[] ca1 = cache.getAtoms(name1);
199                        Atom[] ca2 = cache.getAtoms(name2);
200
201                        // Create initial alignment
202                        AFPChain afpChain = ceA.align(ca1,ca2);
203                        afpChain.setName1(name1);
204                        afpChain.setName2(name2);
205                        for ( AFP afpI : afpChain.getAfpSet()){
206                                System.out.println(afpI);
207                        }
208
209                        /*
210                        // Get background distances
211                        CECalculator calculator = ceA.getCECalculator();
212                        int winSize = params.getWinSize();
213                        int winSizeComb1 = (winSize-1)*(winSize-2)/2;
214                        double[][] m = calculator.initSumOfDistances(ca1.length, ca2.length, params.getWinSize(), winSizeComb1, ca1, ca2);
215                        //double[][] m = calculator.getMatMatrix();
216                        Matrix mat = new Matrix(m);
217
218                        //Find range
219                        double min = mat.get(0, 0);
220                        double max = min;
221                        for(int r=0;r<mat.getRowDimension();r++) {
222                                for(int c=0;c<mat.getColumnDimension();c++) {
223                                        double y = mat.get(r,c);
224                                        if(y<min)
225                                                min = y;
226                                        if(y>max)
227                                                max = y;
228                                }
229                        }
230                        System.out.format("[%f, %f]\n", min, max);
231                        */
232
233                        //afpChain.setDistanceMatrix(mat);
234                        showDotPlotJFrame(afpChain);
235
236                        //StructureAlignmentJmol jmol = new StructureAlignmentJmol(afpChain, ca1, ca2);
237//                      jmol.setStructure(cache.getStructure(name1));
238
239
240                        //////////////////////////
241                        // Now make it circular
242                        ceA = (CeMain) StructureAlignmentFactory.getAlgorithm(CeCPMain.algorithmName);
243
244                        System.out.format("Aligning %s[%d] with %s[%d] with CPs\n",name1,ca1.length,name2,ca2.length);
245                        afpChain = ceA.align(ca1,ca2);
246                        afpChain.setName1(name1);
247                        afpChain.setName2(name2+"-"+name2);
248                        for ( AFP afpI : afpChain.getAfpSet()){
249                                System.out.println(afpI);
250                        }
251
252                        /*/ Reuse mat from the non-cp case, for simplicity
253
254                        // Get background distances
255                        Atom[] ca2clone = new Atom[ca2.length*2];
256                        int pos = 0;
257                        for (Atom a : ca2){
258                                Group g = (Group)a.getParent().clone(); // works because each group has only a CA atom
259
260                                ca2clone[pos] = g.getAtom(StructureTools.caAtomName);
261
262                                pos++;
263                        }
264                        for (Atom a : ca2){
265                                Group g = (Group)a.getParent().clone();
266
267                                ca2clone[pos] = g.getAtom(StructureTools.caAtomName);
268
269                                pos++;
270                        }
271                        m = calculator.initSumOfDistances(ca1.length, ca2clone.length, params.getWinSize(), winSizeComb1, ca1, ca2clone);
272                        //m = calculator.getMatMatrix();
273                        mat = new Matrix(m);/*ca2.length,ca1.length);
274                        for(int i=0;i<ca2.length;i++)
275                                for(int j=0;j<ca1.length;j++) {
276                                        mat.set(i, j, m[i][j]);
277                                }
278                        */
279
280                        showDotPlotJFrame(afpChain);
281
282
283                } catch (StructureException e) {
284                        e.printStackTrace();
285                } catch (IOException e) {
286                        e.printStackTrace();
287                }
288
289        }
290}
291