2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
24 // JBPNote TODO: This class is quite noisy - needs proper log.info/log.debug
26 import java.awt.event.*;
28 import jalview.analysis.*;
29 import jalview.datamodel.*;
31 import jalview.appletgui.*;
32 import jalview.structure.*;
33 import jalview.util.MessageManager;
35 public class AppletPDBCanvas extends Panel implements MouseListener,
36 MouseMotionListener, StructureListener
39 MCMatrix idmat = new MCMatrix(3, 3);
41 MCMatrix objmat = new MCMatrix(3, 3);
43 boolean redrawneeded = true;
65 float[] centre = new float[3];
67 float[] width = new float[3];
77 boolean bysequence = true;
79 boolean depthcue = true;
83 boolean bymolecule = false;
85 boolean zbuffer = true;
101 Font font = new Font("Helvetica", Font.PLAIN, 10);
103 public SequenceI[] sequence;
105 final StringBuffer mappingDetails = new StringBuffer();
107 String appletToolTip = null;
115 boolean pdbAction = false;
117 Bond highlightBond1, highlightBond2;
119 boolean errorLoading = false;
121 boolean seqColoursReady = false;
127 StructureSelectionManager ssm;
129 public AppletPDBCanvas(PDBEntry pdbentry, SequenceI[] seq,
130 String[] chains, AlignmentPanel ap, String protocol)
134 this.pdbentry = pdbentry;
137 ssm = StructureSelectionManager
138 .getStructureSelectionManager(ap.av.applet);
142 pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol);
144 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
145 pdbentry.setFile("INLINE" + pdb.id);
147 } catch (Exception ex)
149 ex.printStackTrace();
153 pdbentry.setId(pdb.id);
155 ssm.addStructureViewerListener(this);
166 // JUST DEAL WITH ONE SEQUENCE FOR NOW
167 SequenceI sequence = seq[0];
169 for (int i = 0; i < pdb.chains.size(); i++)
172 mappingDetails.append("\n\nPDB Sequence is :\nSequence = "
173 + ((PDBChain) pdb.chains.elementAt(i)).sequence
174 .getSequenceAsString());
175 mappingDetails.append("\nNo of residues = "
176 + ((PDBChain) pdb.chains.elementAt(i)).residues.size()
179 // Now lets compare the sequences to get
180 // the start and end points.
181 // Align the sequence to the pdb
182 // TODO: DNa/Pep switch
183 AlignSeq as = new AlignSeq(sequence,
184 ((PDBChain) pdb.chains.elementAt(i)).sequence,
185 ((PDBChain) pdb.chains.elementAt(i)).isNa ? AlignSeq.DNA
187 as.calcScoreMatrix();
189 PrintStream ps = new PrintStream(System.out)
191 public void print(String x)
193 mappingDetails.append(x);
196 public void println()
198 mappingDetails.append("\n");
202 as.printAlignment(ps);
204 if (as.maxscore > max)
209 pdbstart = as.seq2start;
211 seqstart = as.seq1start + sequence.getStart() - 1;
212 seqend = as.seq1end + sequence.getEnd() - 1;
215 mappingDetails.append("\nPDB start/end " + pdbstart + " " + pdbend);
216 mappingDetails.append("\nSEQ start/end " + seqstart + " " + seqend);
219 mainchain = (PDBChain) pdb.chains.elementAt(maxchain);
221 mainchain.pdbstart = pdbstart;
222 mainchain.pdbend = pdbend;
223 mainchain.seqstart = seqstart;
224 mainchain.seqend = seqend;
225 mainchain.isVisible = true;
226 // mainchain.makeExactMapping(maxAlignseq, sequence);
227 // mainchain.transferRESNUMFeatures(sequence, null);
229 this.prefsize = new Dimension(getSize().width, getSize().height);
231 // Initialize the matrices to identity
232 for (int i = 0; i < 3; i++)
234 for (int j = 0; j < 3; j++)
238 idmat.addElement(i, j, 0);
239 objmat.addElement(i, j, 0);
243 idmat.addElement(i, j, 1);
244 objmat.addElement(i, j, 1);
249 addMouseMotionListener(this);
250 addMouseListener(this);
252 addKeyListener(new KeyAdapter()
254 public void keyPressed(KeyEvent evt)
272 seqColoursReady = false;
273 // Sort the bonds by z coord
274 visiblebonds = new Vector();
276 for (int ii = 0; ii < pdb.chains.size(); ii++)
278 if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
280 Vector tmp = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
282 for (int i = 0; i < tmp.size(); i++)
284 visiblebonds.addElement(tmp.elementAt(i));
288 seqColoursReady = true;
294 public void findWidth()
296 float[] max = new float[3];
297 float[] min = new float[3];
299 max[0] = (float) -1e30;
300 max[1] = (float) -1e30;
301 max[2] = (float) -1e30;
303 min[0] = (float) 1e30;
304 min[1] = (float) 1e30;
305 min[2] = (float) 1e30;
307 for (int ii = 0; ii < pdb.chains.size(); ii++)
309 if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
311 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
313 for (int i = 0; i < bonds.size(); i++)
315 Bond tmp = (Bond) bonds.elementAt(i);
317 if (tmp.start[0] >= max[0])
319 max[0] = tmp.start[0];
322 if (tmp.start[1] >= max[1])
324 max[1] = tmp.start[1];
327 if (tmp.start[2] >= max[2])
329 max[2] = tmp.start[2];
332 if (tmp.start[0] <= min[0])
334 min[0] = tmp.start[0];
337 if (tmp.start[1] <= min[1])
339 min[1] = tmp.start[1];
342 if (tmp.start[2] <= min[2])
344 min[2] = tmp.start[2];
347 if (tmp.end[0] >= max[0])
352 if (tmp.end[1] >= max[1])
357 if (tmp.end[2] >= max[2])
362 if (tmp.end[0] <= min[0])
367 if (tmp.end[1] <= min[1])
372 if (tmp.end[2] <= min[2])
380 width[0] = (float) Math.abs(max[0] - min[0]);
381 width[1] = (float) Math.abs(max[1] - min[1]);
382 width[2] = (float) Math.abs(max[2] - min[2]);
386 if (width[1] > width[0])
391 if (width[2] > width[1])
396 // System.out.println("Maxwidth = " + maxwidth);
399 public float findScale()
405 if (getSize().width != 0)
407 width = getSize().width;
408 height = getSize().height;
412 width = prefsize.width;
413 height = prefsize.height;
425 return (float) (dim / (1.5d * maxwidth));
428 public void findCentre()
436 // Find centre coordinate
437 for (int ii = 0; ii < pdb.chains.size(); ii++)
439 if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
441 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
443 bsize += bonds.size();
445 for (int i = 0; i < bonds.size(); i++)
447 xtot = xtot + ((Bond) bonds.elementAt(i)).start[0]
448 + ((Bond) bonds.elementAt(i)).end[0];
450 ytot = ytot + ((Bond) bonds.elementAt(i)).start[1]
451 + ((Bond) bonds.elementAt(i)).end[1];
453 ztot = ztot + ((Bond) bonds.elementAt(i)).start[2]
454 + ((Bond) bonds.elementAt(i)).end[2];
459 centre[0] = xtot / (2 * (float) bsize);
460 centre[1] = ytot / (2 * (float) bsize);
461 centre[2] = ztot / (2 * (float) bsize);
464 public void paint(Graphics g)
469 g.setColor(Color.white);
470 g.fillRect(0, 0, getSize().width, getSize().height);
471 g.setColor(Color.black);
472 g.setFont(new Font("Verdana", Font.BOLD, 14));
473 g.drawString(MessageManager.getString("label.error_loading_pdb_data"), 50, getSize().height / 2);
477 if (!seqColoursReady)
479 g.setColor(Color.black);
480 g.setFont(new Font("Verdana", Font.BOLD, 14));
481 g.drawString(MessageManager.getString("label.fetching_pdb_data"), 50, getSize().height / 2);
485 // Only create the image at the beginning -
486 // this saves much memory usage
487 if ((img == null) || (prefsize.width != getSize().width)
488 || (prefsize.height != getSize().height))
493 prefsize.width = getSize().width;
494 prefsize.height = getSize().height;
497 img = createImage(prefsize.width, prefsize.height);
498 ig = img.getGraphics();
501 } catch (Exception ex)
503 ex.printStackTrace();
509 drawAll(ig, prefsize.width, prefsize.height);
510 redrawneeded = false;
512 if (appletToolTip != null)
514 ig.setColor(Color.red);
515 ig.drawString(appletToolTip, toolx, tooly);
518 g.drawImage(img, 0, 0, this);
523 public void drawAll(Graphics g, int width, int height)
525 ig.setColor(Color.black);
526 ig.fillRect(0, 0, width, height);
531 public void setColours(jalview.schemes.ColourSchemeI cs)
539 // This method has been taken out of PDBChain to allow
540 // Applet and Application specific sequence renderers to be used
541 void colourBySequence()
543 SequenceRenderer sr = new SequenceRenderer(ap.av);
545 StructureMapping[] mapping = ssm.getMapping(pdbentry.getFile());
547 boolean showFeatures = false;
548 if (ap.av.getShowSequenceFeatures())
552 fr = new jalview.appletgui.FeatureRenderer(ap.av);
555 fr.transferSettings(ap.getFeatureRenderer());
561 if (bysequence && pdb != null)
563 for (int ii = 0; ii < pdb.chains.size(); ii++)
565 chain = (PDBChain) pdb.chains.elementAt(ii);
567 for (int i = 0; i < chain.bonds.size(); i++)
569 Bond tmp = (Bond) chain.bonds.elementAt(i);
570 tmp.startCol = Color.lightGray;
571 tmp.endCol = Color.lightGray;
572 if (chain != mainchain)
577 for (int s = 0; s < sequence.length; s++)
579 for (int m = 0; m < mapping.length; m++)
581 if (mapping[m].getSequence() == sequence[s])
583 int pos = mapping[m].getSeqPos(tmp.at1.resNumber) - 1;
586 pos = sequence[s].findIndex(pos);
587 tmp.startCol = sr.getResidueBoxColour(sequence[s], pos);
590 tmp.startCol = fr.findFeatureColour(tmp.startCol,
594 pos = mapping[m].getSeqPos(tmp.at2.resNumber) - 1;
597 pos = sequence[s].findIndex(pos);
598 tmp.endCol = sr.getResidueBoxColour(sequence[s], pos);
601 tmp.endCol = fr.findFeatureColour(tmp.endCol,
616 public void drawScene(Graphics g)
625 zsort.Zsort(visiblebonds);
629 for (int i = 0; i < visiblebonds.size(); i++)
631 tmpBond = (Bond) visiblebonds.elementAt(i);
633 xstart = (int) (((tmpBond.start[0] - centre[0]) * scale) + (getSize().width / 2));
634 ystart = (int) (((centre[1] - tmpBond.start[1]) * scale) + (getSize().height / 2));
636 xend = (int) (((tmpBond.end[0] - centre[0]) * scale) + (getSize().width / 2));
637 yend = (int) (((centre[1] - tmpBond.end[1]) * scale) + (getSize().height / 2));
639 xmid = (xend + xstart) / 2;
640 ymid = (yend + ystart) / 2;
642 if (depthcue && !bymolecule)
644 if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))
646 g.setColor(tmpBond.startCol.darker().darker());
647 drawLine(g, xstart, ystart, xmid, ymid);
649 g.setColor(tmpBond.endCol.darker().darker());
650 drawLine(g, xmid, ymid, xend, yend);
652 else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))
654 g.setColor(tmpBond.startCol.darker());
655 drawLine(g, xstart, ystart, xmid, ymid);
657 g.setColor(tmpBond.endCol.darker());
658 drawLine(g, xmid, ymid, xend, yend);
662 g.setColor(tmpBond.startCol);
663 drawLine(g, xstart, ystart, xmid, ymid);
665 g.setColor(tmpBond.endCol);
666 drawLine(g, xmid, ymid, xend, yend);
670 else if (depthcue && bymolecule)
672 if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))
674 g.setColor(Color.green.darker().darker());
675 drawLine(g, xstart, ystart, xend, yend);
677 else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))
679 g.setColor(Color.green.darker());
680 drawLine(g, xstart, ystart, xend, yend);
684 g.setColor(Color.green);
685 drawLine(g, xstart, ystart, xend, yend);
688 else if (!depthcue && !bymolecule)
690 g.setColor(tmpBond.startCol);
691 drawLine(g, xstart, ystart, xmid, ymid);
692 g.setColor(tmpBond.endCol);
693 drawLine(g, xmid, ymid, xend, yend);
697 drawLine(g, xstart, ystart, xend, yend);
700 if (highlightBond1 != null && highlightBond1 == tmpBond)
702 g.setColor(Color.white);
703 drawLine(g, xmid, ymid, xend, yend);
706 if (highlightBond2 != null && highlightBond2 == tmpBond)
708 g.setColor(Color.white);
709 drawLine(g, xstart, ystart, xmid, ymid);
715 public void drawLine(Graphics g, int x1, int y1, int x2, int y2)
719 if (((float) Math.abs(y2 - y1) / (float) Math.abs(x2 - x1)) < 0.5)
721 g.drawLine(x1, y1, x2, y2);
722 g.drawLine(x1 + 1, y1 + 1, x2 + 1, y2 + 1);
723 g.drawLine(x1, y1 - 1, x2, y2 - 1);
727 g.setColor(g.getColor().brighter());
728 g.drawLine(x1, y1, x2, y2);
729 g.drawLine(x1 + 1, y1, x2 + 1, y2);
730 g.drawLine(x1 - 1, y1, x2 - 1, y2);
735 g.drawLine(x1, y1, x2, y2);
739 public Dimension minimumsize()
744 public Dimension preferredsize()
749 public void doKeyPressed(KeyEvent evt)
751 if (evt.getKeyCode() == KeyEvent.VK_UP)
753 scale = (float) (scale * 1.1);
757 else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
759 scale = (float) (scale * 0.9);
765 public void mousePressed(MouseEvent e)
768 Atom fatom = findAtom(e.getX(), e.getY());
771 fatom.isSelected = !fatom.isSelected;
775 if (foundchain != -1)
777 PDBChain chain = (PDBChain) pdb.chains.elementAt(foundchain);
778 if (chain == mainchain)
780 if (fatom.alignmentMapping != -1)
782 if (highlightRes == null)
784 highlightRes = new Vector();
787 if (highlightRes.contains(fatom.alignmentMapping + "" + ""))
789 highlightRes.removeElement(fatom.alignmentMapping + "");
793 highlightRes.addElement(fatom.alignmentMapping + "");
807 public void mouseMoved(MouseEvent e)
810 if (highlightBond1 != null)
812 highlightBond1.at2.isSelected = false;
813 highlightBond2.at1.isSelected = false;
814 highlightBond1 = null;
815 highlightBond2 = null;
818 Atom fatom = findAtom(e.getX(), e.getY());
820 PDBChain chain = null;
821 if (foundchain != -1)
823 chain = (PDBChain) pdb.chains.elementAt(foundchain);
824 if (chain == mainchain)
826 mouseOverStructure(fatom.resNumber, chain.id);
835 appletToolTip = chain.id + ":" + fatom.resNumber + " "
842 mouseOverStructure(-1, chain != null ? chain.id : null);
843 appletToolTip = null;
849 public void mouseClicked(MouseEvent e)
853 public void mouseEntered(MouseEvent e)
857 public void mouseExited(MouseEvent e)
861 public void mouseDragged(MouseEvent evt)
868 MCMatrix objmat = new MCMatrix(3, 3);
869 objmat.setIdentity();
871 if ((evt.getModifiers() & Event.META_MASK) != 0)
873 objmat.rotatez((float) ((mx - omx)));
877 objmat.rotatex((float) ((omy - my)));
878 objmat.rotatey((float) ((omx - mx)));
882 for (int ii = 0; ii < pdb.chains.size(); ii++)
884 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
886 for (int i = 0; i < bonds.size(); i++)
888 Bond tmpBond = (Bond) bonds.elementAt(i);
890 // Translate the bond so the centre is 0,0,0
891 tmpBond.translate(-centre[0], -centre[1], -centre[2]);
893 // Now apply the rotation matrix
894 tmpBond.start = objmat.vectorMultiply(tmpBond.start);
895 tmpBond.end = objmat.vectorMultiply(tmpBond.end);
897 // Now translate back again
898 tmpBond.translate(centre[0], centre[1], centre[2]);
914 public void mouseReleased(MouseEvent evt)
920 void drawLabels(Graphics g)
923 for (int ii = 0; ii < pdb.chains.size(); ii++)
925 PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
929 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
931 for (int i = 0; i < bonds.size(); i++)
933 Bond tmpBond = (Bond) bonds.elementAt(i);
935 if (tmpBond.at1.isSelected)
937 labelAtom(g, tmpBond, 1);
940 if (tmpBond.at2.isSelected)
943 labelAtom(g, tmpBond, 2);
950 public void labelAtom(Graphics g, Bond b, int n)
956 int xstart = (int) (((b.start[0] - centre[0]) * scale) + (getSize().width / 2));
957 int ystart = (int) (((centre[1] - b.start[1]) * scale) + (getSize().height / 2));
959 g.setColor(Color.red);
960 g.drawString(b.at1.resName + "-" + b.at1.resNumber, xstart, ystart);
965 int xstart = (int) (((b.end[0] - centre[0]) * scale) + (getSize().width / 2));
966 int ystart = (int) (((centre[1] - b.end[1]) * scale) + (getSize().height / 2));
968 g.setColor(Color.red);
969 g.drawString(b.at2.resName + "-" + b.at2.resNumber, xstart, ystart);
975 public Atom findAtom(int x, int y)
981 for (int ii = 0; ii < pdb.chains.size(); ii++)
983 PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
989 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
991 for (int i = 0; i < bonds.size(); i++)
993 tmpBond = (Bond) bonds.elementAt(i);
995 truex = (int) (((tmpBond.start[0] - centre[0]) * scale) + (getSize().width / 2));
997 if (Math.abs(truex - x) <= 2)
999 int truey = (int) (((centre[1] - tmpBond.start[1]) * scale) + (getSize().height / 2));
1001 if (Math.abs(truey - y) <= 2)
1003 fatom = tmpBond.at1;
1010 // Still here? Maybe its the last bond
1012 truex = (int) (((tmpBond.end[0] - centre[0]) * scale) + (getSize().width / 2));
1014 if (Math.abs(truex - x) <= 2)
1016 int truey = (int) (((tmpBond.end[1] - centre[1]) * scale) + (getSize().height / 2));
1018 if (Math.abs(truey - y) <= 2)
1020 fatom = tmpBond.at2;
1028 if (fatom != null) // )&& chain.ds != null)
1030 chain = (PDBChain) pdb.chains.elementAt(foundchain);
1037 public void update(Graphics g)
1042 public void highlightRes(int ii)
1044 if (!seqColoursReady)
1049 if (highlightRes != null && highlightRes.contains((ii - 1) + ""))
1056 for (index = 0; index < mainchain.bonds.size(); index++)
1058 tmpBond = (Bond) mainchain.bonds.elementAt(index);
1059 if (tmpBond.at1.alignmentMapping == ii - 1)
1061 if (highlightBond1 != null)
1063 highlightBond1.at2.isSelected = false;
1066 if (highlightBond2 != null)
1068 highlightBond2.at1.isSelected = false;
1071 highlightBond1 = null;
1072 highlightBond2 = null;
1076 highlightBond1 = (Bond) mainchain.bonds.elementAt(index - 1);
1077 highlightBond1.at2.isSelected = true;
1080 if (index != mainchain.bonds.size())
1082 highlightBond2 = (Bond) mainchain.bonds.elementAt(index);
1083 highlightBond2.at1.isSelected = true;
1090 redrawneeded = true;
1094 public void setAllchainsVisible(boolean b)
1096 for (int ii = 0; ii < pdb.chains.size(); ii++)
1098 PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
1099 chain.isVisible = b;
1101 mainchain.isVisible = true;
1106 // ////////////////////////////////
1107 // /StructureListener
1108 public String[] getPdbFile()
1111 { pdbentry.getFile() };
1116 public void mouseOverStructure(int pdbResNum, String chain)
1118 if (lastMessage == null || !lastMessage.equals(pdbResNum + chain))
1119 ssm.mouseOverStructure(pdbResNum, chain, pdbentry.getFile());
1121 lastMessage = pdbResNum + chain;
1124 StringBuffer resetLastRes = new StringBuffer();
1126 StringBuffer eval = new StringBuffer();
1128 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
1131 if (!seqColoursReady)
1136 if (highlightRes != null && highlightRes.contains((atomIndex - 1) + ""))
1143 for (index = 0; index < mainchain.bonds.size(); index++)
1145 tmpBond = (Bond) mainchain.bonds.elementAt(index);
1146 if (tmpBond.at1.atomIndex == atomIndex)
1148 if (highlightBond1 != null)
1150 highlightBond1.at2.isSelected = false;
1153 if (highlightBond2 != null)
1155 highlightBond2.at1.isSelected = false;
1158 highlightBond1 = null;
1159 highlightBond2 = null;
1163 highlightBond1 = (Bond) mainchain.bonds.elementAt(index - 1);
1164 highlightBond1.at2.isSelected = true;
1167 if (index != mainchain.bonds.size())
1169 highlightBond2 = (Bond) mainchain.bonds.elementAt(index);
1170 highlightBond2.at1.isSelected = true;
1177 redrawneeded = true;
1181 public Color getColour(int atomIndex, int pdbResNum, String chain,
1185 // if (!pdbfile.equals(pdbentry.getFile()))
1188 // return new Color(viewer.getAtomArgb(atomIndex));
1191 public void updateColours(Object source)
1194 redrawneeded = true;
1199 public void releaseReferences(Object svl)
1201 // TODO Auto-generated method stub