1 /***************************************************************
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version 2
6 * of the License, or (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 *
17 *  @author: Copyright (C) Tim Carver
18 *
19 ***************************************************************/
20 
21 package org.emboss.jemboss.editor;
22 
23 import javax.swing.*;
24 
25 import java.awt.*;
26 import java.awt.event.*;
27 import java.util.*;
28 import java.io.File;
29 import javax.swing.border.*;
30 import java.net.URL;
31 
32 import org.emboss.jemboss.JembossParams;
33 import org.emboss.jemboss.gui.form.TextFieldInt;
34 import org.emboss.jemboss.gui.ScrollPanel;
35 import org.emboss.jemboss.gui.Browser;
36 
37 /**
38 *
39 * Displays a grapical representation of a collection of
40 * sequences.
41 *
42 */
43 public class AlignJFrame extends JFrame
44 {
45 
46   protected JScrollPane jspSequence; // Sequence scrollpane
47   protected static GraphicSequenceCollection gsc;
48   private static Matrix mat;
49   private PrettyPlotJFrame ppj = null;
50   protected static JTextField statusField = new JTextField();
51   private File sequenceFile = null;
52   private Cursor cbusy = new Cursor(Cursor.WAIT_CURSOR);
53   private Cursor cdone = new Cursor(Cursor.DEFAULT_CURSOR);
54   protected JCheckBoxMenuItem residueColor;
55   protected Hashtable currentColour;
56   protected boolean useExitMenu = false;  // whether to use 'Exit' or 'Close'
57   protected JMenuBar menuBar;
58   PatternJFrame findPattern;
59   JCheckBoxMenuItem drawColorBox;
60 
61   /**
62   *
63   * @param vseqs	vector containing Sequence objects
64   *
65   */
AlignJFrame(Vector vseqs)66   public AlignJFrame(Vector vseqs)
67   {
68     this();
69     if(vseqs != null && vseqs.size() > 0)
70       openMethod(vseqs);
71   }
72 
73 
74   /**
75   *
76   * @param seqFile	sequence file
77   *
78   */
AlignJFrame(File seqFile)79   public AlignJFrame(File seqFile)
80   {
81     this();
82 
83     SequenceReader sr = new SequenceReader(seqFile);
84     sequenceFile = sr.getSequenceFile();
85 
86     if(sr.getSequenceVector()==null)
87     {
88         statusField.setText("Jemboss not able to read sequences in "+
89                 sequenceFile.getName());
90         return;
91     }
92 
93     openMethod(sr.getSequenceVector());
94     setTitle("Jemboss Alignment Viewer    :: "+
95               sequenceFile.getName());
96   }
97 
98 
99   /**
100   *
101   * @param seqString	formatted sequence string
102   * @param name 	name of sequence set
103   *
104   */
AlignJFrame(String seqString, String name)105   public AlignJFrame(String seqString, String name)
106   {
107     this();
108 
109     SequenceReader sr = new SequenceReader(seqString);
110     sequenceFile = null;
111     openMethod(sr.getSequenceVector());
112     setTitle("Jemboss Alignment Viewer    :: "+name);
113   }
114 
115 
AlignJFrame()116   public AlignJFrame()
117   {
118     this(false);
119   }
120 
121 
122   /**
123   *
124   * @param useExitMenu	true if an exit menu is to be displayed
125   *			otherwise a close menu is used
126   *
127   */
AlignJFrame(boolean useExitMenu)128   public AlignJFrame(boolean useExitMenu)
129   {
130       this(useExitMenu, new Matrix("resources/resources.jar",
131               Matrix.DEFAULT_MATRIX));
132   }
133 
AlignJFrame(boolean useExitMenu, Matrix mat_)134   public AlignJFrame(boolean useExitMenu, Matrix mat_){
135     super("Jemboss Alignment Editor");
136 
137     this.useExitMenu = useExitMenu;
138 
139     final Dimension dScreen = getToolkit().getScreenSize();
140 
141     mat = mat_;
142     jspSequence = new JScrollPane();
143     jspSequence.getViewport().setBackground(Color.white);
144 
145     final JButton leftbutt = new JButton("Lock");
146     jspSequence.setCorner(JScrollPane.LOWER_LEFT_CORNER,
147                                               leftbutt);
148     leftbutt.addActionListener(new ActionListener()
149     {
150       public void actionPerformed(ActionEvent e)
151       {
152         if(leftbutt.getText().equals("Lock"))
153         {
154           gsc.setSequenceLock(true);
155           leftbutt.setText("Unlock");
156         }
157         else
158         {
159           gsc.setSequenceLock(false);
160           leftbutt.setText("Lock");
161         }
162       }
163     });
164 
165     final JPanel mainPane = (JPanel)getContentPane();
166 
167 // set up a menu bar
168     menuBar = new JMenuBar();
169 
170 // File menu
171     JMenu fileMenu = new JMenu("File");
172     fileMenu.setMnemonic(KeyEvent.VK_F);
173 
174 // open sequence file
175     final JMenuItem calculateCons = new JMenuItem("Consensus");
176     final JMenuItem calculatePlotCon = new JMenuItem("Consensus plot");
177 
178     JMenuItem openSequence = new JMenuItem("Open...");
179     openSequence.addActionListener(new ActionListener()
180     {
181       public void actionPerformed(ActionEvent e)
182       {
183         SequenceReader sr = new SequenceReader();
184 
185         if(sr.isReading())
186         {
187           sequenceFile = sr.getSequenceFile();
188           openMethod(sr.getSequenceVector());
189           calculateCons.setText("Calculate consensus");
190           calculatePlotCon.setText("Calculate consensus plot");
191           setTitle("Jemboss Alignment Viewer    :: "+
192                     sequenceFile.getName());
193         }
194       }
195     });
196     fileMenu.add(openSequence);
197 
198 // save
199     JMenuItem saveAsMenu = new JMenuItem("Save As...");
200     saveAsMenu.addActionListener(new ActionListener()
201     {
202       public void actionPerformed(ActionEvent e)
203       {
204         new SequenceSaver(gsc.getSequenceCollection(),sequenceFile);
205       }
206     });
207     fileMenu.add(saveAsMenu);
208 
209     JMenuItem saveConsMenu = new JMenuItem("Save Consensus");
210     saveConsMenu.addActionListener(new ActionListener()
211     {
212       public void actionPerformed(ActionEvent e)
213       {
214         Vector v = new Vector();
215         v.add(gsc.getConsensusSequence());
216         new SequenceSaver(v);
217       }
218     });
219     fileMenu.add(saveConsMenu);
220 
221 
222 // print
223     JMenu printMenu = new JMenu("Print");
224     fileMenu.add(printMenu);
225 
226     JMenuItem print = new JMenuItem("Print Postscript...");
227     print.setToolTipText("Print using available printers in your computer\n" +
228     		"or export alignment image to a postscript file (if you have " +
229     		" installed postscript printers)");
230     print.addActionListener(new ActionListener()
231     {
232       public void actionPerformed(ActionEvent e)
233       {
234         new PrintAlignment(gsc);
235       }
236     });
237     printMenu.add(print);
238 
239 //
240     JMenuItem printImage = new JMenuItem("Print Image Files (png/jpeg)...");
241     printImage.addActionListener(new ActionListener()
242     {
243       public void actionPerformed(ActionEvent e)
244       {
245         PrintAlignmentImage pai = new PrintAlignmentImage(gsc);
246         pai.print();
247       }
248     });
249     printMenu.add(printImage);
250 
251     JMenuItem printOneImage = new JMenuItem("Print to Single Image File...");
252     printOneImage.addActionListener(new ActionListener()
253     {
254       public void actionPerformed(ActionEvent e)
255       {
256         PrintAlignmentImage pai = new PrintAlignmentImage(gsc);
257         String fsave = pai.showOptions();
258         if(fsave == null)
259           return;
260 
261         pai.print(fsave,0.,0.,0.,0.);
262       }
263     });
264     printMenu.add(printOneImage);
265 
266 // print preview
267     JMenu printPreviewMenu = new JMenu("Print Preview");
268     fileMenu.add(printPreviewMenu);
269 
270     JMenuItem printPreview = new JMenuItem("Multiple Pages...");
271     printPreview.addActionListener(new ActionListener()
272     {
273       public void actionPerformed(ActionEvent e)
274       {
275         PrintAlignmentImage pai = new PrintAlignmentImage(gsc);
276         pai.printPreview();
277       }
278     });
279     printPreviewMenu.add(printPreview);
280 
281     JMenuItem printSinglePreview = new JMenuItem("Single Page...");
282     printSinglePreview.addActionListener(new ActionListener()
283     {
284       public void actionPerformed(ActionEvent e)
285       {
286         PrintAlignmentImage pai = new PrintAlignmentImage(gsc);
287         /*String type = */pai.showPrintPreviewOptions();
288         pai.printSinglePagePreview();
289       }
290     });
291     printPreviewMenu.add(printSinglePreview);
292 
293 // close
294     fileMenu.add(new JSeparator());
295     if(!useExitMenu)
296     {
297       JMenuItem close = new JMenuItem("Close");
298       close.setAccelerator(KeyStroke.getKeyStroke(
299               KeyEvent.VK_E, ActionEvent.CTRL_MASK));
300 
301       close.addActionListener(new ActionListener()
302       {
303         public void actionPerformed(ActionEvent e)
304         {
305           dispose();
306           findPattern.dispose();
307         }
308       });
309       fileMenu.add(close);
310     }
311     else         // exit
312     {
313       JMenuItem fileMenuExit = new JMenuItem("Exit");
314       fileMenuExit.addActionListener(new ActionListener()
315       {
316         public void actionPerformed(ActionEvent e)
317         {
318           System.exit(0);
319         }
320       });
321       fileMenu.add(fileMenuExit);
322     }
323     menuBar.add(fileMenu);
324 
325 // Edit menu
326     JMenu editMenu = new JMenu("Edit");
327     menuBar.add(editMenu);
328 
329     JMenuItem insertAnn = new JMenuItem("Insert Annotation Sequence");
330     editMenu.add(insertAnn);
331     insertAnn.addActionListener(new ActionListener()
332     {
333       public void actionPerformed(ActionEvent e)
334       {
335         ScrollPanel pane = new ScrollPanel(new BorderLayout());
336         Box bacross = Box.createVerticalBox();
337         JRadioButton openFile = new JRadioButton("Read from File");
338         JRadioButton cut      = new JRadioButton("Cut and Paste");
339         ButtonGroup group = new ButtonGroup();
340         group.add(openFile);
341         group.add(cut);
342         cut.setSelected(true);
343         bacross.add(openFile);
344         bacross.add(cut);
345         pane.add(bacross,BorderLayout.CENTER);
346         int selectedValue = JOptionPane.showConfirmDialog(null,
347                           pane, "Cut and Paste/Read from File",
348                           JOptionPane.OK_CANCEL_OPTION,
349                           JOptionPane.QUESTION_MESSAGE);
350         if(selectedValue == JOptionPane.OK_OPTION)
351         {
352           SequenceReader sr = null;
353           if(openFile.isSelected())
354             sr = new SequenceReader();
355           else
356           {
357             Paste pastePane = new Paste();
358             selectedValue = JOptionPane.showConfirmDialog(null,
359                           pastePane, "Cut and Paste",
360                           JOptionPane.OK_CANCEL_OPTION,
361                           JOptionPane.QUESTION_MESSAGE);
362             if(selectedValue == JOptionPane.OK_OPTION)
363               sr = new SequenceReader(pastePane.getSequence());
364           }
365           if(sr != null && sr.isReading())
366           {
367             sequenceFile = sr.getSequenceFile();
368             gsc.addAnnotationSequence(sr.getSequence(0));
369             Dimension dpane = gsc.getPanelSize();
370             gsc.setPreferredSize(dpane);
371             gsc.setNamePanelWidth(gsc.getNameWidth());
372             jspSequence.setViewportView(gsc);
373           }
374         }
375       }
376     });
377 
378     JMenuItem trimMenu = new JMenuItem("Trim Sequences");
379     editMenu.add(trimMenu);
380     trimMenu.addActionListener(new ActionListener()
381     {
382       public void actionPerformed(ActionEvent e)
383       {
384         ScrollPanel pane = new ScrollPanel(new BorderLayout());
385         Box bacross = Box.createHorizontalBox();
386         TextFieldInt start = new TextFieldInt();
387         start.setValue(1);
388         TextFieldInt end   = new TextFieldInt();
389         end.setValue(gsc.getMaxSeqLength());
390         bacross.add(start);
391         bacross.add(new JLabel(" start "));
392         bacross.add(end);
393         bacross.add(new JLabel(" end"));
394         pane.add(bacross,BorderLayout.CENTER);
395         int selectedValue = JOptionPane.showConfirmDialog(null,
396                           pane, "Select Sequence Range to Use",
397                           JOptionPane.OK_CANCEL_OPTION,
398                           JOptionPane.QUESTION_MESSAGE);
399         if(selectedValue == JOptionPane.OK_OPTION)
400         {
401           Vector vseq = gsc.getSequenceCollection();
402           Enumeration enumer = vseq.elements();
403           while(enumer.hasMoreElements())
404           {
405             Sequence s = (Sequence)enumer.nextElement();
406             s.trim(start.getValue(),end.getValue());
407           }
408           gsc.setMaxSeqLength();
409           gsc.repaint();
410         }
411       }
412     });
413 
414     JMenuItem unlock = new JMenuItem("Unlock All Sequences");
415     editMenu.add(unlock);
416     unlock.addActionListener(new ActionListener()
417     {
418       public void actionPerformed(ActionEvent e)
419       {
420         gsc.setSequenceLock(false);
421       }
422     });
423 
424 // View menu
425     JMenu viewMenu = new JMenu("View");
426     viewMenu.setMnemonic(KeyEvent.VK_V);
427 
428 // find pattern
429     JMenuItem findMenu = new JMenuItem("Find pattern");
430     viewMenu.add(findMenu);
431     findPattern = new PatternJFrame();
432     final PatternJFrame patFrame = findPattern;
433     findMenu.addActionListener(new ActionListener()
434     {
435       public void actionPerformed(ActionEvent e)
436       {
437         Point pos = getLocationOnScreen();
438         pos.y = pos.y - patFrame.getHeight();
439         if(pos.y+patFrame.getHeight() > dScreen.getHeight())
440           pos.x = (int)(dScreen.getWidth()-patFrame.getHeight());
441 
442         patFrame.setLocation(pos);
443         patFrame.setGraphic(gsc);
444         patFrame.setVisible(true);
445         patFrame.setExtendedState(patFrame.getExtendedState() & ~ICONIFIED);
446         patFrame.requestFocusInWindow();
447         patFrame.toFront();
448       }
449     });
450     viewMenu.add(new JSeparator());
451 
452 // matrix display
453     JMenuItem showMatrix = new JMenuItem("Matrix Display");
454     viewMenu.add(showMatrix);
455     final MatrixJFrame matFrame = new MatrixJFrame(mat,statusField,
456                                                    this);
457     showMatrix.addActionListener(new ActionListener()
458     {
459       public void actionPerformed(ActionEvent e)
460       {
461         matFrame.setMatrix(mat);
462         matFrame.setVisible(true);
463         matFrame.toFront();
464       }
465     });
466 
467 // colour display
468     JMenuItem showColour = new JMenuItem("Colour Display");
469     viewMenu.add(showColour);
470     final ColourJFrame colFrame = new ColourJFrame(this);
471     showColour.addActionListener(new ActionListener()
472     {
473       public void actionPerformed(ActionEvent e)
474       {
475         Point pos = getLocationOnScreen();
476         pos.x = pos.x + getWidth();
477         if(pos.x+colFrame.getWidth() > dScreen.getWidth())
478           pos.x = (int)(dScreen.getWidth()-colFrame.getWidth());
479 
480         colFrame.setLocation(pos);
481         colFrame.setCurrentColour(currentColour);
482         colFrame.setVisible(true);
483         colFrame.toFront();
484       }
485     });
486     viewMenu.add(new JSeparator());
487 
488     colourMenus(viewMenu);
489 
490 //pretty plot
491     final JMenuItem pretty = new JMenuItem("Colour Identical/Matches");
492     viewMenu.add(pretty);
493     viewMenu.add(new JSeparator());
494 
495 //draw black box
496     final JCheckBoxMenuItem drawBoxes = new JCheckBoxMenuItem("Draw boxes",false);
497     drawBoxes.addActionListener(new ActionListener()
498     {
499       public void actionPerformed(ActionEvent e)
500       {
501         gsc.setDrawBoxes(drawBoxes.isSelected());
502       }
503     });
504     viewMenu.add(drawBoxes);
505 
506 //draw colored boxes
507     viewMenu.add(drawColorBox);
508 
509     pretty.addActionListener(new ActionListener()
510     {
511       public void actionPerformed(ActionEvent e)
512       {
513         if(ppj == null)
514           ppj = new PrettyPlotJFrame(gsc);
515         else
516           ppj.setGraphicSequenceCollection(gsc);
517         gsc.setMatrix(mat);
518         ppj.setVisible(true);
519       }
520     });
521     menuBar.add(viewMenu);
522 
523 // calculate menu
524     JMenu calculateMenu = new JMenu("Calculate");
525     menuBar.add(calculateMenu);
526 
527 // consensus sequence
528     final ConsensusOptions options = new ConsensusOptions(jspSequence);
529     calculateCons.addActionListener(new ActionListener()
530     {
531       public void actionPerformed(ActionEvent e)
532       {
533         setCursor(cbusy);
534         try{
535         gsc.deleteSequence(Consensus.DEFAULT_SEQUENCE_NAME);
536 
537         float wgt = getTotalWeight(gsc.getSequenceCollection());
538         float plu = 0.f;
539         try
540         {
541           plu = options.getPlurality();
542         }
543         catch(NumberFormatException nfe)
544         {
545           plu = wgt/2.f;
546         }
547 
548         float cas = 0.f;
549         try
550         {
551           cas = options.getCase();
552         }
553         catch(NumberFormatException nfe)
554         {
555           cas = wgt/2.f;
556         }
557 
558         Consensus conseq = new Consensus(mat,
559                     gsc.getSequenceCollection(),
560                     plu,cas,
561                     options.getIdentity());
562 
563         int fontSize = gsc.getFontSize();
564         gsc.addSequence(conseq.getConsensusSequence(),true,0,fontSize);
565 
566 //      if(pretty.isSelected())
567 //        gsc.setPrettyPlot(pretty.isSelected(),ppj);
568 
569         Dimension dpane = gsc.getPanelSize();
570         gsc.setPreferredSize(dpane);
571         gsc.setNamePanelWidth(gsc.getNameWidth());
572         jspSequence.setViewportView(gsc);
573         calculateCons.setText("Recalculate consensus");
574         } finally {
575             setCursor(cdone);
576         }
577       }
578     });
579     calculateMenu.add(calculateCons);
580 
581 
582     JMenuItem consOptions = new JMenuItem("Set consensus options...");
583     consOptions.addActionListener(new ActionListener()
584     {
585       public void actionPerformed(ActionEvent e)
586       {
587         try
588         {
589 //          Vector vseq = gsc.getSequenceCollection();
590 //        Enumeration enumer = vseq.elements();
591           float wgt = getTotalWeight(gsc.getSequenceCollection());
592           options.setCase(wgt/2.f);
593           options.setPlurality(wgt/2.f);
594           options.setGraphicSequenceCollection(gsc);
595         }
596         catch(NullPointerException npe){}
597         options.setMatrix(mat);
598         options.setVisible(true);
599       }
600     });
601     calculateMenu.add(consOptions);
602     calculateMenu.add(new JSeparator());
603 
604 // %age identity between pairs
605     JMenuItem calculateId = new JMenuItem("Identity table");
606     calculateId.addActionListener(new ActionListener()
607     {
608       public void actionPerformed(ActionEvent e)
609       {
610         IDTableJFrame idtab = new IDTableJFrame(gsc.getSequenceCollection());
611         idtab.setVisible(true);
612       }
613     });
614     calculateMenu.add(calculateId);
615     calculateMenu.add(new JSeparator());
616 
617 // consensus plot
618     calculatePlotCon.addActionListener(new ActionListener()
619     {
620       public void actionPerformed(ActionEvent e)
621       {
622         setCursor(cbusy);
623         gsc.showConsensusPlot(mat,2);
624         setCursor(cdone);
625         calculatePlotCon.setText("Recalculate Consensus plot");
626       }
627     });
628     calculateMenu.add(calculatePlotCon);
629     calculateMenu.add(new JSeparator());
630 
631 // sort by id
632     JMenuItem test = new JMenuItem("Sort by ID");
633     calculateMenu.add(test);
634     test.addActionListener(new ActionListener()
635     {
636       public void actionPerformed(ActionEvent e)
637       {
638         gsc.idSort();
639         jspSequence.setViewportView(gsc);
640       }
641     });
642 
643 // font menu
644     String sizes[] = {"10", "12", "14", "16", "18"};
645     final JComboBox fntSize = new JComboBox(sizes);
646     fntSize.setToolTipText("font size");
647     fntSize.setSelectedItem("12");
648     menuBar.add(fntSize);
649     fntSize.setEditable(true);
650     Dimension dfont = new Dimension(50,20);
651     fntSize.setPreferredSize(dfont);
652     fntSize.setMaximumSize(dfont);
653     fntSize.addActionListener(new ActionListener()
654     {
655       public void actionPerformed(ActionEvent e)
656       {
657         String fsize = (String)fntSize.getSelectedItem();
658         if(gsc !=null)
659           gsc.setFontSizeForCollection(Integer.parseInt(fsize));
660       }
661     });
662 
663     setJMenuBar(menuBar);
664 
665 // help manu
666     JMenu helpMenu = new JMenu("Help");
667     menuBar.add(helpMenu);
668 
669     JMenuItem aboutMenu = new JMenuItem("About");
670     helpMenu.add(aboutMenu);
671     aboutMenu.addActionListener(new ActionListener()
672     {
673       public void actionPerformed(ActionEvent e)
674       {
675         ClassLoader cl = this.getClass().getClassLoader();
676         try
677         {
678           URL inURL = cl.getResource("resources/readmeAlign.html");
679           new Browser(inURL,"resources/readmeAlign.html");
680         }
681         catch (Exception ex)
682         {
683           JOptionPane.showMessageDialog(null,
684                               "Jemboss Alignment Viewer Guide not found!",
685                               "Error", JOptionPane.ERROR_MESSAGE);
686         }
687       }
688     });
689 
690 // set size of sequence panel
691     Dimension d = new Dimension(700,300);
692     jspSequence.setPreferredSize(d);
693 
694     JPanel seqNamePanel = new JPanel(new BorderLayout());
695     seqNamePanel.add(jspSequence,BorderLayout.CENTER);
696 
697     mainPane.add(jspSequence,BorderLayout.CENTER);
698 
699     Border loweredbevel = BorderFactory.createLoweredBevelBorder();
700     Border raisedbevel = BorderFactory.createRaisedBevelBorder();
701     Border compound = BorderFactory.createCompoundBorder(raisedbevel,loweredbevel);
702     statusField.setBorder(compound);
703     statusField.setEditable(false);
704     statusField.setText("Current matrix: "+mat.getCurrentMatrixName());
705     mainPane.add(statusField,BorderLayout.SOUTH);
706 
707     addWindowListener(new winExit());
708     pack();
709     setLocation( (int)(dScreen.getWidth()-getWidth())/3,
710                  (int)(dScreen.getHeight()-getHeight())/3 );
711   }
712 
713 
getTotalWeight(Vector vseq)714   public static float getTotalWeight(Vector vseq)
715   {
716     float wgt = 0.f;
717     vseq = gsc.getSequenceCollection();
718     Enumeration enumer = vseq.elements();
719     while(enumer.hasMoreElements())
720     {
721       Sequence s = (Sequence)enumer.nextElement();
722       if(!s.getName().equals(Consensus.DEFAULT_SEQUENCE_NAME))
723         wgt+=s.getWeight();
724     }
725     return wgt;
726   }
727 
728 
729   /**
730   *
731   * Set the scoring matrix
732   * @param mat 	scoring matrix to use
733   *
734   */
setMatrix(Matrix mat)735   public void setMatrix(Matrix mat)
736   {
737     AlignJFrame.mat = mat;
738   }
739 
740   /**
741   *
742   * Force a re-display of the sequences with a new colour
743   * scheme.
744   * @param hash		hash of the colour scheme
745   *
746   */
repaintSequences(Hashtable hash)747   public void repaintSequences(Hashtable hash)
748   {
749     gsc.setColorScheme(hash);
750     gsc.repaint();
751   }
752 
753   /**
754   *
755   * Given a Vector of Sequence display them in the editor
756   * @param seqVector	vector containing Sequence objects
757   *
758   */
openMethod(Vector seqVector)759   protected void openMethod(Vector seqVector)
760   {
761     gsc = new GraphicSequenceCollection(seqVector,
762                                    jspSequence,true,false,true,true,
763                                    statusField);
764 // set colour scheme
765     gsc.setColorScheme(SequenceProperties.residueColor);
766     currentColour = (Hashtable)SequenceProperties.residueColor.clone();
767     residueColor.setSelected(true);
768     jspSequence.setViewportView(gsc);
769 
770     colourScheme("Residue colour");
771   }
772 
773 
774   /**
775   *
776   * Update the status bar with the selected colour scheme
777   * being used.
778   * @param colScheme 	name of colour scheme
779   *
780   */
colourScheme(String colScheme)781   protected void colourScheme(String colScheme)
782   {
783     String status = statusField.getText();
784     int ncol = status.indexOf("Colour Scheme: ");
785     if(ncol > -1)
786       statusField.setText(status.substring(0,ncol)+
787                           "Colour Scheme: "+colScheme);
788     else
789       statusField.setText(status+"              "+
790                           "Colour Scheme: "+colScheme);
791     drawColorBox.setSelected(true);
792   }
793 
794   /**
795   *
796   * Constructs the colour menus
797   *
798   */
colourMenus(JMenu viewMenu)799   private void colourMenus(JMenu viewMenu)
800   {
801     final ButtonGroup group = new ButtonGroup();
802     // an invisble radio button to workaround earlier versions of java
803     // which is selected only when user deselect "Colour boxes" option
804     final JRadioButton invisibleb = new JRadioButton();
805     group.add(invisibleb);
806     drawColorBox = new JCheckBoxMenuItem("Colour boxes",true);
807     drawColorBox.addItemListener(new ItemListener()
808     {
809         ButtonModel lastSelection;
810         public void itemStateChanged(ItemEvent e) {
811             boolean selected = e.getStateChange() == ItemEvent.SELECTED;
812             gsc.setDrawColor(selected);
813             if(!selected){
814             	lastSelection = group.getSelection();
815             	//java6 has a group.clearSelection(); method that in the future
816             	//can replace the invisible button workaround
817             	invisibleb.setSelected(true);
818             } else if (invisibleb.isSelected()){
819             	lastSelection.setSelected(true);
820             }
821         }
822     });
823 
824 // property colour menus
825     JMenu propertyMenu = new JMenu("Colour by Property");
826     viewMenu.add(propertyMenu);
827 
828     JCheckBoxMenuItem acidColor =
829                 new JCheckBoxMenuItem("Red=acidic, Blue=basic");
830     propertyMenu.add(acidColor);
831     group.add(acidColor);
832     acidColor.addActionListener(new ActionListener()
833     {
834       public void actionPerformed(ActionEvent e)
835       {
836         gsc.setColorScheme(SequenceProperties.acidColor);
837         jspSequence.setViewportView(gsc);
838         currentColour = SequenceProperties.acidColor;
839         colourScheme("Red=acidic, Blue=basic");
840       }
841     });
842 
843     JCheckBoxMenuItem polarColor =
844                 new JCheckBoxMenuItem("Red=polar");
845     propertyMenu.add(polarColor);
846     group.add(polarColor);
847     polarColor.addActionListener(new ActionListener()
848     {
849       public void actionPerformed(ActionEvent e)
850       {
851         gsc.setColorScheme(SequenceProperties.polarColor);
852         jspSequence.setViewportView(gsc);
853         currentColour = SequenceProperties.polarColor;
854         colourScheme("Red=polar");
855       }
856     });
857 
858     JCheckBoxMenuItem hydrophobicColor =
859                new JCheckBoxMenuItem("Red=Hydrophobic");
860     propertyMenu.add(hydrophobicColor);
861     group.add(hydrophobicColor);
862     hydrophobicColor.addActionListener(new ActionListener()
863     {
864       public void actionPerformed(ActionEvent e)
865       {
866         gsc.setColorScheme(SequenceProperties.hydrophobicColor);
867         jspSequence.setViewportView(gsc);
868         currentColour = SequenceProperties.hydrophobicColor;
869         colourScheme("Red=Hydrophobic");
870       }
871     });
872 
873     JCheckBoxMenuItem aromaticColor =
874                new JCheckBoxMenuItem("Red=Aromatic, Blue=Aliphatic");
875     propertyMenu.add(aromaticColor);
876     group.add(aromaticColor);
877     aromaticColor.addActionListener(new ActionListener()
878     {
879       public void actionPerformed(ActionEvent e)
880       {
881         gsc.setColorScheme(SequenceProperties.aromaticColor);
882         jspSequence.setViewportView(gsc);
883         currentColour = SequenceProperties.aromaticColor;
884         colourScheme("Red=Aromatic, Blue=Aliphatic");
885       }
886     });
887 
888     JCheckBoxMenuItem surfaceColor =
889                new JCheckBoxMenuItem("Red=Surface, Blue=Buried");
890     propertyMenu.add(surfaceColor);
891     group.add(surfaceColor);
892     surfaceColor.addActionListener(new ActionListener()
893     {
894       public void actionPerformed(ActionEvent e)
895       {
896         gsc.setColorScheme(SequenceProperties.surfaceColor);
897         jspSequence.setViewportView(gsc);
898         currentColour = SequenceProperties.surfaceColor;
899         colourScheme("Red=Surface, Blue=Buried");
900       }
901     });
902 
903     JCheckBoxMenuItem chargeColor  =
904                new JCheckBoxMenuItem("Red=Positive, Blue=Negative");
905     propertyMenu.add(chargeColor);
906     group.add(chargeColor);
907     chargeColor.addActionListener(new ActionListener()
908     {
909       public void actionPerformed(ActionEvent e)
910       {
911         gsc.setColorScheme(SequenceProperties.chargeColor);
912         jspSequence.setViewportView(gsc);
913         currentColour = SequenceProperties.chargeColor;
914         colourScheme("Red=Positive, Blue=Negative");
915       }
916     });
917 
918     JCheckBoxMenuItem sizeColor  =
919                new JCheckBoxMenuItem("Red=Tiny, Green=Small, Blue=Large");
920     propertyMenu.add(sizeColor);
921     group.add(sizeColor);
922     sizeColor.addActionListener(new ActionListener()
923     {
924       public void actionPerformed(ActionEvent e)
925       {
926         gsc.setColorScheme(SequenceProperties.sizeColor);
927         jspSequence.setViewportView(gsc);
928         currentColour = SequenceProperties.sizeColor;
929         colourScheme("Red=Tiny, Green=Small, Blue=Large");
930       }
931     });
932 
933 // other colour schemes
934     JCheckBoxMenuItem taylor = new JCheckBoxMenuItem("Taylor Colour");
935     viewMenu.add(taylor);
936     group.add(taylor);
937     taylor.addActionListener(new ActionListener()
938     {
939       public void actionPerformed(ActionEvent e)
940       {
941         gsc.setColorScheme(SequenceProperties.taylorColor);
942         jspSequence.setViewportView(gsc);
943         currentColour = SequenceProperties.taylorColor;
944         colourScheme("Taylor");
945       }
946     });
947 
948     residueColor = new JCheckBoxMenuItem("Residue Colour");
949     viewMenu.add(residueColor);
950     group.add(residueColor);
951     residueColor.addActionListener(new ActionListener()
952     {
953       public void actionPerformed(ActionEvent e)
954       {
955         gsc.setColorScheme(SequenceProperties.residueColor);
956         jspSequence.setViewportView(gsc);
957         currentColour = SequenceProperties.residueColor;
958         colourScheme("Residue");
959       }
960     });
961 
962     JCheckBoxMenuItem rasmolColor = new JCheckBoxMenuItem("Rasmol Colour");
963     viewMenu.add(rasmolColor);
964     group.add(rasmolColor);
965     rasmolColor.addActionListener(new ActionListener()
966     {
967       public void actionPerformed(ActionEvent e)
968       {
969         gsc.setColorScheme(SequenceProperties.rasmolColor);
970         jspSequence.setViewportView(gsc);
971         currentColour = SequenceProperties.rasmolColor;
972         colourScheme("Rasmol");
973       }
974     });
975 
976     JCheckBoxMenuItem nuc = new JCheckBoxMenuItem("Nucleotide Colour");
977     viewMenu.add(nuc);
978     group.add(nuc);
979     nuc.addActionListener(new ActionListener()
980     {
981       public void actionPerformed(ActionEvent e)
982       {
983         gsc.setColorScheme(SequenceProperties.baseColor);
984         jspSequence.setViewportView(gsc);
985         currentColour = SequenceProperties.baseColor;
986         colourScheme("Nucleotide");
987       }
988     });
989     viewMenu.add(new JSeparator());
990   }
991 
992 
993   /**
994   *
995   *
996   *  red, blue, cyan, darkGray, gray , green, lightGray,
997   *  magenta , orange, pink, white, yellow, black
998   *
999   */
resolveColor(String[] args,int index)1000   private static Color resolveColor(String[] args,int index)
1001   {
1002     if(args[index].equalsIgnoreCase("red"))
1003       return Color.red;
1004     else if(args[index].equalsIgnoreCase("blue"))
1005       return Color.blue;
1006     else if(args[index].equalsIgnoreCase("black"))
1007       return Color.black;
1008     else if(args[index].equalsIgnoreCase("cyan"))
1009       return Color.cyan;
1010     else if(args[index].equalsIgnoreCase("darkGray"))
1011       return Color.darkGray;
1012     else if(args[index].equalsIgnoreCase("gray"))
1013       return Color.gray;
1014     else if(args[index].equalsIgnoreCase("green"))
1015       return Color.green;
1016     else if(args[index].equalsIgnoreCase("lightGray"))
1017       return Color.lightGray;
1018     else if(args[index].equalsIgnoreCase("magenta"))
1019       return Color.magenta;
1020     else if(args[index].equalsIgnoreCase("orange"))
1021       return Color.orange;
1022     else if(args[index].equalsIgnoreCase("pink"))
1023       return Color.pink;
1024     else if(args[index].equalsIgnoreCase("white"))
1025       return Color.white;
1026     else if(args[index].equalsIgnoreCase("yellow"))
1027       return Color.yellow;
1028     else if(args[index].equalsIgnoreCase("black"))
1029       return Color.black;
1030 
1031     return null;
1032   }
1033 
1034   /**
1035   *
1036   * Extends WindowAdapter to close window
1037   *
1038   */
1039   class winExit extends WindowAdapter
1040   {
windowClosing(WindowEvent we)1041      public void windowClosing(WindowEvent we)
1042      {
1043         dispose();
1044         findPattern.dispose();
1045      }
1046   }
1047 
1048 
main(String args[])1049   public static void main(String args[])
1050   {
1051     AlignJFrame ajFrame = null;
1052 
1053     if( args.length > 0 )
1054     {
1055       for(int i=0;i<args.length;i++)
1056       {
1057         if(args[i].indexOf("-help") > -1)
1058         {
1059           System.out.println(
1060               "\n                  Jemboss Alignment Editor\n\n"+
1061               "DESCRIPTION\n"+
1062               "The Jemboss Alignment Editor can be used interactively to\n"+
1063               "edit a sequence alignment (read in fasta or MSF format). It can\n"+
1064               "also be used from the command line to produce image files\n"+
1065               "of the alignment.\n\nUSAGE\n"+
1066               "java org/emboss/jemboss/editor/AlignJFrame file [options]\n\n"+
1067               "file       This is the multiple sequence alignment in\n"+
1068               "           fasta or MSF format.\n\n"+
1069               "OPTIONS\n"+
1070               "-calc      Calculate consensus and display under the alignment.\n"+
1071               "           The following 3 flags can be used to define values\n"+
1072               "           used in the calculations.\n"+
1073               "           -plu       (plurality) minimum positive match score\n"+
1074               "                      value for there to be a consensus.\n"+
1075               "           -numid     minimum number of identities for there to\n"+
1076               "                      be a consensus.\n"+
1077               "           -case      minimum positive match score for setting\n"+
1078               "                      the consensus to upper-case.\n"+
1079               "-color     Used to define a colour scheme, below is the list of\n"+
1080               "           available colour schemes:\n"+
1081               "           taylor\n"+
1082               "           residue\n"+
1083               "           rasmol\n"+
1084               "           acid\n"+
1085               "           polar\n"+
1086               "           hydrophobic\n"+
1087               "           aromatic\n"+
1088               "           surface\n"+
1089               "           charge\n"+
1090               "           size\n"+
1091               "           base\n\n"+
1092               "       java org.emboss.jemboss.editor.AlignJFrame file -color size\n\n"+
1093               "-font      Set the font size.\n"+
1094               "-id        Display a percentage ID pair table.\n"+
1095               "-noshow    Turns of the alignment display.\n"+
1096               "-nres      Number of residues to each line is a print out.\n"+
1097               "-pretty    EMBOSS prettyplot colour scheme. The -matrix flag option\n"+
1098               "           can be used to define a scoring matrix for identifying\n"+
1099               "           positive matches.\n"+
1100               "           -noBox         switch off box drawing around identical and\n"+
1101               "                          positive matches.\n"+
1102               "           -minID         define the minimum number of identities. The\n"+
1103               "                          default for this is the number of sequences\n"+
1104               "                          in the file.\n"+
1105               "           -match         define a threshold value for the number of\n"+
1106               "                          positive matches, the default is half the\n"+
1107               "                          total wgt.\n"+
1108               "           -colID         define a lettering colour for the identities.\n"+
1109               "           -colIDBack     define a background colour for identities.\n"+
1110               "           -colMatch      define a lettering  colour for positive matches.\n"+
1111               "           -colMatchBack  define a background colour for positive\n"+
1112               "                           matches.\n"+
1113               "           Available colour options:\n"+
1114               "           red, blue, cyan, darkGray, gray , green, lightGray,\n"+
1115               "           magenta , orange, pink, white, yellow, black\n"+
1116               "-print     Print the alignment image. The following 2 flags can be\n"+
1117               "           used along with the print flag\n"+
1118               "           -prefix     prefix for image output file.\n"+
1119               "           -onePage    fit the alignment to one page. This option must be\n"+
1120               "                       be used with the -nres flag to define the residues\n"+
1121               "                       per line.\n"+
1122               "           -type       png or jpeg (default is jpeg).\n"+
1123               "           -antialias  turn anti-aliasing on.\n"+
1124               "           -landscape  Print as landscape (the default is portrait).\n"+
1125               "           -margin     Define the left, right, top and bottom margin\n"+
1126               "                       (in cm).\n"+
1127               "       java org.emboss.jemboss.editor.AlignJFrame file -matrix EBLOSUM62 \\\n"+
1128               "                -noshow -print -margin 0.5 0.5 0.5 0.5\n\n"+
1129               "-matrix    To define a scoring matrix. Used with the -pretty and -calc\n"+
1130               "           option.\n"+
1131               "-list      List the available scoring matrix files.\n\n"+
1132               "EXAMPLE\n"+
1133               "java org.emboss.jemboss.editor.AlignJFrame file -matrix EBLOSUM80 \\\n"+
1134               "                             -pretty -noshow -id -print -type png\n\n"+
1135               "java org.emboss.jemboss.editor.AlignJFrame file -matrix EPAM250 \\\n"+
1136               "                -pretty -colIDBack black -colID white -print \\\n"+
1137               "                -margin 0.5 0.5 0.5 0.0 -noshow\n");
1138           System.exit(0);
1139         }
1140       }
1141 
1142       File seqFile = new File(args[0]);
1143       if(seqFile.canRead())
1144       {
1145         JembossParams jp = new JembossParams();
1146         String ed = jp.getEmbossData();
1147         Matrix m = new Matrix(ed, Matrix.DEFAULT_MATRIX);
1148         ajFrame = new AlignJFrame(true, m);
1149         SequenceReader sr = new SequenceReader(seqFile);
1150         sr.getSequenceFile();
1151         ajFrame.openMethod(sr.getSequenceVector());
1152         ajFrame.setTitle("Jemboss Alignment Viewer    :: "+
1153                          seqFile.getName());
1154         gsc.setMatrix(mat);
1155       }
1156 
1157       String prefix = "output";
1158       String type   = "jpeg";
1159       boolean show  = true;
1160       boolean print = false;
1161       int nresiduesPerLine = 0;
1162 
1163       float wgt = getTotalWeight(gsc.getSequenceCollection());
1164       double lmargin = -0.5;  // left margin
1165       double rmargin = -0.5;  // right margin
1166       double tmargin = -0.5;  // top margin
1167       double bmargin = -0.5;  // bottom margin
1168       float plu = wgt/2.f;
1169       float cas = wgt/2.f;
1170       int ident = 0;
1171       int minID = gsc.getNumberSequences();
1172       float match = wgt/2.f;
1173       Color colID        = Color.red;
1174       Color colMatch     = Color.blue;
1175       Color colIDBack    = Color.white;
1176       Color colMatchBack = Color.white;
1177       boolean prettyBox  = true;
1178       boolean landscape  = false;
1179       boolean onePage    = false;
1180       boolean antialias  = false;
1181 
1182       for(int i=0;i<args.length;i++)
1183       {
1184         if(args[i].indexOf("-matrix") > -1)
1185         {
1186           mat = new Matrix("resources/resources.jar",
1187                            args[i+1]);
1188           gsc.setMatrix(mat);
1189           statusField.setText("Current matrix: "+args[i+1]);
1190         }
1191         else if(args[i].indexOf("-plu") > -1)
1192           plu = Float.parseFloat(args[i+1]);
1193         else if(args[i].indexOf("-match") > -1)
1194           match = Float.parseFloat(args[i+1]);
1195         else if(args[i].indexOf("-case") > -1)
1196           cas = Float.parseFloat(args[i+1]);
1197         else if(args[i].indexOf("-numid") > -1)
1198           ident = Integer.parseInt(args[i+1]);
1199         else if(args[i].indexOf("-colIDBack") > -1)
1200         {
1201           Color col = resolveColor(args,i+1);
1202           if(col != null)
1203             colIDBack = col;
1204         }
1205         else if(args[i].indexOf("-colMatchBack") > -1)
1206         {
1207           Color col = resolveColor(args,i+1);
1208           if(col != null)
1209             colMatchBack = col;
1210         }
1211         else if(args[i].indexOf("-colMatch") > -1)
1212         {
1213           Color col = resolveColor(args,i+1);
1214           if(col != null)
1215             colMatch = col;
1216         }
1217         else if(args[i].indexOf("-colID") > -1)
1218         {
1219           Color col = resolveColor(args,i+1);
1220           if(col != null)
1221             colID = col;
1222         }
1223         else if(args[i].indexOf("-minID") > -1)
1224           minID = Integer.parseInt(args[i+1]);
1225         else if(args[i].indexOf("-noBox") > -1)
1226           prettyBox = false;
1227         else if(args[i].indexOf("-font") > -1)
1228           gsc.setFontSizeForCollection(Integer.parseInt(args[i+1]));
1229         else if(args[i].indexOf("-landscape") > -1)
1230           landscape = true;
1231         else if(args[i].indexOf("-margin") > -1)
1232         {
1233           lmargin = Double.parseDouble(args[i+1]);
1234           rmargin = Double.parseDouble(args[i+2]);
1235           tmargin = Double.parseDouble(args[i+3]);
1236           bmargin = Double.parseDouble(args[i+4]);
1237         }
1238         else if(args[i].indexOf("-onePage") > -1)
1239           onePage = true;
1240         else if(args[i].indexOf("-antialias") > -1)
1241           antialias = true;
1242       }
1243 
1244       for(int i=0;i<args.length;i++)
1245       {
1246         if(args[i].indexOf("-color") > -1)
1247         {
1248           i++;
1249           if(args[i].startsWith("taylor"))
1250             gsc.setColorScheme(SequenceProperties.taylorColor);
1251           else if(args[i].startsWith("residue"))
1252             gsc.setColorScheme(SequenceProperties.residueColor);
1253           else if(args[i].startsWith("rasmol"))
1254             gsc.setColorScheme(SequenceProperties.rasmolColor);
1255           else if(args[i].startsWith("acid"))
1256             gsc.setColorScheme(SequenceProperties.acidColor);
1257           else if(args[i].startsWith("polar"))
1258             gsc.setColorScheme(SequenceProperties.polarColor);
1259           else if(args[i].startsWith("hydro"))
1260             gsc.setColorScheme(SequenceProperties.hydrophobicColor);
1261           else if(args[i].startsWith("aromatic"))
1262             gsc.setColorScheme(SequenceProperties.aromaticColor);
1263           else if(args[i].startsWith("surface"))
1264             gsc.setColorScheme(SequenceProperties.surfaceColor);
1265           else if(args[i].startsWith("charge"))
1266             gsc.setColorScheme(SequenceProperties.chargeColor);
1267           else if(args[i].startsWith("size"))
1268             gsc.setColorScheme(SequenceProperties.sizeColor);
1269           else if(args[i].startsWith("base"))
1270             gsc.setColorScheme(SequenceProperties.baseColor);
1271         }
1272         else if(args[i].indexOf("-calc") > -1)
1273         {
1274           Consensus conseq = new Consensus(mat,
1275                     gsc.getSequenceCollection(),
1276                     plu,cas,ident);
1277 
1278           int fontSize = gsc.getFontSize();
1279           gsc.addSequence(conseq.getConsensusSequence(),true,5,fontSize);
1280 
1281           Dimension dpane = gsc.getPanelSize();
1282           gsc.setPreferredSize(dpane);
1283           gsc.setNamePanelWidth(gsc.getNameWidth());
1284         }
1285         else if(args[i].indexOf("-list") > -1)
1286           System.out.println("AVAILABLE DATABASES:\n"+
1287                              mat.getKeyNamesString());
1288         else if(args[i].indexOf("-id") > -1)
1289         {
1290           IDTableJFrame idtab = new IDTableJFrame(gsc.getSequenceCollection());
1291           idtab.printTable();
1292         }
1293         else if(args[i].indexOf("-noshow") > -1)
1294           show = false;
1295         else if(args[i].indexOf("-print") > -1)
1296           print = true;
1297         else if(args[i].indexOf("-nres")  > -1)
1298           nresiduesPerLine = Integer.parseInt(args[i+1]);
1299         else if(args[i].indexOf("-pretty")  > -1)
1300         {
1301           PrettyPlotJFrame pretty = new PrettyPlotJFrame(minID,
1302                   match,colID,colMatch,
1303                   colIDBack,colMatchBack,prettyBox);
1304           gsc.setPrettyPlot(true,pretty);
1305           gsc.setDrawBoxes(false);
1306           gsc.setDrawColor(false);
1307         }
1308         else if(args[i].indexOf("-preview")  > -1)
1309         {
1310           PrintAlignmentImage pai = new PrintAlignmentImage(gsc);
1311           pai.printPreview();
1312           show = true;
1313         }
1314         else if(args[i].indexOf("-type")  > -1)
1315         {
1316           if( args[i+1].equalsIgnoreCase("png") ||
1317               args[i+1].equalsIgnoreCase("jpeg") )
1318             type = args[i+1];
1319           else
1320             System.out.println("UNKOWN PRINT FORMAT: "+args[i+1]+
1321                                " reverting to default format "+type);
1322         }
1323         else if(args[i].indexOf("-prefix")  > -1)
1324           prefix = args[i+1];
1325       }
1326 
1327       if(print)
1328       {
1329         if(onePage)
1330         {
1331           PrintAlignmentImage pai = new PrintAlignmentImage(gsc);
1332           if(antialias)
1333             pai.setAntiAlias(true);
1334           pai.print(nresiduesPerLine,type,prefix,
1335                     lmargin,rmargin,tmargin,bmargin);
1336         }
1337         else
1338         {
1339           PrintAlignmentImage pai = new PrintAlignmentImage(gsc);
1340           if(antialias)
1341             pai.setAntiAlias(true);
1342           pai.print(nresiduesPerLine,type,prefix,landscape,
1343                     lmargin,rmargin,tmargin,bmargin);
1344         }
1345       }
1346       if(!show)
1347         System.exit(0);
1348     }
1349     else
1350     {
1351       ajFrame = new AlignJFrame(true);
1352     }
1353     ajFrame.setVisible(true);
1354   }
1355 
1356 
1357 }
1358 
1359