/* * Jalview - A Sequence Alignment Editor and Viewer * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package MCview; // JBPNote TODO: This class is quite noisy - needs proper log.info/log.debug import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; import javax.swing.*; import jalview.analysis.AlignSeq; import jalview.datamodel.*; public class rotCanvas extends JPanel implements KeyListener, MouseListener, MouseMotionListener { MCMatrix idmat = new MCMatrix(3,3); MCMatrix objmat = new MCMatrix(3,3); boolean redrawneeded =true; int omx = 0; int mx = 0; int omy = 0; int my = 0; public PDBfile pdb; int bsize; Image img; Graphics ig; Dimension prefsize; float centre[] = new float[3]; float width[] = new float[3]; float maxwidth; float scale; String inStr; String inType; boolean depthcue = true; boolean wire = false; boolean bymolecule = false; boolean zbuffer = true; boolean dragging; int xstart; int xend; int ystart; int yend; int xmid; int ymid; Font font = new Font("Helvetica",Font.PLAIN,10); public rotCanvas(PDBfile pdb, Sequence sequence, jalview.gui.AlignViewport av) throws IOException { int max = -10; int maxchain = -1; int pdbstart=0, pdbend=0, seqstart =0, seqend=0; for (int i=0; i < pdb.chains.size(); i++) { // Now lets compare the sequences to get // the start and end points. java.util.StringTokenizer str = new java.util.StringTokenizer(sequence.getSequence(), "."); String newString = ""; while (str.hasMoreTokens()) { newString += str.nextToken(); } // Align the sequence to the pdb AlignSeq as = new AlignSeq(sequence,((PDBChain)pdb.chains.elementAt(i)).sequence,"pep"); as.calcScoreMatrix(); as.traceAlignment(); as.printAlignment(); if (as.maxscore > max) { max = as.maxscore; maxchain = i; pdbstart = as.seq2start; pdbend = as.seq2end; seqstart = as.seq1start - 1 ; seqend = as.seq1end -1; } System.out.println("PDB start/end " + pdbstart + " " + pdbend); System.out.println("SEQ start/end " + seqstart + " " + seqend); } ( (PDBChain)pdb.chains.elementAt(maxchain)).pdbstart = pdbstart; ( (PDBChain)pdb.chains.elementAt(maxchain)).pdbend = pdbend; ( (PDBChain)pdb.chains.elementAt(maxchain)).seqstart = seqstart; ( (PDBChain)pdb.chains.elementAt(maxchain)).seqend = seqend; ( (PDBChain) pdb.chains.elementAt(maxchain)).isVisible = true; ( (PDBChain) pdb.chains.elementAt(maxchain)).sequence = sequence; ( (PDBChain)pdb.chains.elementAt(maxchain)).colourBySequence(av, sequence); this.pdb = pdb; this.prefsize = new Dimension( getWidth(), getHeight()); //Initialize the matrices to identity for (int i = 0; i < 3; i++) { for (int j = 0; j < 3 ; j++) { if (i != j) { idmat.addElement(i,j,0); objmat.addElement(i,j,0); } else { idmat.addElement(i,j,1); objmat.addElement(i,j,1); } } } addMouseMotionListener(this); addMouseListener(this); addKeyListener(this); addPDBfile(); ToolTipManager.sharedInstance().registerComponent(this); } public void addPDBfile() { findCentre(); findWidth(); scale = findScale(); System.out.println("Scale factor = " + scale); } public void deleteBonds() { scale = 0; maxwidth = 0; width[0] = 0; width[1] = 0; width[2] = 0; centre[0] = 0; centre[1] = 0; centre[2] = 0; for (int i=0; i < pdb.chains.size(); i++) { ((PDBChain)pdb.chains.elementAt(i)).bonds = null; } } public void findWidth() { float max[] = new float[3]; float min[] = new float[3]; max[0] = (float)-1e30; max[1] = (float)-1e30; max[2] = (float)-1e30; min[0] = (float)1e30; min[1] = (float)1e30; min[2] = (float)1e30; for (int ii=0; ii < pdb.chains.size(); ii++) { if (((PDBChain)pdb.chains.elementAt(ii)).isVisible) { Vector bonds = ((PDBChain)pdb.chains.elementAt(ii)).bonds; for (int i = 0; i < bonds.size(); i++) { Bond tmp = (Bond)bonds.elementAt(i); if (tmp.start[0] >= max[0]) max[0] = tmp.start[0]; if (tmp.start[1] >= max[1]) max[1] = tmp.start[1]; if (tmp.start[2] >= max[2]) max[2] = tmp.start[2]; if (tmp.start[0] <= min[0]) min[0] = tmp.start[0]; if (tmp.start[1] <= min[1]) min[1] = tmp.start[1]; if (tmp.start[2] <= min[2]) min[2] = tmp.start[2]; if (tmp.end[0] >= max[0]) max[0] = tmp.end[0]; if (tmp.end[1] >= max[1]) max[1] = tmp.end[1]; if (tmp.end[2] >= max[2]) max[2] = tmp.end[2]; if (tmp.end[0] <= min[0]) min[0] = tmp.end[0]; if (tmp.end[1] <= min[1]) min[1] = tmp.end[1]; if (tmp.end[2] <= min[2]) min[2] = tmp.end[2]; } } } System.out.println("xmax " + max[0] + " min " + min[0]); System.out.println("ymax " + max[1] + " min " + min[1]); System.out.println("zmax " + max[2] + " min " + min[2]); width[0] = (float)Math.abs(max[0] - min[0]); width[1] = (float)Math.abs(max[1] - min[1]); width[2] = (float)Math.abs(max[2] - min[2]); maxwidth = width[0]; if (width[1] > width[0]) maxwidth = width[1]; if (width[2] > width[1]) maxwidth = width[2]; System.out.println("Maxwidth = " + maxwidth); } public float findScale() { int dim, width, height; if ( getWidth() != 0) { width = getWidth(); height = getHeight(); } else { width = prefsize.width; height = prefsize.height; } if (width < height) { dim = width; } else { dim = height; } return (float)(dim/(1.5d*maxwidth)); } public void findCentre() { float xtot = 0; float ytot = 0; float ztot = 0; int bsize = 0; //Find centre coordinate for (int ii = 0; ii < pdb.chains.size() ; ii++) { if (((PDBChain)pdb.chains.elementAt(ii)).isVisible) { Vector bonds = ((PDBChain)pdb.chains.elementAt(ii)).bonds; bsize += bonds.size(); for (int i = 0; i < bonds.size(); i++) { xtot = xtot + ((Bond)bonds.elementAt(i)).start[0] + ((Bond)bonds.elementAt(i)).end[0]; ytot = ytot + ((Bond)bonds.elementAt(i)).start[1] + ((Bond)bonds.elementAt(i)).end[1]; ztot = ztot + ((Bond)bonds.elementAt(i)).start[2] + ((Bond)bonds.elementAt(i)).end[2]; } } } centre[0] = xtot / (2 * (float)bsize); centre[1] = ytot / (2 * (float)bsize); centre[2] = ztot / (2 * (float)bsize); } public void paint(Graphics g) { //Only create the image at the beginning - //this saves much memory usage if ((img == null) || (prefsize.width != getWidth()) || (prefsize.height != getHeight())) { prefsize.width = getWidth(); prefsize.height = getHeight(); scale = findScale(); img = createImage(prefsize.width,prefsize.height); ig = img.getGraphics(); redrawneeded = true; } if (redrawneeded == true) { drawBackground(ig,Color.black); drawScene(ig); redrawneeded = false; } else { ig = img.getGraphics(); } g.drawImage(img,0,0,this); } public void drawBackground(Graphics g, Color col) { g.setColor(col); g.fillRect(0,0,prefsize.width,prefsize.height); } public void drawScene(Graphics g) { // Sort the bonds by z coord Vector bonds = new Vector(); for (int ii = 0; ii < pdb.chains.size() ; ii++) { if (((PDBChain)pdb.chains.elementAt(ii)).isVisible) { Vector tmp = ((PDBChain)pdb.chains.elementAt(ii)).bonds; for (int i=0; i < tmp.size(); i++) { bonds.addElement(tmp.elementAt(i)); } } } if (zbuffer) { Zsort.Zsort(bonds); } for (int i = 0; i < bonds.size(); i++) { Bond tmpBond = (Bond)bonds.elementAt(i); xstart = (int)((tmpBond.start[0] - centre[0])*scale + getWidth()/2); ystart = (int)((tmpBond.start[1] - centre[1])*scale + getHeight()/2); xend = (int)((tmpBond.end[0] - centre[0])*scale + getWidth()/2); yend = (int)((tmpBond.end[1] - centre[1])*scale + getHeight()/2); xmid = (xend+xstart)/2; ymid = (yend+ystart)/2; if (depthcue && !bymolecule) { if (tmpBond.start[2] < (centre[2] - maxwidth/6)) { g.setColor(tmpBond.startCol.darker().darker()); drawLine(g,xstart,ystart,xmid,ymid); g.setColor(tmpBond.endCol.darker().darker()); drawLine(g,xmid,ymid,xend,yend); } else if (tmpBond.start[2] < (centre[2]+maxwidth/6)) { g.setColor(tmpBond.startCol.darker()); drawLine(g,xstart,ystart,xmid,ymid); g.setColor(tmpBond.endCol.darker()); drawLine(g,xmid,ymid,xend,yend); } else { g.setColor(tmpBond.startCol); drawLine(g,xstart,ystart,xmid,ymid); g.setColor(tmpBond.endCol); drawLine(g,xmid,ymid,xend,yend); } } else if (depthcue && bymolecule) { if (tmpBond.start[2] < (centre[2] - maxwidth/6)) { g.setColor(Color.green.darker().darker()); drawLine(g,xstart,ystart,xend,yend); } else if (tmpBond.start[2] < (centre[2]+maxwidth/6)) { g.setColor(Color.green.darker()); drawLine(g,xstart,ystart,xend,yend); } else { g.setColor(Color.green); drawLine(g,xstart,ystart,xend,yend); } } else if (!depthcue && !bymolecule) { g.setColor(tmpBond.startCol); drawLine(g,xstart,ystart,xmid,ymid); g.setColor(tmpBond.endCol); drawLine(g,xmid,ymid,xend,yend); } else { drawLine(g,xstart,ystart,xend,yend); } } } public void drawLine(Graphics g, int x1, int y1, int x2, int y2) { if (!wire) { if (((float)Math.abs(y2-y1)/(float)Math.abs(x2-x1)) < 0.5) { g.drawLine(x1,y1,x2,y2); g.drawLine(x1+1,y1+1,x2+1,y2+1); g.drawLine(x1,y1-1,x2,y2-1); } else { g.setColor(g.getColor().brighter()); g.drawLine(x1,y1,x2,y2); g.drawLine(x1+1,y1,x2+1,y2); g.drawLine(x1-1,y1,x2-1,y2); } } else { g.drawLine(x1,y1,x2,y2); } } public Dimension minimumsize() { return prefsize; } public Dimension preferredsize() { return prefsize; } public void keyTyped(KeyEvent evt) { } public void keyReleased(KeyEvent evt) { } public void keyPressed(KeyEvent evt) { int key = evt.getKeyChar(); if (evt.getKeyCode() == KeyEvent.VK_UP) { scale = (float)(scale * 1.1); redrawneeded = true; repaint(); } else if (evt.getKeyCode() == KeyEvent.VK_DOWN) { scale = (float)(scale * 0.9); redrawneeded = true; repaint(); } else if (key == 'w') { wire = !wire; System.out.println("wireframe " + wire); redrawneeded = true; repaint(); } else if (key == 'd') { depthcue = !depthcue; System.out.println("Depth cueing is " + depthcue); redrawneeded = true; repaint(); } else if (key == 'm') { bymolecule = !bymolecule; System.out.println("Bymolecule is " + bymolecule); redrawneeded = true; repaint(); } else if (key == 'z') { zbuffer = !zbuffer; System.out.println("Z buffering is " + zbuffer); redrawneeded = true; repaint(); } else if (key == 'c') { bymolecule = false; pdb.setChainColours(); System.out.println("Colouring by chain"); redrawneeded = true; repaint(); } else if (key == 'h') { bymolecule = false; pdb.setHydrophobicityColours(); System.out.println("Colouring by hydrophobicity"); redrawneeded = true; repaint(); } else if (key == 'q') { bymolecule = false; pdb.setChargeColours(); System.out.println("Colouring charges and cysteines"); redrawneeded = true; repaint(); } return; } public void mousePressed(MouseEvent e) { mx = e.getX(); my = e.getY(); omx = mx; omy = my; dragging = false; } public void mouseMoved(MouseEvent e) { myAtom fatom = null; for (int ii = 0; ii < pdb.chains.size(); ii++) { PDBChain chain = (PDBChain) pdb.chains.elementAt(ii); if (chain.isVisible) { Vector bonds = ( (PDBChain) pdb.chains.elementAt(ii)).bonds; for (int i = 0; i < bonds.size(); i++) { Bond tmpBond = (Bond) bonds.elementAt(i); int truex = (int) ( (tmpBond.start[0] - centre[0]) * scale + getWidth() / 2); if (Math.abs(truex - e.getX()) <= 2) { int truey = (int) ( (tmpBond.start[1] - centre[1]) * scale + getHeight() / 2); if (Math.abs(truey - e.getY()) <= 2) fatom = tmpBond.at1; } } } } if(fatom!=null) { this.setToolTipText(fatom.resName); } else this.setToolTipText(null); } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseDragged(MouseEvent evt) { int x = evt.getX(); int y = evt.getY(); mx = x; my = y; MCMatrix objmat = new MCMatrix(3,3); objmat.setIdentity(); if ((evt.getModifiers() & Event.META_MASK) != 0) { objmat.rotatez((float)((mx-omx))); } else { objmat.rotatex((float)((my-omy))); objmat.rotatey((float)((omx-mx))); } //Alter the bonds for (int ii = 0; ii < pdb.chains.size() ; ii++) { Vector bonds = ((PDBChain)pdb.chains.elementAt(ii)).bonds; for (int i = 0; i < bonds.size(); i++) { Bond tmpBond = (Bond)bonds.elementAt(i); //Translate the bond so the centre is 0,0,0 tmpBond.translate(-centre[0],-centre[1],-centre[2]); //Now apply the rotation matrix tmpBond.start = objmat.vectorMultiply(tmpBond.start); tmpBond.end = objmat.vectorMultiply(tmpBond.end); //Now translate back again tmpBond.translate(centre[0],centre[1],centre[2]); } } objmat = null; omx = mx; omy = my; redrawneeded = true; paint(this.getGraphics()); dragging = true; return; } public void mouseReleased(MouseEvent evt) { int x = evt.getX(); int y = evt.getY(); if (!dragging) { myAtom tmp = findAtom(x,y); } drawLabels(); return; } public void drawLabels() { redrawneeded = true; paint(this.getGraphics()); for (int ii = 0; ii < pdb.chains.size() ; ii++) { PDBChain chain = (PDBChain)pdb.chains.elementAt(ii); if (chain.isVisible) { Vector bonds = ((PDBChain)pdb.chains.elementAt(ii)).bonds; for (int i = 0; i < bonds.size(); i++) { Bond tmpBond = (Bond)bonds.elementAt(i); if (tmpBond.at1.isSelected) { labelAtom(img.getGraphics(),tmpBond,1); } if (tmpBond.at2.isSelected) { labelAtom(img.getGraphics(),tmpBond,2); } } } } this.getGraphics().drawImage(img,0,0,this); dragging = false; } public void labelAtom(Graphics g,Bond b, int n) { g.setFont(font); if (n ==1) { int xstart = (int)((b.start[0] - centre[0])*scale + getWidth()/2); int ystart = (int)((b.start[1] - centre[1])*scale + getHeight()/2); g.setColor(Color.red); g.drawString(b.at1.resName + "-" + b.at1.resNumber,xstart,ystart); } if (n ==2) { int xstart = (int)((b.end[0] - centre[0])*scale + getWidth()/2); int ystart = (int)((b.end[1] - centre[1])*scale + getHeight()/2); g.setColor(Color.red); g.drawString(b.at2.resName + "-" + b.at2.resNumber,xstart,ystart); } } public myAtom findAtom(int x, int y) { myAtom fatom = null; int foundchain = -1; for (int ii = 0; ii < pdb.chains.size() ; ii++) { PDBChain chain = (PDBChain)pdb.chains.elementAt(ii); if (chain.isVisible) { Vector bonds = ((PDBChain)pdb.chains.elementAt(ii)).bonds; for (int i = 0; i < bonds.size(); i++) { Bond tmpBond = (Bond)bonds.elementAt(i); int truex = (int)((tmpBond.start[0] - centre[0])*scale + getWidth()/2); if (Math.abs(truex - x) <= 2) { int truey = (int)((tmpBond.start[1] - centre[1])*scale + getHeight()/2); if (Math.abs(truey - y) <= 2) { System.out.println("Found match"); System.out.println(x + " " + y); System.out.println(truex + " " + truey); System.out.println(tmpBond.start[0] + " " + tmpBond.start[1]); System.out.println("Atom 1 = " + tmpBond.at1.resName + " " + tmpBond.at1.resNumber + " " + tmpBond.at1.chain); fatom = tmpBond.at1; fatom.isSelected = !fatom.isSelected; foundchain = ii; } } } } if (fatom != null) //)&& chain.ds != null) { chain = (PDBChain)pdb.chains.elementAt(foundchain); // SMJS TODO // int tmp = chain.ds.seqstart + fatom.resNumber - chain.offset; // int pos = chain.ds.findIndex(tmp); // System.out.println("Found seq " + chain.ds.name + " " + tmp + " " + pos); } } return fatom; } public void update(Graphics g) { paint(g); } }