sequence.getStart() in findTrueIndex
[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, AlignSeq.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         mainchain.transferRESNUMFeatures(sequence, null);
148         seqcanvas.getFeatureRenderer().featuresAdded();
149         this.pdb = pdb;
150         this.prefsize = new Dimension(getWidth(), getHeight());
151
152         //Initialize the matrices to identity
153         for (int i = 0; i < 3; i++) {
154             for (int j = 0; j < 3; j++) {
155                 if (i != j) {
156                     idmat.addElement(i, j, 0);
157                     objmat.addElement(i, j, 0);
158                 } else {
159                     idmat.addElement(i, j, 1);
160                     objmat.addElement(i, j, 1);
161                 }
162             }
163         }
164
165         addMouseMotionListener(this);
166         addMouseListener(this);
167
168         addMouseWheelListener(new MouseWheelListener()
169         {
170           public void mouseWheelMoved(MouseWheelEvent e)
171           {
172             if (e.getWheelRotation() > 0)
173             {
174               scale = (float) (scale * 1.1);
175               redrawneeded = true;
176               repaint();
177             }
178
179             else
180             {
181               scale = (float) (scale * 0.9);
182               redrawneeded = true;
183               repaint();
184             }
185           }
186        });
187
188
189         findCentre();
190         findWidth();
191
192         setupBonds();
193
194         scale = findScale();
195
196         ToolTipManager.sharedInstance().registerComponent(this);
197         ToolTipManager.sharedInstance().setInitialDelay(0);
198         ToolTipManager.sharedInstance().setDismissDelay(10000);
199     }
200
201
202     Vector visiblebonds;
203     void setupBonds()
204     {
205       seqColoursReady = false;
206       // Sort the bonds by z coord
207       visiblebonds = new Vector();
208
209       for (int ii = 0; ii < pdb.chains.size(); ii++)
210       {
211         if ( ( (PDBChain) pdb.chains.elementAt(ii)).isVisible)
212         {
213           Vector tmp = ( (PDBChain) pdb.chains.elementAt(ii)).bonds;
214
215           for (int i = 0; i < tmp.size(); i++)
216           {
217             visiblebonds.addElement(tmp.elementAt(i));
218           }
219         }
220       }
221
222       updateSeqColours();
223       seqColoursReady = true;
224       redrawneeded = true;
225       repaint();
226     }
227
228
229     public void findWidth() {
230         float[] max = new float[3];
231         float[] min = new float[3];
232
233         max[0] = (float) -1e30;
234         max[1] = (float) -1e30;
235         max[2] = (float) -1e30;
236
237         min[0] = (float) 1e30;
238         min[1] = (float) 1e30;
239         min[2] = (float) 1e30;
240
241         for (int ii = 0; ii < pdb.chains.size(); ii++) {
242             if (((PDBChain) pdb.chains.elementAt(ii)).isVisible) {
243                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
244
245                 for (int i = 0; i < bonds.size(); i++) {
246                     Bond tmp = (Bond) bonds.elementAt(i);
247
248                     if (tmp.start[0] >= max[0]) {
249                         max[0] = tmp.start[0];
250                     }
251
252                     if (tmp.start[1] >= max[1]) {
253                         max[1] = tmp.start[1];
254                     }
255
256                     if (tmp.start[2] >= max[2]) {
257                         max[2] = tmp.start[2];
258                     }
259
260                     if (tmp.start[0] <= min[0]) {
261                         min[0] = tmp.start[0];
262                     }
263
264                     if (tmp.start[1] <= min[1]) {
265                         min[1] = tmp.start[1];
266                     }
267
268                     if (tmp.start[2] <= min[2]) {
269                         min[2] = tmp.start[2];
270                     }
271
272                     if (tmp.end[0] >= max[0]) {
273                         max[0] = tmp.end[0];
274                     }
275
276                     if (tmp.end[1] >= max[1]) {
277                         max[1] = tmp.end[1];
278                     }
279
280                     if (tmp.end[2] >= max[2]) {
281                         max[2] = tmp.end[2];
282                     }
283
284                     if (tmp.end[0] <= min[0]) {
285                         min[0] = tmp.end[0];
286                     }
287
288                     if (tmp.end[1] <= min[1]) {
289                         min[1] = tmp.end[1];
290                     }
291
292                     if (tmp.end[2] <= min[2]) {
293                         min[2] = tmp.end[2];
294                     }
295                 }
296             }
297         }
298         /*
299         System.out.println("xmax " + max[0] + " min " + min[0]);
300         System.out.println("ymax " + max[1] + " min " + min[1]);
301         System.out.println("zmax " + max[2] + " min " + min[2]);*/
302
303         width[0] = (float) Math.abs(max[0] - min[0]);
304         width[1] = (float) Math.abs(max[1] - min[1]);
305         width[2] = (float) Math.abs(max[2] - min[2]);
306
307         maxwidth = width[0];
308
309         if (width[1] > width[0]) {
310             maxwidth = width[1];
311         }
312
313         if (width[2] > width[1]) {
314             maxwidth = width[2];
315         }
316
317        // System.out.println("Maxwidth = " + maxwidth);
318     }
319
320     public float findScale() {
321         int dim;
322         int width;
323         int height;
324
325         if (getWidth() != 0) {
326             width = getWidth();
327             height = getHeight();
328         } else {
329             width = prefsize.width;
330             height = prefsize.height;
331         }
332
333         if (width < height) {
334             dim = width;
335         } else {
336             dim = height;
337         }
338
339         return (float) (dim / (1.5d * maxwidth));
340     }
341
342     public void findCentre() {
343         float xtot = 0;
344         float ytot = 0;
345         float ztot = 0;
346
347         int bsize = 0;
348
349         //Find centre coordinate
350         for (int ii = 0; ii < pdb.chains.size(); ii++) {
351             if (((PDBChain) pdb.chains.elementAt(ii)).isVisible) {
352                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
353
354                 bsize += bonds.size();
355
356                 for (int i = 0; i < bonds.size(); i++) {
357                     xtot = xtot + ((Bond) bonds.elementAt(i)).start[0] +
358                         ((Bond) bonds.elementAt(i)).end[0];
359
360                     ytot = ytot + ((Bond) bonds.elementAt(i)).start[1] +
361                         ((Bond) bonds.elementAt(i)).end[1];
362
363                     ztot = ztot + ((Bond) bonds.elementAt(i)).start[2] +
364                         ((Bond) bonds.elementAt(i)).end[2];
365                 }
366             }
367         }
368
369         centre[0] = xtot / (2 * (float) bsize);
370         centre[1] = ytot / (2 * (float) bsize);
371         centre[2] = ztot / (2 * (float) bsize);
372     }
373
374     public void paintComponent(Graphics g)
375     {
376       super.paintComponent(g);
377
378       if(!seqColoursReady)
379       {
380         g.setColor(Color.black);
381         g.setFont(new Font("Verdana", Font.BOLD, 14));
382         g.drawString("Retrieving PDB data....", 20, getHeight()/2);
383         return;
384       }
385
386
387         //Only create the image at the beginning -
388         //this saves much memory usage
389         if ((img == null)
390             || (prefsize.width != getWidth())
391             || (prefsize.height != getHeight()))
392
393       {
394             prefsize.width = getWidth();
395             prefsize.height = getHeight();
396
397             scale = findScale();
398             img = createImage(prefsize.width, prefsize.height);
399             ig = img.getGraphics();
400             Graphics2D ig2 = (Graphics2D) ig;
401
402             ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
403                                  RenderingHints.VALUE_ANTIALIAS_ON);
404
405             redrawneeded = true;
406         }
407
408
409         if (redrawneeded)
410         {
411           drawAll(ig, prefsize.width, prefsize.height);
412           redrawneeded = false;
413         }
414
415         g.drawImage(img, 0, 0, this);
416
417         pdbAction = false;
418     }
419
420     public void drawAll(Graphics g, int width, int height)
421     {
422       g.setColor(backgroundColour);
423       g.fillRect(0, 0, width, height);
424       drawScene(g);
425       drawLabels(g);
426     }
427
428
429     public void updateSeqColours()
430     {
431       if(pdbAction)
432       {
433         return;
434       }
435
436      // System.out.println("update seq colours");
437       if(bysequence && pdb!=null)
438       {
439         for (int ii = 0; ii < pdb.chains.size(); ii++)
440         {
441           colourBySequence( (PDBChain) pdb.chains.elementAt(ii));
442         }
443       }
444
445       redrawneeded=true;
446       repaint();
447     }
448
449     int findTrueIndex(int pos)
450     {
451       // returns the alignment position for a residue
452       int j = sequence.getStart(); // first position in PDB atom coordinate sequence
453       int i = 0;
454
455       while ( (i < sequence.getLength()) && (j <= pos+1))
456       {
457         if (!jalview.util.Comparison.isGap(sequence.getCharAt(i)))
458         {
459           j++;
460         }
461
462         i++;
463       }
464
465       if(i>1)
466          i--;
467
468       if (j < pos)
469       {
470         return sequence.getEnd() + 1;
471       }
472       else
473       {
474         return i;
475       }
476     }
477
478     // This method has been taken out of PDBChain to allow
479     // Applet and Application specific sequence renderers to be used
480     void colourBySequence(PDBChain chain)
481     {
482      // System.out.println("colour by seq");
483      boolean showFeatures = false;
484      if(seqcanvas.getViewport().getShowSequenceFeatures())
485      {
486        showFeatures = true;
487        if (fr == null)
488          fr = new jalview.gui.FeatureRenderer(seqcanvas.getViewport());
489
490        fr.transferSettings( seqcanvas.getFeatureRenderer() );
491      }
492
493       Bond tmp;
494       for (int i = 0; i < chain.bonds.size(); i++)
495       {
496         tmp = (Bond) chain.bonds.elementAt(i);
497
498         if(chain!=mainchain)
499           continue;
500
501         //if ( (tmp.at1.resNumber >= ( (chain.offset + chain.pdbstart) - 1)) &&
502         //    (tmp.at1.resNumber <= ( (chain.offset + chain.pdbend) - 1)))
503         {
504             int index = findTrueIndex(tmp.at1.alignmentMapping);
505                 //sequence.findIndex(tmp.at1.alignmentMapping);
506             if (index != -1)
507             {
508               tmp.startCol = seqcanvas.getSequenceRenderer().
509                   getResidueBoxColour( sequence, index);
510
511               if(showFeatures)
512                 tmp.startCol = fr.findFeatureColour(tmp.startCol, sequence, index);
513
514               if(tmp.startCol==null)
515                 tmp.startCol = Color.white;
516             }
517         }
518
519         //if ( (tmp.at2.resNumber >= ( (chain.offset + chain.pdbstart) - 1)) &&
520         //    (tmp.at2.resNumber <= ( (chain.pdbend + chain.offset) - 1)))
521         {
522
523             int index =  findTrueIndex(tmp.at2.alignmentMapping);
524                 //sequence.findIndex( tmp.at2.alignmentMapping );
525             if (index != -1)
526             {
527               tmp.endCol = seqcanvas.getSequenceRenderer().
528                   getResidueBoxColour( sequence, index);
529
530               if(showFeatures)
531                 tmp.endCol = fr.findFeatureColour(tmp.endCol, sequence, index);
532
533               if(tmp.endCol==null)
534                 tmp.endCol = Color.white;
535             }
536         }
537       }
538     }
539
540
541     Zsort zsort;
542     public void drawScene(Graphics g)
543     {
544       if (zbuffer)
545       {
546         if (zsort == null)
547           zsort = new Zsort();
548
549         zsort.Zsort(visiblebonds);
550       }
551
552       Bond tmpBond = null;
553       for (int i = 0; i < visiblebonds.size(); i++)
554       {
555         tmpBond = (Bond) visiblebonds.elementAt(i);
556
557         xstart = (int) ( ( (tmpBond.start[0] - centre[0]) * scale) +
558                         (getWidth() / 2));
559         ystart = (int) ( ( (tmpBond.start[1] - centre[1]) * scale) +
560                         (getHeight() / 2));
561
562         xend = (int) ( ( (tmpBond.end[0] - centre[0]) * scale) +
563                       (getWidth() / 2));
564         yend = (int) ( ( (tmpBond.end[1] - centre[1]) * scale) +
565                       (getHeight() / 2));
566
567         xmid = (xend + xstart) / 2;
568         ymid = (yend + ystart) / 2;
569         if (depthcue && !bymolecule)
570         {
571           if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))
572           {
573
574             g.setColor(tmpBond.startCol.darker().darker());
575             drawLine(g, xstart, ystart, xmid, ymid);
576             g.setColor(tmpBond.endCol.darker().darker());
577             drawLine(g, xmid, ymid, xend, yend);
578
579           }
580           else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))
581           {
582             g.setColor(tmpBond.startCol.darker());
583             drawLine(g, xstart, ystart, xmid, ymid);
584
585             g.setColor(tmpBond.endCol.darker());
586             drawLine(g, xmid, ymid, xend, yend);
587           }
588           else
589           {
590             g.setColor(tmpBond.startCol);
591             drawLine(g, xstart, ystart, xmid, ymid);
592
593             g.setColor(tmpBond.endCol);
594             drawLine(g, xmid, ymid, xend, yend);
595           }
596         }
597         else if (depthcue && bymolecule)
598         {
599           if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))
600           {
601             g.setColor(Color.green.darker().darker());
602             drawLine(g, xstart, ystart, xend, yend);
603           }
604           else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))
605           {
606             g.setColor(Color.green.darker());
607             drawLine(g, xstart, ystart, xend, yend);
608           }
609           else
610           {
611             g.setColor(Color.green);
612             drawLine(g, xstart, ystart, xend, yend);
613           }
614         }
615         else if (!depthcue && !bymolecule)
616         {
617           g.setColor(tmpBond.startCol);
618           drawLine(g, xstart, ystart, xmid, ymid);
619           g.setColor(tmpBond.endCol);
620           drawLine(g, xmid, ymid, xend, yend);
621         }
622         else
623         {
624           drawLine(g, xstart, ystart, xend, yend);
625         }
626
627         if (highlightBond1 != null && highlightBond1 == tmpBond)
628         {
629           g.setColor(tmpBond.endCol.brighter().brighter().brighter().brighter());
630           drawLine(g, xmid, ymid, xend, yend);
631         }
632
633         if (highlightBond2 != null && highlightBond2 == tmpBond)
634         {
635           g.setColor(tmpBond.startCol.brighter().brighter().brighter().brighter());
636           drawLine(g, xstart, ystart, xmid, ymid);
637         }
638
639       }
640
641
642     }
643
644     public void drawLine(Graphics g, int x1, int y1, int x2, int y2) {
645         if (!wire) {
646             if (((float) Math.abs(y2 - y1) / (float) Math.abs(x2 - x1)) < 0.5) {
647                 g.drawLine(x1, y1, x2, y2);
648                 g.drawLine(x1 + 1, y1 + 1, x2 + 1, y2 + 1);
649                 g.drawLine(x1, y1 - 1, x2, y2 - 1);
650             } else {
651                 g.setColor(g.getColor().brighter());
652                 g.drawLine(x1, y1, x2, y2);
653                 g.drawLine(x1 + 1, y1, x2 + 1, y2);
654                 g.drawLine(x1 - 1, y1, x2 - 1, y2);
655             }
656         } else {
657             g.drawLine(x1, y1, x2, y2);
658         }
659     }
660
661     public Dimension minimumsize() {
662         return prefsize;
663     }
664
665     public Dimension preferredsize() {
666         return prefsize;
667     }
668
669     public void keyPressed(KeyEvent evt)
670     {
671       if (evt.getKeyCode() == KeyEvent.VK_UP)
672       {
673         scale = (float) (scale * 1.1);
674         redrawneeded = true;
675         repaint();
676       }
677       else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
678       {
679         scale = (float) (scale * 0.9);
680         redrawneeded = true;
681         repaint();
682       }
683     }
684
685     public void mousePressed(MouseEvent e)
686     {
687         pdbAction = true;
688         Atom fatom = findAtom(e.getX(), e.getY());
689         if(fatom!=null)
690         {
691           fatom.isSelected = !fatom.isSelected;
692
693           redrawneeded = true;
694           repaint();
695           if (foundchain != -1)
696           {
697             PDBChain chain = (PDBChain) pdb.chains.elementAt(foundchain);
698             if (chain == mainchain)
699             {
700               if (fatom.alignmentMapping != -1)
701               {
702                 if (highlightRes == null)
703                   highlightRes = new Vector();
704
705                 if (highlightRes.contains(fatom.alignmentMapping+""))
706                   highlightRes.remove(fatom.alignmentMapping + "");
707                 else
708                   highlightRes.add(fatom.alignmentMapping + "");
709               }
710             }
711           }
712
713         }
714         mx = e.getX();
715         my = e.getY();
716         omx = mx;
717         omy = my;
718         dragging = false;
719     }
720
721     public void mouseMoved(MouseEvent e)
722     {
723       pdbAction = true;
724       if(highlightBond1!=null)
725       {
726         highlightBond1.at2.isSelected = false;
727         highlightBond2.at1.isSelected = false;
728         highlightBond1 = null;
729         highlightBond2 = null;
730       }
731
732         Atom fatom = findAtom(e.getX(), e.getY());
733
734         PDBChain chain = null;
735         if(foundchain!=-1)
736         {
737           chain = (PDBChain) pdb.chains.elementAt(foundchain);
738           if(chain == mainchain)
739           {
740             highlightSeqcanvas( fatom.alignmentMapping );
741           }
742         }
743
744         if (fatom != null)
745         {
746             this.setToolTipText(chain.id+":"+ fatom.resNumber+" "+ fatom.resName);
747         } else
748         {
749             highlightSeqcanvas( -1);
750             this.setToolTipText(null);
751         }
752     }
753
754
755     void highlightSeqcanvas(int pos)
756     {
757       SearchResults searchResults = new SearchResults();
758       if(highlightRes!=null)
759       {
760         for (int i = 0; i < highlightRes.size(); i++)
761         {
762           int a = Integer.parseInt(highlightRes.elementAt(
763               i).toString())+1;
764
765           searchResults.addResult(sequence, a, a);
766         }
767       }
768
769       if(pos!=-1)
770       {
771         searchResults.addResult(sequence, pos+1, pos+1);
772       }
773
774       seqcanvas.highlightSearchResults(searchResults);
775     }
776
777
778     public void mouseClicked(MouseEvent e)  { }
779
780     public void mouseEntered(MouseEvent e) {  }
781
782     public void mouseExited(MouseEvent e) { }
783
784     public void mouseDragged(MouseEvent evt)
785     {
786         int x = evt.getX();
787         int y = evt.getY();
788         mx = x;
789         my = y;
790
791
792         MCMatrix objmat = new MCMatrix(3, 3);
793         objmat.setIdentity();
794
795         if ((evt.getModifiers() & Event.META_MASK) != 0) {
796             objmat.rotatez((float) ((mx - omx)));
797         } else {
798             objmat.rotatex((float) ((my - omy)));
799             objmat.rotatey((float) ((omx - mx)));
800         }
801
802         //Alter the bonds
803         for (int ii = 0; ii < pdb.chains.size(); ii++) {
804             Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
805
806             for (int i = 0; i < bonds.size(); i++) {
807                 Bond tmpBond = (Bond) bonds.elementAt(i);
808
809                 //Translate the bond so the centre is 0,0,0
810                 tmpBond.translate(-centre[0], -centre[1], -centre[2]);
811
812                 //Now apply the rotation matrix
813                 tmpBond.start = objmat.vectorMultiply(tmpBond.start);
814                 tmpBond.end = objmat.vectorMultiply(tmpBond.end);
815
816                 //Now translate back again
817                 tmpBond.translate(centre[0], centre[1], centre[2]);
818             }
819         }
820
821         objmat = null;
822
823         omx = mx;
824         omy = my;
825
826         dragging = true;
827
828         redrawneeded = true;
829
830         repaint();
831     }
832
833     public void mouseReleased(MouseEvent evt)
834     {
835         dragging = false;
836         return;
837     }
838
839     void drawLabels(Graphics g) {
840
841         for (int ii = 0; ii < pdb.chains.size(); ii++)
842         {
843             PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
844
845             if (chain.isVisible)
846             {
847               Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
848
849               for (int i = 0; i < bonds.size(); i++)
850               {
851                   Bond tmpBond = (Bond) bonds.elementAt(i);
852
853                   if (tmpBond.at1.isSelected)
854                   {
855                       labelAtom(g, tmpBond, 1);
856                   }
857
858                   if (tmpBond.at2.isSelected)
859                   {
860
861                       labelAtom(g, tmpBond, 2);
862                   }
863                 }
864             }
865         }
866     }
867
868     public void labelAtom(Graphics g, Bond b, int n) {
869         g.setFont(font);
870         g.setColor(Color.red);
871         if (n == 1)
872         {
873             int xstart = (int) (((b.start[0] - centre[0]) * scale) +
874                 (getWidth() / 2));
875             int ystart = (int) (((b.start[1] - centre[1]) * scale) +
876                 (getHeight() / 2));
877
878             g.drawString(b.at1.resName + "-" + b.at1.resNumber, xstart, ystart);
879         }
880
881         if (n == 2) {
882             int xstart = (int) (((b.end[0] - centre[0]) * scale) +
883                 (getWidth() / 2));
884             int ystart = (int) (((b.end[1] - centre[1]) * scale) +
885                 (getHeight() / 2));
886
887             g.drawString(b.at2.resName + "-" + b.at2.resNumber, xstart, ystart);
888         }
889     }
890
891     int foundchain = -1;
892     public Atom findAtom(int x, int y) {
893         Atom fatom = null;
894
895         foundchain = -1;
896
897         for (int ii = 0; ii < pdb.chains.size(); ii++)
898         {
899             PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
900             int truex;
901             Bond tmpBond=null;
902
903             if (chain.isVisible)
904             {
905                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
906
907                 for (int i = 0; i < bonds.size(); i++)
908                 {
909                     tmpBond = (Bond) bonds.elementAt(i);
910
911                     truex = (int) (((tmpBond.start[0] - centre[0]) * scale) +
912                         (getWidth() / 2));
913
914                     if (Math.abs(truex - x) <= 2)
915                     {
916                         int truey = (int) (((tmpBond.start[1] - centre[1]) * scale) +
917                             (getHeight() / 2));
918
919                         if (Math.abs(truey - y) <= 2)
920                         {
921                             fatom = tmpBond.at1;
922                             foundchain = ii;
923                             break;
924                         }
925                     }
926                 }
927
928                 // Still here? Maybe its the last bond
929
930                 truex = (int) ( ( (tmpBond.end[0] - centre[0]) * scale) +
931                                (getWidth() / 2));
932
933                 if (Math.abs(truex - x) <= 2)
934                 {
935                   int truey = (int) ( ( (tmpBond.end[1] - centre[1]) * scale) +
936                                      (getHeight() / 2));
937
938                   if (Math.abs(truey - y) <= 2)
939                   {
940                     fatom = tmpBond.at2;
941                     foundchain = ii;
942                     break;
943                   }
944                 }
945
946             }
947
948             if (fatom != null) //)&& chain.ds != null)
949              {
950                 chain = (PDBChain) pdb.chains.elementAt(foundchain);
951             }
952         }
953
954         return fatom;
955     }
956
957    Bond highlightBond1, highlightBond2;
958    public void highlightRes(int ii)
959   {
960     if( !seqColoursReady )
961       return;
962
963     if (highlightRes != null
964         && highlightRes.contains((ii-1) + ""))
965     {
966       return;
967     }
968
969     int index = -1;
970     Bond tmpBond;
971     for(index=0; index<mainchain.bonds.size(); index++)
972     {
973       tmpBond = (Bond) mainchain.bonds.elementAt(index);
974       if (tmpBond.at1.alignmentMapping == ii - 1)
975       {
976         if (highlightBond1 != null)
977           highlightBond1.at2.isSelected = false;
978
979         if (highlightBond2 != null)
980           highlightBond2.at1.isSelected = false;
981
982         highlightBond1 = null;
983         highlightBond2 = null;
984
985         if (index > 0)
986         {
987           highlightBond1 = (Bond) mainchain.bonds.elementAt(index - 1);
988           highlightBond1.at2.isSelected = true;
989         }
990
991         if (index != mainchain.bonds.size())
992         {
993           highlightBond2 = (Bond) mainchain.bonds.elementAt(index);
994           highlightBond2.at1.isSelected = true;
995         }
996
997         break;
998       }
999     }
1000
1001     redrawneeded = true;
1002     repaint();
1003   }
1004
1005     public void setAllchainsVisible(boolean b)
1006     {
1007       for (int ii = 0; ii < pdb.chains.size(); ii++)
1008       {
1009         PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
1010         chain.isVisible = b;
1011       }
1012       mainchain.isVisible = true;
1013       findCentre();
1014       setupBonds();
1015     }
1016 }