/*
* PDB web development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public Licence. This should
* be distributed with the code. If you do not have a copy,
* see:
*
* http://www.gnu.org/copyleft/lesser.html
*
* Copyright for this code is held jointly by the individual
* authors. These should be listed in @author doc comments.
*
*
* Created on Jul 28, 2009
* Created by ap3
*
*/
package org.biojava.nbio.structure.align.gui;
import org.biojava.nbio.structure.Atom;
import org.biojava.nbio.structure.StructureException;
import org.biojava.nbio.structure.align.StructureAlignmentFactory;
import org.biojava.nbio.structure.align.ce.CeCPMain;
import org.biojava.nbio.structure.align.ce.CeMain;
import org.biojava.nbio.structure.align.ce.CeParameters;
import org.biojava.nbio.structure.align.helper.JointFragments;
import org.biojava.nbio.structure.align.model.AFP;
import org.biojava.nbio.structure.align.model.AFPChain;
import org.biojava.nbio.structure.align.pairwise.AlternativeAlignment;
import org.biojava.nbio.structure.align.util.AtomCache;
import org.biojava.nbio.structure.gui.ScaleableMatrixPanel;
import org.biojava.nbio.structure.jama.Matrix;
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Displays the dot plot trace for an alignment.
*
* This class adapts ScaleableMatrixPanel, which uses code from org.biojava.nbio.structure.align.pairwise,
* with more BioJava-friendly methods based off AFPChains.
*
* @author Spencer Bliven
*
*/
public class DotPlotPanel extends ScaleableMatrixPanel {
private static final long serialVersionUID = -7641953255857483895L;
/**
*
* @param alignment The alignment to plot
* @param background [Optional]A matrix of 'background colors' over which to draw the alignment.
*
* Originally designed as a matrix of RMSD values between AFPs, so it is colorized
* accordingly from red (0) to black (>10).
*
* If this set to null, the background is set to black.
*/
public DotPlotPanel(AFPChain alignment ){
super();
final double defaultBackground = 100.;
// Convert the AFPChain alignment into the MatrixPanel format
AlternativeAlignment[] aligns = new AlternativeAlignment[alignment.getBlockNum()];
int alignNumber = 0;
//One alternative alignment for each block
int[][][] optAln = alignment.getOptAln(); // [block #][{0,1} chain index][pos]
for(;alignNumber < optAln.length;alignNumber++) {
List<int[]> alignPairs = new ArrayList<int[]>();
for(int pos = 0; pos<optAln[alignNumber][0].length; pos++ ) {
alignPairs.add( new int[] {
optAln[alignNumber][0][pos],
optAln[alignNumber][1][pos] }
);
}
JointFragments frag = new JointFragments();
frag.setIdxlist(alignPairs);
aligns[alignNumber] = new AlternativeAlignment();
aligns[alignNumber].apairs_from_idxlst(frag);
}
/* TODO After the AFPSet is fixed in CeMain#filterDuplicateAFPs, maybe include this again
//add alignment for the AFPs
List<AFP> afps = alignment.getAfpSet();
List<int[]> alignPairs = new ArrayList<int[]>();
for(AFP afp : afps) {
int start1 = afp.getP1();
int start2 = afp.getP2();
for(int i=0;i<afp.getFragLen();i++) {
alignPairs.add( new int[] { start1+i, start2+i } );
}
}
JointFragments frag = new JointFragments();
frag.setIdxlist(alignPairs);
aligns[alignNumber] = new AlternativeAlignment();
aligns[alignNumber].apairs_from_idxlst(frag);
*/
/* AFP boxes are unnecessary.
// Calculate FragmentPairs based on alignment.
// These are displayed as a small box around the start of each alignment.
FragmentPair[] pairs = new FragmentPair[afps.size()];
for(int i=0;i<pairs.length;i++) {
AFP afp = afps.get(i);
pairs[i] = new FragmentPair(afp.getFragLen(), afp.getP1(), afp.getP2());
pairs[i].setRms(afp.getRmsd());
}
this.setFragmentPairs(pairs);
*/
// Now the alignments have been build; add it
this.setAlternativeAligs(aligns);
this.setSelectedAlignmentPos(0); //color white, not red
Matrix background = alignment.getDistanceMatrix();
//Fill with default black background if none given
if(background == null) {
background = new Matrix(alignment.getCa1Length(),alignment.getCa2Length());
for(int i=0;i<background.getRowDimension();i++)
for(int j=0;j<background.getColumnDimension(); j++) {
background.set(i, j, defaultBackground);
}
}
// Set parameters
this.setMatrix(background);
}
/**
* Helper function to create and display a JFrame with a single DotPlotPanel
*
* @param afpChain
* @param background
*/
private static JFrame showDotPlotJFrame(AFPChain afpChain ) {
DotPlotPanel dotplot = new DotPlotPanel(afpChain);
//Create JFrame
String title = String.format("Dot plot of %s vs. %s", afpChain.getName1(),afpChain.getName2());
// Create window
JFrame frame = new JFrame(title);
frame.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e){
JFrame f = (JFrame) e.getSource();
f.setVisible(false);
f.dispose();
}
});
frame.getContentPane().add(dotplot);
frame.pack();
frame.setVisible(true);
return frame;
}
public static void main(String[] args) {
// String name2= "1k5j.A"; //16-68,73-119
// String name1= "1lrh.A"; //80-127,37-79
String name1= "1iu9.A";
String name2= "1h0r.A";
// Hard case
// String name1= "1uiz.A";
// String name2= "1xxa.C";
AtomCache cache = new AtomCache();
try {
CeMain ceA = (CeMain) StructureAlignmentFactory.getAlgorithm(CeMain.algorithmName);
CeParameters params = (CeParameters) ceA.getParameters();
params.setMaxGapSize(0);
Atom[] ca1 = cache.getAtoms(name1);
Atom[] ca2 = cache.getAtoms(name2);
// Create initial alignment
AFPChain afpChain = ceA.align(ca1,ca2);
afpChain.setName1(name1);
afpChain.setName2(name2);
for ( AFP afpI : afpChain.getAfpSet()){
System.out.println(afpI);
}
/*
// Get background distances
CECalculator calculator = ceA.getCECalculator();
int winSize = params.getWinSize();
int winSizeComb1 = (winSize-1)*(winSize-2)/2;
double[][] m = calculator.initSumOfDistances(ca1.length, ca2.length, params.getWinSize(), winSizeComb1, ca1, ca2);
//double[][] m = calculator.getMatMatrix();
Matrix mat = new Matrix(m);
//Find range
double min = mat.get(0, 0);
double max = min;
for(int r=0;r<mat.getRowDimension();r++) {
for(int c=0;c<mat.getColumnDimension();c++) {
double y = mat.get(r,c);
if(y<min)
min = y;
if(y>max)
max = y;
}
}
System.out.format("[%f, %f]\n", min, max);
*/
//afpChain.setDistanceMatrix(mat);
showDotPlotJFrame(afpChain);
//StructureAlignmentJmol jmol = new StructureAlignmentJmol(afpChain, ca1, ca2);
// jmol.setStructure(cache.getStructure(name1));
//////////////////////////
// Now make it circular
ceA = (CeMain) StructureAlignmentFactory.getAlgorithm(CeCPMain.algorithmName);
System.out.format("Aligning %s[%d] with %s[%d] with CPs\n",name1,ca1.length,name2,ca2.length);
afpChain = ceA.align(ca1,ca2);
afpChain.setName1(name1);
afpChain.setName2(name2+"-"+name2);
for ( AFP afpI : afpChain.getAfpSet()){
System.out.println(afpI);
}
/*/ Reuse mat from the non-cp case, for simplicity
// Get background distances
Atom[] ca2clone = new Atom[ca2.length*2];
int pos = 0;
for (Atom a : ca2){
Group g = (Group)a.getParent().clone(); // works because each group has only a CA atom
ca2clone[pos] = g.getAtom(StructureTools.caAtomName);
pos++;
}
for (Atom a : ca2){
Group g = (Group)a.getParent().clone();
ca2clone[pos] = g.getAtom(StructureTools.caAtomName);
pos++;
}
m = calculator.initSumOfDistances(ca1.length, ca2clone.length, params.getWinSize(), winSizeComb1, ca1, ca2clone);
//m = calculator.getMatMatrix();
mat = new Matrix(m);/*ca2.length,ca1.length);
for(int i=0;i<ca2.length;i++)
for(int j=0;j<ca1.length;j++) {
mat.set(i, j, m[i][j]);
}
*/
showDotPlotJFrame(afpChain);
} catch (StructureException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}