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