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