getSequenceAsString
[jalview.git] / src / MCview / PDBCanvas.java
1 /*
2 * Jalview - A Sequence Alignment Editor and Viewer
3 * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18 */
19 package MCview;
20
21 import jalview.analysis.AlignSeq;
22
23 import jalview.datamodel.*;
24
25 // JBPNote TODO: This class is quite noisy - needs proper log.info/log.debug
26 import java.awt.*;
27 import java.awt.event.*;
28
29 import java.io.*;
30
31 import java.util.*;
32
33 import javax.swing.*;
34
35
36 public class PDBCanvas extends JPanel implements MouseListener, MouseMotionListener
37 {
38     MCMatrix idmat = new MCMatrix(3, 3);
39     MCMatrix objmat = new MCMatrix(3, 3);
40     boolean redrawneeded = true;
41     int omx = 0;
42     int mx = 0;
43     int omy = 0;
44     int my = 0;
45     public PDBfile pdb;
46     int bsize;
47     Image img;
48     Graphics ig;
49     Dimension prefsize;
50     float[] centre = new float[3];
51     float[] width = new float[3];
52     float maxwidth;
53     float scale;
54     String inStr;
55     String inType;
56     boolean bysequence = true;
57     boolean depthcue = true;
58     boolean wire = false;
59     boolean bymolecule = false;
60     boolean zbuffer = true;
61     boolean dragging;
62     int xstart;
63     int xend;
64     int ystart;
65     int yend;
66     int xmid;
67     int ymid;
68     Font font = new Font("Helvetica", Font.PLAIN, 10);
69     jalview.gui.SeqCanvas seqcanvas;
70     public Sequence sequence;
71     final StringBuffer mappingDetails = new StringBuffer();
72     PDBChain mainchain;
73     Vector highlightRes;
74     boolean pdbAction = false;
75     boolean seqColoursReady = false;
76     jalview.gui.FeatureRenderer fr;
77     Color backgroundColour = Color.black;
78
79     public PDBCanvas(jalview.gui.SeqCanvas seqcanvas, Sequence seq)
80     {
81       this.seqcanvas = seqcanvas;
82       this.sequence = seq;
83       seqcanvas.setPDBCanvas(this);
84     }
85
86   public void setPDBFile(PDBfile pdb)
87    {
88         int max = -10;
89         int maxchain = -1;
90         int pdbstart = 0;
91         int pdbend = 0;
92         int seqstart = 0;
93         int seqend = 0;
94         AlignSeq maxAlignseq = null;
95
96         for (int i = 0; i < pdb.chains.size(); i++)
97         {
98
99           mappingDetails.append("\n\nPDB Sequence is :\nSequence = " + ((PDBChain) pdb.chains.elementAt(i)).sequence.getSequenceAsString());
100           mappingDetails.append("\nNo of residues = " + ((PDBChain) pdb.chains.elementAt(i)).residues.size()+"\n\n");
101
102             // Now lets compare the sequences to get
103             // the start and end points.
104             // Align the sequence to the pdb
105             AlignSeq as = new AlignSeq(sequence,
106                     ((PDBChain) pdb.chains.elementAt(i)).sequence, "pep");
107             as.calcScoreMatrix();
108             as.traceAlignment();
109             PrintStream  ps = new PrintStream(System.out)
110            {
111               public void print(String x) {
112                    mappingDetails.append(x);
113                }
114                public void println()
115                {
116                  mappingDetails.append("\n");
117                }
118             };
119
120             as.printAlignment(ps);
121
122
123
124             if (as.maxscore > max)
125             {
126                 max = as.maxscore;
127                 maxchain = i;
128                 pdbstart = as.seq2start;
129                 pdbend = as.seq2end;
130                 seqstart = as.seq1start + sequence.getStart()-1;
131                 seqend = as.seq1end + sequence.getEnd()-1;
132                 maxAlignseq = as;
133             }
134
135             mappingDetails.append("\nPDB start/end "  + pdbstart + " " + pdbend);
136             mappingDetails.append("\nSEQ start/end "+ seqstart + " " + seqend);
137         }
138
139         mainchain = (PDBChain) pdb.chains.elementAt(maxchain);
140
141         mainchain.pdbstart = pdbstart;
142         mainchain.pdbend = pdbend;
143         mainchain.seqstart = seqstart;
144         mainchain.seqend = seqend;
145         mainchain.isVisible = true;
146         mainchain.makeExactMapping(maxAlignseq, sequence);
147
148         this.pdb = pdb;
149         this.prefsize = new Dimension(getWidth(), getHeight());
150
151         //Initialize the matrices to identity
152         for (int i = 0; i < 3; i++) {
153             for (int j = 0; j < 3; j++) {
154                 if (i != j) {
155                     idmat.addElement(i, j, 0);
156                     objmat.addElement(i, j, 0);
157                 } else {
158                     idmat.addElement(i, j, 1);
159                     objmat.addElement(i, j, 1);
160                 }
161             }
162         }
163
164         addMouseMotionListener(this);
165         addMouseListener(this);
166
167         addMouseWheelListener(new MouseWheelListener()
168         {
169           public void mouseWheelMoved(MouseWheelEvent e)
170           {
171             if (e.getWheelRotation() > 0)
172             {
173               scale = (float) (scale * 1.1);
174               redrawneeded = true;
175               repaint();
176             }
177
178             else
179             {
180               scale = (float) (scale * 0.9);
181               redrawneeded = true;
182               repaint();
183             }
184           }
185        });
186
187
188         findCentre();
189         findWidth();
190
191         setupBonds();
192
193         scale = findScale();
194
195         ToolTipManager.sharedInstance().registerComponent(this);
196         ToolTipManager.sharedInstance().setInitialDelay(0);
197         ToolTipManager.sharedInstance().setDismissDelay(10000);
198     }
199
200
201     Vector visiblebonds;
202     void setupBonds()
203     {
204       seqColoursReady = false;
205       // Sort the bonds by z coord
206       visiblebonds = new Vector();
207
208       for (int ii = 0; ii < pdb.chains.size(); ii++)
209       {
210         if ( ( (PDBChain) pdb.chains.elementAt(ii)).isVisible)
211         {
212           Vector tmp = ( (PDBChain) pdb.chains.elementAt(ii)).bonds;
213
214           for (int i = 0; i < tmp.size(); i++)
215           {
216             visiblebonds.addElement(tmp.elementAt(i));
217           }
218         }
219       }
220
221       updateSeqColours();
222       seqColoursReady = true;
223       redrawneeded = true;
224       repaint();
225     }
226
227
228     public void findWidth() {
229         float[] max = new float[3];
230         float[] min = new float[3];
231
232         max[0] = (float) -1e30;
233         max[1] = (float) -1e30;
234         max[2] = (float) -1e30;
235
236         min[0] = (float) 1e30;
237         min[1] = (float) 1e30;
238         min[2] = (float) 1e30;
239
240         for (int ii = 0; ii < pdb.chains.size(); ii++) {
241             if (((PDBChain) pdb.chains.elementAt(ii)).isVisible) {
242                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
243
244                 for (int i = 0; i < bonds.size(); i++) {
245                     Bond tmp = (Bond) bonds.elementAt(i);
246
247                     if (tmp.start[0] >= max[0]) {
248                         max[0] = tmp.start[0];
249                     }
250
251                     if (tmp.start[1] >= max[1]) {
252                         max[1] = tmp.start[1];
253                     }
254
255                     if (tmp.start[2] >= max[2]) {
256                         max[2] = tmp.start[2];
257                     }
258
259                     if (tmp.start[0] <= min[0]) {
260                         min[0] = tmp.start[0];
261                     }
262
263                     if (tmp.start[1] <= min[1]) {
264                         min[1] = tmp.start[1];
265                     }
266
267                     if (tmp.start[2] <= min[2]) {
268                         min[2] = tmp.start[2];
269                     }
270
271                     if (tmp.end[0] >= max[0]) {
272                         max[0] = tmp.end[0];
273                     }
274
275                     if (tmp.end[1] >= max[1]) {
276                         max[1] = tmp.end[1];
277                     }
278
279                     if (tmp.end[2] >= max[2]) {
280                         max[2] = tmp.end[2];
281                     }
282
283                     if (tmp.end[0] <= min[0]) {
284                         min[0] = tmp.end[0];
285                     }
286
287                     if (tmp.end[1] <= min[1]) {
288                         min[1] = tmp.end[1];
289                     }
290
291                     if (tmp.end[2] <= min[2]) {
292                         min[2] = tmp.end[2];
293                     }
294                 }
295             }
296         }
297         /*
298         System.out.println("xmax " + max[0] + " min " + min[0]);
299         System.out.println("ymax " + max[1] + " min " + min[1]);
300         System.out.println("zmax " + max[2] + " min " + min[2]);*/
301
302         width[0] = (float) Math.abs(max[0] - min[0]);
303         width[1] = (float) Math.abs(max[1] - min[1]);
304         width[2] = (float) Math.abs(max[2] - min[2]);
305
306         maxwidth = width[0];
307
308         if (width[1] > width[0]) {
309             maxwidth = width[1];
310         }
311
312         if (width[2] > width[1]) {
313             maxwidth = width[2];
314         }
315
316        // System.out.println("Maxwidth = " + maxwidth);
317     }
318
319     public float findScale() {
320         int dim;
321         int width;
322         int height;
323
324         if (getWidth() != 0) {
325             width = getWidth();
326             height = getHeight();
327         } else {
328             width = prefsize.width;
329             height = prefsize.height;
330         }
331
332         if (width < height) {
333             dim = width;
334         } else {
335             dim = height;
336         }
337
338         return (float) (dim / (1.5d * maxwidth));
339     }
340
341     public void findCentre() {
342         float xtot = 0;
343         float ytot = 0;
344         float ztot = 0;
345
346         int bsize = 0;
347
348         //Find centre coordinate
349         for (int ii = 0; ii < pdb.chains.size(); ii++) {
350             if (((PDBChain) pdb.chains.elementAt(ii)).isVisible) {
351                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
352
353                 bsize += bonds.size();
354
355                 for (int i = 0; i < bonds.size(); i++) {
356                     xtot = xtot + ((Bond) bonds.elementAt(i)).start[0] +
357                         ((Bond) bonds.elementAt(i)).end[0];
358
359                     ytot = ytot + ((Bond) bonds.elementAt(i)).start[1] +
360                         ((Bond) bonds.elementAt(i)).end[1];
361
362                     ztot = ztot + ((Bond) bonds.elementAt(i)).start[2] +
363                         ((Bond) bonds.elementAt(i)).end[2];
364                 }
365             }
366         }
367
368         centre[0] = xtot / (2 * (float) bsize);
369         centre[1] = ytot / (2 * (float) bsize);
370         centre[2] = ztot / (2 * (float) bsize);
371     }
372
373     public void paintComponent(Graphics g)
374     {
375       super.paintComponent(g);
376
377       if(!seqColoursReady)
378       {
379         g.setColor(Color.black);
380         g.setFont(new Font("Verdana", Font.BOLD, 14));
381         g.drawString("Retrieving PDB data....", 20, getHeight()/2);
382         return;
383       }
384
385
386         //Only create the image at the beginning -
387         //this saves much memory usage
388         if ((img == null)
389             || (prefsize.width != getWidth())
390             || (prefsize.height != getHeight()))
391
392       {
393             prefsize.width = getWidth();
394             prefsize.height = getHeight();
395
396             scale = findScale();
397             img = createImage(prefsize.width, prefsize.height);
398             ig = img.getGraphics();
399             Graphics2D ig2 = (Graphics2D) ig;
400
401             ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
402                                  RenderingHints.VALUE_ANTIALIAS_ON);
403
404             redrawneeded = true;
405         }
406
407
408         if (redrawneeded)
409         {
410           drawAll(ig, prefsize.width, prefsize.height);
411           redrawneeded = false;
412         }
413
414         g.drawImage(img, 0, 0, this);
415
416         pdbAction = false;
417     }
418
419     public void drawAll(Graphics g, int width, int height)
420     {
421       g.setColor(backgroundColour);
422       g.fillRect(0, 0, width, height);
423       drawScene(g);
424       drawLabels(g);
425     }
426
427
428     public void updateSeqColours()
429     {
430       if(pdbAction)
431       {
432         return;
433       }
434
435      // System.out.println("update seq colours");
436       if(bysequence && pdb!=null)
437       {
438         for (int ii = 0; ii < pdb.chains.size(); ii++)
439         {
440           colourBySequence( (PDBChain) pdb.chains.elementAt(ii));
441         }
442       }
443
444       redrawneeded=true;
445       repaint();
446     }
447
448     int findTrueIndex(int pos)
449     {
450       // returns the alignment position for a residue
451       int j = sequence.getStart();
452       int i = 0;
453
454       while ( (i < sequence.getLength()) && (j <= sequence.getEnd()) && (j <= pos+1))
455       {
456         if (!jalview.util.Comparison.isGap(sequence.getCharAt(i)))
457         {
458           j++;
459         }
460
461         i++;
462       }
463
464       if(i>1)
465          i--;
466
467       if ( (j == sequence.getEnd()) && (j < pos))
468       {
469         return sequence.getEnd() + 1;
470       }
471       else
472       {
473         return i;
474       }
475     }
476
477     // This method has been taken out of PDBChain to allow
478     // Applet and Application specific sequence renderers to be used
479     void colourBySequence(PDBChain chain)
480     {
481      // System.out.println("colour by seq");
482      boolean showFeatures = false;
483      if(seqcanvas.getViewport().getShowSequenceFeatures())
484      {
485        showFeatures = true;
486        if (fr == null)
487          fr = new jalview.gui.FeatureRenderer(seqcanvas.getViewport());
488
489        fr.transferSettings( seqcanvas.getFeatureRenderer() );
490      }
491
492       Bond tmp;
493       for (int i = 0; i < chain.bonds.size(); i++)
494       {
495         tmp = (Bond) chain.bonds.elementAt(i);
496
497         if(chain!=mainchain)
498           continue;
499
500         if ( (tmp.at1.resNumber >= ( (chain.offset + chain.pdbstart) - 1)) &&
501             (tmp.at1.resNumber <= ( (chain.offset + chain.pdbend) - 1)))
502         {
503             int index = findTrueIndex(tmp.at1.alignmentMapping);
504                 //sequence.findIndex(tmp.at1.alignmentMapping);
505             if (index != -1)
506             {
507               tmp.startCol = seqcanvas.getSequenceRenderer().
508                   getResidueBoxColour( sequence, index);
509
510               if(showFeatures)
511                 tmp.startCol = fr.findFeatureColour(tmp.startCol, sequence, index);
512
513               if(tmp.startCol==null)
514                 tmp.startCol = Color.white;
515             }
516         }
517
518         if ( (tmp.at2.resNumber >= ( (chain.offset + chain.pdbstart) - 1)) &&
519             (tmp.at2.resNumber <= ( (chain.pdbend + chain.offset) - 1)))
520         {
521
522             int index =  findTrueIndex(tmp.at2.alignmentMapping);
523                 //sequence.findIndex( tmp.at2.alignmentMapping );
524             if (index != -1)
525             {
526               tmp.endCol = seqcanvas.getSequenceRenderer().
527                   getResidueBoxColour( sequence, index);
528
529               if(showFeatures)
530                 tmp.endCol = fr.findFeatureColour(tmp.endCol, sequence, index);
531
532               if(tmp.endCol==null)
533                 tmp.endCol = Color.white;
534             }
535         }
536       }
537     }
538
539
540     Zsort zsort;
541     public void drawScene(Graphics g)
542     {
543       if (zbuffer)
544       {
545         if (zsort == null)
546           zsort = new Zsort();
547
548         zsort.Zsort(visiblebonds);
549       }
550
551       Bond tmpBond = null;
552       for (int i = 0; i < visiblebonds.size(); i++)
553       {
554         tmpBond = (Bond) visiblebonds.elementAt(i);
555
556         xstart = (int) ( ( (tmpBond.start[0] - centre[0]) * scale) +
557                         (getWidth() / 2));
558         ystart = (int) ( ( (tmpBond.start[1] - centre[1]) * scale) +
559                         (getHeight() / 2));
560
561         xend = (int) ( ( (tmpBond.end[0] - centre[0]) * scale) +
562                       (getWidth() / 2));
563         yend = (int) ( ( (tmpBond.end[1] - centre[1]) * scale) +
564                       (getHeight() / 2));
565
566         xmid = (xend + xstart) / 2;
567         ymid = (yend + ystart) / 2;
568         if (depthcue && !bymolecule)
569         {
570           if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))
571           {
572
573             g.setColor(tmpBond.startCol.darker().darker());
574             drawLine(g, xstart, ystart, xmid, ymid);
575             g.setColor(tmpBond.endCol.darker().darker());
576             drawLine(g, xmid, ymid, xend, yend);
577
578           }
579           else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))
580           {
581             g.setColor(tmpBond.startCol.darker());
582             drawLine(g, xstart, ystart, xmid, ymid);
583
584             g.setColor(tmpBond.endCol.darker());
585             drawLine(g, xmid, ymid, xend, yend);
586           }
587           else
588           {
589             g.setColor(tmpBond.startCol);
590             drawLine(g, xstart, ystart, xmid, ymid);
591
592             g.setColor(tmpBond.endCol);
593             drawLine(g, xmid, ymid, xend, yend);
594           }
595         }
596         else if (depthcue && bymolecule)
597         {
598           if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))
599           {
600             g.setColor(Color.green.darker().darker());
601             drawLine(g, xstart, ystart, xend, yend);
602           }
603           else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))
604           {
605             g.setColor(Color.green.darker());
606             drawLine(g, xstart, ystart, xend, yend);
607           }
608           else
609           {
610             g.setColor(Color.green);
611             drawLine(g, xstart, ystart, xend, yend);
612           }
613         }
614         else if (!depthcue && !bymolecule)
615         {
616           g.setColor(tmpBond.startCol);
617           drawLine(g, xstart, ystart, xmid, ymid);
618           g.setColor(tmpBond.endCol);
619           drawLine(g, xmid, ymid, xend, yend);
620         }
621         else
622         {
623           drawLine(g, xstart, ystart, xend, yend);
624         }
625
626         if (highlightBond1 != null && highlightBond1 == tmpBond)
627         {
628           g.setColor(tmpBond.endCol.brighter().brighter().brighter().brighter());
629           drawLine(g, xmid, ymid, xend, yend);
630         }
631
632         if (highlightBond2 != null && highlightBond2 == tmpBond)
633         {
634           g.setColor(tmpBond.startCol.brighter().brighter().brighter().brighter());
635           drawLine(g, xstart, ystart, xmid, ymid);
636         }
637
638       }
639
640
641     }
642
643     public void drawLine(Graphics g, int x1, int y1, int x2, int y2) {
644         if (!wire) {
645             if (((float) Math.abs(y2 - y1) / (float) Math.abs(x2 - x1)) < 0.5) {
646                 g.drawLine(x1, y1, x2, y2);
647                 g.drawLine(x1 + 1, y1 + 1, x2 + 1, y2 + 1);
648                 g.drawLine(x1, y1 - 1, x2, y2 - 1);
649             } else {
650                 g.setColor(g.getColor().brighter());
651                 g.drawLine(x1, y1, x2, y2);
652                 g.drawLine(x1 + 1, y1, x2 + 1, y2);
653                 g.drawLine(x1 - 1, y1, x2 - 1, y2);
654             }
655         } else {
656             g.drawLine(x1, y1, x2, y2);
657         }
658     }
659
660     public Dimension minimumsize() {
661         return prefsize;
662     }
663
664     public Dimension preferredsize() {
665         return prefsize;
666     }
667
668     public void keyPressed(KeyEvent evt)
669     {
670       if (evt.getKeyCode() == KeyEvent.VK_UP)
671       {
672         scale = (float) (scale * 1.1);
673         redrawneeded = true;
674         repaint();
675       }
676       else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
677       {
678         scale = (float) (scale * 0.9);
679         redrawneeded = true;
680         repaint();
681       }
682     }
683
684     public void mousePressed(MouseEvent e)
685     {
686         pdbAction = true;
687         Atom fatom = findAtom(e.getX(), e.getY());
688         if(fatom!=null)
689         {
690           fatom.isSelected = !fatom.isSelected;
691
692           redrawneeded = true;
693           repaint();
694           if (foundchain != -1)
695           {
696             PDBChain chain = (PDBChain) pdb.chains.elementAt(foundchain);
697             if (chain == mainchain)
698             {
699               if (fatom.alignmentMapping != -1)
700               {
701                 if (highlightRes == null)
702                   highlightRes = new Vector();
703
704                 if (highlightRes.contains(fatom.alignmentMapping+""))
705                   highlightRes.remove(fatom.alignmentMapping + "");
706                 else
707                   highlightRes.add(fatom.alignmentMapping + "");
708               }
709             }
710           }
711
712         }
713         mx = e.getX();
714         my = e.getY();
715         omx = mx;
716         omy = my;
717         dragging = false;
718     }
719
720     public void mouseMoved(MouseEvent e)
721     {
722       pdbAction = true;
723       if(highlightBond1!=null)
724       {
725         highlightBond1.at2.isSelected = false;
726         highlightBond2.at1.isSelected = false;
727         highlightBond1 = null;
728         highlightBond2 = null;
729       }
730
731         Atom fatom = findAtom(e.getX(), e.getY());
732
733         PDBChain chain = null;
734         if(foundchain!=-1)
735         {
736           chain = (PDBChain) pdb.chains.elementAt(foundchain);
737           if(chain == mainchain)
738           {
739             highlightSeqcanvas( fatom.alignmentMapping );
740           }
741         }
742
743         if (fatom != null)
744         {
745             this.setToolTipText(chain.id+":"+ fatom.resNumber+" "+ fatom.resName);
746         } else
747         {
748             highlightSeqcanvas( -1);
749             this.setToolTipText(null);
750         }
751     }
752
753
754     void highlightSeqcanvas(int pos)
755     {
756       SearchResults searchResults = new SearchResults();
757       if(highlightRes!=null)
758       {
759         for (int i = 0; i < highlightRes.size(); i++)
760         {
761           int a = Integer.parseInt(highlightRes.elementAt(
762               i).toString())+1;
763
764           searchResults.addResult(sequence, a, a);
765         }
766       }
767
768       if(pos!=-1)
769       {
770         searchResults.addResult(sequence, pos+1, pos+1);
771       }
772
773       seqcanvas.highlightSearchResults(searchResults);
774     }
775
776
777     public void mouseClicked(MouseEvent e)  { }
778
779     public void mouseEntered(MouseEvent e) {  }
780
781     public void mouseExited(MouseEvent e) { }
782
783     public void mouseDragged(MouseEvent evt)
784     {
785         int x = evt.getX();
786         int y = evt.getY();
787         mx = x;
788         my = y;
789
790
791         MCMatrix objmat = new MCMatrix(3, 3);
792         objmat.setIdentity();
793
794         if ((evt.getModifiers() & Event.META_MASK) != 0) {
795             objmat.rotatez((float) ((mx - omx)));
796         } else {
797             objmat.rotatex((float) ((my - omy)));
798             objmat.rotatey((float) ((omx - mx)));
799         }
800
801         //Alter the bonds
802         for (int ii = 0; ii < pdb.chains.size(); ii++) {
803             Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
804
805             for (int i = 0; i < bonds.size(); i++) {
806                 Bond tmpBond = (Bond) bonds.elementAt(i);
807
808                 //Translate the bond so the centre is 0,0,0
809                 tmpBond.translate(-centre[0], -centre[1], -centre[2]);
810
811                 //Now apply the rotation matrix
812                 tmpBond.start = objmat.vectorMultiply(tmpBond.start);
813                 tmpBond.end = objmat.vectorMultiply(tmpBond.end);
814
815                 //Now translate back again
816                 tmpBond.translate(centre[0], centre[1], centre[2]);
817             }
818         }
819
820         objmat = null;
821
822         omx = mx;
823         omy = my;
824
825         dragging = true;
826
827         redrawneeded = true;
828
829         repaint();
830     }
831
832     public void mouseReleased(MouseEvent evt)
833     {
834         dragging = false;
835         return;
836     }
837
838     void drawLabels(Graphics g) {
839
840         for (int ii = 0; ii < pdb.chains.size(); ii++)
841         {
842             PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
843
844             if (chain.isVisible)
845             {
846               Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
847
848               for (int i = 0; i < bonds.size(); i++)
849               {
850                   Bond tmpBond = (Bond) bonds.elementAt(i);
851
852                   if (tmpBond.at1.isSelected)
853                   {
854                       labelAtom(g, tmpBond, 1);
855                   }
856
857                   if (tmpBond.at2.isSelected)
858                   {
859
860                       labelAtom(g, tmpBond, 2);
861                   }
862                 }
863             }
864         }
865     }
866
867     public void labelAtom(Graphics g, Bond b, int n) {
868         g.setFont(font);
869         g.setColor(Color.red);
870         if (n == 1)
871         {
872             int xstart = (int) (((b.start[0] - centre[0]) * scale) +
873                 (getWidth() / 2));
874             int ystart = (int) (((b.start[1] - centre[1]) * scale) +
875                 (getHeight() / 2));
876
877             g.drawString(b.at1.resName + "-" + b.at1.resNumber, xstart, ystart);
878         }
879
880         if (n == 2) {
881             int xstart = (int) (((b.end[0] - centre[0]) * scale) +
882                 (getWidth() / 2));
883             int ystart = (int) (((b.end[1] - centre[1]) * scale) +
884                 (getHeight() / 2));
885
886             g.drawString(b.at2.resName + "-" + b.at2.resNumber, xstart, ystart);
887         }
888     }
889
890     int foundchain = -1;
891     public Atom findAtom(int x, int y) {
892         Atom fatom = null;
893
894         foundchain = -1;
895
896         for (int ii = 0; ii < pdb.chains.size(); ii++)
897         {
898             PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
899             int truex;
900             Bond tmpBond=null;
901
902             if (chain.isVisible)
903             {
904                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
905
906                 for (int i = 0; i < bonds.size(); i++)
907                 {
908                     tmpBond = (Bond) bonds.elementAt(i);
909
910                     truex = (int) (((tmpBond.start[0] - centre[0]) * scale) +
911                         (getWidth() / 2));
912
913                     if (Math.abs(truex - x) <= 2)
914                     {
915                         int truey = (int) (((tmpBond.start[1] - centre[1]) * scale) +
916                             (getHeight() / 2));
917
918                         if (Math.abs(truey - y) <= 2)
919                         {
920                             fatom = tmpBond.at1;
921                             foundchain = ii;
922                             break;
923                         }
924                     }
925                 }
926
927                 // Still here? Maybe its the last bond
928
929                 truex = (int) ( ( (tmpBond.end[0] - centre[0]) * scale) +
930                                (getWidth() / 2));
931
932                 if (Math.abs(truex - x) <= 2)
933                 {
934                   int truey = (int) ( ( (tmpBond.end[1] - centre[1]) * scale) +
935                                      (getHeight() / 2));
936
937                   if (Math.abs(truey - y) <= 2)
938                   {
939                     fatom = tmpBond.at2;
940                     foundchain = ii;
941                     break;
942                   }
943                 }
944
945             }
946
947             if (fatom != null) //)&& chain.ds != null)
948              {
949                 chain = (PDBChain) pdb.chains.elementAt(foundchain);
950             }
951         }
952
953         return fatom;
954     }
955
956    Bond highlightBond1, highlightBond2;
957    public void highlightRes(int ii)
958   {
959     if( !seqColoursReady )
960       return;
961
962     if (highlightRes != null
963         && highlightRes.contains((ii-1) + ""))
964     {
965       return;
966     }
967
968     int index = -1;
969     Bond tmpBond;
970     for(index=0; index<mainchain.bonds.size(); index++)
971     {
972       tmpBond = (Bond) mainchain.bonds.elementAt(index);
973       if (tmpBond.at1.alignmentMapping == ii - 1)
974       {
975         if (highlightBond1 != null)
976           highlightBond1.at2.isSelected = false;
977
978         if (highlightBond2 != null)
979           highlightBond2.at1.isSelected = false;
980
981         highlightBond1 = null;
982         highlightBond2 = null;
983
984         if (index > 0)
985         {
986           highlightBond1 = (Bond) mainchain.bonds.elementAt(index - 1);
987           highlightBond1.at2.isSelected = true;
988         }
989
990         if (index != mainchain.bonds.size())
991         {
992           highlightBond2 = (Bond) mainchain.bonds.elementAt(index);
993           highlightBond2.at1.isSelected = true;
994         }
995
996         break;
997       }
998     }
999
1000     redrawneeded = true;
1001     repaint();
1002   }
1003
1004     public void setAllchainsVisible(boolean b)
1005     {
1006       for (int ii = 0; ii < pdb.chains.size(); ii++)
1007       {
1008         PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
1009         chain.isVisible = b;
1010       }
1011       mainchain.isVisible = true;
1012       findCentre();
1013       setupBonds();
1014     }
1015 }