Jalview Imported Sources start
authoramwaterhouse <Andrew Waterhouse>
Tue, 2 Nov 2004 10:46:54 +0000 (10:46 +0000)
committeramwaterhouse <Andrew Waterhouse>
Tue, 2 Nov 2004 10:46:54 +0000 (10:46 +0000)
110 files changed:
BartonGroupBanner.gif [new file with mode: 0755]
JalviewX.jpx [new file with mode: 0755]
src/jalview/analysis/AAFrequency.java [new file with mode: 0755]
src/jalview/analysis/AlignSeq.java [new file with mode: 0755]
src/jalview/analysis/AlignmentSorter.java [new file with mode: 0755]
src/jalview/analysis/AlignmentUtil.java [new file with mode: 0755]
src/jalview/analysis/CompareAlignments.java [new file with mode: 0755]
src/jalview/analysis/Conservation.java [new file with mode: 0755]
src/jalview/analysis/NJTree.java [new file with mode: 0755]
src/jalview/analysis/PCA.java [new file with mode: 0755]
src/jalview/bin/Cache.java [new file with mode: 0755]
src/jalview/bin/Jalview.java [new file with mode: 0755]
src/jalview/datamodel/Alignment.java [new file with mode: 0755]
src/jalview/datamodel/AlignmentI.java [new file with mode: 0755]
src/jalview/datamodel/BinaryNode.java [new file with mode: 0755]
src/jalview/datamodel/BinarySequence.java [new file with mode: 0755]
src/jalview/datamodel/FeaturePair.java [new file with mode: 0755]
src/jalview/datamodel/Sequence.java [new file with mode: 0755]
src/jalview/datamodel/SequenceFeature.java [new file with mode: 0755]
src/jalview/datamodel/SequenceGroup.java [new file with mode: 0755]
src/jalview/datamodel/SequenceI.java [new file with mode: 0755]
src/jalview/datamodel/SequenceNode.java [new file with mode: 0755]
src/jalview/datamodel/SequencePoint.java [new file with mode: 0755]
src/jalview/gui/AlignFrame.java [new file with mode: 0755]
src/jalview/gui/AlignViewport.java [new file with mode: 0755]
src/jalview/gui/AlignmentPanel.java [new file with mode: 0755]
src/jalview/gui/BlockRenderer.java [new file with mode: 0755]
src/jalview/gui/ColourKey.java [new file with mode: 0755]
src/jalview/gui/ColumnSelection.java [new file with mode: 0755]
src/jalview/gui/CpGRenderer.java [new file with mode: 0755]
src/jalview/gui/CutAndPasteTransfer.java [new file with mode: 0755]
src/jalview/gui/Desktop.java [new file with mode: 0755]
src/jalview/gui/DrawableSequence.java [new file with mode: 0755]
src/jalview/gui/FeatureRenderer.java [new file with mode: 0755]
src/jalview/gui/GraphRenderer.java [new file with mode: 0755]
src/jalview/gui/IdCanvas.java [new file with mode: 0755]
src/jalview/gui/IdPanel.java [new file with mode: 0755]
src/jalview/gui/PCAPanel.java [new file with mode: 0755]
src/jalview/gui/PaintRefresher.java [new file with mode: 0755]
src/jalview/gui/PairwiseAlignPanel.java [new file with mode: 0755]
src/jalview/gui/RendererI.java [new file with mode: 0755]
src/jalview/gui/RotatableCanvas.java [new file with mode: 0755]
src/jalview/gui/ScaleCanvas.java [new file with mode: 0755]
src/jalview/gui/ScalePanel.java [new file with mode: 0755]
src/jalview/gui/ScorePanel.java [new file with mode: 0755]
src/jalview/gui/Selection.java [new file with mode: 0755]
src/jalview/gui/SeqCanvas.java [new file with mode: 0755]
src/jalview/gui/SeqPanel.java [new file with mode: 0755]
src/jalview/gui/SequenceRenderer.java [new file with mode: 0755]
src/jalview/gui/TreeCanvas.java [new file with mode: 0755]
src/jalview/gui/TreePanel.java [new file with mode: 0755]
src/jalview/gui/UserDefinedColours.java [new file with mode: 0755]
src/jalview/io/AlignFile.java [new file with mode: 0755]
src/jalview/io/BLCFile.java [new file with mode: 0755]
src/jalview/io/ClustalFile.java [new file with mode: 0755]
src/jalview/io/FastaFile.java [new file with mode: 0755]
src/jalview/io/FileParse.java [new file with mode: 0755]
src/jalview/io/FileProperties.java [new file with mode: 0755]
src/jalview/io/FormatAdapter.java [new file with mode: 0755]
src/jalview/io/FormatFactory.java [new file with mode: 0755]
src/jalview/io/FormatProperties.java [new file with mode: 0755]
src/jalview/io/FormatProperty.java [new file with mode: 0755]
src/jalview/io/FormatPropertyVector.java [new file with mode: 0755]
src/jalview/io/HTMLOutput.java [new file with mode: 0755]
src/jalview/io/IdentifyFile.java [new file with mode: 0755]
src/jalview/io/MSFfile.java [new file with mode: 0755]
src/jalview/io/OutputGenerator.java [new file with mode: 0755]
src/jalview/io/PIRFile.java [new file with mode: 0755]
src/jalview/io/PfamFile.java [new file with mode: 0755]
src/jalview/io/PostscriptProperties.java [new file with mode: 0755]
src/jalview/io/SequenceFeatureSourceI.java [new file with mode: 0755]
src/jalview/jbgui/GAlignFrame.java [new file with mode: 0755]
src/jalview/jbgui/GAlignmentPanel.java [new file with mode: 0755]
src/jalview/jbgui/GColourKey.java [new file with mode: 0755]
src/jalview/jbgui/GCutAndPasteTransfer.java [new file with mode: 0755]
src/jalview/jbgui/GDesktop.java [new file with mode: 0755]
src/jalview/jbgui/GPCAPanel.java [new file with mode: 0755]
src/jalview/jbgui/GPairwiseAlignPanel.java [new file with mode: 0755]
src/jalview/jbgui/GTreePanel.java [new file with mode: 0755]
src/jalview/jbgui/GUserDefinedColours.java [new file with mode: 0755]
src/jalview/math/Matrix.java [new file with mode: 0755]
src/jalview/math/RotatableMatrix.java [new file with mode: 0755]
src/jalview/schemes/Blosum62ColourScheme.java [new file with mode: 0755]
src/jalview/schemes/BuriedColourScheme.java [new file with mode: 0755]
src/jalview/schemes/ClustalxColourScheme.java [new file with mode: 0755]
src/jalview/schemes/ColourProperties.java [new file with mode: 0755]
src/jalview/schemes/ColourSchemeFactory.java [new file with mode: 0755]
src/jalview/schemes/ColourSchemeI.java [new file with mode: 0755]
src/jalview/schemes/ColourSchemeProperty.java [new file with mode: 0755]
src/jalview/schemes/ColourSchemePropertyVector.java [new file with mode: 0755]
src/jalview/schemes/HelixColourScheme.java [new file with mode: 0755]
src/jalview/schemes/HydrophobicColourScheme.java [new file with mode: 0755]
src/jalview/schemes/PIDColourScheme.java [new file with mode: 0755]
src/jalview/schemes/ResidueColourScheme.java [new file with mode: 0755]
src/jalview/schemes/ResidueProperties.java [new file with mode: 0755]
src/jalview/schemes/ScoreColourScheme.java [new file with mode: 0755]
src/jalview/schemes/SecondaryColourScheme.java [new file with mode: 0755]
src/jalview/schemes/StrandColourScheme.java [new file with mode: 0755]
src/jalview/schemes/TaylorColourScheme.java [new file with mode: 0755]
src/jalview/schemes/TurnColourScheme.java [new file with mode: 0755]
src/jalview/schemes/UserColourScheme.java [new file with mode: 0755]
src/jalview/schemes/ZappoColourScheme.java [new file with mode: 0755]
src/jalview/util/BrowserLauncher.java [new file with mode: 0755]
src/jalview/util/Comparison.java [new file with mode: 0755]
src/jalview/util/ErrorLog.java [new file with mode: 0755]
src/jalview/util/Format.java [new file with mode: 0755]
src/jalview/util/Format.save [new file with mode: 0755]
src/jalview/util/ListenList.java [new file with mode: 0755]
src/jalview/util/QuickSort.java [new file with mode: 0755]
src/jalview/util/WindowUtil.java [new file with mode: 0755]

diff --git a/BartonGroupBanner.gif b/BartonGroupBanner.gif
new file mode 100755 (executable)
index 0000000..6b0b6e2
Binary files /dev/null and b/BartonGroupBanner.gif differ
diff --git a/JalviewX.jpx b/JalviewX.jpx
new file mode 100755 (executable)
index 0000000..4179212
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--JBuilder XML Project-->\r
+<project>\r
+  <property category="debug.0" name="SmartStepRedefineClasses" value="0"/>\r
+  <property category="debug.0" name="SmartStepSkipStaticInitializers" value="0"/>\r
+  <property category="debug.0" name="SmartStepSkipSynthetics" value="0"/>\r
+  <property category="javaFormatting" name="EventStyle" value="0"/>\r
+  <property category="javaFormatting" name="classBraceNextLine" value="1"/>\r
+  <property category="javaFormatting" name="methodBraceNextLine" value="1"/>\r
+  <property category="javaFormatting" name="otherBraceNextLine" value="1"/>\r
+  <property category="javaFormatting" name="throwsOnNewLine" value="1"/>\r
+  <property category="javadoc" name="custom.tags.1" value="todo;a;To Do:"/>\r
+  <property category="optimize.0" name="OptimizableType" value="com.borland.jbuilder.optimize.IntroOptimizeitProfiler"/>\r
+  <property category="personality" name="personality" value=""/>\r
+  <property category="runtime" name="DefaultConfiguration" value="-1"/>\r
+  <property category="runtime.0" name="BuildTargetOnRun" value="com.borland.jbuilder.build.ProjectBuilder$ProjectBuildAction;make"/>\r
+  <property category="runtime.0" name="ConfigurationName" value="From the top"/>\r
+  <property category="runtime.0" name="ExclusionFilter" value="3"/>\r
+  <property category="runtime.0" name="RunnableType" value="com.borland.jbuilder.runtime.ApplicationRunner"/>\r
+  <property category="runtime.0" name="application.class" value="jalview.bin.Jalview"/>\r
+  <property category="runtime.0" name="application.parameters" value="C:\JalviewX\fasta"/>\r
+  <property category="serverservices" name="single.server.name" value="Tomcat 4.0"/>\r
+  <property category="sys" name="AuthorLabel" value="@author"/>\r
+  <property category="sys" name="BackupPath" value="bak"/>\r
+  <property category="sys" name="CheckStable" value="1"/>\r
+  <property category="sys" name="Company" value="Dundee University"/>\r
+  <property category="sys" name="CompanyLabel" value="Company:"/>\r
+  <property category="sys" name="Copyright" value="Copyright (c) 2004"/>\r
+  <property category="sys" name="CopyrightLabel" value="Copyright:"/>\r
+  <property category="sys" name="DefaultPath" value="src"/>\r
+  <property category="sys" name="Description" value="Jalview Re-engineered"/>\r
+  <property category="sys" name="DescriptionLabel" value="Description:"/>\r
+  <property category="sys" name="DocPath" value="doc"/>\r
+  <property category="sys" name="ExcludeClassEnabled" value="0"/>\r
+  <property category="sys" name="IncludeTestPath" value="1"/>\r
+  <property category="sys" name="InstanceVisibility" value="2"/>\r
+  <property category="sys" name="JDK" value="java version 1.4.2_01-b06"/>\r
+  <property category="sys" name="JvmVersion" value="1.2"/>\r
+  <property category="sys" name="LastTag" value="0"/>\r
+  <property category="sys" name="Libraries" value=""/>\r
+  <property category="sys" name="MakeStable" value="0"/>\r
+  <property category="sys" name="OutPath" value="classes"/>\r
+  <property category="sys" name="SourcePath" value="src;test"/>\r
+  <property category="sys" name="TestPath" value="test"/>\r
+  <property category="sys" name="Title" value="JalviewX"/>\r
+  <property category="sys" name="TitleLabel" value="Title:"/>\r
+  <property category="sys" name="Version" value="1.0"/>\r
+  <property category="sys" name="VersionLabel" value="@version"/>\r
+  <property category="sys" name="WorkingDirectory" value="."/>\r
+  <property category="sys" name="uidesign.size.jalview.gimp.GCutAndPasteTransfer" value="400,436"/>\r
+  <property category="sys" name="uidesign.size.jalview.gimp.GUserDefinedColours" value="464,485"/>\r
+  <property category="sys" name="uidesign.size.jalview.gui.GAlignmentPanel" value="573,436"/>\r
+  <property category="sys" name="uidesign.size.jalview.gui.GColorKey" value="442,252"/>\r
+  <property category="sys" name="uidesign.size.jalview.gui.GColourKey" value="400,400"/>\r
+  <property category="sys" name="uidesign.size.jalview.gui.GCutAndPasteTransfer" value="400,300"/>\r
+  <property category="sys" name="uidesign.size.jalview.gui.GTreePanel" value="529,329"/>\r
+  <property category="sys" name="uidesign.size.jalview.gui.GUserDefinedColours" value="447,499"/>\r
+  <property category="sys" name="uidesign.size.jalview.gui.TreePanel" value="402,303"/>\r
+</project>\r
diff --git a/src/jalview/analysis/AAFrequency.java b/src/jalview/analysis/AAFrequency.java
new file mode 100755 (executable)
index 0000000..c8e6388
--- /dev/null
@@ -0,0 +1,383 @@
+package jalview.analysis;\r
+\r
+import jalview.jbgui.*;\r
+import jalview.datamodel.*;\r
+import jalview.io.*;\r
+import jalview.analysis.*;\r
+\r
+import java.awt.*;\r
+import java.applet.Applet;\r
+import java.util.*;\r
+import java.net.*;\r
+import java.io.*;\r
+\r
+public class AAFrequency {\r
+\r
+    // Takes in a vector of sequences and column start and column end\r
+    // and returns a vector of size (end-start+1). Each element of the\r
+    // vector contains a hashtable with the keys being residues and\r
+    // the values being the count of each residue in that column.\r
+    // This class is used extensively in calculating alignment colourschemes\r
+    // that depend on the amount of conservation in each alignment column.\r
+\r
+    public static Vector calculate(Vector sequences,int start,int end) {\r
+\r
+    Vector result = new Vector();\r
+\r
+    for (int i = start;i <= end; i++)\r
+    {\r
+\r
+      Hashtable residueHash = new Hashtable();\r
+      int       maxCount    = -1;\r
+      String    maxResidue  = "-";\r
+      int       nongap      = 0;\r
+      for (int j=0; j < sequences.size(); j++)\r
+      {\r
+\r
+        if (sequences.elementAt(j) instanceof Sequence)\r
+        {\r
+          Sequence s = (Sequence)sequences.elementAt(j);\r
+\r
+          if (s.getSequence().length() > i)\r
+          {\r
+\r
+            String res = s.getSequence().substring(i,i+1);\r
+\r
+            if (!res.equals("-"))\r
+              nongap++;\r
+\r
+            if (residueHash.containsKey(res))\r
+            {\r
+\r
+              int count = ((Integer)residueHash.get(res)).intValue() ;\r
+              count++;\r
+\r
+             if (!res.equals("-") && count >= maxCount)\r
+              {\r
+\r
+                  if(count>maxCount)\r
+                      maxResidue = res;\r
+                  else if(maxResidue.indexOf(res)==-1)\r
+                      maxResidue += res;\r
+\r
+                  maxCount = count;\r
+             }\r
+\r
+              residueHash.put(res,new Integer(count));\r
+            }\r
+            else\r
+              residueHash.put(res,new Integer(1));\r
+\r
+\r
+          }\r
+          else\r
+          {\r
+            if (residueHash.containsKey("-"))\r
+            {\r
+              int count = ((Integer)residueHash.get("-")).intValue() ;\r
+              count++;\r
+              residueHash.put("-",new Integer(count));\r
+            }\r
+            else\r
+              residueHash.put("-",new Integer(1));\r
+\r
+          }\r
+        }\r
+      }\r
+      residueHash.put("maxCount",new Integer(maxCount));\r
+      residueHash.put("maxResidue", maxResidue);\r
+      residueHash.put("size", new Integer(sequences.size()));\r
+      residueHash.put("nongap", new Integer(nongap));\r
+      result.addElement(residueHash);\r
+    }\r
+\r
+    return result;\r
+  }\r
+\r
+    public static Vector calculatePID(SequenceI refseq,Vector sequences,int window,int start,int end) {\r
+\r
+    Vector result = new Vector();\r
+\r
+    boolean init = true;\r
+\r
+\r
+    Vector prev = null;\r
+\r
+    for (int i = start;i <= end; i++) {\r
+       Vector values = new Vector();\r
+\r
+       result.addElement(values);\r
+\r
+       // If start < window/2 then set value to zero.\r
+\r
+       if (i< window/2 || i >= refseq.getSequence().length()-window/2) {\r
+           for (int j = 0; j < sequences.size(); j++) {\r
+               values.addElement(new Integer(0));\r
+           }\r
+       } else  if (init == true) {\r
+           init = false;\r
+\r
+           int winstart = i-window/2;\r
+           int winend   = i+window/2;\r
+\r
+            if (window%2 != 0) {\r
+              winend++;\r
+            }\r
+\r
+           for (int j = 0; j < sequences.size(); j++) {\r
+               values.addElement(new Integer(0));\r
+           }\r
+\r
+           for (int k = winstart; k <= winend; k++) {\r
+               String refchar = refseq.getSequence().substring(k,k+1);\r
+\r
+               for (int j = 0; j < sequences.size(); j++) {\r
+\r
+                   if (refchar.equals("-") == false) {\r
+\r
+                       Sequence s = (Sequence)sequences.elementAt(j);\r
+\r
+                       if (s.getSequence().length() > k) {\r
+\r
+                           String res = s.getSequence().substring(k,k+1);\r
+\r
+                           if (res.equals(refchar)) {\r
+                               int val = ((Integer)values.elementAt(j)).intValue();\r
+                               val++;\r
+                               values.setElementAt(new Integer(val),j);\r
+                           }\r
+                       }\r
+                   }\r
+               }\r
+           }\r
+           prev = values;\r
+       } else {\r
+           int winstart = i-window/2;\r
+           int winend   = i+window/2;\r
+\r
+            if (window%2 != 0) {\r
+              winend++;\r
+            }\r
+           // We need to take the previous set of values\r
+           // subtract the pid at winstart-1\r
+           // and add the pid at winend;\r
+\r
+           String pre_refchar  = refseq.getSequence().substring(winstart-1,winstart);\r
+            String pos_refchar = "-";\r
+\r
+            if (refseq.getSequence().length() > winend) {\r
+             pos_refchar  = refseq.getSequence().substring(winend,winend+1);\r
+            }\r
+\r
+           for (int j = 0; j < sequences.size(); j++) {\r
+               // First copy the pid value from i-1\r
+\r
+               int val = ((Integer)prev.elementAt(j)).intValue();\r
+\r
+               Sequence s = (Sequence)sequences.elementAt(j);\r
+\r
+               String pre_char = s.getSequence().substring(winstart-1,winstart);\r
+\r
+                String pos_char = "-";\r
+\r
+                if (s.getSequence().length() > winend) {\r
+                 pos_char = s.getSequence().substring(winend,winend+1);\r
+                }\r
+\r
+               // Now substract 1 if the chars at winstart-1 match\r
+\r
+               if (pre_refchar.equals("-") == false && pre_char.equals(pre_refchar)) {\r
+                   val--;\r
+               }\r
+\r
+               if (pos_refchar.equals("-") == false && pos_char.equals(pos_refchar)) {\r
+                   val++;\r
+               }\r
+\r
+               values.addElement(new Integer(val));\r
+\r
+\r
+           }\r
+           prev = values;\r
+       }\r
+    }\r
+\r
+    return result;\r
+    }\r
+\r
+    public static Hashtable findBlocks(Vector seqs, int start, int end,Vector exc) {\r
+\r
+       // start and end are in real (not relative coords);\r
+\r
+       // The coords in the hashtable that is returned are in relative coords\r
+       // i.e. start from 0\r
+\r
+       Hashtable blocks = new Hashtable();\r
+\r
+       boolean prev = false;\r
+       int     bstart = -1;\r
+\r
+       for (int i = start; i <= end ; i++) {\r
+           SequenceI seq = (SequenceI)seqs.elementAt(0);\r
+\r
+           char      c   = seq.getCharAt(i);\r
+\r
+           boolean found = true;\r
+\r
+           int j = 1;\r
+\r
+           while (j < seqs.size() && found == true) {\r
+\r
+               SequenceI jseq  = (SequenceI)seqs.elementAt(j);\r
+\r
+               if (!exc.contains(jseq)) {\r
+\r
+                   char cc = jseq.getCharAt(i);\r
+\r
+                   if ( cc != c) {\r
+                       found = false;\r
+                   }\r
+               }\r
+               j++;\r
+           }\r
+\r
+\r
+           if (prev == false && found == true) {\r
+               bstart = i;\r
+           } else if (prev == true && found == false && bstart != -1) {\r
+\r
+               int blockstart = bstart-start;\r
+               int blocklen   = i-bstart;\r
+\r
+               //System.out.println("Start len " + blockstart + " " + blocklen);\r
+\r
+               for (int jj = blockstart; jj < blockstart + blocklen;jj++) {\r
+                   blocks.put(new Integer(jj),new Integer(blocklen));\r
+               }\r
+\r
+               bstart = -1;\r
+           }\r
+           prev = found;\r
+       }\r
+\r
+       if (bstart != -1) {\r
+\r
+           int blockstart = bstart-start;\r
+           int blocklen   = end-bstart;\r
+\r
+         //  System.out.println("Start len " + blockstart + " " + blocklen);\r
+\r
+           for (int jj = blockstart; jj < blockstart + blocklen;jj++) {\r
+               blocks.put(new Integer(blockstart),new Integer(blocklen));\r
+           }\r
+\r
+       }\r
+       return blocks;\r
+    }\r
+\r
+\r
+\r
+    public static Hashtable findKmerCount(SequenceI seq, int start, int end,int window, int step,Vector kmers) {\r
+\r
+       int tmpstart = start;\r
+       Hashtable vals = new Hashtable();\r
+\r
+       while (tmpstart <= end) {\r
+\r
+           String tmpstr = seq.getSequence().substring(tmpstart-window/2,tmpstart+window/2);\r
+\r
+           int count = 0;\r
+\r
+           //System.out.println("Str " + tmpstr);\r
+\r
+          for (int ii = 0; ii < kmers.size(); ii++) {\r
+              String kmer = ((SequenceI)kmers.elementAt(ii)).getSequence();\r
+\r
+              int i = -1;\r
+\r
+              while (tmpstr.indexOf(kmer,i) != -1) {\r
+               i = tmpstr.indexOf(kmer,i);\r
+\r
+               i++;\r
+               count++;\r
+              }\r
+              ii++;\r
+          }\r
+           vals.put(new Integer(tmpstart),new Integer(count));\r
+           tmpstart += step;\r
+       }\r
+       return vals;\r
+    }\r
+\r
+    public static Hashtable findBlockStarts(Vector seqs, int start, int end,Vector exc) {\r
+\r
+       // start and end are in real (not relative coords);\r
+\r
+       // The coords in the hashtable that is returned are in relative coords\r
+       // i.e. start from 0\r
+\r
+       Hashtable blocks = new Hashtable();\r
+\r
+       boolean prev = false;\r
+       int     bstart = -1;\r
+\r
+       for (int i = start; i <= end ; i++) {\r
+           SequenceI seq = (SequenceI)seqs.elementAt(0);\r
+\r
+           char      c   = seq.getCharAt(i);\r
+\r
+           boolean found = true;\r
+\r
+           int j = 1;\r
+\r
+           while (j < seqs.size() && found == true) {\r
+\r
+               SequenceI jseq  = (SequenceI)seqs.elementAt(j);\r
+\r
+               if (!exc.contains(jseq)) {\r
+\r
+                   char cc = jseq.getCharAt(i);\r
+\r
+                   if ( cc != c) {\r
+                       found = false;\r
+                   }\r
+               }\r
+               j++;\r
+           }\r
+\r
+\r
+           if (prev == false && found == true) {\r
+               bstart = i;\r
+           } else if (prev == true && found == false && bstart != -1) {\r
+\r
+               int blockstart = bstart-start;\r
+               int blocklen   = i-bstart;\r
+\r
+               //              System.out.println("Start len " + blockstart + " " + blocklen);\r
+\r
+               //for (int jj = blockstart; jj < blockstart + blocklen;jj++) {\r
+                   blocks.put(new Integer(blockstart),new Integer(blocklen));\r
+       //      }\r
+\r
+               bstart = -1;\r
+           }\r
+           prev = found;\r
+       }\r
+\r
+       if (bstart != -1) {\r
+\r
+           int blockstart = bstart-start;\r
+           int blocklen   = end-bstart;\r
+\r
+         //  System.out.println("Start len " + blockstart + " " + blocklen);\r
+\r
+           //for (int jj = blockstart; jj < blockstart + blocklen;jj++) {\r
+               blocks.put(new Integer(blockstart),new Integer(blocklen));\r
+          // }\r
+\r
+       }\r
+       return blocks;\r
+    }\r
+\r
+}\r
+\r
diff --git a/src/jalview/analysis/AlignSeq.java b/src/jalview/analysis/AlignSeq.java
new file mode 100755 (executable)
index 0000000..81874e0
--- /dev/null
@@ -0,0 +1,541 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+package jalview.analysis;\r
+\r
+import jalview.schemes.*;\r
+import jalview.datamodel.SequenceI;\r
+import jalview.util.*;\r
+import jalview.io.*;\r
+\r
+import java.util.*;\r
+import java.io.*;\r
+import java.awt.*;\r
+\r
+public class AlignSeq {\r
+\r
+  int[][] score;\r
+  int[][] E;\r
+  int[][] F;\r
+  int[][] traceback;\r
+\r
+  int[] seq1;\r
+  int[] seq2;\r
+\r
+  SequenceI s1;\r
+  SequenceI s2;\r
+\r
+  String s1str;\r
+  String s2str;\r
+\r
+  int maxi;\r
+  int maxj;\r
+\r
+  int[] aseq1;\r
+  int[] aseq2;\r
+\r
+  String astr1 = "";\r
+  String astr2 = "";\r
+\r
+  int seq1start;\r
+  int seq1end;\r
+  int seq2start;\r
+  int seq2end;\r
+\r
+  int count;\r
+\r
+  int maxscore;\r
+  float pid;\r
+  int prev = 0;\r
+\r
+  public static java.util.Hashtable dnaHash = new java.util.Hashtable();\r
+\r
+  static  {\r
+    dnaHash.put("C", new Integer(0));\r
+    dnaHash.put("T", new Integer(1));\r
+    dnaHash.put("A", new Integer(2));\r
+    dnaHash.put("G", new Integer(3));\r
+    dnaHash.put("-", new Integer(4));\r
+  }\r
+\r
+  static String dna[] = {"C","T","A","G","-"};\r
+  static String pep[] = {"A","R","N","D","C","Q","E","G","H","I","L","K","M","F","P","S","T","W","Y","V","B","Z","X","-"};\r
+\r
+  int gapOpen = 120;\r
+  int gapExtend = 20;\r
+\r
+  int lookup[][] = ResidueProperties.getBLOSUM62();\r
+  String intToStr[] = pep;\r
+  int defInt = 23;\r
+\r
+  String output = "";\r
+\r
+  String type;\r
+  Runtime rt;\r
+  public AlignSeq() {}\r
+\r
+  public AlignSeq(SequenceI s1, SequenceI s2,String type) {\r
+    rt  = Runtime.getRuntime();\r
+    SeqInit(s1,s2,type);\r
+  }\r
+\r
+  public int getMaxScore() {\r
+    return maxscore;\r
+  }\r
+\r
+  public int getSeq2Start() {\r
+    return seq2start;\r
+  }\r
+\r
+  public int getSeq2End() {\r
+    return seq2end;\r
+  }\r
+\r
+  public int getSeq1Start() {\r
+    return seq1start;\r
+  }\r
+\r
+  public int getSeq1End() {\r
+    return seq1end;\r
+  }\r
+\r
+  public String getOutput() {\r
+    return output;\r
+  }\r
+\r
+  public String getAStr1() {\r
+    return astr1;\r
+  }\r
+  public String getAStr2() {\r
+    return astr2;\r
+  }\r
+  public int [] getASeq1() {\r
+    return aseq1;\r
+  }\r
+  public int [] getASeq2() {\r
+    return aseq2;\r
+  }\r
+  public SequenceI getS1() {\r
+    return s1;\r
+  }\r
+  public SequenceI getS2() {\r
+    return s2;\r
+  }\r
+\r
+  public void SeqInit(SequenceI s1, SequenceI s2,String type) {\r
+    s1str = extractGaps(".",s1.getSequence());\r
+    s2str = extractGaps(".",s2.getSequence());\r
+    s1str = extractGaps("-",s1str);\r
+    s2str = extractGaps("-",s2str);\r
+    s1str = extractGaps(" ",s1str);\r
+    s2str = extractGaps(" ",s2str);\r
+\r
+    this.s1 = s1;\r
+    this.s2 = s2;\r
+\r
+    this.type = type;\r
+\r
+    if (type.equals("pep")) {\r
+      lookup = ResidueProperties.getBLOSUM62();\r
+      intToStr = pep;\r
+      defInt = 23;\r
+    } else if (type.equals("dna")) {\r
+      lookup = ResidueProperties.getDNA();\r
+      intToStr = dna;\r
+      defInt = 4;\r
+    } else {\r
+      output = output + ("Wrong type = dna or pep only");\r
+      System.exit(0);\r
+    }\r
+\r
+\r
+    //System.out.println("lookuip " + rt.freeMemory() + " "+  rt.totalMemory());\r
+    seq1 = new int[s1str.length()];\r
+    //System.out.println("seq1 " + rt.freeMemory() +" "  + rt.totalMemory());\r
+    seq2 = new int[s2str.length()];\r
+    //System.out.println("seq2 " + rt.freeMemory() + " " + rt.totalMemory());\r
+    score = new int[s1str.length()][s2str.length()];\r
+    //System.out.println("score " + rt.freeMemory() + " " + rt.totalMemory());\r
+    E = new int[s1str.length()][s2str.length()];\r
+    //System.out.println("E " + rt.freeMemory() + " " + rt.totalMemory());\r
+    F = new int[s1str.length()][s2str.length()];\r
+    traceback = new int[s1str.length()][s2str.length()];\r
+    //System.out.println("F " + rt.freeMemory() + " " + rt.totalMemory());\r
+    seq1 = stringToInt(s1str,type);\r
+    //System.out.println("seq1 " + rt.freeMemory() + " " + rt.totalMemory());\r
+    seq2 = stringToInt(s2str,type);\r
+    //System.out.println("Seq2 " + rt.freeMemory() + " " + rt.totalMemory());\r
+\r
+    //   long tstart = System.currentTimeMillis();\r
+    //    calcScoreMatrix();\r
+    //long tend = System.currentTimeMillis();\r
+\r
+    //System.out.println("Time take to calculate score matrix = " + (tend-tstart) + " ms");\r
+\r
+\r
+    //   printScoreMatrix(score);\r
+    //System.out.println();\r
+\r
+    //printScoreMatrix(traceback);\r
+    //System.out.println();\r
+\r
+    //  printScoreMatrix(E);\r
+    //System.out.println();\r
+\r
+    ///printScoreMatrix(F);\r
+    //System.out.println();\r
+    // tstart = System.currentTimeMillis();\r
+    //traceAlignment();\r
+    //tend = System.currentTimeMillis();\r
+    //System.out.println("Time take to traceback alignment = " + (tend-tstart) + " ms");\r
+  }\r
+\r
+  public void traceAlignment() {\r
+\r
+    // Find the maximum score along the rhs or bottom row\r
+    int max = -9999;\r
+    for (int i = 0; i < seq1.length; i++) {\r
+      if (score[i][seq2.length - 1] > max ) {\r
+        max = score[i][seq2.length - 1];\r
+        maxi = i;\r
+        maxj = seq2.length-1;\r
+      }\r
+    }\r
+    for (int j = 0; j < seq2.length; j++) {\r
+      if (score[seq1.length - 1][j] > max ) {\r
+        max = score[seq1.length - 1][j];\r
+        maxi = seq1.length-1;\r
+        maxj = j;\r
+      }\r
+    }\r
+\r
+    //  System.out.println(maxi + " " + maxj + " " + score[maxi][maxj]);\r
+\r
+    int i = maxi;\r
+    int j = maxj;\r
+    int trace;\r
+    maxscore = score[i][j] / 10;\r
+\r
+    seq1end = maxi+1;\r
+    seq2end = maxj+1;\r
+\r
+    aseq1 = new int[seq1.length + seq2.length];\r
+    aseq2 = new int[seq1.length + seq2.length];\r
+\r
+    count = seq1.length + seq2.length - 1;\r
+\r
+    while (i>0 && j >0) {\r
+\r
+      if (aseq1[count] != defInt && i >=0) {\r
+        aseq1[count] = seq1[i];\r
+        astr1 = intToStr[seq1[i]] + astr1;\r
+      }\r
+\r
+      if (aseq2[count] != defInt && j > 0) {\r
+        aseq2[count] = seq2[j];\r
+        astr2 = intToStr[seq2[j]] + astr2;\r
+      }\r
+      trace = findTrace(i,j);\r
+      if (trace == 0) {\r
+        i--;\r
+        j--;\r
+\r
+      } else  if (trace == 1) {\r
+        j--;\r
+        aseq1[count] = defInt;\r
+        astr1 = "-" + astr1.substring(1);\r
+      } else  if (trace == -1) {\r
+        i--;\r
+        aseq2[count] = defInt;\r
+        astr2 = "-" + astr2.substring(1);\r
+      }\r
+      count--;\r
+    }\r
+\r
+    seq1start = i+1;\r
+    seq2start = j+1;\r
+\r
+    if (aseq1[count] != defInt) {\r
+      aseq1[count] = seq1[i];\r
+      astr1 = intToStr[seq1[i]] + astr1;\r
+    }\r
+\r
+    if (aseq2[count] != defInt) {\r
+      aseq2[count] = seq2[j];\r
+      astr2 = intToStr[seq2[j]] + astr2;\r
+    }\r
+  }\r
+\r
+  public void printAlignment() {\r
+    // Find the biggest id length for formatting purposes\r
+    int maxid = s1.getName().length();\r
+\r
+    if (s2.getName().length() > maxid) {\r
+      maxid = s2.getName().length();\r
+    }\r
+\r
+    int len = 72 - maxid - 1;\r
+    int nochunks = ((aseq1.length - count) / len) + 1;\r
+    pid = 0;\r
+    int overlap = 0;\r
+\r
+    output = output + ("Score = " + score[maxi][maxj] + "\n");\r
+    output = output + ("Length of alignment = " + (aseq1.length-count) + "\n");\r
+    output = output + ("Sequence ");\r
+    output = output + (new Format("%" + maxid + "s").form(s1.getName()));\r
+    output = output + (" :  " + seq1start + " - " + seq1end + " (Sequence length = " + s1str.length() + ")\n");\r
+    output = output + ("Sequence ");\r
+    output = output + (new Format("%" + maxid + "s").form(s2.getName()));\r
+    output = output + (" :  " + seq2start + " - " + seq2end + " (Sequence length = " + s2str.length() + ")\n\n");\r
+\r
+    for (int j = 0; j < nochunks; j++) {\r
+      // Print the first aligned sequence\r
+      output = output + (new Format("%" + (maxid) + "s").form(s1.getName()) + " ");\r
+      for (int i = 0; i < len ; i++) {\r
+\r
+        if ((count + i + j*len) < aseq1.length) {\r
+          output = output + (new Format("%s").form(intToStr[aseq1[count + i + j*len]]));\r
+        }\r
+      }\r
+\r
+      output = output + ("\n");\r
+      output = output + (new Format("%" + (maxid) + "s").form(" ") + " ");\r
+      // Print out the matching chars\r
+      for (int i = 0; i < len ; i++) {\r
+\r
+        if ((count + i + j*len) < aseq1.length) {\r
+          if ( intToStr[aseq1[count+i+j*len]].equals(intToStr[aseq2[count+i+j*len]]) && !intToStr[aseq1[count+i+j*len]].equals("-")) {\r
+            pid++;\r
+            output = output + ("|");\r
+          } else if (type.equals("pep")) {\r
+            if (ResidueProperties.getPAM250(intToStr[aseq1[count+i+j*len]],intToStr[aseq2[count+i+j*len]]) > 0) {\r
+              output  = output + (".");\r
+            } else {\r
+              output = output + (" ");\r
+            }\r
+          } else {\r
+            output = output + (" ");\r
+          }\r
+\r
+        }\r
+      }\r
+      // Now print the second aligned sequence\r
+      output = output + ("\n");\r
+      output = output + (new Format("%" + (maxid) + "s").form(s2.getName()) + " " );\r
+      for (int i = 0; i < len ; i++) {\r
+        if ((count + i + j*len) < aseq1.length) {\r
+          output = output + (new Format("%s").form(intToStr[aseq2[count + i + j*len]]));\r
+        }\r
+      }\r
+      output = output + ("\n\n");\r
+    }\r
+    pid = pid/(float)(aseq1.length-count)*100;\r
+    output = output + (new Format("Percentage ID = %2.2f\n\n").form(pid));\r
+\r
+  }\r
+\r
+  public void printScoreMatrix(int[][] mat) {\r
+    int n = seq1.length;\r
+    int m = seq2.length;\r
+\r
+    for (int i = 0; i < n;i++) {\r
+      // Print the top sequence\r
+      if (i == 0) {\r
+        Format.print(System.out,"%8s",s2str.substring(0,1));\r
+        for (int jj = 1;jj < m; jj++) {\r
+          Format.print(System.out,"%5s",s2str.substring(jj,jj+1));\r
+        }\r
+        System.out.println();\r
+      }\r
+\r
+      for (int j = 0;j < m; j++) {\r
+        if (j == 0) {\r
+          Format.print(System.out,"%3s",s1str.substring(i,i+1));\r
+        }\r
+        Format.print(System.out,"%3d ",mat[i][j]/10);\r
+      }\r
+      System.out.println();\r
+    }\r
+  }\r
+\r
+  public int findTrace(int i,int j) {\r
+    int t = 0;\r
+    int max = score[i-1][j-1] + lookup[seq1[i]][seq2[j]] * 10;\r
+\r
+    if (F[i][j] > max) {\r
+      max = F[i][j];\r
+      t = -1;\r
+    } else if (F[i][j] == max) {\r
+      if (prev == -1) {\r
+        max = F[i][j];\r
+        t = -1;\r
+      }\r
+    }\r
+    if (E[i][j] >= max) {\r
+      max = E[i][j];\r
+      t = 1;\r
+    } else if (E[i][j] == max) {\r
+      if (prev == 1) {\r
+        max = E[i][j];\r
+        t = 1;\r
+      }\r
+    }\r
+    prev = t;\r
+    return t;\r
+  }\r
+\r
+  public void calcScoreMatrix() {\r
+\r
+\r
+    int n = seq1.length;\r
+    int m = seq2.length;\r
+\r
+\r
+    // top left hand element\r
+    score[0][0] =  lookup[seq1[0]][seq2[0]] * 10;\r
+    E[0][0] = -gapExtend;\r
+    F[0][0] = 0;\r
+\r
+    // Calculate the top row first\r
+    for (int j=1; j < m; j++) {\r
+      // What should these values be? 0 maybe\r
+      E[0][j] = max(score[0][j-1] - gapOpen,E[0][j-1] - gapExtend);\r
+      F[0][j] = -gapExtend;\r
+\r
+      score[0][j] = max( lookup[seq1[0]][seq2[j]] * 10 ,-gapOpen,-gapExtend);\r
+\r
+      traceback[0][j] = 1;\r
+    }\r
+\r
+    // Now do the left hand column\r
+    for (int i=1; i < n; i++) {\r
+      E[i][0] =  -gapOpen;\r
+      F[i][0] =  max(score[i-1][0]-gapOpen,F[i-1][0]-gapExtend);\r
+\r
+      score[i][0] = max( lookup[seq1[i]][seq2[0]] * 10 ,E[i][0],F[i][0]);\r
+      traceback[i][0] = -1;\r
+    }\r
+\r
+    // Now do all the other rows\r
+    for (int i = 1; i < n; i++) {\r
+      for (int j = 1; j < m; j++) {\r
+\r
+        E[i][j] = max(score[i][j-1] - gapOpen,  E[i][j-1] - gapExtend);\r
+        F[i][j] = max(score[i-1][j] - gapOpen,  F[i-1][j] - gapExtend);\r
+\r
+        score[i][j] = max(score[i-1][j-1] + lookup[seq1[i]][seq2[j]]*10,\r
+                          E[i][j],\r
+                          F[i][j]);\r
+        traceback[i][j] = findTrace(i,j);\r
+      }\r
+    }\r
+\r
+  }\r
+  public static String extractChars(String chars, String seq) {\r
+    String out = seq;\r
+    for (int i=0; i < chars.length(); i++) {\r
+      String gap = chars.substring(i,i+1);\r
+      out = extractGaps(gap,out);\r
+    }\r
+    return out;\r
+  }\r
+  public static String extractGaps(String gapChar, String seq) {\r
+    StringTokenizer str = new StringTokenizer(seq,gapChar);\r
+    String newString = "";\r
+\r
+    while (str.hasMoreTokens()) {\r
+      newString  = newString + str.nextToken();\r
+    }\r
+    return newString;\r
+  }\r
+\r
+\r
+  public int max(int i1, int i2, int i3) {\r
+    int max = i1;\r
+    if (i2 > i1)  {\r
+      max = i2;\r
+    }\r
+    if (i3 > max) {\r
+      max = i3;\r
+    }\r
+    return max;\r
+  }\r
+\r
+  public int max(int i1, int i2) {\r
+    int max = i1;\r
+    if (i2 > i1)  {\r
+      max = i2;\r
+    }\r
+    return max;\r
+  }\r
+\r
+  public int[] stringToInt(String s,String type) {\r
+    int[] seq1 = new int[s.length()];\r
+\r
+    for (int i = 0;i < s.length(); i++) {\r
+      String ss = s.substring(i,i+1).toUpperCase();\r
+      try {\r
+        if (type.equals("pep")) {\r
+          seq1[i] = ((Integer)ResidueProperties.aaHash.get(ss)).intValue();\r
+        } else if (type.equals("dna")) {\r
+          seq1[i] = ((Integer)dnaHash.get(ss)).intValue();\r
+        }\r
+        if (seq1[i] > 23) {\r
+          seq1[i] = 23;\r
+        }\r
+      } catch (Exception e) {\r
+        if (type.equals("dna")) {\r
+          seq1[i] = 4;\r
+        } else {\r
+          seq1[i] = 23;\r
+        }\r
+      }\r
+    }\r
+    return seq1;\r
+  }\r
+\r
+  public static void displayMatrix(Graphics g, int[][] mat, int n, int m,int psize) {\r
+\r
+    int max = -1000;\r
+    int min = 1000;\r
+\r
+    for (int i=0; i < n; i++) {\r
+      for (int j=0; j < m; j++) {\r
+        if (mat[i][j] >= max) {\r
+          max = mat[i][j];\r
+        }\r
+        if (mat[i][j] <= min) {\r
+          min = mat[i][j];\r
+        }\r
+      }\r
+    }\r
+    System.out.println(max + " " + min);\r
+    for (int i=0; i < n; i++) {\r
+      for (int j=0; j < m; j++) {\r
+        int x = psize*i;\r
+        int y = psize*j;\r
+        //     System.out.println(mat[i][j]);\r
+        float score = (float)(mat[i][j] - min)/(float)(max-min);\r
+        g.setColor(new Color(score,0,0));\r
+        g.fillRect(x,y,psize,psize);\r
+        //     System.out.println(x + " " + y + " " + score);\r
+      }\r
+\r
+    }\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/analysis/AlignmentSorter.java b/src/jalview/analysis/AlignmentSorter.java
new file mode 100755 (executable)
index 0000000..3881266
--- /dev/null
@@ -0,0 +1,181 @@
+package jalview.analysis;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+import jalview.io.*;\r
+\r
+import java.util.*;\r
+\r
+/** Data structure to hold and manipulate a multiple sequence alignment\r
+ */\r
+public class AlignmentSorter {\r
+\r
+  private AlignmentSorter() {\r
+  }\r
+\r
+  public static void sortGroups(AlignmentI align) {\r
+    Vector groups = align.getGroups();\r
+    int    nGroup = groups.size();\r
+\r
+    float[]  arr = new float [nGroup];\r
+    Object[] s   = new Object[nGroup];\r
+\r
+    for (int i=0; i < nGroup; i++) {\r
+      arr[i] = ((SequenceGroup)groups.elementAt(i)).getSize();\r
+      s[i]   = groups.elementAt(i);\r
+    }\r
+\r
+    QuickSort.sort(arr,s);\r
+\r
+    Vector newg = new Vector(nGroup);\r
+\r
+    for (int i=nGroup-1; i >= 0; i--) {\r
+      newg.addElement(s[i]);\r
+    }\r
+\r
+    //    align.setGroups(newg);\r
+  }\r
+\r
+  /**    */\r
+  public static void sortByPID(AlignmentI align, SequenceI s) {\r
+    int nSeq = align.getHeight();\r
+\r
+    float     scores[] = new float[nSeq];\r
+    SequenceI seqs[]   = new SequenceI[nSeq];\r
+\r
+    for (int i = 0; i < nSeq; i++) {\r
+      scores[i] = Comparison.compare(align.getSequenceAt(i),s);\r
+      seqs[i]   = align.getSequenceAt(i);\r
+    }\r
+\r
+    QuickSort.sort(scores,0,scores.length-1,seqs);\r
+\r
+   setReverseOrder(align,seqs);\r
+  }\r
+\r
+  private static void setReverseOrder(AlignmentI align, SequenceI [] seqs) {\r
+    int nSeq = seqs.length;\r
+\r
+    int len = 0;\r
+    if (nSeq%2 == 0) {\r
+      len = nSeq/2;\r
+    } else {\r
+      len = (nSeq+1)/2;\r
+    }\r
+\r
+// NOTE: DO NOT USE align.setSequenceAt() here - it will NOT work\r
+    for (int i = 0; i < len; i++) {\r
+      //SequenceI tmp = seqs[i];\r
+      align.getSequences().setElementAt(seqs[nSeq-i-1],i);\r
+      align.getSequences().setElementAt(seqs[i],nSeq-i-1);\r
+    }\r
+  }\r
+\r
+  private static void setOrder(AlignmentI align, Vector tmp) {\r
+    setOrder(align,vectorToArray(tmp));\r
+  }\r
+\r
+  private static void setOrder(AlignmentI align, SequenceI [] seqs) {\r
+// NOTE: DO NOT USE align.setSequenceAt() here - it will NOT work\r
+    for (int i = 0; i < seqs.length; i++) {\r
+      align.getSequences().setElementAt(seqs[i],i);\r
+    }\r
+  }\r
+\r
+  /**    */\r
+  public static void sortByID(AlignmentI align) {\r
+    int nSeq = align.getHeight();\r
+\r
+    String    ids[]   = new String[nSeq];\r
+    SequenceI seqs[]  = new SequenceI[nSeq];\r
+\r
+    for (int i = 0; i < nSeq; i++) {\r
+      ids[i]  = align.getSequenceAt(i).getName();\r
+      seqs[i] = align.getSequenceAt(i);\r
+    }\r
+\r
+    QuickSort.sort(ids,seqs);\r
+\r
+    setReverseOrder(align,seqs);\r
+  }\r
+\r
+  public static void sortByGroup(AlignmentI align) {\r
+    int    nSeq = align.getHeight();\r
+    Vector groups = align.getGroups();\r
+\r
+    Vector seqs = new Vector();\r
+\r
+    for (int i=0; i < groups.size(); i++) {\r
+      SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
+\r
+      for (int j = 0; j < sg.getSize(); j++) {\r
+        seqs.addElement(sg.getSequenceAt(j));\r
+      }\r
+    }\r
+\r
+    if (seqs.size() != nSeq) {\r
+      System.err.println("ERROR: tmp.size() != nseq in sortByGroups");\r
+      if (seqs.size() < nSeq) {\r
+        addStrays(align,seqs);\r
+      }\r
+    }\r
+\r
+    setOrder(align,seqs);\r
+  }\r
+\r
+  private static SequenceI [] vectorToArray(Vector tmp) {\r
+    SequenceI[] seqs = new SequenceI[tmp.size()];\r
+\r
+    for (int i=0; i < tmp.size(); i++) {\r
+      seqs[i] = (SequenceI)tmp.elementAt(i);\r
+    }\r
+    return seqs;\r
+  }\r
+\r
+  public static void sortByTree(AlignmentI align, NJTree tree) {\r
+    int    nSeq = align.getHeight();\r
+\r
+    Vector tmp = new Vector();\r
+\r
+    tmp = _sortByTree(tree.getTopNode(),tmp);\r
+\r
+    if (tmp.size() != nSeq) {\r
+      System.err.println("ERROR: tmp.size() != nseq in sortByTree");\r
+      if (tmp.size() < nSeq) {\r
+        addStrays(align,tmp);\r
+      }\r
+    }\r
+\r
+    setOrder(align,tmp);\r
+  }\r
+\r
+  private static void addStrays(AlignmentI align, Vector seqs) {\r
+    int    nSeq = align.getHeight();\r
+    for (int i=0;i<nSeq;i++) {\r
+      if (!seqs.contains(align.getSequenceAt(i))) {\r
+        seqs.addElement(align.getSequenceAt(i));\r
+      }\r
+    }\r
+    if (nSeq != seqs.size()) {\r
+      System.err.println("ERROR: Size still not right even after addStrays");\r
+    }\r
+  }\r
+\r
+  public static Vector _sortByTree(SequenceNode node, Vector tmp) {\r
+    if (node == null) {return tmp;}\r
+\r
+    SequenceNode left = (SequenceNode)node.left();\r
+    SequenceNode right = (SequenceNode)node.right();\r
+\r
+    if (left == null && right == null) {\r
+      if (node.element() instanceof SequenceI) {\r
+        tmp.addElement((SequenceI)node.element());\r
+        return tmp;\r
+      }\r
+    } else {\r
+      _sortByTree(left,tmp);\r
+      _sortByTree(right,tmp);\r
+    }\r
+    return tmp;\r
+  }\r
+}\r
diff --git a/src/jalview/analysis/AlignmentUtil.java b/src/jalview/analysis/AlignmentUtil.java
new file mode 100755 (executable)
index 0000000..5a773a0
--- /dev/null
@@ -0,0 +1,229 @@
+package jalview.analysis;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.io.*;\r
+import jalview.util.*;\r
+\r
+import java.util.*;\r
+\r
+public class AlignmentUtil {\r
+\r
+  private AlignmentUtil() {\r
+  }\r
+\r
+  public static int[][] percentIdentity2(AlignmentI align) {\r
+    return percentIdentity2(align,0,align.getWidth()-1);\r
+  }\r
+\r
+  public static int[][] percentIdentity2(AlignmentI align, int start, int end) {\r
+    int [][] cons2 = new int[align.getWidth()][24];\r
+    // Initialize the array\r
+    for (int j=0;j<24;j++) {\r
+      for (int i=0; i < align.getWidth();i++) {\r
+        cons2[i][j] = 0;\r
+      }\r
+    }\r
+\r
+    return cons2;\r
+  }\r
+  public static int getPixelHeight(int i, int j,int charHeight) {\r
+    int h=0;\r
+    while (i < j) {\r
+      h += charHeight;\r
+      i++;\r
+    }\r
+    return h;\r
+  }\r
+\r
+\r
+    public static Vector substitution_rates (AlignmentI align, int start, int end) {\r
+\r
+       Vector rates = new Vector();\r
+\r
+       int len = (end-start+1);\r
+\r
+       // Turn seqs into char arrays\r
+\r
+       int[][] seqint = new int[align.getHeight()][len];\r
+\r
+\r
+       for (int j = 0; j < align.getHeight(); j++) {\r
+\r
+           SequenceI seq = align.getSequenceAt(j);\r
+\r
+           for (int i = 0 ; i < len; i++) {\r
+               char c = seq.getCharAt(start + i - 1);\r
+\r
+               if (c == 'A') {\r
+                   seqint[j][i] = 0;\r
+               } else if (c == 'C') {\r
+                   seqint[j][i] = 1;\r
+               } else if (c == 'T') {\r
+                   seqint[j][i] = 2;\r
+               } else if (c == 'G') {\r
+                   seqint[j][i] = 3;\r
+               } else {\r
+                   seqint[j][i] = -1;\r
+               }\r
+\r
+           }\r
+\r
+       }\r
+\r
+\r
+       //      print_matrix(seqint,2,len);     for (int j = 0; j < align.getHeight(); j++) {\r
+\r
+           for (int j = 0; j < align.getHeight(); j++) {\r
+\r
+               for (int k = 0; k < align.getHeight(); k++) {\r
+\r
+               int counts[][] = new int[4][4];\r
+               int tot  = 0;\r
+               int tots[] = new int[4];\r
+               int fulltot = 0;\r
+               int fulltots[] = new int[4];\r
+\r
+               for (int i = 0 ; i < len; i++) {\r
+\r
+                   if (k != j) {\r
+\r
+                       //                      System.out.println("Seq " + j + " " + k + " " + i + " " + seqint[j][i] + " " + seqint[k][i]);\r
+                       if (seqint[j][i] >= 0 &&\r
+                           seqint[k][i] >= 0) {\r
+                           counts[seqint[k][i]][seqint[j][i]]++;\r
+\r
+                           //  print_matrix(counts,4,4);\r
+                           tots[seqint[j][i]]++;\r
+                           tot++;\r
+                       }\r
+                       if (seqint[j][i] != -1) {\r
+                           fulltots[seqint[j][i]]++;\r
+                           fulltot++;\r
+                       }\r
+                   }\r
+               }\r
+\r
+               if (k != j) {\r
+\r
+                   System.out.println();\r
+\r
+                   System.out.println("Sequence " + align.getSequenceAt(j).getName() + " "  + align.getSequenceAt(k).getName());\r
+\r
+                   System.out.println();\r
+                   print_matrix(counts,4,4);\r
+                   System.out.println();\r
+\r
+\r
+\r
+                   double[][] out = new double[4][4];// = constant_multiply_matrix(counts,1.0/tot,4,4);\r
+\r
+                   for (int i = 0; i < 4; i++) {\r
+                       for (int jj = 0; jj < 4; jj++) {\r
+                           out[i][jj] = (double)counts[i][jj]/tots[jj];\r
+                       }\r
+                   }\r
+\r
+                   print_matrix(out,4,4);\r
+                   System.out.println();\r
+\r
+\r
+                   System.out.print("RATES\t");\r
+                   System.out.print(align.getSequenceAt(j).getName() + "\t"  + align.getSequenceAt(k).getName() + "\t");\r
+\r
+                   for (int i = 0; i < 4; i++) {\r
+                       for (int jj = 0; jj < 4; jj++) {\r
+                           Format.print(System.out,"%4.3f\t",out[i][jj]);\r
+                       }\r
+                   }\r
+                   System.out.println();\r
+\r
+                   for (int i = 0; i < 4; i++) {\r
+                       Format.print(System.out,"%4.3f\t",(double)fulltots[i]*1.0/fulltot);\r
+                   }\r
+\r
+                   System.out.println();\r
+                   System.out.print("\nGC ");\r
+\r
+                   Format.print(System.out,"%4.3f\t",(double)(100*fulltots[1]+fulltots[3])/fulltot);\r
+\r
+                   System.out.print((fulltots[1]+fulltots[3]) + "\t" + fulltot);\r
+\r
+\r
+                   System.out.println();\r
+\r
+                   rates.addElement(out);\r
+               }\r
+\r
+           }\r
+       }\r
+       return rates;\r
+    }\r
+\r
+    public static double[][]  constant_multiply_matrix(int[][] matrix, double c,int n, int m) {\r
+       double[][] out = new double[n][m];\r
+\r
+       for (int i = 0; i < n; i++) {\r
+           for (int j = 0; j < m; j++) {\r
+\r
+               out[i][j] = matrix[i][j]*c;\r
+           }\r
+       }\r
+       return out;\r
+    }\r
+\r
+\r
+    public static void print_matrix(int[][] matrix, int n, int m) {\r
+\r
+\r
+       for (int i = 0; i < n; i++) {\r
+           for (int j = 0; j < m; j++) {\r
+\r
+               System.out.print(matrix[i][j] + "\t");\r
+           }\r
+           System.out.println();\r
+       }\r
+    }\r
+    public static void print_matrix(double[][] matrix, int n, int m) {\r
+\r
+\r
+       for (int i = 0; i < n; i++) {\r
+           for (int j = 0; j < m; j++) {\r
+\r
+               Format.print(System.out,"%4.3f\t",matrix[i][j]);\r
+\r
+           }\r
+           System.out.println();\r
+       }\r
+    }\r
+\r
+    public static Hashtable findKmers(SequenceI seq, int start, int end, Vector kmers) {\r
+\r
+         Hashtable pos = new Hashtable();\r
+\r
+         for (int j = 0; j < kmers.size(); j++) {\r
+\r
+           String   kmer    = ((Sequence)kmers.elementAt(j)).getSequence();\r
+           Sequence kmerseq = (Sequence)kmers.elementAt(j);\r
+\r
+           if (end < seq.getLength()) {\r
+\r
+              String str = seq.getSequence(start,end);\r
+\r
+              int i = 0;\r
+\r
+              while (str.indexOf(kmer,i) != -1) {\r
+\r
+              //               System.out.println("STring " + str + " " + i);\r
+                  int coord = str.indexOf(kmer,i);\r
+\r
+                  pos.put(new Integer(coord),new Integer(kmerseq.getLength()));\r
+\r
+                  i  = coord + 1;\r
+\r
+              }\r
+          }\r
+         }\r
+         return pos;\r
+    }\r
+\r
+}\r
diff --git a/src/jalview/analysis/CompareAlignments.java b/src/jalview/analysis/CompareAlignments.java
new file mode 100755 (executable)
index 0000000..3cb8144
--- /dev/null
@@ -0,0 +1,166 @@
+package jalview.analysis;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.io.*;\r
+\r
+import java.util.*;\r
+\r
+public class CompareAlignments {\r
+\r
+    Vector align;\r
+    String refId;\r
+    Vector ids;\r
+\r
+    public CompareAlignments(Vector align) {\r
+\r
+       this.align = align;\r
+\r
+       ids = new Vector();\r
+\r
+       Alignment al0 = (Alignment)align.elementAt(0);\r
+\r
+       for (int i = 0; i < al0.getHeight(); i++) {\r
+           SequenceI seq = al0.getSequenceAt(i);\r
+\r
+           ids.addElement(seq.getName());\r
+\r
+           if (i == 0) {\r
+               setReferenceId(seq.getName());\r
+           }\r
+       }\r
+\r
+    }\r
+\r
+    public void compare() {\r
+\r
+       Hashtable positions = new Hashtable();\r
+\r
+       for (int k = 0; k < ids.size(); k++) {\r
+\r
+           String id = (String)ids.elementAt(k);\r
+\r
+           System.out.println("Ids " + id + " " + refId);\r
+\r
+           if (!id.equals(refId)) {\r
+\r
+               Hashtable fullhash = new Hashtable();\r
+\r
+               for (int i = 0; i < align.size(); i++) {\r
+                   System.out.println("Alignment " + i);\r
+\r
+                   Alignment al = (Alignment)align.elementAt(i);\r
+\r
+                   SequenceI refseq = null;\r
+\r
+                   for (int j = 0; j < al.getHeight(); j++) {\r
+                       if (((SequenceI)al.getSequenceAt(j)).getName().equals(refId)) {\r
+                           refseq = (SequenceI)al.getSequenceAt(j);\r
+                       }\r
+                   }\r
+\r
+                   if (refseq != null) {\r
+\r
+                       System.out.println("Refseq " + refseq.getName());\r
+\r
+                       for (int jj = 0; jj < al.getHeight(); jj++) {\r
+                           SequenceI seq = (SequenceI)al.getSequenceAt(jj);\r
+\r
+                           if (seq.getName().equals(id)) {\r
+                               Hashtable hash = getAlignPositions(seq,refseq);\r
+\r
+                               Enumeration keys = hash.keys();\r
+\r
+                               while (keys.hasMoreElements()) {\r
+                                   Integer key = (Integer)keys.nextElement();\r
+                                   //                          System.out.println(key + " " + hash.get(key));\r
+                                   if (fullhash.get(key) == null) {\r
+                                       fullhash.put(key,new Vector());\r
+                                   }\r
+\r
+                                   Vector tmp = (Vector)fullhash.get(key);\r
+\r
+                                   tmp.addElement(hash.get(key));\r
+                               }\r
+                           }\r
+\r
+                       }\r
+                   }\r
+               }\r
+\r
+               System.out.println ("\nId " + id);\r
+\r
+               Enumeration keys = fullhash.keys();\r
+\r
+\r
+               int totdiff = 0;\r
+               while (keys.hasMoreElements()) {\r
+                   Integer key = (Integer)keys.nextElement();\r
+\r
+                   Vector tmp = (Vector)fullhash.get(key);\r
+\r
+\r
+\r
+                   int diff0 = ((Integer)tmp.elementAt(0)).intValue();;\r
+                   int diff = 0;\r
+\r
+                   for (int l = 1; l < tmp.size(); l++) {\r
+                       diff += Math.abs(diff0 - ((Integer)tmp.elementAt(l)).intValue());\r
+\r
+                   }\r
+\r
+                   if (diff > 0) {\r
+                       totdiff++;\r
+                       System.out.print(id + " Ref pos " + key + " : " + diff0 + " " + diff + " : ");\r
+\r
+                       for (int l = 1; l < tmp.size(); l++) {\r
+                           System.out.print(diff0 - ((Integer)tmp.elementAt(l)).intValue() + " ");\r
+                       }\r
+                       System.out.println();\r
+                   }\r
+               }\r
+\r
+               System.out.println("Total " + id + " " + totdiff);\r
+\r
+           }\r
+       }\r
+    }\r
+\r
+\r
+    public void setReferenceId(String id) {\r
+       this.refId = id;\r
+    }\r
+\r
+    public Hashtable getAlignPositions(SequenceI seq1, SequenceI seq2) {\r
+\r
+       Hashtable hash = new Hashtable();\r
+\r
+       int i = 0;\r
+\r
+       int pos1 = 0;\r
+       int pos2 = 0;\r
+\r
+       while (i < seq1.getLength()) {\r
+\r
+           char c1 = seq1.getCharAt(i);\r
+           char c2 = seq2.getCharAt(i);\r
+\r
+           if (c1 != '-') {\r
+               pos1++;\r
+           }\r
+\r
+           if (c2 != '-') {\r
+               pos2++;\r
+           }\r
+\r
+           if (c1 != '-') {\r
+               hash.put(new Integer(pos1),new Integer(pos2));\r
+           }\r
+\r
+           i++;\r
+       }\r
+       return hash;\r
+    }\r
+\r
+\r
+\r
+}\r
diff --git a/src/jalview/analysis/Conservation.java b/src/jalview/analysis/Conservation.java
new file mode 100755 (executable)
index 0000000..db572ac
--- /dev/null
@@ -0,0 +1,185 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+package jalview.analysis;\r
+\r
+\r
+import java.util.*;\r
+import jalview.gui.*;\r
+import jalview.datamodel.*;\r
+\r
+\r
+public class Conservation {\r
+  Vector sequences;\r
+  int    start;\r
+  int    end;\r
+\r
+  Vector total = new Vector();\r
+\r
+  String consString = "";\r
+\r
+  DrawableSequence consSequence;\r
+  Hashtable        propHash;\r
+  int              threshold;\r
+  Hashtable[]      freqs;\r
+\r
+  String name = "";\r
+\r
+  public Conservation(String name,Hashtable[] freqs,Hashtable propHash, int threshold, Vector sequences, int start, int end) {\r
+    this.name      = name;\r
+    this.freqs     = freqs;\r
+    this.propHash  = propHash;\r
+    this.threshold = threshold;\r
+    this.sequences = sequences;\r
+    this.start     = start;\r
+    this.end       = end;\r
+  }\r
+\r
+\r
+  public void  calculate() {\r
+\r
+    for (int i = start;i <= end; i++) {\r
+      Hashtable resultHash  = null;\r
+      Hashtable residueHash = null;\r
+\r
+      resultHash  = new Hashtable();\r
+      residueHash = new Hashtable();\r
+\r
+      for (int j=0; j < sequences.size(); j++) {\r
+\r
+        if (sequences.elementAt(j) instanceof Sequence) {\r
+          Sequence s = (Sequence)sequences.elementAt(j);\r
+\r
+          if (s.getSequence().length() > i) {\r
+            String res = s.getSequence().substring(i,i+1);\r
+\r
+            if (residueHash.containsKey(res)) {\r
+              int count = ((Integer)residueHash.get(res)).intValue() ;\r
+              count++;\r
+              residueHash.put(res,new Integer(count));\r
+            } else {\r
+              residueHash.put(res,new Integer(1));\r
+            }\r
+          } else {\r
+            if (residueHash.containsKey("-")) {\r
+              int count = ((Integer)residueHash.get("-")).intValue() ;\r
+              count++;\r
+              residueHash.put("-",new Integer(count));\r
+            } else {\r
+              residueHash.put("-",new Integer(1));\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      //What is the count threshold to count the residues in residueHash()\r
+      int thresh = threshold*(sequences.size())/100;\r
+\r
+      //loop over all the found residues\r
+      Enumeration e = residueHash.keys();\r
+\r
+      while (e.hasMoreElements()) {\r
+\r
+        String res = (String)e.nextElement();\r
+        if (((Integer)residueHash.get(res)).intValue() > thresh) {\r
+\r
+          //Now loop over the properties\r
+          Enumeration e2 = propHash.keys();\r
+\r
+          while (e2.hasMoreElements()) {\r
+            String    type = (String)e2.nextElement();\r
+            Hashtable ht   = (Hashtable)propHash.get(type);\r
+\r
+            //Have we ticked this before?\r
+            if (! resultHash.containsKey(type)) {\r
+              if (ht.containsKey(res)) {\r
+                resultHash.put(type,ht.get(res));\r
+              } else {\r
+                resultHash.put(type,ht.get("-"));\r
+              }\r
+            } else if ( ((Integer)resultHash.get(type)).equals((Integer)ht.get(res)) == false) {\r
+              resultHash.put(type,new Integer(-1));\r
+            }\r
+          }\r
+        }\r
+      }\r
+      total.addElement(resultHash);\r
+    }\r
+  }\r
+\r
+  public int countGaps(int j) {\r
+    int count = 0;\r
+\r
+    for (int i = 0; i < sequences.size();i++) {\r
+      String tmp = ((Sequence)sequences.elementAt(i)).getSequence().substring(j,j+1);\r
+      if (tmp.equals(" ") || tmp.equals(".") || tmp.equals("-")) {\r
+        count++;\r
+      }\r
+    }\r
+    return count;\r
+  }\r
+\r
+  public  void  verdict(boolean consflag, float percentageGaps) {\r
+    String consString = "";\r
+\r
+    for (int i=start; i <= end; i++) {\r
+      int totGaps = countGaps(i);\r
+      float pgaps = (float)totGaps*100/(float)sequences.size();\r
+\r
+      if (percentageGaps > pgaps) {\r
+        Hashtable resultHash = (Hashtable)total.elementAt(i);\r
+\r
+        //Now find the verdict\r
+        int         count = 0;\r
+        Enumeration e3    = resultHash.keys();\r
+\r
+        while (e3.hasMoreElements()) {\r
+          String type    = (String)e3.nextElement();\r
+          Integer result = (Integer)resultHash.get(type);\r
+\r
+          //Do we want to count +ve conservation or +ve and -ve cons.?\r
+\r
+          if (consflag) {\r
+            if (result.intValue() == 1) {\r
+              count++;\r
+            }\r
+          } else {\r
+            if (result.intValue() != -1) {\r
+              count++;\r
+            }\r
+          }\r
+        }\r
+\r
+        if (count < 10) {\r
+          consString = consString + String.valueOf(count);\r
+        } else {\r
+          consString = consString + "*";\r
+        }\r
+      } else {\r
+        consString = consString + "-";\r
+      }\r
+    }\r
+\r
+    consSequence = new DrawableSequence(name,consString,start,end);\r
+\r
+  }\r
+\r
+  public jalview.gui.DrawableSequence getConsSequence() {\r
+    return consSequence;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/analysis/NJTree.java b/src/jalview/analysis/NJTree.java
new file mode 100755 (executable)
index 0000000..4aeee3d
--- /dev/null
@@ -0,0 +1,667 @@
+package jalview.analysis;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+import jalview.schemes.ResidueProperties;\r
+import java.util.*;\r
+\r
+public class NJTree {\r
+\r
+  Vector cluster;\r
+  SequenceI[] sequence;\r
+\r
+  int done[];\r
+  int noseqs;\r
+  int noClus;\r
+\r
+  float distance[][];\r
+\r
+  int mini;\r
+  int minj;\r
+  float ri;\r
+  float rj;\r
+\r
+  Vector groups = new Vector();\r
+  SequenceNode maxdist;\r
+  SequenceNode top;\r
+\r
+  float maxDistValue;\r
+  float maxheight;\r
+\r
+  int ycount;\r
+\r
+  Vector node;\r
+\r
+  String type;\r
+  String pwtype;\r
+\r
+  Object found = null;\r
+  Object leaves = null;\r
+\r
+  int start;\r
+  int end;\r
+\r
+  public NJTree(SequenceNode node) {\r
+    top = node;\r
+    maxheight = findHeight(top);\r
+  }\r
+\r
+  public NJTree(SequenceI[] sequence,int start, int end) {\r
+    this(sequence,"NJ","BL",start,end);\r
+  }\r
+\r
+  public NJTree(SequenceI[] sequence,String type,String pwtype,int start, int end ) {\r
+\r
+    this.sequence = sequence;\r
+    this.node     = new Vector();\r
+    this.type     = type;\r
+    this.pwtype   = pwtype;\r
+    this.start    = start;\r
+    this.end      = end;\r
+\r
+    if (!(type.equals("NJ"))) {\r
+      type = "AV";\r
+    }\r
+\r
+    if (!(pwtype.equals("PID"))) {\r
+      type = "BL";\r
+    }\r
+\r
+    int i=0;\r
+\r
+    done = new int[sequence.length];\r
+\r
+\r
+    while (i < sequence.length  && sequence[i] != null) {\r
+      done[i] = 0;\r
+      i++;\r
+    }\r
+\r
+    noseqs = i++;\r
+\r
+    distance = findDistances();\r
+\r
+    makeLeaves();\r
+\r
+    noClus = cluster.size();\r
+\r
+    cluster();\r
+\r
+  }\r
+\r
+\r
+  public void cluster() {\r
+\r
+    while (noClus > 2) {\r
+      if (type.equals("NJ")) {\r
+        float mind = findMinNJDistance();\r
+      } else {\r
+        float mind = findMinDistance();\r
+      }\r
+\r
+      Cluster c = joinClusters(mini,minj);\r
+\r
+\r
+      done[minj] = 1;\r
+\r
+      cluster.setElementAt(null,minj);\r
+      cluster.setElementAt(c,mini);\r
+\r
+      noClus--;\r
+    }\r
+\r
+    boolean onefound = false;\r
+\r
+    int one = -1;\r
+    int two = -1;\r
+\r
+    for (int i=0; i < noseqs; i++) {\r
+      if (done[i] != 1) {\r
+        if (onefound == false) {\r
+          two = i;\r
+          onefound = true;\r
+        } else {\r
+          one = i;\r
+        }\r
+      }\r
+    }\r
+\r
+    Cluster c = joinClusters(one,two);\r
+    top = (SequenceNode)(node.elementAt(one));\r
+\r
+    reCount(top);\r
+    findHeight(top);\r
+    findMaxDist(top);\r
+\r
+  }\r
+\r
+  public Cluster joinClusters(int i, int j) {\r
+\r
+    float dist = distance[i][j];\r
+\r
+    int noi = ((Cluster)cluster.elementAt(i)).value.length;\r
+    int noj = ((Cluster)cluster.elementAt(j)).value.length;\r
+\r
+    int[] value = new int[noi + noj];\r
+\r
+    for (int ii = 0; ii < noi;ii++) {\r
+      value[ii] =  ((Cluster)cluster.elementAt(i)).value[ii];\r
+    }\r
+\r
+    for (int ii = noi; ii < noi+ noj;ii++) {\r
+      value[ii] =  ((Cluster)cluster.elementAt(j)).value[ii-noi];\r
+    }\r
+\r
+    Cluster c = new Cluster(value);\r
+\r
+    ri = findr(i,j);\r
+    rj = findr(j,i);\r
+\r
+    if (type.equals("NJ")) {\r
+      findClusterNJDistance(i,j);\r
+    } else {\r
+      findClusterDistance(i,j);\r
+    }\r
+\r
+    SequenceNode sn = new SequenceNode();\r
+\r
+    sn.setLeft((SequenceNode)(node.elementAt(i)));\r
+    sn.setRight((SequenceNode)(node.elementAt(j)));\r
+\r
+    SequenceNode tmpi = (SequenceNode)(node.elementAt(i));\r
+    SequenceNode tmpj = (SequenceNode)(node.elementAt(j));\r
+\r
+    if (type.equals("NJ")) {\r
+      findNewNJDistances(tmpi,tmpj,dist);\r
+    } else {\r
+      findNewDistances(tmpi,tmpj,dist);\r
+    }\r
+\r
+    tmpi.setParent(sn);\r
+    tmpj.setParent(sn);\r
+\r
+    node.setElementAt(sn,i);\r
+    return c;\r
+  }\r
+\r
+  public void findNewNJDistances(SequenceNode tmpi, SequenceNode tmpj, float dist) {\r
+\r
+    float ih = 0;\r
+    float jh = 0;\r
+\r
+    SequenceNode sni = tmpi;\r
+    SequenceNode snj = tmpj;\r
+\r
+    tmpi.dist = (dist + ri - rj)/2;\r
+    tmpj.dist = (dist - tmpi.dist);\r
+\r
+    if (tmpi.dist < 0) {\r
+      tmpi.dist = 0;\r
+    }\r
+    if (tmpj.dist < 0) {\r
+      tmpj.dist = 0;\r
+    }\r
+  }\r
+\r
+  public void findNewDistances(SequenceNode tmpi,SequenceNode tmpj,float dist) {\r
+\r
+    float ih = 0;\r
+    float jh = 0;\r
+\r
+    SequenceNode sni = tmpi;\r
+    SequenceNode snj = tmpj;\r
+\r
+    while (sni != null) {\r
+      ih = ih + sni.dist;\r
+      sni = (SequenceNode)sni.left();\r
+    }\r
+\r
+    while (snj != null) {\r
+      jh = jh + snj.dist;\r
+      snj = (SequenceNode)snj.left();\r
+    }\r
+\r
+    tmpi.dist = (dist/2 - ih);\r
+    tmpj.dist = (dist/2 - jh);\r
+  }\r
+\r
+\r
+\r
+  public void findClusterDistance(int i, int j) {\r
+\r
+    int noi = ((Cluster)cluster.elementAt(i)).value.length;\r
+    int noj = ((Cluster)cluster.elementAt(j)).value.length;\r
+\r
+    // New distances from cluster to others\r
+    float[] newdist = new float[noseqs];\r
+\r
+    for (int l = 0; l < noseqs; l++) {\r
+      if ( l != i && l != j) {\r
+        newdist[l] = (distance[i][l] * noi + distance[j][l] * noj)/(noi + noj);\r
+      } else {\r
+        newdist[l] = 0;\r
+      }\r
+    }\r
+\r
+    for (int ii=0; ii < noseqs;ii++) {\r
+      distance[i][ii] = newdist[ii];\r
+      distance[ii][i] = newdist[ii];\r
+    }\r
+  }\r
+\r
+  public void findClusterNJDistance(int i, int j) {\r
+\r
+    int noi = ((Cluster)cluster.elementAt(i)).value.length;\r
+    int noj = ((Cluster)cluster.elementAt(j)).value.length;\r
+\r
+    // New distances from cluster to others\r
+    float[] newdist = new float[noseqs];\r
+\r
+    for (int l = 0; l < noseqs; l++) {\r
+      if ( l != i && l != j) {\r
+        newdist[l] = (distance[i][l] + distance[j][l] - distance[i][j])/2;\r
+      } else {\r
+        newdist[l] = 0;\r
+      }\r
+    }\r
+\r
+    for (int ii=0; ii < noseqs;ii++) {\r
+      distance[i][ii] = newdist[ii];\r
+      distance[ii][i] = newdist[ii];\r
+    }\r
+  }\r
+\r
+  public float findr(int i, int j) {\r
+\r
+    float tmp = 1;\r
+    for (int k=0; k < noseqs;k++) {\r
+      if (k!= i && k!= j && done[k] != 1) {\r
+        tmp = tmp + distance[i][k];\r
+      }\r
+    }\r
+\r
+    if (noClus > 2) {\r
+      tmp = tmp/(noClus - 2);\r
+    }\r
+\r
+    return tmp;\r
+  }\r
+\r
+  public float findMinNJDistance() {\r
+\r
+    float min = 100000;\r
+\r
+    for (int i=0; i < noseqs-1; i++) {\r
+      for (int j=i+1;j < noseqs;j++) {\r
+        if (done[i] != 1 && done[j] != 1) {\r
+          float tmp = distance[i][j] - (findr(i,j) + findr(j,i));\r
+          if (tmp < min) {\r
+\r
+            mini = i;\r
+            minj = j;\r
+\r
+            min = tmp;\r
+\r
+          }\r
+        }\r
+      }\r
+    }\r
+    return min;\r
+  }\r
+\r
+  public float findMinDistance() {\r
+\r
+    float min = 100000;\r
+\r
+    for (int i=0; i < noseqs-1;i++) {\r
+      for (int j = i+1; j < noseqs;j++) {\r
+        if (done[i] != 1 && done[j] != 1) {\r
+          if (distance[i][j] < min) {\r
+            mini = i;\r
+            minj = j;\r
+\r
+            min = distance[i][j];\r
+          }\r
+        }\r
+      }\r
+    }\r
+    return min;\r
+  }\r
+\r
+  public float[][] findDistances() {\r
+\r
+    float[][] distance = new float[noseqs][noseqs];\r
+\r
+    if (pwtype.equals("PID")) {\r
+      for (int i = 0; i < noseqs-1; i++) {\r
+        for (int j = i; j < noseqs; j++) {\r
+          if (j==i) {\r
+            distance[i][i] = 0;\r
+          } else {\r
+            distance[i][j] = 100-Comparison.compare(sequence[i],sequence[j],start,end);\r
+            distance[j][i] = distance[i][j];\r
+          }\r
+        }\r
+      }\r
+    } else if (pwtype.equals("BL")) {\r
+      int   maxscore = 0;\r
+\r
+      for (int i = 0; i < noseqs-1; i++) {\r
+        for (int j = i; j < noseqs; j++) {\r
+          int score = 0;\r
+          for (int k=0; k < sequence[i].getLength(); k++) {\r
+            try{\r
+              score +=\r
+                  ResidueProperties.getBLOSUM62(sequence[i].getSequence(k,\r
+                  k + 1),\r
+                                                sequence[j].getSequence(k,\r
+                  k + 1));\r
+            }catch(Exception ex){System.out.println("err creating BLOSUM62 tree");}\r
+          }\r
+          distance[i][j] = (float)score;\r
+          if (score > maxscore) {\r
+            maxscore = score;\r
+          }\r
+        }\r
+      }\r
+      for (int i = 0; i < noseqs-1; i++) {\r
+        for (int j = i; j < noseqs; j++) {\r
+          distance[i][j] =  (float)maxscore - distance[i][j];\r
+          distance[j][i] = distance[i][j];\r
+        }\r
+      }\r
+    } else if (pwtype.equals("SW")) {\r
+      float max = -1;\r
+      for (int i = 0; i < noseqs-1; i++) {\r
+        for (int j = i; j < noseqs; j++) {\r
+          AlignSeq as = new AlignSeq(sequence[i],sequence[j],"pep");\r
+          as.calcScoreMatrix();\r
+          as.traceAlignment();\r
+          as.printAlignment();\r
+          distance[i][j] = (float)as.maxscore;\r
+          if (max < distance[i][j]) {\r
+            max = distance[i][j];\r
+          }\r
+        }\r
+      }\r
+      for (int i = 0; i < noseqs-1; i++) {\r
+        for (int j = i; j < noseqs; j++) {\r
+          distance[i][j] =  max - distance[i][j];\r
+          distance[j][i] = distance[i][j];\r
+        }\r
+      }\r
+    }\r
+\r
+    return distance;\r
+  }\r
+\r
+  public void makeLeaves() {\r
+    cluster = new Vector();\r
+\r
+    for (int i=0; i < noseqs; i++) {\r
+      SequenceNode sn = new SequenceNode();\r
+\r
+      sn.setElement(sequence[i]);\r
+      sn.setName(sequence[i].getName());\r
+      node.addElement(sn);\r
+\r
+      int[] value = new int[1];\r
+      value[0] = i;\r
+\r
+      Cluster c = new Cluster(value);\r
+      cluster.addElement(c);\r
+    }\r
+  }\r
+\r
+  public Vector findLeaves(SequenceNode node, Vector leaves) {\r
+    if (node == null) {\r
+      return leaves;\r
+    }\r
+\r
+    if (node.left() == null && node.right() == null) {\r
+      leaves.addElement(node);\r
+      return leaves;\r
+    } else {\r
+      findLeaves((SequenceNode)node.left(),leaves);\r
+      findLeaves((SequenceNode)node.right(),leaves);\r
+    }\r
+    return leaves;\r
+  }\r
+\r
+  public Object findLeaf(SequenceNode node, int count) {\r
+    found = _findLeaf(node,count);\r
+\r
+    return found;\r
+  }\r
+  public Object _findLeaf(SequenceNode node,int count) {\r
+    if (node == null) {\r
+      return null;\r
+    }\r
+    if (node.ycount == count) {\r
+      found = node.element();\r
+      return found;\r
+    } else {\r
+      _findLeaf((SequenceNode)node.left(),count);\r
+      _findLeaf((SequenceNode)node.right(),count);\r
+    }\r
+\r
+    return found;\r
+  }\r
+\r
+  public void printNode(SequenceNode node) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+    if (node.left() == null && node.right() == null) {\r
+      System.out.println("Leaf = " + ((SequenceI)node.element()).getName());\r
+      System.out.println("Dist " + ((SequenceNode)node).dist);\r
+      System.out.println("Boot " + node.getBootstrap());\r
+    } else {\r
+      System.out.println("Dist " + ((SequenceNode)node).dist);\r
+      printNode((SequenceNode)node.left());\r
+      printNode((SequenceNode)node.right());\r
+    }\r
+  }\r
+  public void findMaxDist(SequenceNode node) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+    if (node.left() == null && node.right() == null) {\r
+\r
+      float dist = ((SequenceNode)node).dist;\r
+      if (dist > maxDistValue) {\r
+         maxdist      = (SequenceNode)node;\r
+         maxDistValue = dist;\r
+      }\r
+    } else {\r
+      findMaxDist((SequenceNode)node.left());\r
+      findMaxDist((SequenceNode)node.right());\r
+    }\r
+  }\r
+    public Vector getGroups() {\r
+       return groups;\r
+    }\r
+    public float getMaxHeight() {\r
+       return maxheight;\r
+    }\r
+  public void  groupNodes(SequenceNode node, float threshold) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+\r
+    if (node.height/maxheight > threshold) {\r
+      groups.addElement(node);\r
+    } else {\r
+      groupNodes((SequenceNode)node.left(),threshold);\r
+      groupNodes((SequenceNode)node.right(),threshold);\r
+    }\r
+  }\r
+\r
+  public float findHeight(SequenceNode node) {\r
+\r
+    if (node == null) {\r
+      return maxheight;\r
+    }\r
+\r
+    if (node.left() == null && node.right() == null) {\r
+      node.height = ((SequenceNode)node.parent()).height + node.dist;\r
+\r
+      if (node.height > maxheight) {\r
+        return node.height;\r
+      } else {\r
+        return maxheight;\r
+      }\r
+    } else {\r
+      if (node.parent() != null) {\r
+        node.height = ((SequenceNode)node.parent()).height + node.dist;\r
+      } else {\r
+        maxheight = 0;\r
+        node.height = (float)0.0;\r
+      }\r
+\r
+      maxheight = findHeight((SequenceNode)(node.left()));\r
+      maxheight = findHeight((SequenceNode)(node.right()));\r
+    }\r
+    return maxheight;\r
+  }\r
+  public SequenceNode reRoot() {\r
+    if (maxdist != null) {\r
+      ycount = 0;\r
+      float tmpdist = maxdist.dist;\r
+\r
+      // New top\r
+      SequenceNode sn = new SequenceNode();\r
+      sn.setParent(null);\r
+\r
+      // New right hand of top\r
+      SequenceNode snr = (SequenceNode)maxdist.parent();\r
+      changeDirection(snr,maxdist);\r
+      System.out.println("Printing reversed tree");\r
+      printN(snr);\r
+      snr.dist = tmpdist/2;\r
+      maxdist.dist = tmpdist/2;\r
+\r
+      snr.setParent(sn);\r
+      maxdist.setParent(sn);\r
+\r
+      sn.setRight(snr);\r
+      sn.setLeft(maxdist);\r
+\r
+      top = sn;\r
+\r
+      ycount = 0;\r
+      reCount(top);\r
+      findHeight(top);\r
+\r
+    }\r
+    return top;\r
+  }\r
+  public static void printN(SequenceNode node) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+\r
+    if (node.left() != null && node.right() != null) {\r
+      printN((SequenceNode)node.left());\r
+      printN((SequenceNode)node.right());\r
+    } else {\r
+      System.out.println(" name = " + ((SequenceI)node.element()).getName());\r
+    }\r
+    System.out.println(" dist = " + ((SequenceNode)node).dist + " " + ((SequenceNode)node).count + " " + ((SequenceNode)node).height);\r
+  }\r
+\r
+    public void reCount(SequenceNode node) {\r
+       ycount = 0;\r
+       _reCount(node);\r
+    }\r
+  public void _reCount(SequenceNode node) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+\r
+    if (node.left() != null && node.right() != null) {\r
+      _reCount((SequenceNode)node.left());\r
+      _reCount((SequenceNode)node.right());\r
+\r
+      SequenceNode l = (SequenceNode)node.left();\r
+      SequenceNode r = (SequenceNode)node.right();\r
+\r
+      ((SequenceNode)node).count  = l.count + r.count;\r
+      ((SequenceNode)node).ycount = (l.ycount + r.ycount)/2;\r
+\r
+    } else {\r
+      ((SequenceNode)node).count = 1;\r
+      ((SequenceNode)node).ycount = ycount++;\r
+    }\r
+\r
+  }\r
+    public void swapNodes(SequenceNode node) {\r
+       if (node == null) {\r
+           return;\r
+       }\r
+       SequenceNode tmp = (SequenceNode)node.left();\r
+\r
+       node.setLeft(node.right());\r
+       node.setRight(tmp);\r
+    }\r
+  public void changeDirection(SequenceNode node, SequenceNode dir) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+    if (node.parent() != top) {\r
+      changeDirection((SequenceNode)node.parent(), node);\r
+\r
+      SequenceNode tmp = (SequenceNode)node.parent();\r
+\r
+      if (dir == node.left()) {\r
+        node.setParent(dir);\r
+        node.setLeft(tmp);\r
+      } else if (dir == node.right()) {\r
+        node.setParent(dir);\r
+        node.setRight(tmp);\r
+      }\r
+\r
+    } else {\r
+      if (dir == node.left()) {\r
+        node.setParent(node.left());\r
+\r
+        if (top.left() == node) {\r
+          node.setRight(top.right());\r
+        } else {\r
+          node.setRight(top.left());\r
+        }\r
+      } else {\r
+        node.setParent(node.right());\r
+\r
+        if (top.left() == node) {\r
+          node.setLeft(top.right());\r
+        } else {\r
+          node.setLeft(top.left());\r
+        }\r
+      }\r
+    }\r
+  }\r
+    public void setMaxDist(SequenceNode node) {\r
+       this.maxdist = maxdist;\r
+    }\r
+    public SequenceNode getMaxDist() {\r
+       return maxdist;\r
+    }\r
+    public SequenceNode getTopNode() {\r
+       return top;\r
+    }\r
+\r
+}\r
+\r
+\r
+\r
+class Cluster {\r
+\r
+  int[] value;\r
+\r
+  public Cluster(int[] value) {\r
+    this.value = value;\r
+  }\r
+\r
+}\r
+\r
diff --git a/src/jalview/analysis/PCA.java b/src/jalview/analysis/PCA.java
new file mode 100755 (executable)
index 0000000..c14a1b8
--- /dev/null
@@ -0,0 +1,189 @@
+package jalview.analysis;\r
+\r
+import jalview.math.*;\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+\r
+import java.awt.*;\r
+import java.io.*;\r
+\r
+public class PCA implements Runnable {\r
+  Matrix m;\r
+  Matrix symm;\r
+  Matrix m2;\r
+\r
+  double[] eigenvalue;\r
+  Matrix eigenvector;\r
+\r
+  public PCA(Matrix m) {\r
+    this.m = m;\r
+  }\r
+\r
+  public PCA(SequenceI[] s) {\r
+    Runtime rt = Runtime.getRuntime();\r
+\r
+    BinarySequence[] bs = new BinarySequence[s.length];\r
+    int ii = 0;\r
+    while (ii < s.length && s[ii] != null) {\r
+\r
+      bs[ii] = new BinarySequence(s[ii]);\r
+      bs[ii].encode();\r
+      ii++;\r
+    }\r
+\r
+    BinarySequence[] bs2 = new BinarySequence[s.length];\r
+    ii = 0;\r
+    while (ii < s.length && s[ii] != null) {\r
+\r
+      bs2[ii] = new BinarySequence(s[ii]);\r
+      bs2[ii].blosumEncode();\r
+      ii++;\r
+    }\r
+\r
+\r
+    //System.out.println("Created binary encoding");\r
+    //printMemory(rt);\r
+\r
+    int count=0;\r
+    while (count < bs.length && bs[count] != null) {\r
+      count++;\r
+    }\r
+    double[][] seqmat = new double[count][bs[0].getDBinary().length];\r
+    double[][] seqmat2 = new double[count][bs2[0].getDBinary().length];\r
+    int i=0;\r
+    while (i < count) {\r
+      seqmat[i] = bs[i].getDBinary();\r
+      seqmat2[i] = bs2[i].getDBinary();\r
+      i++;\r
+    }\r
+    //System.out.println("Created array");\r
+    //printMemory(rt);\r
+    //    System.out.println(" --- Original matrix ---- ");\r
+    m = new Matrix(seqmat,count,bs[0].getDBinary().length);\r
+    m2 = new Matrix(seqmat2,count,bs2[0].getDBinary().length);\r
+\r
+    //System.out.println("Created matrix");\r
+    printMemory(rt);\r
+  }\r
+\r
+  public static void printMemory(Runtime rt) {\r
+    System.out.println("Free memory = " + rt.freeMemory());\r
+  }\r
+\r
+  public Matrix getM() {\r
+    return m;\r
+  }\r
+\r
+  public double[] getEigenvector(int i) {\r
+    return eigenvector.getColumn(i);\r
+  }\r
+\r
+  public double getEigenvalue(int i) {\r
+    return eigenvector.d[i];\r
+  }\r
+  public float[][] getComponents(int l, int n, int mm) {\r
+    return getComponents(l,n,mm,1);\r
+  }\r
+  public float[][] getComponents(int l, int n, int mm, float factor) {\r
+    float[][] out = new float[m.rows][3];\r
+\r
+    for (int i = 0; i < m.rows;i++) {\r
+      out[i][0] = (float)component(i,l)*factor;\r
+      out[i][1] = (float)component(i,n)*factor;\r
+      out[i][2] = (float)component(i,mm)*factor;\r
+    }\r
+    return out;\r
+  }\r
+\r
+  public double[] component(int n) {\r
+    // n = index of eigenvector\r
+    double[] out = new double[m.rows];\r
+\r
+    for (int i=0; i < m.rows; i++) {\r
+      out[i] = component(i,n);\r
+    }\r
+    return out;\r
+  }\r
+  public double component(int row, int n) {\r
+    double out = 0.0;\r
+\r
+    for (int i = 0; i < symm.cols; i++) {\r
+      out += symm.value[row][i] * eigenvector.value[i][n];\r
+    }\r
+    return out/eigenvector.d[n];\r
+  }\r
+\r
+  public void checkEigenvector(int n,PrintStream ps) {\r
+    ps.println(" --- Eigenvector " + n  + " --- ");\r
+\r
+    double[] eigenv = eigenvector.getColumn(n);\r
+\r
+    for (int i=0; i < eigenv.length;i++) {\r
+      Format.print(ps,"%15.4f",eigenv[i]);\r
+    }\r
+\r
+    System.out.println();\r
+\r
+    double[] neigenv = symm.vectorPostMultiply(eigenv);\r
+    System.out.println(" --- symmat * eigenv / lambda --- ");\r
+    if (eigenvector.d[n] > 1e-4) {\r
+      for (int i=0; i < neigenv.length;i++) {\r
+        Format.print(System.out,"%15.4f",neigenv[i]/eigenvector.d[n]);\r
+      }\r
+    }\r
+    System.out.println();\r
+  }\r
+\r
+  public void run() {\r
+    Matrix mt = m.transpose();\r
+    //    System.out.println(" --- OrigT * Orig ---- ");\r
+    eigenvector = mt.preMultiply(m2);\r
+    //  eigenvector.print(System.out);\r
+    symm = eigenvector.copy();\r
+\r
+    //TextArea ta = new TextArea(25,72);\r
+    //TextAreaPrintStream taps = new TextAreaPrintStream(System.out,ta);\r
+    //Frame f = new Frame("PCA output");\r
+    //f.resize(500,500);\r
+    //f.setLayout(new BorderLayout());\r
+    //f.add("Center",ta);\r
+    //f.show();\r
+    //symm.print(taps);\r
+    long tstart = System.currentTimeMillis();\r
+    eigenvector.tred();\r
+    long tend = System.currentTimeMillis();\r
+    //taps.println("Time take for tred = " + (tend-tstart) + "ms");\r
+    //taps.println(" ---Tridiag transform matrix ---");\r
+\r
+    //taps.println(" --- D vector ---");\r
+    //eigenvector.printD(taps);\r
+    //taps.println();\r
+    //taps.println(" --- E vector ---");\r
+    //    eigenvector.printE(taps);\r
+    //taps.println();\r
+\r
+    // Now produce the diagonalization matrix\r
+    tstart = System.currentTimeMillis();\r
+    eigenvector.tqli();\r
+    tend = System.currentTimeMillis();\r
+    //System.out.println("Time take for tqli = " + (tend-tstart) + " ms");\r
+\r
+    //System.out.println(" --- New diagonalization matrix ---");\r
+\r
+    //System.out.println(" --- Eigenvalues ---");\r
+    //eigenvector.printD(taps);\r
+\r
+    //System.out.println();\r
+\r
+    // for (int i=0; i < eigenvector.cols; i++) {\r
+    // checkEigenvector(i,taps);\r
+    // taps.println();\r
+    // }\r
+\r
+    //  taps.println();\r
+    //  taps.println("Transformed sequences = ");\r
+    // Matrix trans =  m.preMultiply(eigenvector);\r
+    //  trans.print(System.out);\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java
new file mode 100755 (executable)
index 0000000..b054bc3
--- /dev/null
@@ -0,0 +1,15 @@
+/********************
+ * 2004 Jalview Reengineered
+ * Barton Group
+ * Dundee University
+ *
+ * AM Waterhouse
+ *******************/
+
+
+package jalview.bin;
+
+public class Cache
+{
+  public static String LAST_DIRECTORY = ".";
+}
diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java
new file mode 100755 (executable)
index 0000000..de8aa70
--- /dev/null
@@ -0,0 +1,50 @@
+/********************\r
+ * 2004 Jalview Reengineered\r
+ * Barton Group\r
+ * Dundee University\r
+ *\r
+ * AM Waterhouse\r
+ *******************/\r
+\r
+\r
+package jalview.bin;\r
+\r
+import jalview.gui.*;\r
+import javax.swing.*;\r
+\r
+public class Jalview\r
+{\r
+\r
+   public static void main(String[] args) {\r
+     try{\r
+       UIManager.setLookAndFeel //("javax.swing.plaf.metal.MetalLookAndFeel");\r
+           ( UIManager.getCrossPlatformLookAndFeelClassName() );\r
+\r
+       //   ("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");\r
+      // ("com.sun.java.swing.plaf.motif.MotifLookAndFeel" );\r
+     }\r
+     catch (Exception ex)\r
+     {}\r
+\r
+     JFrame.setDefaultLookAndFeelDecorated(true);\r
+     Desktop frame = new Desktop();\r
+     frame.setResizable(true);\r
+     frame.setVisible(true);\r
+\r
+\r
+     if(args!=null && args.length>0)\r
+     {\r
+         String file = args[0];\r
+         jalview.bin.Cache.LAST_DIRECTORY = file;\r
+         String protocol = "File";\r
+         if(file.indexOf("http:")>-1)\r
+           protocol = "URL";\r
+\r
+         String format = jalview.io.IdentifyFile.Identify(file, protocol);\r
+\r
+         frame.LoadFile(file, protocol, format);\r
+     }\r
+\r
+   }\r
+\r
+}\r
diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java
new file mode 100755 (executable)
index 0000000..69b66e0
--- /dev/null
@@ -0,0 +1,453 @@
+package jalview.datamodel;\r
+\r
+import jalview.jbgui.*;\r
+import jalview.schemes.*;\r
+import jalview.analysis.*;\r
+import jalview.util.*;\r
+import java.util.*;\r
+\r
+/** Data structure to hold and manipulate a multiple sequence alignment\r
+ */\r
+public class Alignment implements AlignmentI\r
+{\r
+\r
+  protected Vector      sequences;\r
+  protected Vector      groups = new Vector();\r
+  public    Hashtable[] cons;\r
+  protected String      gapCharacter = ".";\r
+\r
+  /** Make an alignment from an array of Sequences.\r
+  *\r
+  * @param sequences\r
+  */\r
+  public Alignment(SequenceI[] seqs) {\r
+    sequences = new Vector();\r
+\r
+    for (int i=0; i < seqs.length; i++) {\r
+      sequences.addElement(seqs[i]);\r
+    }\r
+\r
+    groups.addElement(new SequenceGroup());\r
+\r
+    int i = 0;\r
+\r
+    while (i < seqs.length) {\r
+      addToGroup((SequenceGroup)groups.elementAt(0),seqs[i]);\r
+      i++;\r
+    }\r
+\r
+    getWidth();\r
+  }\r
+\r
+  public Vector      getSequences() {\r
+    return sequences;\r
+  }\r
+\r
+  public SequenceI getSequenceAt(int i) {\r
+    if (i < sequences.size()) {\r
+      return (SequenceI)sequences.elementAt(i);\r
+    }\r
+\r
+    return null;\r
+  }\r
+\r
+  /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
+   * Should put the new sequence in a sequence group!!!\r
+   *\r
+   * @param snew\r
+   */\r
+  public void addSequence(SequenceI snew) {\r
+    sequences.addElement(snew);\r
+\r
+    ((SequenceGroup)groups.lastElement()).addSequence(snew);\r
+  }\r
+\r
+  public void addSequence(SequenceI[] seq) {\r
+    for (int i=0; i < seq.length; i++) {\r
+      addSequence(seq[i]);\r
+    }\r
+  }\r
+\r
+  /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
+   * Should put the new sequence in a sequence group!!!\r
+   *\r
+   * @param snew\r
+   */\r
+  public void setSequenceAt(int i,SequenceI snew) {\r
+    SequenceI oldseq = getSequenceAt(i);\r
+    deleteSequence(oldseq);\r
+\r
+    sequences.setElementAt(snew,i);\r
+\r
+    ((SequenceGroup)groups.lastElement()).addSequence(snew);\r
+  }\r
+\r
+  public Vector getGroups() {\r
+    return groups;\r
+  }\r
+\r
+  /** Sorts the sequences by sequence group size - largest to smallest.\r
+   * Uses QuickSort.\r
+   */\r
+  public void sortGroups() {\r
+    float[]  arr = new float [groups.size()];\r
+    Object[] s   = new Object[groups.size()];\r
+\r
+    for (int i=0; i < groups.size(); i++) {\r
+      arr[i] = ((SequenceGroup)groups.elementAt(i)).sequences.size();\r
+      s[i]   = groups.elementAt(i);\r
+    }\r
+\r
+    QuickSort.sort(arr,s);\r
+\r
+    Vector newg = new Vector(groups.size());\r
+\r
+    for (int i=groups.size()-1; i >= 0; i--) {\r
+      newg.addElement(s[i]);\r
+    }\r
+\r
+    groups = newg;\r
+  }\r
+\r
+  /** Takes out columns consisting entirely of gaps (-,.," ")\r
+   */\r
+  public void removeGaps()\r
+  {\r
+\r
+    SequenceI current;\r
+    int iSize = getWidth();\r
+    for (int i=0; i < iSize; i++)\r
+    {\r
+      boolean delete = true;\r
+      for (int j=0; j < getHeight(); j++)\r
+      {\r
+        current = getSequenceAt(j);\r
+        if (current.getLength() > i)\r
+        {\r
+           /* MC Should move this to a method somewhere */\r
+          if (current.getCharAt(i)!='-' && current.getCharAt(i)!='.' && current.getCharAt(i)!=' ')\r
+            delete = false;\r
+\r
+        }\r
+      }\r
+\r
+      if ( delete )\r
+      {\r
+        deleteColumns(i,i);\r
+        iSize--;\r
+        i--;\r
+      }\r
+    }\r
+\r
+\r
+  }\r
+\r
+  /** Returns an array of Sequences containing columns\r
+   * start to end (inclusive) only.\r
+   *\r
+   * @param start start column to fetch\r
+   * @param end end column to fetch\r
+   * @return Array of Sequences, ready to put into a new Alignment\r
+   */\r
+  public SequenceI[] getColumns(int start, int end) {\r
+    return getColumns(0,getHeight()-1,start,end);\r
+  }\r
+\r
+  /** Removes a range of columns (start to end inclusive).\r
+   *\r
+   * @param start Start column in the alignment\r
+   * @param end End column in the alignment\r
+   */\r
+  public void deleteColumns(int start, int end) {\r
+    deleteColumns(0,getHeight()-1,start,end);\r
+  }\r
+\r
+  public void deleteColumns(int seq1, int seq2, int start, int end) {\r
+\r
+    for (int i=0; i <= (end-start); i++) {\r
+      for (int j=seq1; j <= seq2; j++) {\r
+        getSequenceAt(j).deleteCharAt(start);\r
+      }\r
+    }\r
+  }\r
+\r
+  public void insertColumns(SequenceI[] seqs, int pos) {\r
+    if (seqs.length == getHeight()) {\r
+      for (int i=0; i < getHeight();i++) {\r
+        String tmp = new String(getSequenceAt(i).getSequence());\r
+        getSequenceAt(i).setSequence(tmp.substring(0,pos) + seqs[i].getSequence() + tmp.substring(pos));\r
+      }\r
+\r
+    }\r
+  }\r
+\r
+  public SequenceI[] getColumns(int seq1, int seq2, int start, int end) {\r
+    SequenceI[] seqs = new Sequence[(seq2-seq1)+1];\r
+    for (int i=seq1; i<= seq2; i++ ) {\r
+      seqs[i] = new Sequence(getSequenceAt(i).getName(),\r
+                             getSequenceAt(i).getSequence().substring(start,end),\r
+                             getSequenceAt(i).findPosition(start),\r
+                             getSequenceAt(i).findPosition(end));\r
+    }\r
+    return seqs;\r
+  }\r
+\r
+  public void trimLeft(int i) {\r
+    for (int j = 0;j< getHeight();j++) {\r
+\r
+      SequenceI s        = getSequenceAt(j);\r
+      int       newstart = s.findPosition(i);\r
+\r
+      s.setStart(newstart);\r
+      s.setSequence(s.getSequence().substring(i));\r
+\r
+    }\r
+  }\r
+\r
+  public void  trimRight(int i) {\r
+    for (int j = 0;j< getHeight();j++) {\r
+      SequenceI s      = getSequenceAt(j);\r
+      int       newend = s.findPosition(i);\r
+\r
+      s.setEnd(newend);\r
+      s.setSequence(s.getSequence().substring(0,i+1));\r
+    }\r
+  }\r
+\r
+  public void deleteSequence(SequenceI s)\r
+  {\r
+    for (int i=0; i < getHeight(); i++)\r
+      if (getSequenceAt(i) == s)\r
+        deleteSequence(i);\r
+  }\r
+\r
+  public void  deleteSequence(int i)\r
+  {\r
+    sequences.removeElementAt(i);\r
+  }\r
+\r
+\r
+  public Vector removeRedundancy(float threshold, Vector sel) {\r
+    Vector del = new Vector();\r
+\r
+    for (int i=1; i < sel.size(); i++) {\r
+      for (int j = 0; j < i; j++) {\r
+        // Only do the comparison if either have not been deleted\r
+        if (!del.contains((SequenceI)sel.elementAt(i)) ||\r
+            !del.contains((SequenceI)sel.elementAt(j))) {\r
+\r
+          float pid = Comparison.compare((SequenceI)sel.elementAt(j),\r
+                                         (SequenceI)sel.elementAt(i));\r
+\r
+          if (pid >= threshold) {\r
+            // Delete the shortest one\r
+            if (((SequenceI)sel.elementAt(j)).getSequence().length() >\r
+                ((SequenceI)sel.elementAt(i)).getSequence().length()) {\r
+              del.addElement(sel.elementAt(i));\r
+              System.out.println("Deleting sequence " + ((SequenceI)sel.elementAt(i)).getName());\r
+            } else {\r
+              del.addElement(sel.elementAt(i));\r
+              System.out.println("Deleting sequence " + ((SequenceI)sel.elementAt(i)).getName());\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    // Now delete the sequences\r
+    for (int i=0; i < del.size(); i++) {\r
+      System.out.println("Deleting sequence " + ((SequenceI)del.elementAt(i)).getName());\r
+      deleteSequence((SequenceI)del.elementAt(i));\r
+    }\r
+\r
+    return del;\r
+  }\r
+\r
+  public void sortByPID(SequenceI s) {\r
+\r
+    float     scores[] = new float[getHeight()];\r
+    SequenceI seqs[]   = new SequenceI[getHeight()];\r
+\r
+    for (int i = 0; i < getHeight(); i++) {\r
+      scores[i] = Comparison.compare(getSequenceAt(i),s);\r
+      seqs[i]   = getSequenceAt(i);\r
+    }\r
+\r
+    QuickSort.sort(scores,0,scores.length-1,seqs);\r
+\r
+    int len = 0;\r
+\r
+    if (getHeight()%2 == 0) {\r
+      len = getHeight()/2;\r
+    } else {\r
+      len = (getHeight()+1)/2;\r
+    }\r
+\r
+    for (int i = 0; i < len; i++) {\r
+      SequenceI tmp = seqs[i];\r
+      sequences.setElementAt(seqs[getHeight()-i-1],i);\r
+      sequences.setElementAt(tmp,getHeight()-i-1);\r
+    }\r
+  }\r
+\r
+  public void sortByID() {\r
+    String    ids[]   = new String[getHeight()];\r
+    SequenceI seqs[]  = new SequenceI[getHeight()];\r
+\r
+    for (int i = 0; i < getHeight(); i++) {\r
+      ids[i]  = getSequenceAt(i).getName();\r
+      seqs[i] = getSequenceAt(i);\r
+    }\r
+\r
+    QuickSort.sort(ids,seqs);\r
+\r
+    int len = 0;\r
+\r
+    if (getHeight()%2 == 0) {\r
+      len = getHeight()/2;\r
+    } else {\r
+      len = (getHeight()+1)/2;\r
+      System.out.println("Sort len is odd = " + len);\r
+    }\r
+    for (int i = 0; i < len; i++) {\r
+      System.out.println("Swapping " + seqs[i].getName() + " and " + seqs[getHeight()-i-1].getName());\r
+      SequenceI tmp = seqs[i];\r
+      sequences.setElementAt(seqs[getHeight()-i-1],i);\r
+      sequences.setElementAt(tmp,getHeight()-i-1);\r
+    }\r
+  }\r
+\r
+  /**    */\r
+  public SequenceGroup findGroup(int i) {\r
+    return findGroup(getSequenceAt(i));\r
+  }\r
+\r
+  /**    */\r
+  public SequenceGroup findGroup(SequenceI s) {\r
+    for (int i = 0; i < this.groups.size();i++) {\r
+      SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
+      if (sg.sequences.contains(s)) {\r
+        return sg;\r
+      }\r
+    }\r
+    return null;\r
+\r
+  }\r
+  /**    */\r
+  public void addToGroup(SequenceGroup g, SequenceI s) {\r
+    if (!(g.sequences.contains(s))) {\r
+      g.sequences.addElement(s);\r
+    }\r
+  }\r
+  /**    */\r
+  public void removeFromGroup(SequenceGroup g,SequenceI s) {\r
+    if (g != null && g.sequences != null) {\r
+      if (g.sequences.contains(s)) {\r
+        g.sequences.removeElement(s);\r
+        if (g.sequences.size() == 0) {\r
+          groups.removeElement(g);\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  /**    */\r
+  public void addGroup(SequenceGroup sg) {\r
+    groups.addElement(sg);\r
+  }\r
+\r
+  /**    */\r
+  public SequenceGroup addGroup() {\r
+    SequenceGroup sg = new SequenceGroup();\r
+    groups.addElement(sg);\r
+    return sg;\r
+  }\r
+\r
+  /**    */\r
+  public void deleteGroup(SequenceGroup g) {\r
+    if (groups.contains(g)) {\r
+      groups.removeElement(g);\r
+    }\r
+  }\r
+\r
+  /**    */\r
+  public SequenceI findName(String name) {\r
+    int i = 0;\r
+    while (i < sequences.size()) {\r
+      SequenceI s = getSequenceAt(i);\r
+      if (s.getName().equals(name)) {\r
+        return s;\r
+      }\r
+      i++;\r
+    }\r
+    return null;\r
+  }\r
+\r
+  /**    */\r
+  public int findIndex(SequenceI s) {\r
+    int i=0;\r
+    while (i < sequences.size()) {\r
+      if (s == getSequenceAt(i)) {\r
+        return i;\r
+      }\r
+      i++;\r
+    }\r
+    return -1;\r
+  }\r
+\r
+  public int getHeight() {\r
+    return sequences.size();\r
+  }\r
+\r
+\r
+  public int getWidth()\r
+  {\r
+    int maxLength = -1;\r
+    for (int i = 0; i < sequences.size(); i++)\r
+    {\r
+      if (getSequenceAt(i).getLength() > maxLength)\r
+        maxLength = getSequenceAt(i).getLength();\r
+    }\r
+\r
+    return maxLength;\r
+  }\r
+\r
+\r
+  public int getMaxIdLength() {\r
+    int max = 0;\r
+    int i   = 0;\r
+\r
+    while (i < sequences.size()) {\r
+      SequenceI seq = getSequenceAt(i);\r
+      String    tmp = seq.getName() + "/" + seq.getStart() + "-" + seq.getEnd();\r
+\r
+      if (tmp.length() > max) {\r
+        max = tmp.length();\r
+      }\r
+\r
+      i++;\r
+    }\r
+    return max;\r
+  }\r
+\r
+  public void setGapCharacter(String gc) {\r
+    gapCharacter = gc;\r
+  }\r
+\r
+  public String getGapCharacter() {\r
+    return gapCharacter;\r
+  }\r
+\r
+  public Vector getAAFrequency()\r
+  {\r
+    return AAFrequency.calculate(sequences, 0, getWidth());\r
+  }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/datamodel/AlignmentI.java b/src/jalview/datamodel/AlignmentI.java
new file mode 100755 (executable)
index 0000000..6a1e026
--- /dev/null
@@ -0,0 +1,64 @@
+package jalview.datamodel;\r
+\r
+import jalview.jbgui.*;\r
+import java.util.*;\r
+\r
+/** Data structure to hold and manipulate a multiple sequence alignment\r
+ */\r
+public interface AlignmentI {\r
+\r
+  public int         getHeight() ;\r
+  public int         getWidth() ;\r
+  public int         getMaxIdLength() ;\r
+\r
+  public Vector      getSequences();\r
+  public SequenceI   getSequenceAt(int i);\r
+\r
+  public void        addSequence(SequenceI seq) ;\r
+  public void        setSequenceAt(int i,SequenceI seq);\r
+\r
+  public void        deleteSequence(SequenceI s) ;\r
+  public void        deleteSequence(int i) ;\r
+\r
+  public SequenceI[] getColumns(int start, int end) ;\r
+  public SequenceI[] getColumns(int seq1, int seq2, int start, int end) ;\r
+\r
+  public void        deleteColumns(int start, int end) ;\r
+  public void        deleteColumns(int seq1, int seq2, int start, int end) ;\r
+\r
+  public void        insertColumns(SequenceI[] seqs, int pos) ;\r
+\r
+  public SequenceI   findName(String name) ;\r
+  public int         findIndex(SequenceI s) ;\r
+\r
+  // Modifying\r
+  public void        trimLeft(int i) ;\r
+  public void        trimRight(int i) ;\r
+\r
+  public void        removeGaps() ;\r
+  public Vector      removeRedundancy(float threshold, Vector sel) ;\r
+\r
+\r
+  // Grouping methods\r
+  public SequenceGroup findGroup(int i) ;\r
+  public SequenceGroup findGroup(SequenceI s) ;\r
+  public void          addToGroup(SequenceGroup g, SequenceI s) ;\r
+  public void          removeFromGroup(SequenceGroup g,SequenceI s) ;\r
+  public void          addGroup(SequenceGroup sg) ;\r
+  public SequenceGroup addGroup() ;\r
+  public void          deleteGroup(SequenceGroup g) ;\r
+  public Vector        getGroups();\r
+\r
+  // Sorting\r
+  public void          sortGroups() ;\r
+  public void          sortByPID(SequenceI s) ;\r
+  public void          sortByID() ;\r
+\r
+  public void          setGapCharacter(String gc);\r
+  public String        getGapCharacter();\r
+\r
+    public Vector        getAAFrequency();\r
+}\r
+\r
+\r
+\r
diff --git a/src/jalview/datamodel/BinaryNode.java b/src/jalview/datamodel/BinaryNode.java
new file mode 100755 (executable)
index 0000000..77b5971
--- /dev/null
@@ -0,0 +1,73 @@
+package jalview.datamodel;\r
+\r
+public class BinaryNode {\r
+\r
+  Object element;\r
+  String name;\r
+  BinaryNode left;\r
+  BinaryNode right;\r
+  BinaryNode parent;\r
+  public int bootstrap;\r
+\r
+  public BinaryNode() {\r
+    left = right = parent = null;\r
+  }\r
+\r
+  public BinaryNode(Object element, BinaryNode parent,String name) {\r
+    this.element = element;\r
+    this.parent  = parent;\r
+    this.name    = name;\r
+\r
+    left=right=null;\r
+  }\r
+\r
+  public Object element() {\r
+    return element;\r
+  }\r
+\r
+  public Object setElement(Object v) {\r
+    return element=v;\r
+  }\r
+\r
+  public BinaryNode left() {\r
+    return left;\r
+  }\r
+\r
+  public BinaryNode setLeft(BinaryNode n) {\r
+    return left=n;\r
+  }\r
+\r
+  public BinaryNode right() {\r
+    return right;\r
+  }\r
+\r
+  public BinaryNode setRight(BinaryNode n) {\r
+    return right=n;\r
+  }\r
+\r
+  public BinaryNode parent() {\r
+    return parent;\r
+  }\r
+\r
+  public BinaryNode setParent(BinaryNode n) {\r
+    return parent=n;\r
+  }\r
+\r
+  public boolean isLeaf() {\r
+    return (left == null) && (right == null);\r
+  }\r
+\r
+    public void setName(String name) {\r
+         this.name = name;\r
+    }\r
+    public String getName() {\r
+       return this.name;\r
+    }\r
+  public void setBootstrap(int boot) {\r
+    this.bootstrap = boot;\r
+       }\r
+  public int getBootstrap() {\r
+    return bootstrap;\r
+  }\r
+}\r
+\r
diff --git a/src/jalview/datamodel/BinarySequence.java b/src/jalview/datamodel/BinarySequence.java
new file mode 100755 (executable)
index 0000000..b029641
--- /dev/null
@@ -0,0 +1,109 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+package jalview.datamodel;\r
+\r
+import jalview.io.*;\r
+import jalview.analysis.PCA;\r
+import jalview.jbgui.*;\r
+import jalview.schemes.*;\r
+\r
+import java.awt.*;\r
+\r
+public class BinarySequence extends Sequence {\r
+  int[] binary;\r
+  double[] dbinary;\r
+\r
+  public BinarySequence(SequenceI s) {\r
+    super(s.getName(),s.getSequence(),s.getStart(),s.getEnd());\r
+  }\r
+\r
+  public BinarySequence(String name, String sequence, int start, int end) {\r
+    super(name,sequence,start,end);\r
+  }\r
+\r
+  public void encode() {\r
+    // Set all matrix to 0\r
+    dbinary = new double[getSequence().length() * 21];\r
+    int nores = 21;\r
+    for (int i = 0; i < dbinary.length; i++) {\r
+      dbinary[i] = 0.0;\r
+    }\r
+\r
+    for (int i=0; i < getSequence().length(); i++ ) {\r
+      int aanum = 20;\r
+      try {\r
+        aanum = ((Integer)ResidueProperties.getAAHash().get(getSequence().substring(i,i+1))).intValue();\r
+      } catch (NullPointerException e) {\r
+        aanum = 20;\r
+      }\r
+      if (aanum > 20) {\r
+        aanum = 20;\r
+      }\r
+\r
+      dbinary[i* nores + aanum] = 1.0;\r
+\r
+    }\r
+  }\r
+\r
+  public void blosumEncode() {\r
+\r
+    // Set all matrix to 0\r
+    dbinary = new double[getSequence().length() * 21];\r
+    int nores = 21;\r
+    //for (int i = 0; i < dbinary.length; i++) {\r
+    //  dbinary[i] = 0.0;\r
+    //}\r
+\r
+    for (int i=0; i < getSequence().length(); i++ ) {\r
+      int aanum = 20;\r
+      try {\r
+        aanum = ((Integer)ResidueProperties.getAAHash().get(getSequence().substring(i,i+1))).intValue();\r
+      } catch (NullPointerException e) {\r
+        aanum = 20;\r
+      }\r
+      if (aanum > 20) {\r
+        aanum = 20;\r
+      }\r
+\r
+      // Do the blosum thing\r
+      for (int j = 0;j < 20;j++) {\r
+        dbinary[i * nores + j] = ResidueProperties.getBLOSUM62()[aanum][j];\r
+      }\r
+\r
+    }\r
+  }\r
+\r
+  public String toBinaryString() {\r
+    String out = "";\r
+    for (int i=0; i < binary.length;i++) {\r
+      out += (new Integer(binary[i])).toString();\r
+      if (i < binary.length-1) {\r
+        out += " ";\r
+      }\r
+    }\r
+    return out;\r
+  }\r
+\r
+  public double[] getDBinary() {\r
+    return dbinary;\r
+  }\r
+\r
+  public static void printMemory(Runtime rt) {\r
+    System.out.println("Free memory = " + rt.freeMemory());\r
+  }\r
+}\r
diff --git a/src/jalview/datamodel/FeaturePair.java b/src/jalview/datamodel/FeaturePair.java
new file mode 100755 (executable)
index 0000000..025d2af
--- /dev/null
@@ -0,0 +1,118 @@
+package jalview.datamodel;\r
+\r
+import java.util.*;\r
+\r
+public class FeaturePair {\r
+  SequenceFeature f1;\r
+  SequenceFeature f2;\r
+\r
+  public FeaturePair() {\r
+      this.f1 = new SequenceFeature();\r
+      this.f2 = new SequenceFeature();\r
+  }\r
+  public FeaturePair(SequenceFeature f1, SequenceFeature f2) {\r
+    this.f1 = f1;\r
+    this.f2 = f2;\r
+  }\r
+  public void        setQueryFeature(SequenceFeature feature) {\r
+    this.f1 = feature;\r
+  }\r
+  public SequenceFeature getQueryFeature() {\r
+    return f1;\r
+  }\r
+  public void        setHitFeature(SequenceFeature feature) {\r
+    this.f2 = feature;\r
+  }\r
+  public SequenceFeature getHitFeature() {\r
+    return f2;\r
+  }\r
+  public void        setStart(int start) {\r
+    f1.setStart(start);\r
+  }\r
+  public int        getStart() {\r
+    return f1.getStart();\r
+  }\r
+  public void        setEnd(int end) {\r
+    f1.setEnd(end);\r
+  }\r
+  public int        getEnd() {\r
+    return f1.getEnd();\r
+  }\r
+  public void        setStrand(int strand) {\r
+    f1.setStrand(strand);\r
+  }\r
+  public int         getStrand() {\r
+    return f1.getStrand();\r
+  }\r
+  public String      getId() {\r
+    return f1.getId();\r
+  }\r
+  public void setId(String id) {\r
+      f1.setId(id);\r
+  }\r
+  public double      getScore() {\r
+    return f1.getScore();\r
+  }\r
+  public void        setScore(double score) {\r
+    f1.setScore(score);\r
+      f2.setScore(score);\r
+  }\r
+\r
+  public String      getHitId() {\r
+    return f2.getId();\r
+  }\r
+  public void        setHitId(String name) {\r
+    f2.setId(name);\r
+  }\r
+  public int        getHstart() {\r
+    return f2.getStart();\r
+  }\r
+  public void        setHstart(int start) {\r
+    f2.setStart(start);\r
+  }\r
+  public int        getHend() {\r
+    return f2.getEnd();\r
+  }\r
+  public void        setHend(int end) {\r
+    f2.setEnd(end);\r
+  }\r
+  public void        setHstrand(int strand) {\r
+    f2.setStrand(strand);\r
+  }\r
+  public int         getHstrand() {\r
+    return f2.getStrand();\r
+  }\r
+\r
+  public double getPValue() {\r
+      return f1.getPValue();\r
+  }\r
+  public void setPValue(double value) {\r
+      f1.setPValue(value);\r
+      f2.setPValue(value);\r
+  }\r
+  public double getPercentId() {\r
+      return f1.getPercentId();\r
+  }\r
+  public void setPercentId(double pid) {\r
+      f1.setPercentId(pid);\r
+      f2.setPercentId(pid);\r
+  }\r
+  \r
+  public void invert() {\r
+    SequenceFeature tmp = f1;\r
+    f1 = f2;\r
+    f2 = tmp;\r
+  }\r
+\r
+  public String toGFFString() {\r
+      String tmp = f1.toGFFString();\r
+\r
+      tmp = tmp + "\t" + getHitId() + "\t" + getHstart() + "\t" + getHend() + "\t" + getPValue() + "\t" + getPercentId();\r
+\r
+      return tmp;\r
+  }\r
+  \r
+  public static void main(String[] args) {\r
+      FeaturePair fp  = new FeaturePair();\r
+  }\r
+}
\ No newline at end of file
diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java
new file mode 100755 (executable)
index 0000000..1875557
--- /dev/null
@@ -0,0 +1,157 @@
+package jalview.datamodel;\r
+\r
+\r
+import java.awt.*;\r
+\r
+public class Sequence implements SequenceI {\r
+  protected String   name;\r
+  protected String   sequence;\r
+  protected int      start;\r
+  protected int      end;\r
+  protected String   description;\r
+  protected int      charHeight;\r
+  protected String   displayId;\r
+  protected Color    color = Color.black;\r
+\r
+  public Sequence(String name, String sequence, int start, int end)\r
+  {\r
+\r
+    this.name     = name;\r
+    this.sequence = sequence;\r
+    this.start    = start;\r
+    this.end      = end;\r
+\r
+    setDisplayId();\r
+\r
+  }\r
+\r
+  public Sequence(String name,String sequence) {\r
+    this(name,sequence,1,sequence.length());\r
+  }\r
+  public Sequence(SequenceI seq) {\r
+    this(seq.getName(),seq.getSequence(),seq.getStart(),seq.getEnd());\r
+  }\r
+  public String getDisplayId() {\r
+    return displayId;\r
+  }\r
+  public void setDisplayId() {\r
+    displayId = name + "/" + start + "-" + end;\r
+  }\r
+  public void setName(String name) {\r
+    this.name = name;\r
+    setDisplayId();\r
+  }\r
+  public String getName() {\r
+    return this.name;\r
+  }\r
+  public void setStart(int start) {\r
+    this.start = start;\r
+    setDisplayId();\r
+  }\r
+  public int getStart() {\r
+    return this.start;\r
+  }\r
+  public void setEnd(int end) {\r
+    this.end = end;\r
+    setDisplayId();\r
+  }\r
+  public int getEnd() {\r
+    return this.end;\r
+  }\r
+  public int getLength() {\r
+    return this.sequence.length();\r
+  }\r
+  public void setSequence(String seq) {\r
+    this.sequence = seq;\r
+  }\r
+  public String getSequence() {\r
+    return this.sequence;\r
+  }\r
+  public String getSequence(int start,int end) {\r
+    return this.sequence.substring(start,end);\r
+  }\r
+\r
+  public char getCharAt(int i) {\r
+    if (i < sequence.length()) {\r
+      return sequence.charAt(i);\r
+    } else {\r
+      return ' ';\r
+    }\r
+  }\r
+  public void setDescription(String desc) {\r
+    this.description = desc;\r
+  }\r
+  public String getDescription() {\r
+    return this.description;\r
+  }\r
+\r
+  public int findIndex(int pos) {\r
+    // returns the alignment position for a residue\r
+    int j = start;\r
+    int i = 0;\r
+\r
+    while (i< sequence.length() && j <= end && j <= pos) {\r
+\r
+      String s = sequence.substring(i,i+1);\r
+\r
+      if (!(s.equals(".") || s.equals("-") || s.equals(" "))) {\r
+        j++;\r
+      }\r
+      i++;\r
+    }\r
+    if (j == end && j < pos) {\r
+      return end+1;\r
+    } else {\r
+\r
+      return i;\r
+    }\r
+  }\r
+\r
+  public int findPosition(int i) {\r
+    // Returns the sequence position for an alignment position\r
+    int j   = 0;\r
+    int pos = start;\r
+\r
+    while (j < i) {\r
+      String s = sequence.substring(j,j+1);\r
+\r
+      if (!(s.equals(".") || s.equals("-") || s.equals(" "))) {\r
+        pos++;\r
+      }\r
+      j++;\r
+    }\r
+    return pos;\r
+  }\r
+  public void deleteCharAt(int i)\r
+  {\r
+    StringBuffer sbuffer = new StringBuffer(sequence);\r
+    sbuffer.deleteCharAt(i);\r
+    sequence = sbuffer.toString();\r
+  }\r
+\r
+  public void insertCharAt(int i, char c)\r
+  {\r
+    insertCharAt(i,c,true);\r
+  }\r
+\r
+  public void insertCharAt(int i,char c,boolean chop) {\r
+\r
+    String tmp = new String(sequence);\r
+\r
+    if (i < sequence.length()) {\r
+      sequence = tmp.substring(0,i) + String.valueOf(c) + tmp.substring(i);\r
+    } else {\r
+      sequence = tmp + String.valueOf(c);\r
+    }\r
+\r
+  }\r
+\r
+  public void        setColor(Color c) {\r
+    this.color = c;\r
+  }\r
+\r
+  public Color       getColor() {\r
+    return color;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/datamodel/SequenceFeature.java b/src/jalview/datamodel/SequenceFeature.java
new file mode 100755 (executable)
index 0000000..2512978
--- /dev/null
@@ -0,0 +1,197 @@
+package jalview.datamodel;\r
+\r
+import jalview.util.*;\r
+import jalview.jbgui.*;\r
+import jalview.schemes.*;\r
+import java.awt.*;\r
+\r
+public class SequenceFeature {\r
+  int start;\r
+  int end;\r
+  String type;\r
+  String description;\r
+  Color color;\r
+  Sequence sequence;\r
+  String id;\r
+  double score;\r
+  int strand;\r
+  double pvalue;\r
+  double pid;\r
+\r
+  public SequenceFeature() {\r
+  }\r
+\r
+  public SequenceFeature(Sequence sequence,String type, int start, int end, String description) {\r
+    this.sequence = sequence;\r
+    this.type = type;\r
+    this.start = start;\r
+    this.end = end;\r
+    this.description = description;\r
+\r
+    setColor();\r
+  }\r
+\r
+\r
+  public String toGFFString() {\r
+      String gff = id + "\t" + type + "\tfeature\t" + start + "\t" + end + "\t" + score + "\t" + strand + "\t.";\r
+      return gff;\r
+  }\r
+  public double getScore() {\r
+      return score;\r
+  }\r
+\r
+  public void setScore(double score) {\r
+      this.score = score;\r
+  }\r
+\r
+  public String getId() {\r
+      return this.id;\r
+  }\r
+  public void setId(String id) {\r
+      this.id = id;\r
+  }\r
+  public void setSequence(Sequence seq) {\r
+    this.sequence = seq;\r
+  }\r
+  public void setStart(int start) {\r
+      this.start = start;\r
+  }\r
+  public void setEnd(int end) {\r
+      this.end = end;\r
+  }\r
+  public int getStrand() {\r
+      return strand;\r
+  }\r
+  public void setStrand(int strand) {\r
+      this.strand = strand;\r
+  }\r
+  public int getStart() {\r
+    return start;\r
+  }\r
+\r
+  public int getEnd() {\r
+    return end;\r
+  }\r
+\r
+  public String getType() {\r
+    return type;\r
+  }\r
+\r
+  public String getDescription() {\r
+    return description;\r
+  }\r
+\r
+  public double getPValue() {\r
+      return pvalue;\r
+  }\r
+  public void setPValue(double value) {\r
+      this.pvalue = value;\r
+  }\r
+  public double getPercentId() {\r
+      return pid;\r
+  }\r
+  public void setPercentId(double pid) {\r
+      this.pid = pid;\r
+  }\r
+  public Color getColor() {\r
+    return color;\r
+  }\r
+\r
+  public void setColor() {\r
+    if (type.equals("CHAIN")) {\r
+      color = Color.white;\r
+    } else if (type.equals("DOMAIN")) {\r
+      color = Color.white;\r
+    } else if (type.equals("TRANSMEM")) {\r
+      color = Color.red.darker();\r
+    } else if (type.equals("SIGNAL")) {\r
+      color = Color.cyan;\r
+    } else if (type.equals("HELIX")) {\r
+      color = Color.magenta;\r
+    } else if (type.equals("TURN")) {\r
+      color = Color.cyan;\r
+    } else if (type.equals("SHEET")) {\r
+      color = Color.yellow;\r
+    } else if (type.equals("STRAND")) {\r
+      color = Color.yellow;\r
+    } else if (type.equals("CARBOHYD")) {\r
+      color = Color.pink;\r
+    } else if (type.equals("ACT_SITE")) {\r
+      color = Color.red;\r
+    } else if (type.equals("TRANSIT")) {\r
+      color = Color.orange;\r
+    } else if (type.equals("VARIANT")) {\r
+      color = Color.orange.darker();\r
+    } else if (type.equals("BINDING")) {\r
+      color = Color.blue;\r
+    } else if (type.equals("DISULFID")) {\r
+      color = Color.yellow.darker();\r
+    } else if (type.equals("NP_BIND")) {\r
+      color = Color.red;\r
+    } else if (type.indexOf("BIND") > 0) {\r
+      color = Color.red;\r
+    } else {\r
+      color = Color.lightGray;\r
+    }\r
+  }\r
+  public String print() {\r
+    String tmp = new Format("%15s").form(type);\r
+    tmp = tmp +  new Format("%6d").form(start);\r
+    tmp = tmp +  new Format("%6d").form(end);\r
+    tmp = tmp +  " " + description;\r
+    return tmp;\r
+  }\r
+  public void draw(Graphics g, int fstart, int fend, int x1, int y1, int width, int height) {\r
+    g.setColor(new Color((float)(Math.random()),(float)(Math.random()),(float)(Math.random())));\r
+\r
+    //    int xstart = sequence.findIndex(start);\r
+    //int xend = sequence.findIndex(end);\r
+    int xstart = start;\r
+    int xend = end;\r
+    long tstart = System.currentTimeMillis();\r
+    if (!(xend < fstart && xstart > fend)) {\r
+\r
+      if (xstart > fstart) {\r
+        x1 = x1 + (xstart-fstart)*width;\r
+        fstart = xstart;\r
+      }\r
+\r
+      if (xend < fend) {\r
+        fend = xend;\r
+      }\r
+\r
+      for (int i = fstart; i <= fend; i++) {\r
+        String s = sequence.sequence.substring(i,i+1);\r
+        if (!(s.equals(".") || s.equals("-") || s.equals(" "))) {\r
+          g.fillRect(x1+(i-fstart)*width,y1,width,height);\r
+        } else {\r
+          g.drawString("-",x1+(i-fstart)*width,y1+height);\r
+        }\r
+      }\r
+\r
+    }\r
+    long tend = System.currentTimeMillis();\r
+    System.out.println("Time = " + (tend-tstart) + "ms");\r
+\r
+  }\r
+\r
+  public static void main(String[] args) {\r
+      SequenceFeature sf = new SequenceFeature();\r
+\r
+      System.out.println("Feature " + sf);\r
+  }\r
+  public static int CHAIN = 0;\r
+  public static int DOMAIN = 1;\r
+  public static int TRANSMEM = 2;\r
+  public static int SIGNAL = 3;\r
+  public static int HELIX = 4;\r
+  public static int TURN = 5;\r
+  public static int SHEET = 6;\r
+  public static int CARBOHYD = 7;\r
+  public static int ACT_SITE = 8;\r
+  public static int TRANSIT = 9;\r
+  public static int VARIANT = 10;\r
+  public static int BINDING = 11;\r
+\r
+}\r
+\r
diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java
new file mode 100755 (executable)
index 0000000..de746ba
--- /dev/null
@@ -0,0 +1,107 @@
+package jalview.datamodel;\r
+\r
+import jalview.jbgui.*;\r
+import jalview.schemes.*;\r
+import jalview.analysis.*;\r
+import jalview.datamodel.*;\r
+\r
+import java.util.Vector;\r
+import java.awt.*;\r
+\r
+public class SequenceGroup {\r
+    boolean isSelected;\r
+    boolean displayBoxes;\r
+    boolean displayText;\r
+    boolean colourText;\r
+    boolean display;\r
+    Conservation conserve;\r
+    Vector   aaFrequency;\r
+    boolean     aaFrequencyValid = false;\r
+    Vector sequences = new Vector();\r
+    int         width = -1;\r
+\r
+\r
+  public SequenceGroup() {\r
+    this.isSelected = false;\r
+    this.displayBoxes = true;\r
+    this.displayText = true;\r
+    this.colourText = false;\r
+    this.display = true;\r
+  }\r
+\r
+  public SequenceGroup( ColourSchemeI scheme, boolean isSelected,\r
+                        boolean displayBoxes, boolean displayText,\r
+                        boolean colourText,\r
+                        boolean display) {\r
+\r
+    this.isSelected = isSelected;\r
+    this.displayBoxes = displayBoxes;\r
+    this.displayText = displayText;\r
+    this.colourText = colourText;\r
+    this.display = display;\r
+  }\r
+\r
+  public Conservation getConservation() {\r
+     return conserve;\r
+  }\r
+  public void addSequence(SequenceI s) {\r
+    sequences.addElement(s);\r
+  }\r
+\r
+  public void deleteSequence(SequenceI s) {\r
+    sequences.removeElement(s);\r
+  }\r
+\r
+  public void setColourText(boolean state) {\r
+    colourText = state;\r
+  }\r
+  public boolean getColourText() {\r
+    return colourText;\r
+  }\r
+\r
+  public void setDisplayText(boolean state) {\r
+    displayText = state;\r
+  }\r
+\r
+  public boolean getDisplayText() {\r
+    return displayText;\r
+  }\r
+\r
+  public void setDisplayBoxes(boolean state) {\r
+    displayBoxes = state;\r
+  }\r
+\r
+  public boolean getDisplayBoxes() {\r
+    return displayBoxes;\r
+  }\r
+\r
+    public int getSize() {\r
+       return sequences.size();\r
+    }\r
+    public SequenceI  getSequenceAt(int i) {\r
+       return (SequenceI)sequences.elementAt(i);\r
+    }\r
+\r
+    public Vector getAAFrequency() {\r
+       if (aaFrequency == null || aaFrequencyValid == false) {\r
+           aaFrequency = AAFrequency.calculate(sequences,1,getWidth());\r
+           aaFrequencyValid = true;\r
+       }\r
+       return aaFrequency;\r
+    }\r
+    public int getWidth() {\r
+       // MC This needs to get reset when characters are inserted and deleted\r
+       if (width == -1) {\r
+           for (int i = 0; i < sequences.size(); i++) {\r
+               SequenceI seq = (SequenceI)sequences.elementAt(i);\r
+               if (seq.getLength() > width) {\r
+                   width = seq.getLength();\r
+               }\r
+           }\r
+       }\r
+\r
+       return width;\r
+    }\r
+}\r
+\r
+\r
diff --git a/src/jalview/datamodel/SequenceI.java b/src/jalview/datamodel/SequenceI.java
new file mode 100755 (executable)
index 0000000..2183131
--- /dev/null
@@ -0,0 +1,50 @@
+package jalview.datamodel;\r
+\r
+import jalview.jbgui.*;\r
+import java.awt.*;\r
+\r
+import java.util.Vector;\r
+\r
+public interface SequenceI {\r
+  public void        setName(String name);\r
+  public String      getName();\r
+\r
+  public void        setStart(int start);\r
+  public int         getStart();\r
+\r
+  public String      getDisplayId();\r
+\r
+  public void        setEnd(int end);\r
+  public int         getEnd();\r
+\r
+  public int         getLength();\r
+\r
+  public void        setSequence(String sequence);\r
+  public String      getSequence();\r
+  public String      getSequence(int start,int end);\r
+  public char        getCharAt(int i);\r
+\r
+  public void        setDescription(String desc);\r
+  public String      getDescription();\r
+\r
+  public int         findIndex(int pos);\r
+  public int         findPosition(int i);\r
+\r
+  public void       deleteCharAt(int i);\r
+  public void       insertCharAt(int i, char c);\r
+  public void       insertCharAt(int i,char c,boolean chop);\r
+\r
+  public void        setColor(Color c);\r
+  public Color       getColor();\r
+  }\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/datamodel/SequenceNode.java b/src/jalview/datamodel/SequenceNode.java
new file mode 100755 (executable)
index 0000000..6e35ee3
--- /dev/null
@@ -0,0 +1,21 @@
+package jalview.datamodel;\r
+\r
+import java.awt.Color;\r
+\r
+public class SequenceNode extends BinaryNode {\r
+\r
+  public float dist;\r
+  public int count;\r
+  public float height;\r
+  public float ycount;\r
+  public Color color = Color.black;\r
+\r
+  public SequenceNode() {\r
+    super();\r
+  }\r
+  \r
+  public SequenceNode(Object val, SequenceNode parent, float dist,String name) {\r
+    super(val,parent,name);\r
+    this.dist = dist;\r
+  }\r
+}\r
diff --git a/src/jalview/datamodel/SequencePoint.java b/src/jalview/datamodel/SequencePoint.java
new file mode 100755 (executable)
index 0000000..093c45a
--- /dev/null
@@ -0,0 +1,36 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.datamodel;\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+\r
+public class SequencePoint {\r
+\r
+  // SMJS PUBLIC\r
+  public SequenceI sequence;\r
+  public float[] coord;\r
+  // SMJS ENDPUBLIC\r
+\r
+  public SequencePoint(SequenceI sequence, float[] coord) {\r
+    this.sequence = sequence;\r
+    this.coord = coord;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java
new file mode 100755 (executable)
index 0000000..af8a6c0
--- /dev/null
@@ -0,0 +1,509 @@
+/********************\r
+ * 2004 Jalview Reengineered\r
+ * Barton Group\r
+ * Dundee University\r
+ *\r
+ * AM Waterhouse\r
+ *******************/\r
+\r
+\r
+\r
+\r
+package jalview.gui;\r
+\r
+import jalview.jbgui.GAlignFrame;\r
+import jalview.schemes.*;\r
+import jalview.datamodel.*;\r
+import jalview.analysis.*;\r
+import jalview.io.*;\r
+import java.awt.event.*;\r
+import java.awt.*;\r
+import javax.swing.*;\r
+\r
+public class AlignFrame extends GAlignFrame\r
+{\r
+  AlignmentPanel alignPanel;\r
+  AlignViewport viewport;\r
+  public AlignFrame(AlignmentI al)\r
+  {\r
+    super();\r
+    viewport = new AlignViewport(al,true,true,true,false);\r
+    alignPanel = new AlignmentPanel(this, viewport);\r
+    getContentPane().add(alignPanel, java.awt.BorderLayout.CENTER);\r
+    fontNameMenuItem.setText(viewport.getFont().getName());\r
+    fontSizeMenuItem.setText(viewport.getFont().getSize()+"");\r
+  }\r
+\r
+  protected void saveAs_actionPerformed(ActionEvent e)\r
+  {\r
+    JFileChooser chooser = new JFileChooser(jalview.bin.Cache.LAST_DIRECTORY);\r
+    chooser.setDialogTitle("Save Alignment to file - "+e.getActionCommand() +" format.");\r
+    chooser.setToolTipText("Save");\r
+    int value = chooser.showSaveDialog(this);\r
+    if(value == JFileChooser.APPROVE_OPTION)\r
+    {\r
+      String choice =  chooser.getSelectedFile().getPath();\r
+      jalview.bin.Cache.LAST_DIRECTORY = choice;\r
+      String output = FormatAdapter.get(e.getActionCommand(), viewport.getAlignment().getSequences());\r
+      try{\r
+        java.io.PrintWriter out = new java.io.PrintWriter( new java.io.FileWriter( choice )  );\r
+        out.println(output);\r
+        out.close();\r
+      }\r
+      catch(Exception ex){}\r
+    }\r
+\r
+  }\r
+\r
+  protected void outputText_actionPerformed(ActionEvent e)\r
+  {\r
+     CutAndPasteTransfer cap = new CutAndPasteTransfer(false);\r
+     JInternalFrame frame = new JInternalFrame();\r
+     cap.formatForOutput();\r
+     frame.setContentPane(cap);\r
+     Desktop.addInternalFrame(frame, "Alignment output - "+e.getActionCommand(), 600, 500);\r
+     cap.setText( FormatAdapter.get(e.getActionCommand(), viewport.getAlignment().getSequences()));\r
+  }\r
+\r
+  protected void htmlMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    HTMLOutput htmlOutput = new HTMLOutput(viewport.getAlignment(), alignPanel.seqPanel.getColourScheme());\r
+    htmlOutput = null;\r
+  }\r
+\r
+  public void saveAsPostscriptMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  public void closeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    try{\r
+      this.setClosed(true);\r
+    }catch(Exception ex){}\r
+  }\r
+\r
+  public void groupsMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  public void groupEditingMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    Selection sel = viewport.getSelection();\r
+    for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)\r
+      sel.addElement( viewport.getAlignment().getSequenceAt(i));\r
+    PaintRefresher.Refresh(null);\r
+  }\r
+\r
+  public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.getSelection().clear();\r
+    PaintRefresher.Refresh(null);\r
+  }\r
+\r
+  public void invertSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    Selection sel = viewport.getSelection();\r
+    for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)\r
+    {\r
+      if (sel.contains(viewport.getAlignment().getSequenceAt(i)))\r
+        sel.removeElement(viewport.getAlignment().getSequenceAt(i));\r
+      else\r
+        sel.addElement(viewport.getAlignment().getSequenceAt(i));\r
+    }\r
+    PaintRefresher.Refresh(null);\r
+  }\r
+\r
+  public void deleteSelectedMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    for (int i=0;i < viewport.getSelection().size(); i++)\r
+            viewport.getAlignment().deleteSequence(viewport.getSelection().sequenceAt(i));\r
+\r
+    viewport.getSelection().clear();\r
+    viewport.resetSeqLimits(alignPanel.seqPanel.seqCanvas.getHeight());\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void moveSelectedMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    copySelectedMenuItem_actionPerformed(null);\r
+    deleteSelectedMenuItem_actionPerformed(null);\r
+    alignPanel.repaint();\r
+  }\r
+\r
+  public void copySelectedMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if(viewport.getSelection().size()==0)\r
+      return;\r
+\r
+   SequenceI[] s = new Sequence[viewport.getSelection().size()];\r
+   for (int i=0; i < viewport.getSelection().size(); i++) {\r
+     s[i] = new Sequence(viewport.getSelection().sequenceAt(i));\r
+    }\r
+    AlignFrame af = new AlignFrame(new Alignment(s));\r
+\r
+    int newHeight = s.length * af.viewport.getCharHeight() + 200;\r
+    if(newHeight>500)\r
+      newHeight=500;\r
+    Desktop.addInternalFrame(af, "Copied sequences", 700,newHeight);\r
+  }\r
+\r
+  public void deselectAllColumnsMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.getColumnSelection().clear();\r
+    repaint();\r
+  }\r
+\r
+  public void remove2LeftMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    ColumnSelection colSel = viewport.getColumnSelection();\r
+    if (colSel.size() > 0)\r
+    {\r
+      int min = colSel.getMin();\r
+      viewport.getAlignment().trimLeft(min);\r
+      colSel.compensateForEdit(0,min);\r
+      alignPanel.RefreshPanels();\r
+    }\r
+  }\r
+\r
+  public void remove2RightMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    ColumnSelection colSel = viewport.getColumnSelection();\r
+    if (colSel.size() > 0)\r
+    {\r
+      int max = colSel.getMax();\r
+      if(max>1)\r
+        viewport.getAlignment().trimRight(max);\r
+\r
+      alignPanel.RefreshPanels();\r
+    }\r
+\r
+  }\r
+\r
+  public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.getAlignment().removeGaps();\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    SequenceI current;\r
+    int jSize;\r
+    for (int i=0; i < viewport.getAlignment().getSequences().size();i++)\r
+    {\r
+      current = viewport.getAlignment().getSequenceAt(i);\r
+      jSize = current.getLength();\r
+      for (int j=0; j < jSize; j++)\r
+        if (current.getCharAt(j)=='-' || current.getCharAt(j)=='.' || current.getCharAt(j)==' ')\r
+        {\r
+          current.deleteCharAt(j);\r
+          j--;\r
+          jSize--;\r
+        }\r
+    }\r
+\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void setGapCharMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    String thisChar = "-";\r
+    String nextChar = ".";\r
+    if(viewport.getGapCharacter().equals("-"))\r
+    {\r
+      thisChar = ".";\r
+      nextChar = "-";\r
+    }\r
+    setGapCharMenuItem.setText("Set gap character to \""+nextChar+"\"");\r
+    viewport.setGapCharacter(thisChar);\r
+  }\r
+\r
+\r
+  public void fontNameMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    String fonts[] = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();\r
+\r
+\r
+    String selection = JOptionPane.showInputDialog(this,\r
+                                "Select font",\r
+                                "Font selection",\r
+                                JOptionPane.QUESTION_MESSAGE,\r
+                                null,fonts\r
+                                ,fontNameMenuItem.getText()).toString();\r
+    if(selection!=null)\r
+    {\r
+       fontNameMenuItem.setText(selection);\r
+       SetFont();\r
+     }\r
+\r
+  }\r
+\r
+  public void fontSizeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    String selection = JOptionPane.showInputDialog(this,\r
+                                "Select font size",\r
+                                "Font size",\r
+                                JOptionPane.QUESTION_MESSAGE,\r
+                                null, new String[]{"1","2","4","6","8","10","12","14","16","18","20"}\r
+                                ,fontSizeMenuItem.getText()).toString();\r
+    if(selection!=null)\r
+     {\r
+       fontSizeMenuItem.setText(selection);\r
+       SetFont();\r
+     }\r
+  }\r
+\r
+  public void fontStyleMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    String selection = JOptionPane.showInputDialog(this,\r
+                                "Select font style",\r
+                                "Font style",\r
+                                JOptionPane.QUESTION_MESSAGE,\r
+                                null, new String[]{"plain", "bold", "italic"}\r
+                                ,fontStyleMenuItem.getText()).toString();\r
+    if(selection!=null)\r
+    {\r
+      fontStyleMenuItem.setText(selection);\r
+      SetFont();\r
+    }\r
+\r
+  }\r
+\r
+  protected void colourTextMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setColourText( colourTextMenuItem.isSelected() );\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  void SetFont()\r
+  {\r
+      int style = java.awt.Font.PLAIN;\r
+      if(fontStyleMenuItem.getText().equals("bold"))\r
+        style = java.awt.Font.BOLD;\r
+      else if(fontStyleMenuItem.getText().equals("italic"))\r
+        style = java.awt.Font.ITALIC;\r
+\r
+      viewport.setFont(new java.awt.Font(fontNameMenuItem.getText(),\r
+                                           style,\r
+                                           Integer.parseInt(fontSizeMenuItem.getText())));\r
+      alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void viewBoxesMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowBoxes( viewBoxesMenuItem.isSelected() );\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void viewTextMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowText( viewTextMenuItem.isSelected() );\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+\r
+  public void consensusGraphMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.setGraphPanelVisible( consensusGraphMenuItem.isSelected() );\r
+  }\r
+\r
+\r
+  public void clustalColour_actionPerformed(ActionEvent e)\r
+  {\r
+   // alignPanel.seqPanel.setColourScheme( new ClustalxColourScheme() );\r
+  }\r
+\r
+  public void zappoColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new ZappoColourScheme() );\r
+  }\r
+\r
+  public void taylorColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new TaylorColourScheme() );\r
+  }\r
+\r
+\r
+  public void hydrophobicityColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new HydrophobicColourScheme() );\r
+  }\r
+\r
+  public void helixColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new HelixColourScheme() );\r
+  }\r
+\r
+  public void strandColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new StrandColourScheme() );\r
+  }\r
+\r
+  public void turnColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new TurnColourScheme() );\r
+  }\r
+\r
+  public void buriedColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new BuriedColourScheme() );\r
+  }\r
+\r
+  public void conservationColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  public void conservationColourIncMenuItem_actionPerformed(ActionEvent e)\r
+ {\r
+\r
+ }\r
+\r
+\r
+  public void abovePIDColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new PIDColourScheme() );\r
+  }\r
+\r
+\r
+  public void userDefinedColour_actionPerformed(ActionEvent e)\r
+  {\r
+    JInternalFrame frame = new JInternalFrame();\r
+    UserDefinedColours chooser = new UserDefinedColours( frame, alignPanel.seqPanel );\r
+    frame.setContentPane(chooser);\r
+    Desktop.addInternalFrame(frame,"User defined colours", 450,540 );\r
+    frame.setResizable(false);\r
+    frame.setIconifiable(false);\r
+    frame.setMaximizable(false);\r
+  }\r
+\r
+  public void PIDColour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new PIDColourScheme() );\r
+  }\r
+\r
+  public void BLOSUM62Colour_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.seqPanel.setColourScheme( new Blosum62ColourScheme(viewport) );\r
+  }\r
+\r
+\r
+  protected void schemeKeyMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    ColourKey colourKey = new ColourKey( alignPanel.seqPanel.getColourScheme() );\r
+    Desktop.addInternalFrame(colourKey, "Colour scheme key", 400, 320);\r
+  }\r
+\r
+\r
+  public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    AlignmentSorter.sortByPID(viewport.getAlignment(), viewport.getAlignment().getSequenceAt(0));\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void sortIDMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    AlignmentSorter.sortByID( viewport.getAlignment() );\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void sortGroupMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    AlignmentSorter.sortGroups(viewport.getAlignment());\r
+    AlignmentSorter.sortGroups(viewport.getAlignment());\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void sortTreeOrderMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if(viewport.getCurrentTree()==null)\r
+      return;\r
+\r
+    AlignmentSorter.sortByTree(viewport.getAlignment(), viewport.getCurrentTree());\r
+    alignPanel.RefreshPanels();\r
+  }\r
+\r
+  public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if(viewport.getSelection().size()<2)\r
+      JOptionPane.showMessageDialog(this, "You must select at least 2 sequences.", "Invalid Selection", JOptionPane.WARNING_MESSAGE);\r
+    else\r
+    {\r
+      JInternalFrame frame = new JInternalFrame();\r
+      frame.setContentPane(new PairwiseAlignPanel(viewport));\r
+      Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);\r
+    }\r
+  }\r
+\r
+  public void PCAMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    PCAPanel pcaPanel = new PCAPanel(viewport, null);\r
+    JInternalFrame frame = new JInternalFrame();\r
+    frame.setContentPane(pcaPanel);\r
+    Desktop.addInternalFrame(frame, "Principal component analysis", 400,400);\r
+  }\r
+\r
+  public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    NewTreePanel("AV", "PID", "Average distance tree using PID");\r
+  }\r
+\r
+  public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");\r
+  }\r
+\r
+\r
+  protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");\r
+  }\r
+\r
+  protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62PID");\r
+  }\r
+\r
+  void NewTreePanel(String type, String pwType, String title)\r
+  {\r
+    JInternalFrame frame = new javax.swing.JInternalFrame();\r
+    TreePanel tp=null;\r
+   if (viewport.getSelection() != null && viewport.getSelection().size() > 3)\r
+   {\r
+     tp = new TreePanel(viewport, viewport.getSelection().asVector(),type, pwType,\r
+                         viewport.getStartRes(), viewport.getEndRes());\r
+   }\r
+   else\r
+   {\r
+     tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),\r
+                         type, pwType, viewport.getStartRes(),\r
+                         viewport.getEndRes());\r
+   }\r
+\r
+   frame.setContentPane(tp);\r
+   Desktop.addInternalFrame(frame, title, 600, 500);\r
+  }\r
+\r
+\r
+\r
+  public void clustalAlignMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    JOptionPane.showMessageDialog(this, "Jalview is currently being reengineered"\r
+                                  +"\nwithin the Barton Group, Dundee University."\r
+                                  +"\nThis will be available as a web service 2005",\r
+                                  "Web service", JOptionPane.INFORMATION_MESSAGE);\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/AlignViewport.java b/src/jalview/gui/AlignViewport.java
new file mode 100755 (executable)
index 0000000..1324c1e
--- /dev/null
@@ -0,0 +1,346 @@
+package jalview.gui;\r
+\r
+import java.awt.*;\r
+import jalview.io.*;\r
+import jalview.analysis.NJTree;\r
+import jalview.datamodel.*;\r
+import java.util.*;\r
+\r
+public class AlignViewport\r
+{\r
+  int startRes;\r
+  int endRes;\r
+\r
+  int startSeq;\r
+  int endSeq;\r
+\r
+  boolean showScores;\r
+  boolean showText;\r
+  boolean showColourText;\r
+  boolean showBoxes;\r
+  boolean wrapAlignment;\r
+\r
+  boolean groupEdit    = false;\r
+\r
+  RendererI renderer = new SequenceRenderer();\r
+\r
+  int             charHeight;\r
+  double          charWidth;\r
+  int             chunkWidth;\r
+  int             chunkHeight;\r
+\r
+  Color           backgroundColour;\r
+\r
+  Font            font = new Font("SansSerif",Font.PLAIN,10);\r
+  AlignmentI      alignment;\r
+\r
+  Selection       sel    = new Selection();\r
+  ColumnSelection colSel = new ColumnSelection();\r
+\r
+  OutputGenerator og;\r
+\r
+  String visibleConsensus;\r
+\r
+  int threshold;\r
+  int increment;\r
+\r
+  NJTree currentTree = null;\r
+\r
+  int window   = 50;\r
+  int baseline = 30;\r
+\r
+  Vector kmers;\r
+\r
+  public AlignViewport(AlignmentI da,\r
+                       boolean showScores,\r
+                       boolean showText,\r
+                       boolean showBoxes,\r
+                       boolean wrapAlignment) {\r
+    this(0,da.getWidth()-1,0,da.getHeight()-1,showScores,\r
+         showText,\r
+         showBoxes,\r
+         wrapAlignment);\r
+\r
+    setAlignment(da);\r
+  }\r
+\r
+  public AlignViewport(int startRes, int endRes,\r
+                       int startSeq, int endSeq,\r
+                       boolean showScores,\r
+                       boolean showText,\r
+                       boolean showBoxes,\r
+                       boolean wrapAlignment) {\r
+\r
+    this.startRes = startRes;\r
+    this.endRes   = endRes;\r
+    this.startSeq = startSeq;\r
+    this.endSeq   = endSeq;\r
+\r
+    this.showScores    = showScores;\r
+    this.showText      = showText;\r
+    this.showBoxes     = showBoxes;\r
+    this.wrapAlignment = wrapAlignment;\r
+\r
+   // og  = new AlignmentOutputGenerator(this);\r
+\r
+    setFont( font );\r
+ }\r
+\r
+  public AlignViewport(int startRes, int endRes,\r
+                       int startSeq, int endSeq,\r
+                       boolean showScores,\r
+                       boolean showText,\r
+                       boolean showBoxes,\r
+                       boolean wrapAlignment,\r
+                       Color backgroundColour) {\r
+    this(startRes,endRes,startSeq,endSeq,showScores,showText,showBoxes,wrapAlignment);\r
+\r
+    this.backgroundColour = backgroundColour;\r
+  }\r
+\r
+\r
+  public String getVisibleConsensus()\r
+  {\r
+    return visibleConsensus;\r
+  }\r
+\r
+  Vector consensus = new Vector();\r
+\r
+  public Vector getConsensus(boolean recalculate)\r
+  {\r
+    if(recalculate || consensus.size()<1)\r
+    {\r
+      consensus = alignment.getAAFrequency();\r
+      StringBuffer sb = new StringBuffer();\r
+      Hashtable hash = null;\r
+      for (int i = 0; i < consensus.size(); i++)\r
+      {\r
+        hash = (Hashtable) consensus.elementAt(i);\r
+        sb.append(hash.get("maxResidue").toString().charAt(0));\r
+      }\r
+      visibleConsensus = sb.toString();\r
+    }\r
+\r
+\r
+    return consensus;\r
+  }\r
+\r
+\r
+  public int getStartRes() {\r
+    return startRes;\r
+  }\r
+\r
+  public int getEndRes() {\r
+    return endRes;\r
+  }\r
+\r
+  public int getStartSeq() {\r
+    return startSeq;\r
+  }\r
+\r
+\r
+  public void setStartRes(int res) {\r
+    this.startRes = res;\r
+  }\r
+  public void setStartSeq(int seq) {\r
+    this.startSeq = seq;\r
+  }\r
+  public void setEndRes(int res) {\r
+    if (res > alignment.getWidth()-1) {\r
+      System.out.println(" Corrected res from " + res + " to maximum " + (alignment.getWidth()-1));\r
+       res = alignment.getWidth() -1;\r
+    }\r
+    if (res < 0) {\r
+      res = 0;\r
+    }\r
+    this.endRes = res;\r
+  }\r
+  public void setEndSeq(int seq) {\r
+    if (seq > alignment.getHeight()) {\r
+      seq = alignment.getHeight();\r
+    }\r
+    if (seq < 0) {\r
+      seq = 0;\r
+    }\r
+    this.endSeq = seq;\r
+  }\r
+  public int getEndSeq() {\r
+    return endSeq;\r
+  }\r
+\r
+  public void setFont(Font f) {\r
+    font = f;\r
+    javax.swing.JFrame temp = new javax.swing.JFrame();\r
+    temp.addNotify();\r
+    java.awt.FontMetrics fm = temp.getGraphics().getFontMetrics(font);\r
+    setCharHeight(fm.getHeight());\r
+    setCharWidth(fm.charWidth('M'));\r
+  }\r
+\r
+  public Font getFont() {\r
+    return font;\r
+  }\r
+  public void setCharWidth(double w) {\r
+    this.charWidth = w;\r
+  }\r
+  public double getCharWidth() {\r
+    return charWidth;\r
+  }\r
+  public void setCharHeight(int h) {\r
+    this.charHeight = h;\r
+  }\r
+  public int getCharHeight() {\r
+    return charHeight;\r
+  }\r
+  public void setChunkWidth(int w) {\r
+    this.chunkWidth = w;\r
+  }\r
+  public int getChunkWidth() {\r
+    return chunkWidth;\r
+  }\r
+  public void setChunkHeight(int h) {\r
+    this.chunkHeight = h;\r
+  }\r
+  public int getChunkHeight() {\r
+    return chunkHeight;\r
+  }\r
+  public AlignmentI getAlignment() {\r
+    return alignment;\r
+  }\r
+  public void setAlignment(AlignmentI align) {\r
+    this.alignment = align;\r
+  }\r
+  public void setShowScores(boolean state) {\r
+    showScores = state;\r
+  }\r
+  public void setWrapAlignment(boolean state) {\r
+    wrapAlignment = state;\r
+  }\r
+  public void setShowText(boolean state) {\r
+    showText = state;\r
+  }\r
+\r
+  public boolean getColourText()\r
+  {\r
+    return showColourText;\r
+  }\r
+\r
+  public void setColourText(boolean state)\r
+  {\r
+    showColourText = state;\r
+  }\r
+\r
+  public void setShowBoxes(boolean state) {\r
+    showBoxes = state;\r
+  }\r
+  public boolean getShowScores() {\r
+    return showScores;\r
+  }\r
+  public boolean getWrapAlignment() {\r
+      return wrapAlignment;\r
+  }\r
+  public boolean getShowText() {\r
+    return showText;\r
+  }\r
+  public boolean getShowBoxes() {\r
+    return showBoxes;\r
+  }\r
+ // public CommandParser getCommandLog() {\r
+ ///   return log;\r
+ // }\r
+  public boolean getGroupEdit() {\r
+    return groupEdit;\r
+  }\r
+  public void setGroupEdit(boolean state) {\r
+    groupEdit = state;\r
+  }\r
+  public String getGapCharacter() {\r
+    return getAlignment().getGapCharacter();\r
+  }\r
+  public void setGapCharacter(String gap) {\r
+    if (getAlignment() != null) {\r
+      getAlignment().setGapCharacter(gap);\r
+    }\r
+  }\r
+  public void setThreshold(int thresh) {\r
+    threshold = thresh;\r
+  }\r
+  public int getThreshold() {\r
+    return threshold;\r
+  }\r
+  public void setIncrement(int inc) {\r
+    increment = inc;\r
+  }\r
+  public int getIncrement() {\r
+    return increment;\r
+  }\r
+  public int getIndex(int y) {\r
+    int y1     = 0;\r
+    int starty = getStartSeq();\r
+    int endy   = getEndSeq();\r
+\r
+    for (int i = starty; i <= endy; i++) {\r
+      if (i < alignment.getHeight() && alignment.getSequenceAt(i) != null) {\r
+        int y2 = y1 + getCharHeight();\r
+\r
+        if (y>=y1 && y <=y2) {\r
+          return i;\r
+        }\r
+        y1  = y2;\r
+      } else {\r
+        return -1;\r
+      }\r
+    }\r
+    return -1;\r
+  }\r
+  public Selection getSelection() {\r
+    return sel;\r
+  }\r
+  public ColumnSelection getColumnSelection() {\r
+    return colSel;\r
+  }\r
+  public OutputGenerator getOutputGenerator() {\r
+    return og;\r
+  }\r
+  public void resetSeqLimits(int height) {\r
+    setStartSeq(0);\r
+    setEndSeq(height/getCharHeight());\r
+  }\r
+  public void setCurrentTree(NJTree tree) {\r
+      currentTree = tree;\r
+  }\r
+  public NJTree getCurrentTree() {\r
+    return currentTree;\r
+  }\r
+\r
+    public void setRenderer(RendererI rend) {\r
+       this.renderer = rend;\r
+    }\r
+\r
+    public RendererI getRenderer() {\r
+       return renderer;\r
+    }\r
+    public int getPIDWindow() {\r
+       return window;\r
+    }\r
+    public void setPIDWindow(int window) {\r
+       this.window = window;\r
+    }\r
+\r
+    public int getPIDBaseline() {\r
+       return baseline;\r
+    }\r
+    public void setPIDBaseline(int baseline) {\r
+       this.baseline = baseline;\r
+    }\r
+\r
+    public void setKmers(Vector kmers) {\r
+        this.kmers = kmers;\r
+    }\r
+\r
+    public Vector getKmers() {\r
+        return this.kmers;\r
+    }\r
+\r
+\r
+}\r
diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java
new file mode 100755 (executable)
index 0000000..cf3e3df
--- /dev/null
@@ -0,0 +1,136 @@
+package jalview.gui;\r
+\r
+import jalview.jbgui.GAlignmentPanel;\r
+import java.awt.*;\r
+import javax.swing.*;\r
+import java.awt.event.*;\r
+\r
+public class AlignmentPanel extends GAlignmentPanel implements AdjustmentListener\r
+{\r
+\r
+  AlignViewport     av;\r
+  public SeqPanel   seqPanel;\r
+  public IdPanel    idPanel;\r
+  public AlignFrame alignFrame;\r
+  public ScalePanel scalePanel;\r
+  public ScorePanel scorePanel;\r
+\r
+  public boolean    groupEdit = false;\r
+\r
+  public AlignmentPanel(AlignFrame af, AlignViewport av)\r
+  {\r
+    alignFrame = af;\r
+    this.av         = av;\r
+    seqPanel        = new SeqPanel  (av, this);\r
+    idPanel         = new IdPanel   (av, this);\r
+    scalePanel = new ScalePanel(av);\r
+    scorePanel = new ScorePanel(av);\r
+\r
+    idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
+    scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
+    scorePanelHolder.add(scorePanel, BorderLayout.CENTER);\r
+    seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
+    setScrollValues(0,0);\r
+\r
+    hscroll.addAdjustmentListener(this);\r
+    vscroll.addAdjustmentListener(this);\r
+    selectAll(false);\r
+\r
+    addComponentListener(new ComponentAdapter()\r
+   {\r
+       public void componentResized(ComponentEvent evt)\r
+     {      RefreshPanels();    }\r
+   });\r
+\r
+  }\r
+\r
+  public int countSelected()\r
+  {\r
+    return av.getSelection().size();\r
+  }\r
+\r
+  public void selectAll(boolean flag) {\r
+    int i = 0;\r
+    if (flag) {\r
+      while (i < seqPanel.align.getHeight()) {\r
+        if (! av.getSelection().contains(av.getAlignment().getSequenceAt(i))) {\r
+          av.getSelection().addElement(av.getAlignment().getSequenceAt(i));\r
+        }\r
+        i++;\r
+      }\r
+    } else {\r
+      av.getSelection().clear();\r
+    }\r
+  }\r
+\r
+\r
+\r
+  public void setGraphPanelVisible(boolean b)\r
+  {\r
+    scorePanelHolder.setVisible(b);\r
+    idSpaceFillerPanel.setVisible(b);\r
+    RefreshPanels();\r
+  }\r
+\r
+\r
+\r
+  public void RefreshPanels()\r
+  {\r
+    invalidate();\r
+    idPanelHolder.setPreferredSize( idPanel.idCanvas.getPreferredSize() );\r
+    validate();\r
+    idPanel.idCanvas.paintFlag = true;\r
+    seqPanel.seqCanvas.paintFlag = true;\r
+    setScrollValues(av.getStartRes(), av.getStartSeq());\r
+    av.getConsensus(true);\r
+    repaint();\r
+  }\r
+\r
+  int hextent = 0;\r
+  int vextent = 0;\r
+\r
+  public void setScrollValues(int x, int y)\r
+  {\r
+    hextent = (int)(seqPanel.seqCanvas.getWidth()/av.getCharWidth());\r
+    vextent = seqPanel.seqCanvas.getHeight()/av.getCharHeight();\r
+\r
+    if(hextent+x  >  av.getAlignment().getWidth())\r
+      x =  av.getAlignment().getWidth()- hextent;\r
+\r
+    if(vextent+y > av.getAlignment().getHeight())\r
+      y = av.getAlignment().getHeight() - vextent;\r
+\r
+    if(y<0)\r
+      y = 0;\r
+\r
+    if(x<0)\r
+      x=0;\r
+\r
+    hscroll.setValues(x,hextent,0,av.getAlignment().getWidth());\r
+    vscroll.setValues(y,vextent,0,av.getAlignment().getHeight() );\r
+\r
+  }\r
+\r
+\r
+  public void adjustmentValueChanged(AdjustmentEvent evt) {\r
+\r
+    if (evt.getSource() == hscroll)\r
+    {\r
+      int x = hscroll.getValue();\r
+      av.setStartRes(x);\r
+      av.setEndRes(x + (int)(seqPanel.seqCanvas.getWidth()/av.getCharWidth()-1));\r
+    }\r
+\r
+    if (evt.getSource() == vscroll)\r
+    {\r
+        int offy = vscroll.getValue();\r
+        av.setStartSeq(offy);\r
+        av.setEndSeq(offy + seqPanel.seqCanvas.getHeight()/av.getCharHeight());\r
+    }\r
+\r
+    repaint();\r
+  }\r
+\r
+\r
+\r
+}\r
diff --git a/src/jalview/gui/BlockRenderer.java b/src/jalview/gui/BlockRenderer.java
new file mode 100755 (executable)
index 0000000..1dca1c4
--- /dev/null
@@ -0,0 +1,136 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+import jalview.analysis.*;\r
+import jalview.util.*;\r
+import java.awt.*;\r
+import java.util.*;\r
+\r
+public class BlockRenderer implements RendererI {\r
+    protected Color   color = Color.black;\r
+    protected Color   maroon = new Color(200,0,50);\r
+    protected Color   purple = new Color(255,100,255);\r
+\r
+    public Color getResidueBoxColour(ColourSchemeI cs, SequenceI seq, int i) {\r
+       Color c = cs.findColour(seq,seq.getSequence(i,i+1),i,null);\r
+       return c;\r
+    }\r
+\r
+    public void drawSequence(Graphics g,ColourSchemeI cs,SequenceI seq,int start, int end, int x1, int y1, double width, int height,boolean showScores, boolean displayBoxes, boolean displayText,Vector pid, int seqnum,AlignViewport av) {\r
+\r
+/*     int i      = start;\r
+       int length = seq.getLength();\r
+\r
+       Color currentColor = Color.white;\r
+       Vector kmers = av.getKmers();\r
+\r
+       g.setColor(Color.black);\r
+\r
+        int prev = -1;\r
+\r
+       int seqno = -1;\r
+\r
+       for (int ii = 0; ii < av.getAlignment().getHeight(); ii++) {\r
+           if (av.getSelection().contains(av.getAlignment().getSequenceAt(ii))) {\r
+               seqno = ii;\r
+           }\r
+       }\r
+\r
+       int blstart = start - 20;\r
+       int blend   = end   + 20;\r
+\r
+       if (blstart < 0) {\r
+           blstart = 0;\r
+       }\r
+\r
+       if (blend > av.getAlignment().getWidth()) {\r
+           blend = av.getAlignment().getWidth();\r
+       }\r
+\r
+       Hashtable blocks = AAFrequency.findBlocks(av.getAlignment().getSequences(),\r
+                                                 blstart,\r
+                                                 blend,\r
+                                                 av.getSelection().asVector());\r
+\r
+       Hashtable hkmer = AlignmentUtil.findKmers(seq,blstart,blend,kmers);\r
+\r
+       boolean   inblock = false;\r
+\r
+       int       bstart = -1;\r
+       int       blen   = -1;\r
+       int       klen   = -1;\r
+       int       block_end = -1;\r
+       Color bc;\r
+\r
+       // System.out.println("Rendering " + start + " " + end);\r
+\r
+       while (i <= blend && i < length) {\r
+           boolean foundblock = false;\r
+\r
+           if (blocks.get(new Integer(i-blstart)) != null) {\r
+\r
+               blen   = ((Integer)blocks.get(new Integer(i-blstart))).intValue();\r
+\r
+               foundblock = true;\r
+\r
+               block_end = i + blen-1;\r
+\r
+               g.setColor(getColor(blen));\r
+               g.fillRect(x1+(int)(width*(i-start)),y1,\r
+                          (int)width+1,             height/2);\r
+           }\r
+\r
+           boolean foundKmer = false;\r
+\r
+           if (hkmer.get(new Integer(i-blstart)) != null) {\r
+\r
+\r
+               klen   = ((Integer)hkmer.get(new Integer(i-blstart))).intValue();\r
+\r
+               //              System.out.println("Got kmer " + i + " " + start + " kength " + klen);\r
+\r
+               foundKmer = true;\r
+\r
+               g.setColor(Color.lightGray);\r
+\r
+               if ((int)width> 5) {\r
+                   g.fillRect(x1+(int)(width*(i-start)),y1+height/2,\r
+                              (int)(width*klen)+1,             height/2);\r
+               } else {\r
+                   g.fillRect(x1+(int)(width*(i-start)),y1+height/2,\r
+                              (int)(width*klen)+1,             height/2);\r
+\r
+               }\r
+\r
+           }\r
+\r
+           if (width > 5) {\r
+               g.setColor(Color.black);\r
+               g.drawString(seq.getSequence().substring(i,i+1),x1+(int)(width*(i-start)),y1+height);\r
+           }\r
+           i++;\r
+       }*/\r
+    }\r
+\r
+    public Color getColor(int blen) {\r
+\r
+       Color bc;\r
+\r
+       if (blen > 20 ) {\r
+           bc = Color.yellow;\r
+       }else if (blen > 10) {\r
+           bc = Color.red;\r
+       } else if (blen > 5) {\r
+           bc = Color.blue;\r
+       } else if (blen > 2) {\r
+           bc = purple;\r
+       } else if (blen == 2) {\r
+           bc = Color.orange;\r
+\r
+       } else {\r
+           bc = Color.lightGray;\r
+       }\r
+       return bc;\r
+    }\r
+}\r
diff --git a/src/jalview/gui/ColourKey.java b/src/jalview/gui/ColourKey.java
new file mode 100755 (executable)
index 0000000..4dd62a2
--- /dev/null
@@ -0,0 +1,240 @@
+package jalview.gui;\r
+\r
+import jalview.jbgui.GColourKey;\r
+import jalview.schemes.*;\r
+import javax.swing.*;\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+\r
+\r
+public class ColourKey extends GColourKey\r
+{\r
+\r
+ Color midBlue = new Color(100,100,255);\r
+ public ColourKey(ColourSchemeI current)\r
+ {\r
+   if(current==null)\r
+        zappoMenuItem_actionPerformed(null);\r
+\r
+   else if(current instanceof Blosum62ColourScheme)\r
+        blosumMenuItem_actionPerformed(null);\r
+\r
+  else if(current instanceof BuriedColourScheme)\r
+    buriedMenuItem_actionPerformed(null);\r
+\r
+//  else if(current instanceof ClustalxColourScheme)\r
+ //   cl\r
+  else if(current instanceof HelixColourScheme)\r
+    helixMenuItem_actionPerformed(null);\r
+\r
+  else if(current instanceof HydrophobicColourScheme)\r
+    hydroMenuItem_actionPerformed(null);\r
+\r
+  else if(current instanceof StrandColourScheme)\r
+    strandMenuItem_actionPerformed(null);\r
+\r
+  else if(current instanceof TaylorColourScheme)\r
+    taylorMenuItem_actionPerformed(null);\r
+\r
+  else if(current instanceof TurnColourScheme)\r
+    turnMenuItem_actionPerformed(null);\r
+\r
+  else // default\r
+     zappoMenuItem_actionPerformed(null);\r
+ }\r
+\r
+ void displayKey(String [] residue, String [] description, Color []  colour, String comment)\r
+ {\r
+   this.getContentPane().removeAll();\r
+\r
+   for(int i=0; i<colour.length; i++)\r
+   {\r
+     JPanel rowPanel = new JPanel();\r
+     JLabel residueLabel = new JLabel();\r
+     JLabel textLabel = new JLabel();\r
+     JPanel colourPanel = new JPanel();\r
+     rowPanel.setLayout(new BorderLayout());\r
+     residueLabel.setFont(new java.awt.Font("Verdana", Font.BOLD, 12));\r
+     residueLabel.setPreferredSize(new Dimension(80, 20));\r
+     if(residue!=null)\r
+       residueLabel.setText(residue[i]);\r
+     residueLabel.setOpaque(false);\r
+     residueLabel.setHorizontalAlignment(SwingConstants.CENTER);\r
+     residueLabel.setHorizontalTextPosition(SwingConstants.CENTER);\r
+     textLabel.setFont(new java.awt.Font("Verdana", 0, 12));\r
+     textLabel.setPreferredSize(new Dimension(250,20));\r
+     textLabel.setBackground(Color.white);\r
+     if(description != null)\r
+        textLabel.setText(description[i]);\r
+\r
+     colourPanel.setBackground(colour[i]);\r
+     colourPanel.setBorder(BorderFactory.createRaisedBevelBorder());\r
+     colourPanel.setPreferredSize(new Dimension(80, 20));\r
+     colourPanel.setLayout(new BorderLayout());\r
+     colourPanel.add(residueLabel, BorderLayout.CENTER);\r
+\r
+     rowPanel.add(colourPanel, BorderLayout.CENTER);\r
+     if(description!=null)\r
+       rowPanel.add(textLabel, BorderLayout.WEST);\r
+     this.getContentPane().add(rowPanel);\r
+   }\r
+\r
+   if(comment!=null)\r
+   {\r
+     JTextArea ta = new JTextArea(comment);\r
+     ta.setLineWrap(true);\r
+     ta.setWrapStyleWord(true);\r
+     ta.setPreferredSize( new Dimension(this.getWidth()-20, 120) );\r
+     this.getContentPane().add(ta);\r
+   }\r
+   validate();\r
+   repaint();\r
+ }\r
+\r
+\r
+protected void clustalMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+  menu.setText("ClustalX colour scheme");\r
+  this.getContentPane().removeAll();\r
+  repaint();\r
+}\r
+\r
+protected void zappoMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+    menu.setText("Zappo colour scheme");\r
+    displayKey(\r
+        new String[]{"ILVAM", "FWY", "KRH", "DE", "STNQ", "PG", "C"},\r
+        new String[]{"Aliphatic/hydrophobic residues", "Aromatic",\r
+        "Positive", "Negative", "Hydrophilic", "conformationally special", "Cysteine"},\r
+        new Color[]{ Color.pink, Color.orange, midBlue, Color.red, Color.green, Color.magenta, Color.yellow}\r
+        ,null\r
+        );\r
+\r
+}\r
+\r
+protected void taylorMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+  menu.setText("Taylor colour scheme");\r
+  String [] res = new String[]{"A","V","I","L","M","F","Y","W","H","R","K","N","Q","E","D","S","T","G","P","C"};\r
+  Color [] col = new Color[20];\r
+  for (int i=0; i<20; i++)\r
+    col[i] = ResidueProperties.taylor[ ((Integer)ResidueProperties.aaHash.get(res[i])).intValue() ];\r
+\r
+\r
+  displayKey( res, null, col, "These colours were invented by Willie Taylor and an entertaining description of their birth can be found in Protein Engineering, Vol 10 , 743-746 (1997)"\r
+ );\r
+}\r
+\r
+protected void hydroMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+\r
+  menu.setText("Hydrophobicity colour scheme");\r
+  String [] res = new String[]{"I","V","L","F","C","M","A","G","X","T","S","W","Y","P","H","E","Z","Q","D","B","N","K","R"};\r
+  Color [] col = new Color[20];\r
+  HydrophobicColourScheme cs = new HydrophobicColourScheme();\r
+  for (int i=0; i<20; i++)\r
+    col[i] = cs.findColour(null,  res[i], -1,  null);\r
+\r
+  displayKey( res, null, col, "According to the hydrophobicity table of  Kyte, J., and Doolittle, R.F., J. Mol. Biol. 1157, 105-132, 1982.  The most hydrophobic residues according to this table are coloured red and the most hydrophilic ones are coloured blue.");\r
+\r
+}\r
+\r
+protected void helixMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+  menu.setText("Helix propensity colour scheme");\r
+  String[] res = new String[]\r
+      {"E","M","A","Z","L","K","F","Q","I","W","V","D","X","H","R","B","T","S","C","Y","N","G","P"};\r
+  Color[] col = new Color[res.length];\r
+  HelixColourScheme cs = new HelixColourScheme();\r
+  for (int i = 0; i < res.length; i++)\r
+    col[i] = cs.findColour(null, res[i], -1, null);\r
+\r
+  displayKey(res, null, col, null);\r
+}\r
+\r
+protected void strandMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+  menu.setText("Strand propensity colour scheme");\r
+  String[] res = new String[]\r
+    {"V","I","Y","F","W","L","T","C","Q","M","X","R","N","H","A","S","G","Z","K","B","P","D","E"};\r
+Color[] col = new Color[res.length];\r
+StrandColourScheme cs = new StrandColourScheme();\r
+for (int i = 0; i < res.length; i++)\r
+  col[i] = cs.findColour(null, res[i], -1, null);\r
+  displayKey(res, null, col, null);\r
+}\r
+\r
+protected void turnMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+  menu.setText("Turn propensity colour scheme");\r
+  String[] res = new String[]\r
+    {"N","G","P","B","D","S","C","Y","K","X","Q","W","T","R","H","Z","E","A","F","M","L","V","I"};\r
+Color[] col = new Color[res.length];\r
+TurnColourScheme cs = new TurnColourScheme();\r
+for (int i = 0; i < res.length; i++)\r
+  col[i] = cs.findColour(null, res[i], -1, null);\r
+\r
+  displayKey(res, null, col, null);\r
+}\r
+\r
+protected void buriedMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+  menu.setText("Buried Index colour scheme");\r
+  String[] res = new String[]\r
+    {"C","I","V","L","F","M","G","A","W","X","S","H","T","P","Y","N","B","D","Q","Z","E","R","K"};\r
+Color[] col = new Color[res.length];\r
+BuriedColourScheme cs = new BuriedColourScheme();\r
+for (int i = 0; i < res.length; i++)\r
+  col[i] = cs.findColour(null, res[i], -1, null);\r
+\r
+  displayKey(res, null, col, null);\r
+}\r
+\r
+protected void blosumMenuItem_actionPerformed(ActionEvent e)\r
+{\r
+  menu.setText("BLOSUM62 colour scheme");\r
+  displayKey( null,\r
+              new String[]{"Consensus","+ve Blosum62", " "},\r
+              new Color[]{ new Color(154, 154, 255), new Color(204, 204, 255),  Color.white },\r
+              "Gaps are coloured white. If a residue matchs the consensus sequence residue at that position"\r
+             +" it is colored dark blue. If it does not match the consensus residue but the 2 residues have a positive Blosum62 score, it is colored light blue.");\r
+\r
+}\r
+}\r
+\r
+\r
+/*\r
+Blosum62 - Sequence positions which are gaps are colored white. For sequence positions which are non-gaps,\r
+if a residue matchs the consensus sequence residue at that position, it is colored dark blue.\r
+If it does not match the consensus residue but the 2 residues have a positive Blosum62 score, it is colored light blue.\r
+Otherwise, it is colored white.\r
+Percentage Identity - Sequence positions which are gaps are colored white. For sequence positions which are non-gaps,\r
+if the residue at a given position is conserved in less than 40% of the sequences in the alignment, it is colored white.\r
+For residues conserved in greater than 40% of the sequences in the alignment, a shade of blue is assigned depending on\r
+the level of conservation, with darker blues corresponding to residues that are more conserver.\r
+*/\r
+\r
+   /*\r
+   This depends on the applet having performed a consensus calculation on the alignment.  This is done automatically when the applet first starts up but is not done for subsequent alignment windows.  If the consensus seuqence is calculated again by selecting 'Consensus' from the Calculate menu then the consensus is calculated for the selected sequences only  and all the alignment sequences are coloured according to that consensus.  This can be useful to display how similar all the other sequences in the alignment are compared to one (or a few) selected sequences.\r
+The PID option colours the residues (boxes and/or text) according to the percentage of the residues in each column that agree with the consensus sequence.  Only the residues that agree with the consensus residue for each column are coloured.\r
+\r
+  Percentage agreement Colour\r
+> 80 % Mid blue\r
+> 60 % Light blue\r
+> 40 % Light grey\r
+<= 40% White\r
+*/\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/gui/ColumnSelection.java b/src/jalview/gui/ColumnSelection.java
new file mode 100755 (executable)
index 0000000..d6eae09
--- /dev/null
@@ -0,0 +1,75 @@
+package jalview.gui;\r
+\r
+import java.util.*;\r
+\r
+/**\r
+ * NOTE: Columns are zero based.\r
+ */\r
+public class ColumnSelection {\r
+  Vector selected = new Vector();\r
+\r
+  public void addElement(int col) {\r
+    selected.addElement(new Integer(col));\r
+  }\r
+\r
+  public void clear() {\r
+    selected.removeAllElements();\r
+  }\r
+\r
+  public void removeElement(int col) {\r
+    Integer colInt = new Integer(col);\r
+    if (selected.contains(colInt)) {\r
+      selected.removeElement(colInt);\r
+    } else {\r
+      System.err.println("WARNING: Tried to remove Integer NOT in ColumnSelection");\r
+    }\r
+  }\r
+\r
+  public boolean contains(int col) {\r
+    return selected.contains(new Integer(col));\r
+  }\r
+\r
+  public int columnAt(int i) {\r
+    return ((Integer)selected.elementAt(i)).intValue();\r
+  }\r
+\r
+  public int size() {\r
+    return selected.size();\r
+  }\r
+\r
+  public int getMax() {\r
+    int max = -1;\r
+\r
+    for (int i=0;i<selected.size();i++) {\r
+      if (columnAt(i) > max) {\r
+        max = columnAt(i);\r
+      }\r
+    }\r
+    return max;\r
+  }\r
+\r
+  public int getMin() {\r
+    int min = 1000000000;\r
+\r
+    for (int i=0;i<selected.size();i++) {\r
+      if (columnAt(i) < min) {\r
+        min = columnAt(i);\r
+      }\r
+    }\r
+    return min;\r
+  }\r
+\r
+  public Vector asVector() {\r
+    return selected;\r
+  }\r
+\r
+  public void compensateForEdit(int start, int change) {\r
+    for (int i=0; i < size();i++) {\r
+      int temp = columnAt(i);\r
+\r
+      if (temp >= start) {\r
+        selected.setElementAt(new Integer(temp-change),i);\r
+      }\r
+    }\r
+  }\r
+}\r
diff --git a/src/jalview/gui/CpGRenderer.java b/src/jalview/gui/CpGRenderer.java
new file mode 100755 (executable)
index 0000000..b5dc128
--- /dev/null
@@ -0,0 +1,87 @@
+package jalview.gui;\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+import jalview.util.*;\r
+import jalview.analysis.*;\r
+import java.awt.*;\r
+import java.awt.geom.*;\r
+import java.util.*;\r
+\r
+public class CpGRenderer implements RendererI {\r
+    protected Color   color = Color.black;\r
+\r
+    public Color getResidueBoxColour(ColourSchemeI cs, SequenceI seq, int i) {\r
+       Color c = cs.findColour(seq,seq.getSequence(i,i+1),i,null);\r
+       return c;\r
+    }\r
+\r
+    public void drawSequence(Graphics g,ColourSchemeI cs,SequenceI seq,int start, int end, int x1, int y1, double width, int height,boolean showScores, boolean displayBoxes, boolean displayText,Vector pid, int seqnum,AlignViewport av) {\r
+\r
+       int i      = start;\r
+       int length = seq.getLength();\r
+\r
+       Color currentColor = Color.white;\r
+\r
+       g.setColor(Color.black);\r
+\r
+        int window = 1000;\r
+        int max    = window/5;\r
+\r
+        int step = window/10;\r
+\r
+        if (step > window) {\r
+          step = window;\r
+        }\r
+\r
+        if (window < 2) {\r
+           window = 2;\r
+           step = 1;\r
+        }\r
+\r
+        int cpgstart = start;\r
+        int cpgend   = end;\r
+\r
+       if (cpgstart <= window/2 ) {\r
+           cpgstart = window/2;\r
+       }\r
+       if (cpgend+window/2 >= length) {\r
+           cpgend = length-window/2;\r
+       }\r
+\r
+       Hashtable vals = AAFrequency.findKmerCount(seq,cpgstart,cpgend,window,step,av.getKmers());\r
+\r
+       Enumeration en = vals.keys();\r
+\r
+       Vector valset = new Vector();\r
+\r
+       while (en.hasMoreElements()) {\r
+           valset.add((Integer)en.nextElement());\r
+       }\r
+       Collections.sort(valset);\r
+\r
+       g.setColor(Color.black);\r
+\r
+       int j = 0;\r
+\r
+       while (j < valset.size()) {\r
+\r
+           Integer posInt = (Integer)valset.elementAt(j);\r
+           int     count  = ((Integer)vals.get(posInt)).intValue();\r
+           int     pos    = posInt.intValue();\r
+\r
+            if (count > 40) {\r
+               g.setColor(Color.red);\r
+            } else {\r
+               g.setColor(Color.black);\r
+            }\r
+\r
+           g.fillRect(x1 + (int)(width*(pos-start-width/2)),\r
+                      y1+height - (int)(count*height/max),\r
+                      (int)(step*width),\r
+                      (int)(count*height/max));\r
+\r
+           j++;\r
+       }\r
+    }\r
+\r
+}\r
diff --git a/src/jalview/gui/CutAndPasteTransfer.java b/src/jalview/gui/CutAndPasteTransfer.java
new file mode 100755 (executable)
index 0000000..67bce4a
--- /dev/null
@@ -0,0 +1,55 @@
+/********************
+ * 2004 Jalview Reengineered
+ * Barton Group
+ * Dundee University
+ *
+ * AM Waterhouse
+ *******************/
+
+package jalview.gui;
+
+import jalview.jbgui.GCutAndPasteTransfer;
+import java.awt.*;
+
+public class CutAndPasteTransfer extends GCutAndPasteTransfer
+{
+  public CutAndPasteTransfer(boolean forImport)
+  {
+    super();
+    for (int i = 0; i < jalview.io.FormatProperties.getFormats().size(); i++) {
+     formatChoice.addItem((String)jalview.io.FormatProperties.getFormats().elementAt(i));
+   }
+
+
+    if(forImport)
+    {
+      formatLabel.setVisible(false);
+      formatChoice.setVisible(false);
+      textarea.setBounds(new Rectangle(9, 6, 383, 284));
+    }
+  }
+
+  // this method is called once the user has selected an output format
+  public void formatForOutput()
+  {
+    textarea.setFont(new Font("Monospaced", Font.PLAIN, 12));
+    setLayout(new BorderLayout());
+    add(scrollPane, BorderLayout.CENTER);
+    remove(formatLabel);
+    remove(formatChoice);
+  }
+
+  public String getFormat()
+  {
+    return formatChoice.getSelectedItem().toString();
+  }
+  public String getText()
+  {
+    return textarea.getText();
+  }
+
+  public void setText(String text)
+  {
+    textarea.setText(text);
+  }
+}
diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java
new file mode 100755 (executable)
index 0000000..f92f01c
--- /dev/null
@@ -0,0 +1,222 @@
+/********************\r
+ * 2004 Jalview Reengineered\r
+ * Barton Group\r
+ * Dundee University\r
+ *\r
+ * AM Waterhouse\r
+ *******************/\r
+\r
+\r
+package jalview.gui;\r
+\r
+import jalview.gui.*;\r
+import jalview.io.*;\r
+import jalview.datamodel.*;\r
+import javax.swing.*;\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+\r
+\r
+public class Desktop extends jalview.jbgui.GDesktop\r
+{\r
+  public static JDesktopPane desktop;\r
+  static int openFrameCount = 0;\r
+  static final int xOffset = 30, yOffset = 30;\r
+\r
+  public Desktop()\r
+  {\r
+    try{\r
+      java.net.URL url = getClass().getResource("/BartonGroupBanner.gif");\r
+      if(url!=null)\r
+      {\r
+        Image image = java.awt.Toolkit.getDefaultToolkit().createImage(url);\r
+        MediaTracker mt = new MediaTracker(this);\r
+        mt.addImage(image, 0);\r
+        mt.waitForID(0);\r
+        setIconImage(image);\r
+      }\r
+\r
+    }catch(Exception ex){}\r
+\r
+    setTitle("Jalview 2005");\r
+    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\r
+    setVisible(true);\r
+    desktop = new JDesktopPane();\r
+    setContentPane(desktop);\r
+    desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);\r
+    int inset = 150;\r
+    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();\r
+    setBounds(inset, inset,\r
+              screenSize.width  - inset*2,\r
+              screenSize.height - inset*2);\r
+  }\r
+\r
+  public static void addInternalFrame(final JInternalFrame frame, String title, int w, int h)\r
+  {\r
+   frame.setVisible(true); //necessary as of 1.3\r
+   desktop.add(frame);\r
+   openFrameCount++;\r
+   try {\r
+       frame.setSelected(true);\r
+   } catch (java.beans.PropertyVetoException e) {}\r
+   frame.setTitle(title);\r
+   frame.setResizable(true);\r
+   frame.setSize(w,h);\r
+   frame.setClosable(true);\r
+   frame.setMaximizable(true);\r
+   frame.setIconifiable(true);\r
+   frame.setLocation(xOffset*openFrameCount, yOffset*openFrameCount);\r
+   frame.toFront();\r
+   final JMenuItem menuItem = new JMenuItem(title);\r
+   frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()\r
+                                   { public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt)\r
+                                     {\r
+                                       openFrameCount--;\r
+                                       windowMenu.remove(menuItem);\r
+                                     };\r
+                                   });\r
+\r
+   menuItem.addActionListener(new ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        try{  frame.setSelected(true);   frame.setIcon(false); }\r
+        catch(java.beans.PropertyVetoException ex){};\r
+      }\r
+    });\r
+\r
+   windowMenu.add(menuItem);\r
+ }\r
+\r
+\r
+\r
+ public void inputLocalFileMenuItem_actionPerformed(ActionEvent e)\r
+ {\r
+   JFileChooser chooser = new JFileChooser(jalview.bin.Cache.LAST_DIRECTORY);\r
+   chooser.setDialogTitle("Open local file");\r
+   chooser.setToolTipText("Open");\r
+   int value = chooser.showOpenDialog(this);\r
+   if(value == JFileChooser.APPROVE_OPTION)\r
+   {\r
+     String choice =  chooser.getSelectedFile().getPath();\r
+     jalview.bin.Cache.LAST_DIRECTORY = choice;\r
+     String format = IdentifyFile.Identify(choice, "File");\r
+     LoadFile(choice, "File", format);\r
+   }\r
+ }\r
+\r
+ public void LoadFile(String file, String protocol,  String format)\r
+ {\r
+   SequenceI [] sequences = null;\r
+\r
+\r
+   if (FormatProperties.contains(format))\r
+       sequences = FormatAdapter.read(file, protocol, format);\r
+\r
+   if (sequences != null)\r
+   {\r
+     AlignFrame af = new AlignFrame(new Alignment(sequences));\r
+     addInternalFrame(af, file, 700, 500);\r
+     af.statusBar.setText("Successfully loaded file " + file);\r
+   }\r
+   else\r
+     JOptionPane.showMessageDialog(this,  "Couldn't open file.\n"\r
+                          + "Formats currently supported are\n"\r
+                          + "Fasta, MSF, Clustal, BLC, PIR, MSP or PFAM"\r
+                          ,"Error loading file",\r
+                                   JOptionPane.WARNING_MESSAGE);\r
+\r
+ }\r
+\r
+ public void inputURLMenuItem_actionPerformed(ActionEvent e)\r
+ {\r
+   String url = JOptionPane.showInputDialog(this,"Enter url of input file",\r
+                                            "Input alignment from URL",\r
+                                            JOptionPane.QUESTION_MESSAGE);\r
+   if (url == null)\r
+     return;\r
+\r
+   String format = IdentifyFile.Identify(url, "URL");\r
+\r
+   System.out.println(format +" format");\r
+   if (format.equals("URL NOT FOUND"))\r
+   {\r
+     JOptionPane.showMessageDialog(this,"Couldn't locate " + url,\r
+                                   "URL not found",\r
+                                   JOptionPane.WARNING_MESSAGE);\r
+     return;\r
+   }\r
+\r
+    LoadFile(url, "URL", format);\r
+ }\r
+\r
+ public void inputTextboxMenuItem_actionPerformed(ActionEvent e)\r
+ {\r
+   CutAndPasteTransfer cap = new CutAndPasteTransfer(true);\r
+   int accept =  JOptionPane.showInternalOptionDialog(desktop, cap, "Cut & paste Alignment File",\r
+                                       JOptionPane.YES_NO_CANCEL_OPTION,\r
+                                       JOptionPane.PLAIN_MESSAGE,\r
+                                       null,\r
+                                       new Object[]{"Accept", "Cancel", }, null);\r
+\r
+\r
+  if(accept == JOptionPane.YES_OPTION)\r
+  {\r
+    String format = IdentifyFile.Identify(cap.getText(), "Paste");\r
+    SequenceI [] sequences = null;\r
+\r
+    if (FormatProperties.contains( format ))\r
+      sequences = FormatAdapter.read(cap.getText(), "Paste", format);\r
+\r
+\r
+      if(sequences!=null)\r
+      {\r
+        AlignFrame af = new AlignFrame(new Alignment(sequences));\r
+        addInternalFrame(af, "Cut & Paste input - "+format, 700, 500);\r
+        af.statusBar.setText("Successfully pasted alignment file");\r
+      }\r
+      else\r
+        JOptionPane.showMessageDialog(this, "Couldn't read the pasted text.\n"\r
+                                      +"Formats currently supported are\n"\r
+                                      +"Fasta, MSF, Clustal, BLC, PIR, MSP or PFAM",\r
+                                      "Error parsing text", JOptionPane.WARNING_MESSAGE);\r
+\r
+\r
+   }\r
+ }\r
+\r
+/*\r
+* Exit the program\r
+*/\r
+ public void quit_actionPerformed(ActionEvent e)\r
+ {\r
+   this.setVisible(false);\r
+   System.exit(0);\r
+ }\r
+\r
+\r
+ protected void colourIndexMenuItem_actionPerformed(ActionEvent e)\r
+ {\r
+   ColourKey colourKey = new ColourKey(null);\r
+   addInternalFrame(colourKey, "Colour scheme key", 400, 320);\r
+ }\r
+\r
+\r
+ public void aboutMenuItem_actionPerformed(ActionEvent e)\r
+ {\r
+   JOptionPane.showInternalMessageDialog(desktop,\r
+                                         "Jalview 1998-2005\n"\r
+                                        +"Sequence Alignment viewer & editor",\r
+                                         "About Jalview",\r
+                                         JOptionPane.INFORMATION_MESSAGE);\r
+ }\r
+\r
+ public void documentationMenuItem_actionPerformed(ActionEvent e)\r
+ {\r
+   try{\r
+     jalview.util.BrowserLauncher.openURL("http://jalview.org/documentation.html");\r
+   }catch(Exception ex){}\r
+ }\r
+\r
+\r
+}\r
diff --git a/src/jalview/gui/DrawableSequence.java b/src/jalview/gui/DrawableSequence.java
new file mode 100755 (executable)
index 0000000..8b7015b
--- /dev/null
@@ -0,0 +1,204 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+import jalview.analysis.*;\r
+import java.awt.*;\r
+\r
+public class DrawableSequence implements SequenceI {\r
+  protected boolean fastDraw = true;\r
+\r
+  protected Color   color = Color.black;\r
+\r
+  protected SequenceI sequence;\r
+\r
+  ColourSchemeI cs = new ZappoColourScheme();\r
+\r
+  public DrawableSequence(SequenceI s) {\r
+    this.sequence = s;\r
+\r
+    _init();\r
+  }\r
+\r
+  public DrawableSequence(String name,String seq, int start, int end) {\r
+    sequence   = new Sequence(name,seq,start,end);\r
+\r
+    _init();\r
+  }\r
+\r
+  private void _init() {\r
+\r
+  }\r
+\r
+  public void setColourScheme(ColourSchemeI cs) {\r
+    this.cs = cs;\r
+  }\r
+\r
+  public Color getResidueBoxColour(int i) {\r
+    Color c = cs.findColour(this,sequence.getSequence(i,i+1),i,null);\r
+    return c;\r
+  }\r
+\r
+  public void drawSequence(Graphics g,int start, int end, int x1, int y1, int width, int height,boolean showScores, boolean displayBoxes, boolean displayText) {\r
+\r
+    if (displayBoxes == true) {\r
+      drawBoxes(g,start,end,x1,y1,width, height);\r
+    }\r
+    if (displayText == true) {\r
+        drawText(g,start,end,x1,y1,width,height);\r
+    }\r
+  }\r
+\r
+  public void drawBoxes(Graphics g,int start, int end, int x1, int y1, int width, int height) {\r
+    int i      = start;\r
+    int length = getSequence().length();\r
+\r
+    Color currentColor = Color.white;\r
+\r
+    int curStart = x1;\r
+    int curWidth = width;\r
+\r
+    while (i <= end && i < length) {\r
+      Color c = getResidueBoxColour(i);\r
+\r
+      if (c != currentColor || c != null) {\r
+        g.fillRect(x1+width*(curStart-start),y1,curWidth,height);\r
+\r
+        currentColor = c;\r
+        g.setColor(c);\r
+\r
+        curStart = i;\r
+        curWidth = width;\r
+      } else {\r
+        curWidth += width;\r
+      }\r
+\r
+      i++;\r
+    }\r
+    g.fillRect(x1+width*(curStart-start),y1,curWidth,height);\r
+  }\r
+\r
+  public void drawText(Graphics g, int start, int end, int x1, int y1, int width, int height) {\r
+    int pady = 2;\r
+    g.setColor(Color.black);\r
+System.out.println("drawablesequence is drawing");\r
+    // Need to find the sequence position here.\r
+\r
+    if (fastDraw) {\r
+       String s;\r
+       if (end < getSequence().length()) {\r
+           s = getSequence().substring(start,end+1);\r
+       } else {\r
+           s = getSequence().substring(start);\r
+       }\r
+        System.out.println(s+" "+x1+" "+y1);\r
+      g.drawString(s,x1,y1+height-pady);\r
+    } else {\r
+\r
+      for (int i=start; i <= end; i++) {\r
+        String s = "";\r
+\r
+        if (i < end && i < getSequence().length()) {\r
+          s = getSequence().substring(i,i+1);\r
+        } else {\r
+          s = getSequence().substring(i,i+1);\r
+        }\r
+\r
+\r
+        g.drawString(s,x1+width*(i-start),y1+height-pady);\r
+      }\r
+\r
+    }\r
+  }\r
+\r
+\r
+  public int getPosition(int res) {\r
+\r
+    return res;\r
+  }\r
+\r
+  public int getResidue(int pos) {\r
+\r
+    return pos;\r
+  }\r
+\r
+  // SequenceI methods\r
+\r
+  public void        setName(String name) {\r
+    sequence.setName(name);\r
+  }\r
+  public String      getName() {\r
+    return sequence.getName();\r
+  }\r
+  public String      getDisplayId() {\r
+    return sequence.getDisplayId();\r
+  }\r
+\r
+  public void        setStart(int start) {\r
+    sequence.setStart(start);\r
+  }\r
+  public int         getStart() {\r
+    return sequence.getStart();\r
+  }\r
+\r
+  public void        setEnd(int end) {\r
+    sequence.setEnd(end);\r
+  }\r
+  public int         getEnd() {\r
+    return sequence.getEnd();\r
+  }\r
+\r
+  public int         getLength() {\r
+    return sequence.getLength();\r
+  }\r
+\r
+  public void        setSequence(String seq) {\r
+    sequence.setSequence(seq);\r
+  }\r
+  public String      getSequence() {\r
+    return sequence.getSequence();\r
+  }\r
+  public String      getSequence(int start,int end) {\r
+    return sequence.getSequence(start,end);\r
+  }\r
+  public char        getCharAt(int i) {\r
+    return sequence.getCharAt(i);\r
+  }\r
+\r
+  public void        setDescription(String desc) {\r
+    sequence.setDescription(desc);\r
+  }\r
+  public String      getDescription() {\r
+    return sequence.getDescription();\r
+  }\r
+\r
+  public int         findIndex(int pos) {\r
+    return sequence.findIndex(pos);\r
+  }\r
+  public int         findPosition(int i) {\r
+    return sequence.findPosition(i);\r
+  }\r
+\r
+\r
+  public void deleteCharAt(int i) {\r
+    sequence.deleteCharAt(i);\r
+  }\r
+\r
+  public void insertCharAt(int i,char c) {\r
+    sequence.insertCharAt(i,c);\r
+\r
+  }\r
+\r
+  public void       insertCharAt(int i,char c,boolean chop) {\r
+    sequence.insertCharAt(i,c,chop);\r
+\r
+  }\r
+  public Color getColor() {\r
+    return this.color;\r
+  }\r
+\r
+  public void setColor(Color c) {\r
+    this.color = c;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/FeatureRenderer.java b/src/jalview/gui/FeatureRenderer.java
new file mode 100755 (executable)
index 0000000..cd754c7
--- /dev/null
@@ -0,0 +1,85 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+import java.awt.*;\r
+import java.util.*;\r
+\r
+public class FeatureRenderer implements RendererI {\r
+\r
+\r
+    public Color getResidueBoxColour(ColourSchemeI cs, SequenceI seq, int i) {\r
+       Color c = cs.findColour(seq,seq.getSequence(i,i+1),i,null);\r
+       return c;\r
+    }\r
+\r
+    public void drawSequence(Graphics g,ColourSchemeI cs,SequenceI seq,int start, int end, int x1, int y1, double width, int height,boolean showScores, boolean displayBoxes, boolean displayText,Vector pid, int seqnum,AlignViewport av) {\r
+\r
+       int i      = start;\r
+       int length = seq.getLength();\r
+\r
+       Color currentColor = Color.black;\r
+\r
+\r
+       int    prev   = -1;\r
+        int    fstart = 0;\r
+        char   prevc   = '-';\r
+\r
+       g.setColor(Color.magenta);\r
+\r
+       while (i <= end && i < length) {\r
+            char c = seq.getCharAt(i);\r
+           if (c != '-') {\r
+\r
+              if (prevc != c) {\r
+\r
+                if (prevc == 'F') {\r
+                  g.setColor(Color.green);\r
+                } else if (prevc == 'R') {\r
+                  g.setColor(Color.cyan);\r
+                } else if (prevc == 'M') {\r
+                  g.setColor(Color.magenta);\r
+                } else if (prevc == 'P') {\r
+                  g.setColor(Color.yellow);\r
+                }\r
+               g.fillRect(x1+(int)(width*(i-fstart)),y1+height/4,(int)((prev-fstart+1)*width),height/2);\r
+\r
+                prevc   = c;\r
+                fstart = i;\r
+            }\r
+          } else if (prevc != '-') {\r
+                if (prevc == 'F') {\r
+                  g.setColor(Color.green);\r
+                } else if (prevc == 'R') {\r
+                  g.setColor(Color.cyan);\r
+                } else if (prevc == 'M') {\r
+                  g.setColor(Color.magenta);\r
+                } else if (prevc == 'P') {\r
+                  g.setColor(Color.yellow);\r
+                }\r
+               g.fillRect(x1+(int)(width*(fstart-start)),y1+height/4,(int)((i-fstart+1)*width),height/2);\r
+\r
+                prevc = c;\r
+          } else {\r
+            fstart = -1;\r
+          }\r
+           i++;\r
+       }\r
+\r
+        if (fstart != -1) {\r
+        if (prevc == 'F') {\r
+          g.setColor(Color.green);\r
+        } else if (prevc == 'R') {\r
+          g.setColor(Color.cyan);\r
+        } else if (prevc == 'M') {\r
+          g.setColor(Color.magenta);\r
+        } else if (prevc == 'P') {\r
+          g.setColor(Color.yellow);\r
+        }\r
+\r
+       //g.fillRect(x1+(int)(width*(fstart-start)),y1+height/4,(int)((end-fstart+1)*width),height/2);\r
+\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/src/jalview/gui/GraphRenderer.java b/src/jalview/gui/GraphRenderer.java
new file mode 100755 (executable)
index 0000000..e7d1757
--- /dev/null
@@ -0,0 +1,128 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+import jalview.util.*;\r
+\r
+import java.awt.*;\r
+import java.awt.geom.*;\r
+import java.util.*;\r
+\r
+public class GraphRenderer implements RendererI {\r
+    protected Color   color = Color.black;\r
+    protected Color   maroon = new Color(200,0,50);\r
+\r
+    public Color getResidueBoxColour(ColourSchemeI cs, SequenceI seq, int i) {\r
+       Color c = cs.findColour(seq,seq.getSequence(i,i+1),i,null);\r
+       return c;\r
+    }\r
+\r
+    public void drawSequence(Graphics g,ColourSchemeI cs,SequenceI seq,int start, int end, int x1, int y1, double width, int height,boolean showScores, boolean displayBoxes, boolean displayText,Vector pid, int seqnum,AlignViewport av) {\r
+\r
+       int i      = start;\r
+       int length = seq.getLength();\r
+\r
+       Color currentColor = Color.white;\r
+\r
+       g.setColor(Color.black);\r
+\r
+        int prev = -1;\r
+\r
+       while (i <= end && i < length) {\r
+            char c = seq.getCharAt(i);\r
+\r
+            if (c != '-') {\r
+           Vector values = (Vector)pid.elementAt(i-start);\r
+           int val = ((Integer)values.elementAt(seqnum)).intValue();\r
+\r
+           int frac = (int)(100*val/(av.getPIDWindow()+1));\r
+\r
+//         if (frac > 95) {\r
+ //               g.setColor(maroon);\r
+  //          } else if (frac > 90) {\r
+//             g.setColor(Color.red);\r
+//         } else if (frac > 80) {\r
+//             g.setColor(Color.orange);\r
+//         } else if (frac > 70) {\r
+//             g.setColor(Color.pink);\r
+//         } else if (frac > 50) {\r
+//             g.setColor(Color.yellow);\r
+//         } else if (frac > 30) {\r
+//             g.setColor(Color.lightGray);\r
+//         }\r
+\r
+            int baseline = av.getPIDBaseline();\r
+\r
+            frac -= baseline;\r
+\r
+            if (frac < 0) {\r
+              frac = 0;\r
+            }\r
+           if (baseline == 100) {\r
+               baseline = 99;\r
+           }\r
+\r
+             Graphics2D g2d = (Graphics2D)g;\r
+\r
+            g2d.setColor(new Color(255*frac/(100-baseline),50*frac/(100-baseline),50*frac/(100-baseline)));\r
+\r
+             //g.setColor(new Color(255*frac/(100-baseline),50*frac/(100-baseline),255-50*frac/(100-baseline)));\r
+            //g.fillRect(x1+(int)(width*(i-start)),y1+height - (int)(frac*height/(100-baseline)),\r
+                          //width,                      (int)(frac*height/(100-baseline)));\r
+\r
+             int[] xpoints = new int[4];\r
+             int[] ypoints = new int[4];\r
+\r
+             if (prev == -1) {\r
+               prev = y1 + height - (int)(frac*height/(100-baseline));\r
+             }\r
+\r
+            //   1----2\r
+            //   |    |\r
+            //   4----3\r
+\r
+            xpoints[0] = (x1+ (int)(width*(i-start)));\r
+             ypoints[0] = prev;\r
+\r
+             xpoints[1] = (x1 + (int)(width*(i-start+1)));\r
+             ypoints[1] = y1 + height - (int)(frac*height/(100-baseline));\r
+\r
+             xpoints[3] = (x1 + (int)(width*(i-start)));;\r
+             ypoints[3] = y1 + height;\r
+\r
+             xpoints[2] = (x1  + (int)(width*(i-start+1)));\r
+             ypoints[2] = y1 + height;\r
+\r
+            Polygon poly = new Polygon();\r
+\r
+            poly.xpoints = xpoints;\r
+            poly.ypoints = ypoints;\r
+            poly.npoints = 4;\r
+\r
+             g2d.fill(poly);\r
+\r
+             if (width > 5) {\r
+                g.setColor(Color.black);\r
+                g.drawString(seq.getSequence().substring(i,i+1),x1+(int)(width*(i-start)),y1+height);\r
+             } else {\r
+                g.setColor(Color.black);\r
+\r
+                if (prev != -1) {\r
+\r
+              g.drawLine(x1+(int)(width*(i-start)-width/2),  prev,\r
+                         x1+(int)(width*(i-start+1)-width/2),y1+height - (int)(frac*height/(100-baseline)));\r
+              } else {\r
+              g.drawLine(x1+(int)(width*(i-start)),  y1+height - (int)(frac*height/(100-baseline)),\r
+                         x1+(int)(width*(i-start+1)),y1+height - (int)(frac*height/(100-baseline)));\r
+              }\r
+\r
+            }\r
+            prev = ypoints[1];\r
+           }  else {\r
+              prev = -1;\r
+            }\r
+           i++;\r
+       }\r
+    }\r
+\r
+}\r
diff --git a/src/jalview/gui/IdCanvas.java b/src/jalview/gui/IdCanvas.java
new file mode 100755 (executable)
index 0000000..03b85e4
--- /dev/null
@@ -0,0 +1,231 @@
+package jalview.gui;\r
+\r
+import java.awt.*;\r
+import javax.swing.*;\r
+import jalview.datamodel.*;\r
+import jalview.analysis.*;\r
+public class IdCanvas extends JPanel\r
+{\r
+  protected Image    img;\r
+  protected Graphics gg;\r
+\r
+  protected int      imgWidth;\r
+  protected int      imgHeight;\r
+\r
+  protected AlignViewport av;\r
+\r
+  public boolean paintFlag   = false;\r
+  protected boolean showScores  = true;\r
+\r
+  protected int     maxIdLength = -1;\r
+  protected String  maxIdStr    = null;\r
+\r
+  public IdCanvas(AlignViewport av)\r
+  {\r
+    setLayout(new BorderLayout());\r
+    this.av         = av;\r
+    PaintRefresher.Register(this);\r
+  }\r
+\r
+  public void drawIdString(Graphics g,SequenceI ds,int i, int starty, int ypos) {\r
+      int charHeight = av.getCharHeight();\r
+\r
+      if (av.getSelection().contains(ds)) {\r
+         gg.setColor(Color.gray);\r
+         gg.fillRect(0,AlignmentUtil.getPixelHeight(starty,i,charHeight)+ ypos,getWidth(),charHeight);\r
+         gg.setColor(Color.white);\r
+      } else {\r
+         gg.setColor(ds.getColor());\r
+         gg.fillRect(0,AlignmentUtil.getPixelHeight(starty,i,charHeight)+ ypos,getWidth(),charHeight);\r
+         gg.setColor(Color.black);\r
+      }\r
+\r
+      String string = ds.getName() + "/" + ds.getStart() + "-" + ds.getEnd();\r
+\r
+      gg.drawString(string,0,AlignmentUtil.getPixelHeight(starty,i,charHeight) + ypos + charHeight/2);\r
+\r
+  }\r
+\r
+  public void paintComponent(Graphics g) {\r
+    AlignmentI da         = av.getAlignment();\r
+    int        charWidth  = (int)av.getCharWidth();\r
+    int        charHeight = av.getCharHeight();\r
+    Font       f          = av.getFont();\r
+\r
+    if (img == null ||\r
+        imgWidth != getWidth()   ||\r
+        imgHeight != getHeight() ||\r
+        paintFlag == true) {\r
+\r
+      imgWidth = getWidth();\r
+      imgHeight = getHeight();\r
+\r
+      if (imgWidth <= 0 )  {\r
+        imgWidth  = 700;\r
+      }\r
+      if (imgHeight <= 0 ) {\r
+        imgHeight = 500;\r
+      }\r
+\r
+      img = createImage(imgWidth,imgHeight);\r
+\r
+      gg = img.getGraphics();\r
+      gg.setColor(Color.white);\r
+      gg.fillRect(0,0,imgWidth,imgHeight);\r
+\r
+      gg.setFont(f);\r
+\r
+      paintFlag = false;\r
+\r
+    }\r
+\r
+\r
+    //Fill in the background\r
+    gg.setColor(Color.white);\r
+    gg.fillRect(0,0,imgWidth,imgHeight);\r
+\r
+    Color currentColor     = Color.white;\r
+    Color currentTextColor = Color.black;\r
+\r
+    //Which ids are we printing\r
+    int starty = av.getStartSeq();\r
+    int endy   = av.getEndSeq();\r
+\r
+\r
+\r
+    if (av.getWrapAlignment()) {\r
+       starty = starty%av.getChunkHeight();\r
+\r
+       int ypos     = 0;\r
+       int rowstart = starty;\r
+\r
+       if (starty == 0) {\r
+           ypos = 2*charHeight;\r
+       } else if (starty == 1) {\r
+           starty = 0;\r
+           ypos = charHeight;\r
+       }\r
+\r
+       endy   = starty + da.getHeight();\r
+\r
+       if (endy > da.getHeight()) {\r
+           endy = da.getHeight();\r
+       }\r
+\r
+       for (int i = starty; i < endy; i++) {\r
+         SequenceI s = da.getSequenceAt(i);\r
+         drawIdString(gg,s,i,starty,ypos);\r
+       }\r
+       if (rowstart == 0) {\r
+           ypos   = ypos +  av.getChunkHeight();\r
+       } else if (rowstart == 1) {\r
+           ypos   = ypos +  av.getChunkHeight();\r
+       } else {\r
+           ypos   = ypos +  av.getChunkHeight() - rowstart*charHeight;\r
+       }\r
+\r
+       starty = 0;\r
+\r
+       int chunkwidth = av.getChunkWidth();\r
+       int startx = (int)(av.getEndSeq()/chunkwidth)*chunkwidth;\r
+       int endx   = startx + chunkwidth;\r
+\r
+\r
+       while (ypos <= getHeight() && endx < da.getWidth()) {\r
+\r
+           for (int i = starty; i < endy; i++) {\r
+             SequenceI s = da.getSequenceAt(i);\r
+             drawIdString(gg,s,i,starty,ypos);\r
+           }\r
+\r
+           ypos   += av.getChunkHeight();\r
+           startx += chunkwidth;\r
+           endx = startx + chunkwidth;\r
+\r
+           if (endx > da.getWidth()) {\r
+               endx = da.getWidth();\r
+           }\r
+\r
+           starty = 0;\r
+\r
+           if (endy > da.getHeight()) {\r
+               endy = da.getHeight();\r
+           }\r
+\r
+       }\r
+    } else {\r
+\r
+    //Now draw the id strings\r
+    for (int i = starty; i < endy; i++)\r
+    {\r
+\r
+      // Selected sequence colours\r
+\r
+      if (av.getSelection().contains(da.getSequenceAt(i))) {\r
+        if (currentColor != Color.gray) {\r
+          currentColor     = Color.gray;\r
+          currentTextColor = Color.black;\r
+        }\r
+      } else if (da.getSequenceAt(i).getColor() != null)\r
+      {\r
+        currentColor = Color.white;\r
+       /* Color newcol = da.getSequenceAt(i).getColor();\r
+        if (newcol != currentColor) {\r
+          currentColor = newcol;\r
+          if (newcol == Color.black) {\r
+            currentTextColor = Color.white;\r
+          } else {\r
+            currentTextColor = Color.black;\r
+          }\r
+        }*/\r
+      }\r
+\r
+      gg.setColor(currentColor);\r
+\r
+      if (currentColor != Color.white) {\r
+        gg.fillRect(0,\r
+                    AlignmentUtil.getPixelHeight(starty,i,charHeight),\r
+                    getWidth(),\r
+                    charHeight);\r
+      }\r
+\r
+      gg.setColor(currentTextColor);\r
+\r
+      String string = da.getSequenceAt(i).getDisplayId();\r
+\r
+      gg.drawString(string,0,AlignmentUtil.getPixelHeight(starty,i,charHeight) +  charHeight-   (charHeight/5));\r
+    }\r
+    }\r
+\r
+    g.drawImage(img,0,0,this);\r
+  }\r
+\r
+\r
+  public Dimension getLabelWidth()\r
+  {\r
+\r
+   FontMetrics fm = this.getGraphics().getFontMetrics(av.font);\r
+   AlignmentI al = av.getAlignment();\r
+\r
+   int i   = 0;\r
+   int idWidth = 0;\r
+\r
+   while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
+   {\r
+     SequenceI s   = al.getSequenceAt(i);\r
+     String str   = s.getDisplayId();\r
+     if (fm.stringWidth(str) > idWidth)\r
+       idWidth = fm.stringWidth(str);\r
+     i++;\r
+   }\r
+\r
+   return new Dimension(idWidth + 10,getHeight());\r
+ }\r
+\r
+ public Dimension getPreferredSize()\r
+ {\r
+   return getLabelWidth();\r
+ }\r
+\r
+\r
+}\r
diff --git a/src/jalview/gui/IdPanel.java b/src/jalview/gui/IdPanel.java
new file mode 100755 (executable)
index 0000000..26d4199
--- /dev/null
@@ -0,0 +1,126 @@
+package jalview.gui;\r
+\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+\r
+import jalview.datamodel.*;\r
+\r
+import javax.swing.*;\r
+\r
+public class IdPanel extends JPanel implements MouseListener, MouseMotionListener {\r
+\r
+  protected IdCanvas       idCanvas;\r
+  protected AlignViewport  av;\r
+  protected AlignmentPanel alignPanel;\r
+\r
+  protected int            offy;\r
+  public    int            width;\r
+  public    int            lastid;\r
+\r
+\r
+\r
+  boolean mouseDown;\r
+  boolean mouseUp;\r
+\r
+  public IdPanel(AlignViewport av, AlignmentPanel parent)\r
+  {\r
+    this.av         = av;\r
+    alignPanel = parent;\r
+    idCanvas = new IdCanvas(av);\r
+    setLayout(new BorderLayout());\r
+    add(idCanvas, BorderLayout.CENTER);\r
+    addMouseListener(this);\r
+    addMouseMotionListener(this);\r
+  }\r
+\r
+  public void mouseMoved(MouseEvent e) {}\r
+\r
+  public void selectSeqs(int start, int end) {\r
+     if (end < start) {\r
+       int tmp = start;\r
+       start = end;\r
+       end   = tmp;\r
+     }\r
+\r
+     for (int i = start; i <= end; i++) {\r
+       SequenceI pickedSeq = av.getAlignment().getSequenceAt(i);\r
+\r
+       if (av.getSelection().contains(pickedSeq)) {\r
+         av.getSelection().removeElement(pickedSeq);\r
+       } else {\r
+         av.getSelection().addElement(pickedSeq);\r
+       }\r
+     }\r
+\r
+     repaint();\r
+\r
+   }\r
+\r
+  public void mouseDragged(MouseEvent e) {\r
+    int y = e.getY();\r
+\r
+    int seq = av.getIndex(y);\r
+\r
+    if (mouseDown == true) {\r
+      if (seq < lastid) {\r
+        selectSeqs(lastid-1,seq);\r
+      } else if (seq > lastid) {\r
+         selectSeqs(lastid+1,seq);\r
+      }\r
+      lastid = seq;\r
+    }\r
+\r
+    return;\r
+  }\r
+\r
+  public void mouseClicked(MouseEvent e) { }\r
+  public void mouseEntered(MouseEvent e) { }\r
+  public void mouseExited (MouseEvent e) { }\r
+\r
+  public void mousePressed(MouseEvent e) {\r
+    int x = e.getX();\r
+    int y = e.getY();\r
+\r
+    int seq = av.getIndex(y);\r
+\r
+    mouseDown = true;\r
+\r
+      if( javax.swing.SwingUtilities.isRightMouseButton(e))\r
+      {\r
+        String id = av.getAlignment().getSequenceAt(seq).getName();\r
+        String s = (String)JOptionPane.showInputDialog(\r
+                    this,\r
+                    "Edit sequence name",\r
+                    "Edit sequence name",\r
+                    JOptionPane.PLAIN_MESSAGE,\r
+                    null,\r
+                    null,\r
+                    id);\r
+\r
+        if(s!=null)\r
+        {\r
+          av.getAlignment().getSequenceAt(seq).setName(s);\r
+          alignPanel.RefreshPanels();\r
+        }\r
+\r
+      }\r
+      else\r
+      {\r
+        if (seq != -1)\r
+          selectSeqs(seq,seq);\r
+\r
+        lastid = seq;\r
+      }\r
+    return;\r
+  }\r
+\r
+  public void mouseReleased(MouseEvent e) {\r
+    lastid = -1;\r
+\r
+    mouseDown = false;\r
+    mouseUp   = true;\r
+\r
+    PaintRefresher.Refresh(this);\r
+\r
+  }\r
+}\r
diff --git a/src/jalview/gui/PCAPanel.java b/src/jalview/gui/PCAPanel.java
new file mode 100755 (executable)
index 0000000..97df517
--- /dev/null
@@ -0,0 +1,112 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.analysis.PCA;\r
+import jalview.jbgui.*;\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+import java.util.*;\r
+\r
+\r
+public class PCAPanel extends GPCAPanel implements Runnable\r
+{\r
+  PCA pca;\r
+  int top;\r
+  RotatableCanvas rc;\r
+  AlignViewport av;\r
+\r
+  public void run()\r
+  {\r
+    // do stuff\r
+  }\r
+\r
+  public PCAPanel(AlignViewport av, SequenceI[] s) {\r
+\r
+    this.av = av;\r
+    if(s==null)\r
+    {\r
+      s = new Sequence[av.getAlignment().getHeight()];\r
+      for (int i = 0; i < av.getAlignment().getHeight(); i++)\r
+        s[i] = av.getAlignment().getSequenceAt(i);\r
+     }\r
+\r
+//////////////////////This part was done in PCATHread originally. Is it too slow???\r
+    pca = new PCA(s);\r
+    pca.run();\r
+\r
+    // Now find the component coordinates\r
+    int ii=0;\r
+    while (ii < s.length && s[ii] != null)\r
+    {\r
+      ii++;\r
+    }\r
+\r
+    double[][] comps = new double[ii][ii];\r
+\r
+    for (int i=0; i < ii; i++ )\r
+    {\r
+      if (pca.getEigenvalue(i) > 1e-4)\r
+      {\r
+        comps[i]  = pca.component(i);\r
+      }\r
+    }\r
+\r
+    //////////////////\r
+\r
+    xCombobox.setSelectedIndex(0);\r
+    yCombobox.setSelectedIndex(1);\r
+    zCombobox.setSelectedIndex(2);\r
+\r
+    top = pca.getM().rows-1;\r
+\r
+    Vector points = new Vector();\r
+    float[][] scores = pca.getComponents(top-1,top-2,top-3,100);\r
+\r
+    for (int i =0; i < pca.getM().rows; i++ ) {\r
+      SequencePoint sp = new SequencePoint(s[i],scores[i]);\r
+      points.addElement(sp);\r
+    }\r
+    rc = new RotatableCanvas(av,points,pca.getM().rows);\r
+\r
+    //rc.printPoints();\r
+\r
+    add(rc, BorderLayout.CENTER);\r
+  }\r
+\r
+\r
+  void doDimensionChange()\r
+  {\r
+    if(top==0)\r
+      return;\r
+\r
+    int dim1 = top - xCombobox.getSelectedIndex();\r
+    int dim2 = top - yCombobox.getSelectedIndex();\r
+    int dim3 = top - zCombobox.getSelectedIndex();\r
+\r
+    float[][] scores  = pca.getComponents(dim1,dim2,dim3,100);\r
+    for (int i=0; i < pca.getM().rows; i++) {\r
+      ((SequencePoint)rc.points.elementAt(i)).coord = scores[i];\r
+    }\r
+\r
+    rc.img = null;\r
+    rc.rotmat.setIdentity();\r
+    rc.initAxes();\r
+    rc.paint(rc.getGraphics());\r
+  }\r
+\r
+  protected void xCombobox_actionPerformed(ActionEvent e)\r
+  {\r
+    doDimensionChange();\r
+  }\r
+\r
+  protected void yCombobox_actionPerformed(ActionEvent e)\r
+  {\r
+    doDimensionChange();\r
+  }\r
+\r
+  protected void zCombobox_actionPerformed(ActionEvent e)\r
+  {\r
+    doDimensionChange();\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/PaintRefresher.java b/src/jalview/gui/PaintRefresher.java
new file mode 100755 (executable)
index 0000000..051721b
--- /dev/null
@@ -0,0 +1,35 @@
+package jalview.gui;\r
+import java.awt.*;\r
+import java.util.*;\r
+\r
+public class PaintRefresher\r
+{\r
+  static Vector containers = new Vector();\r
+\r
+  public static void Register(Container c)\r
+  {\r
+    if(!containers.contains(c))\r
+      containers.add(c);\r
+    else\r
+      containers.remove(c);\r
+  }\r
+\r
+  public static void Refresh(Container c)\r
+  {\r
+    Container temp;\r
+    Enumeration e = containers.elements();\r
+    while( e.hasMoreElements() )\r
+    {\r
+      temp = (Container)e.nextElement();\r
+\r
+      if(!temp.isValid())\r
+        containers.removeElement( temp );\r
+      else if( temp == c )\r
+           continue;\r
+\r
+      temp.repaint();\r
+    }\r
+\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/PairwiseAlignPanel.java b/src/jalview/gui/PairwiseAlignPanel.java
new file mode 100755 (executable)
index 0000000..c771693
--- /dev/null
@@ -0,0 +1,73 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.jbgui.GPairwiseAlignPanel;\r
+import jalview.analysis.*;\r
+import java.awt.event.*;\r
+import javax.swing.*;\r
+import java.util.*;\r
+\r
+\r
+public class PairwiseAlignPanel extends GPairwiseAlignPanel\r
+{\r
+    Vector sequences = new Vector();\r
+    AlignViewport av;\r
+\r
+    public PairwiseAlignPanel(AlignViewport av)\r
+    {\r
+      super();\r
+      this.av = av;\r
+      float scores[][] = new float[av.getAlignment().getHeight()][av.getAlignment().getHeight()];\r
+      double totscore = 0;\r
+      int count = av.getSelection().size();\r
+\r
+      int acount = 0;\r
+        for (int i = 1; i < count; i++)\r
+        {\r
+          for (int j = 0; j < i; j++)\r
+          {\r
+            acount++;\r
+            AlignSeq as = new AlignSeq(av.getSelection().sequenceAt(i),av.getSelection().sequenceAt(j),"pep");\r
+            //tf.status.setText("Aligning " + as.getS1().getName() + " and " + as.getS2().getName() + " (" + acount + "/" + (count*(count-1)/2) + ")");\r
+\r
+            as.calcScoreMatrix();\r
+            as.traceAlignment();\r
+            as.printAlignment();\r
+            scores[i][j] = (float)as.getMaxScore()/(float)as.getASeq1().length;\r
+            totscore = totscore + scores[i][j];\r
+\r
+            textarea.append(as.getOutput());\r
+            sequences.add( as.getS1() );\r
+            sequences.add( as.getS2() );\r
+\r
+          }\r
+        }\r
+\r
+        if (count > 2)\r
+        {\r
+          for (int i = 0; i < count;i++)\r
+            for (int j = 0; j < i; j++)\r
+              jalview.util.Format.print(System.out,"%7.3f",scores[i][j]/totscore);\r
+        }\r
+      }\r
+\r
+\r
+  protected void viewInEditorButton_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+      Sequence [] seq = new Sequence[sequences.size()];\r
+\r
+      for (int i=0;i<sequences.size();i++)\r
+       seq[i] = (Sequence) sequences.elementAt(i);\r
+\r
+\r
+      AlignFrame af = new AlignFrame(new Alignment(seq));\r
+      int newHeight = seq.length * af.viewport.getCharHeight() + 200;\r
+      if(newHeight>500)\r
+        newHeight=500;\r
+\r
+      Desktop.addInternalFrame(af, "Pairwise Aligned Sequences", 700,newHeight);\r
+\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/RendererI.java b/src/jalview/gui/RendererI.java
new file mode 100755 (executable)
index 0000000..81c5612
--- /dev/null
@@ -0,0 +1,14 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+import java.awt.*;\r
+import java.util.*;\r
+\r
+public interface RendererI {\r
+\r
+    public Color getResidueBoxColour(ColourSchemeI cs, SequenceI seq, int i);\r
+\r
+    public void drawSequence(Graphics g,ColourSchemeI cs,SequenceI seq,int start, int end, int x1, int y1, double width, int  height,boolean showScores, boolean displayBoxes, boolean displayText,Vector pid, int seqnum,AlignViewport av);\r
+\r
+}\r
diff --git a/src/jalview/gui/RotatableCanvas.java b/src/jalview/gui/RotatableCanvas.java
new file mode 100755 (executable)
index 0000000..90688d0
--- /dev/null
@@ -0,0 +1,514 @@
+package jalview.gui;\r
+\r
+import jalview.math.*;\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+import javax.swing.*;\r
+import java.util.*;\r
+\r
+\r
+public class RotatableCanvas extends JPanel implements MouseListener,\r
+                                                       MouseMotionListener,\r
+                                                       KeyListener\r
+                                                       //RubberbandListener,\r
+                                                       //SequenceSelectionListener\r
+{\r
+  RotatableMatrix idmat  = new RotatableMatrix(3,3);\r
+  RotatableMatrix objmat = new RotatableMatrix(3,3);\r
+  RotatableMatrix rotmat = new RotatableMatrix(3,3);\r
+\r
+  //RubberbandRectangle rubberband;\r
+\r
+  boolean drawAxes = true;\r
+\r
+  int omx = 0;\r
+  int mx = 0;\r
+  int omy = 0;\r
+  int my = 0;\r
+\r
+  Image img;\r
+  Graphics ig;\r
+\r
+  Dimension prefsize;\r
+\r
+  float centre[] = new float[3];\r
+  float width[] = new float[3];\r
+\r
+  float max[] = new float[3];\r
+  float min[] = new float[3];\r
+\r
+  float maxwidth;\r
+  float scale;\r
+\r
+  int npoint;\r
+\r
+  Vector points;\r
+  float[][] orig;\r
+  float[][] axes;\r
+\r
+  int startx;\r
+  int starty;\r
+\r
+  int lastx;\r
+  int lasty;\r
+\r
+  int rectx1;\r
+  int recty1;\r
+  int rectx2;\r
+  int recty2;\r
+\r
+  float scalefactor = 1;\r
+\r
+  AlignViewport av;\r
+//  Controller    controller;\r
+\r
+\r
+  public RotatableCanvas(AlignViewport av,\r
+                          Vector points, int npoint) {\r
+    this.points = points;\r
+    this.npoint = npoint;\r
+    this.av = av;\r
+    ToolTipManager.sharedInstance().registerComponent(this);\r
+    PaintRefresher.Register(this);\r
+//\r
+    prefsize = getPreferredSize();\r
+    orig = new float[npoint][3];\r
+\r
+    for (int i=0; i < npoint; i++) {\r
+      SequencePoint sp = (SequencePoint)points.elementAt(i);\r
+      for (int j=0; j < 3; j++) {\r
+        orig[i][j] = sp.coord[j];\r
+      }\r
+    }\r
+    //Initialize the matrices to identity\r
+\r
+    for (int i = 0; i < 3; i++) {\r
+      for (int j = 0; j < 3 ; j++) {\r
+        if (i != j) {\r
+          idmat.addElement(i,j,0);\r
+          objmat.addElement(i,j,0);\r
+          rotmat.addElement(i,j,0);\r
+        } else {\r
+          idmat.addElement(i,j,0);\r
+          objmat.addElement(i,j,0);\r
+          rotmat.addElement(i,j,0);\r
+        }\r
+      }\r
+    }\r
+\r
+    axes = new float[3][3];\r
+    initAxes();\r
+\r
+    findCentre();\r
+    findWidth();\r
+\r
+    scale = findScale();\r
+\r
+    //    System.out.println("Scale factor = " + scale);\r
+\r
+    addMouseListener(this);\r
+    addKeyListener(this);\r
+   // if (getParent() != null) {\r
+   //   getParent().addKeyListener(this);\r
+    //}\r
+    addMouseMotionListener(this);\r
+\r
+    // Add rubberband\r
+ //   rubberband  = new RubberbandRectangle(this);\r
+  //  rubberband.setActive(true);\r
+ //   rubberband.addListener(this);\r
+  }\r
+\r
+ /* public boolean handleSequenceSelectionEvent(SequenceSelectionEvent evt) {\r
+    redrawneeded = true;\r
+    repaint();\r
+    return true;\r
+  }\r
+\r
+  public void removeNotify() {\r
+    controller.removeListener(this);\r
+    super.removeNotify();\r
+  }*/\r
+\r
+  public void initAxes() {\r
+    for (int i = 0; i < 3; i++) {\r
+      for (int j=0; j < 3; j++) {\r
+        if (i != j) {\r
+          axes[i][j] = 0;\r
+        } else {\r
+          axes[i][j] = 1;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  public void findWidth() {\r
+    max = new float[3];\r
+    min = new float[3];\r
+\r
+    max[0] = (float)-1e30;\r
+    max[1] = (float)-1e30;\r
+    max[2] = (float)-1e30;\r
+\r
+    min[0] = (float)1e30;\r
+    min[1] = (float)1e30;\r
+    min[2] = (float)1e30;\r
+\r
+    for (int i = 0; i < 3; i++) {\r
+      for (int j = 0; j < npoint; j++) {\r
+        SequencePoint sp = (SequencePoint)points.elementAt(j);\r
+        if (sp.coord[i] >= max[i]) {\r
+          max[i] = sp.coord[i];\r
+        }\r
+        if (sp.coord[i] <= min[i]) {\r
+          min[i] = sp.coord[i];\r
+        }\r
+      }\r
+    }\r
+\r
+    //    System.out.println("xmax " + max[0] + " min " + min[0]);\r
+    //System.out.println("ymax " + max[1] + " min " + min[1]);\r
+    //System.out.println("zmax " + max[2] + " min " + min[2]);\r
+\r
+    width[0] = Math.abs(max[0] - min[0]);\r
+    width[1] = Math.abs(max[1] - min[1]);\r
+    width[2] = Math.abs(max[2] - min[2]);\r
+\r
+    maxwidth = width[0];\r
+\r
+    if (width[1] > width[0])\r
+      maxwidth = width[1];\r
+    if (width[2] > width[1])\r
+      maxwidth = width[2];\r
+\r
+    //System.out.println("Maxwidth = " + maxwidth);\r
+  }\r
+\r
+  public float findScale() {\r
+    int dim, width, height;\r
+    if (getWidth() != 0) {\r
+      width = getWidth();\r
+      height = getHeight();\r
+    } else {\r
+      width = prefsize.width;\r
+      height = prefsize.height;\r
+    }\r
+\r
+    if (width < height) {\r
+      dim = width;\r
+    } else {\r
+      dim = height;\r
+    }\r
+\r
+    return (float)(dim*scalefactor/(2*maxwidth));\r
+  }\r
+\r
+  public void findCentre() {\r
+    //Find centre coordinate\r
+    findWidth();\r
+\r
+    centre[0] = (max[0] + min[0])/2;\r
+    centre[1] = (max[1] + min[1])/2;\r
+    centre[2] = (max[2] + min[2])/2;\r
+\r
+    //    System.out.println("Centre x " + centre[0]);\r
+    //System.out.println("Centre y " + centre[1]);\r
+    //System.out.println("Centre z " + centre[2]);\r
+  }\r
+\r
+  public Dimension getPreferredSize() {\r
+    if (prefsize != null) {\r
+      return prefsize;\r
+    } else {\r
+      return new Dimension(400,400);\r
+    }\r
+  }\r
+\r
+  public Dimension getMinimumSize() {\r
+    return getPreferredSize();\r
+  }\r
+\r
+  public void paintComponent(Graphics g) {\r
+    //Only create the image at the beginning -\r
+    if ((img == null) || (prefsize.width != getWidth()) || (prefsize.height != getHeight())) {\r
+      prefsize.width = getWidth();\r
+      prefsize.height = getHeight();\r
+\r
+      scale = findScale();\r
+\r
+      //      System.out.println("New scale = " + scale);\r
+      img = createImage(getWidth(),getHeight());\r
+      ig = img.getGraphics();\r
+\r
+    }\r
+\r
+\r
+      drawBackground(ig,Color.black);\r
+      drawScene(ig);\r
+      if (drawAxes == true)\r
+      {\r
+        drawAxes(ig);\r
+      }\r
+\r
+\r
+    g.drawImage(img,0,0,this);\r
+  }\r
+\r
+  public void drawAxes(Graphics g) {\r
+\r
+    g.setColor(Color.yellow);\r
+    for (int i=0; i < 3 ; i++) {\r
+      g.drawLine(getWidth()/2,getHeight()/2,\r
+                 (int)(axes[i][0]*scale*max[0] + getWidth()/2),\r
+                 (int)(axes[i][1]*scale*max[1] + getHeight()/2));\r
+    }\r
+  }\r
+\r
+  public void drawBackground(Graphics g, Color col) {\r
+    g.setColor(col);\r
+    g.fillRect(0,0,prefsize.width,prefsize.height);\r
+  }\r
+\r
+\r
+  public void drawScene(Graphics g) {\r
+    boolean darker = false;\r
+\r
+    int halfwidth = getWidth()/2;\r
+    int halfheight = getHeight()/2;\r
+\r
+    for (int i = 0; i < npoint; i++) {\r
+      SequencePoint sp = (SequencePoint)points.elementAt(i);\r
+      int x = (int)((float)(sp.coord[0] - centre[0])*scale) + halfwidth;\r
+      int y = (int)((float)(sp.coord[1] - centre[1])*scale) + halfheight;\r
+      float z = sp.coord[1] - centre[2];\r
+      if (sp.sequence instanceof DrawableSequence) {\r
+        if (((DrawableSequence)sp.sequence).color == Color.black) {\r
+          g.setColor(Color.white);\r
+        } else {\r
+          g.setColor(((DrawableSequence)sp.sequence).color);\r
+        }\r
+      } else {\r
+        g.setColor(Color.red);\r
+      }\r
+      if (av != null) {\r
+        if (av.getSelection().contains(((SequencePoint)points.elementAt(i)).sequence)) {\r
+          g.setColor(Color.gray);\r
+        }\r
+      }\r
+      if (z < 0) {\r
+        g.setColor(g.getColor().darker());\r
+      }\r
+\r
+      g.fillRect(x-3,y-3,6,6);\r
+      g.setColor(Color.red);\r
+    }\r
+//    //Now the rectangle\r
+//    if (rectx2 != -1 && recty2 != -1) {\r
+//      g.setColor(Color.white);\r
+//\r
+//      g.drawRect(rectx1,recty1,rectx2-rectx1,recty2-recty1);\r
+//    }\r
+  }\r
+\r
+  public Dimension minimumsize() {\r
+    return prefsize;\r
+  }\r
+\r
+  public Dimension preferredsize() {\r
+    return prefsize;\r
+  }\r
+\r
+  public void keyTyped(KeyEvent evt) { }\r
+  public void keyReleased(KeyEvent evt) { }\r
+\r
+  public void keyPressed(KeyEvent evt) {\r
+    requestFocus();\r
+    if (evt.getKeyCode() == KeyEvent.VK_UP) {\r
+      scalefactor = (float)(scalefactor * 1.1);\r
+      scale = findScale();\r
+    } else if (evt.getKeyCode() == KeyEvent.VK_DOWN) {\r
+      scalefactor = (float)(scalefactor * 0.9);\r
+      scale = findScale();\r
+    } else if (evt.getKeyChar() == 's') {\r
+      System.out.println("Rectangle selection");\r
+      if (rectx2 != -1 && recty2 != -1) {\r
+        rectSelect(rectx1,recty1,rectx2,recty2);\r
+\r
+      }\r
+    }\r
+    repaint();\r
+  }\r
+\r
+  public void printPoints() {\r
+    for (int i=0; i < npoint; i++) {\r
+      SequencePoint sp = (SequencePoint)points.elementAt(i);\r
+      Format.print(System.out,"%5d ", i);\r
+      for (int j=0; j < 3;j++) {\r
+        Format.print(System.out,"%13.3f  ",sp.coord[j]);\r
+      }\r
+      System.out.println();\r
+    }\r
+  }\r
+\r
+  public void mouseClicked(MouseEvent evt) { }\r
+  public void mouseEntered(MouseEvent evt) { }\r
+  public void mouseExited(MouseEvent evt) { }\r
+  public void mouseReleased(MouseEvent evt) { }\r
+\r
+  public void mousePressed(MouseEvent evt) {\r
+    int x = evt.getX();\r
+    int y = evt.getY();\r
+\r
+    mx = x;\r
+    my = y;\r
+\r
+    omx = mx;\r
+    omy = my;\r
+\r
+    startx = x;\r
+    starty = y;\r
+\r
+    rectx1 = x;\r
+    recty1 = y;\r
+\r
+    rectx2 = -1;\r
+    recty2 = -1;\r
+\r
+    SequenceI found = findPoint(x,y);\r
+\r
+    if (found != null) {\r
+      if (av != null) {\r
+\r
+        if (av.getSelection().contains(found)) {\r
+          av.getSelection().removeElement(found);\r
+        } else {\r
+          av.getSelection().addElement(found);\r
+        }\r
+        PaintRefresher.Refresh(this);\r
+      }\r
+    }\r
+    repaint();\r
+  }\r
+\r
+ // private void fireSequenceSelectionEvent(Selection sel) {\r
+ //   controller.handleSequenceSelectionEvent(new SequenceSelectionEvent(this,sel));\r
+  //}\r
+\r
+  public void mouseMoved(MouseEvent evt)\r
+  {\r
+   SequenceI found = findPoint(evt.getX(), evt.getY());\r
+   if (found != null)\r
+     this.setToolTipText(found.getName());\r
+   else\r
+     this.setToolTipText(null);\r
+ }\r
+\r
+  public void mouseDragged(MouseEvent evt) {\r
+    mx = evt.getX();\r
+    my = evt.getY();\r
+    //Check if this is a rectangle drawing drag\r
+    if ((evt.getModifiers() & InputEvent.BUTTON2_MASK) != 0) {\r
+//      rectx2 = evt.getX();\r
+//      recty2 = evt.getY();\r
+    } else {\r
+      rotmat.setIdentity();\r
+\r
+      rotmat.rotate((float)(my-omy),'x');\r
+      rotmat.rotate((float)(mx-omx),'y');\r
+\r
+      for (int i = 0; i < npoint; i++) {\r
+        SequencePoint sp = (SequencePoint)points.elementAt(i);\r
+        sp.coord[0] -= centre[0];\r
+        sp.coord[1] -= centre[1];\r
+        sp.coord[2] -= centre[2];\r
+\r
+        //Now apply the rotation matrix\r
+        sp.coord= rotmat.vectorMultiply(sp.coord);\r
+\r
+        //Now translate back again\r
+        sp.coord[0] += centre[0];\r
+        sp.coord[1] += centre[1];\r
+        sp.coord[2] += centre[2];\r
+      }\r
+\r
+      for (int i=0; i < 3; i++) {\r
+        axes[i] = rotmat.vectorMultiply(axes[i]);\r
+      }\r
+      omx = mx;\r
+      omy = my;\r
+\r
+      paint(this.getGraphics());\r
+    }\r
+\r
+  }\r
+\r
+  public void rectSelect(int x1, int y1, int x2, int y2) {\r
+    boolean changedSel = false;\r
+    for (int i=0; i < npoint; i++) {\r
+      SequencePoint sp = (SequencePoint)points.elementAt(i);\r
+      int tmp1 = (int)((sp.coord[0] - centre[0])*scale + (float)getWidth()/2.0);\r
+      int tmp2 = (int)((sp.coord[1] - centre[1])*scale + (float)getHeight()/2.0);\r
+\r
+      if (tmp1 > x1 && tmp1 < x2 && tmp2 > y1 && tmp2 < y2) {\r
+        if (av != null) {\r
+          if (!av.getSelection().contains(sp.sequence)) {\r
+            changedSel = true;\r
+            av.getSelection().addElement(sp.sequence);\r
+          }\r
+        }\r
+      }\r
+    }\r
+   // if (changedSel) {\r
+   //    fireSequenceSelectionEvent(av.getSelection());\r
+   // }\r
+  }\r
+  public SequenceI findPoint(int x, int y) {\r
+\r
+    int halfwidth = getWidth()/2;\r
+    int halfheight = getHeight()/2;\r
+\r
+    int found = -1;\r
+\r
+    for (int i=0; i < npoint; i++) {\r
+\r
+      SequencePoint sp = (SequencePoint)points.elementAt(i);\r
+      int px = (int)((float)(sp.coord[0] - centre[0])*scale) + halfwidth;\r
+      int py = (int)((float)(sp.coord[1] - centre[1])*scale) + halfheight;\r
+\r
+\r
+      if (Math.abs(px-x)<3 && Math.abs(py - y) < 3 ) {\r
+        found = i;\r
+      }\r
+    }\r
+    if (found != -1) {\r
+      return ((SequencePoint)points.elementAt(found)).sequence;\r
+    } else {\r
+      return null;\r
+    }\r
+  }\r
+/*  public boolean handleRubberbandEvent(RubberbandEvent evt) {\r
+    System.out.println("Rubberband handler called in RotatableCanvas with " +\r
+                       evt.getBounds());\r
+\r
+    Rubberband rb = (Rubberband)evt.getSource();\r
+\r
+    // Clear the current selection (instance variable)\r
+    //if ((rb.getModifiers() & Event.SHIFT_MASK) == 0) {\r
+    //   clearSelection();\r
+    //}\r
+\r
+    if (rb.getComponent() == this) {\r
+      Rectangle bounds = evt.getBounds();\r
+      rectSelect(bounds.x,bounds.y,bounds.x+bounds.width,bounds.y+bounds.height);\r
+    }\r
+\r
+    redrawneeded = true;\r
+    paint(this.getGraphics());\r
+\r
+    return true;\r
+  }*/\r
+\r
+}\r
diff --git a/src/jalview/gui/ScaleCanvas.java b/src/jalview/gui/ScaleCanvas.java
new file mode 100755 (executable)
index 0000000..090b272
--- /dev/null
@@ -0,0 +1,130 @@
+package jalview.gui;\r
+\r
+import java.awt.*;\r
+import javax.swing.*;\r
+\r
+public class ScaleCanvas extends JPanel {\r
+\r
+  Image    img;\r
+  Graphics gg;\r
+\r
+  int      imgWidth;\r
+  int      imgHeight;\r
+  int      xoffset;\r
+\r
+  public static final int HEIGHT = 30;\r
+\r
+  boolean paintFlag = false;\r
+\r
+  protected AlignViewport av;\r
+\r
+  public ScaleCanvas(AlignViewport av) {\r
+    this.av         = av;\r
+\r
+  }\r
+  public void paintComponent(Graphics g) {\r
+\r
+   double charWidth  = av.getCharWidth();\r
+    int charHeight = av.getCharHeight();\r
+\r
+    if (img == null ||\r
+        imgWidth  != getWidth()  ||\r
+        imgHeight != getHeight() ||\r
+        paintFlag == true) {\r
+\r
+      imgWidth  = getWidth();\r
+      imgHeight = getHeight();\r
+      img       = createImage(imgWidth,imgHeight);\r
+\r
+      gg = img.getGraphics();\r
+      gg.setColor(Color.white);\r
+      gg.fillRect(0,0,imgWidth,imgHeight);\r
+\r
+\r
+\r
+      paintFlag = false;\r
+    }\r
+    gg.setFont(av.getFont());\r
+\r
+    //Fill in the background\r
+\r
+    gg.setColor(Color.white);\r
+    gg.fillRect(0,0,imgWidth,imgHeight);\r
+\r
+    int tickSpace;\r
+\r
+    int resWidth = av.getEndRes() - av.getStartRes() + 1;\r
+\r
+    // We want roughly one tick every 50 pixels\r
+\r
+    double rough = getWidth()/50.0;\r
+\r
+    double roughtick = resWidth/rough;\r
+\r
+    int   digits  = (int)(Math.log(roughtick)/Math.log(10));\r
+    int   num     = (int)(roughtick/Math.pow(10,digits));\r
+\r
+    if (Math.abs(10-num) < 3) {\r
+        num = 10;\r
+    } else if (Math.abs(5-num) <= 2) {\r
+        num = 5;\r
+    } else {\r
+        num = 2;\r
+    }\r
+    //System.out.println("Dig " + digits + " " + rough + " " + roughtick + " " + getWidth() + " " + num);\r
+\r
+    int space = (int)(num * Math.pow(10,digits));\r
+\r
+    //Set the text font\r
+\r
+    gg.setColor(Color.black);\r
+\r
+    int startx      = av.getStartRes();\r
+    int endx        = av.getEndRes();\r
+    int scalestartx = startx - startx%space + space;\r
+\r
+\r
+    //Fill the selected columns\r
+    ColumnSelection cs = av.getColumnSelection();\r
+    int width = (int)charWidth;\r
+    if (width == 0)\r
+      width = 1;\r
+\r
+    gg.setColor(new Color(220,0,0));\r
+    for (int i=0; i<cs.size(); i++) {\r
+      int sel  = cs.columnAt(i);\r
+      //      System.out.println("Selection = " + sel);\r
+      if ( sel >= startx  && sel <= endx) {\r
+\r
+        gg.fillRect((int)((sel-startx)*charWidth),0,width,getHeight());\r
+      }\r
+    }\r
+\r
+    // Draw the scale numbers\r
+    gg.setColor(Color.black);\r
+\r
+\r
+    for (int i=scalestartx;i < endx;i+= space) {\r
+\r
+      String string = String.valueOf(i);\r
+\r
+      gg.drawString(string,(int)((i-startx-1)*charWidth),15);\r
+      gg.drawLine( (int)((i-startx-1)*charWidth +charWidth/2), 17, (int)((i-startx-1)*charWidth +charWidth/2), 24);\r
+\r
+    }\r
+\r
+\r
+    g.drawImage(img,0,0,this);\r
+\r
+  }\r
+\r
+  public Dimension getMinimumSize() {\r
+    return new Dimension(500,HEIGHT);\r
+  }\r
+\r
+  public Dimension getPreferredSize() {\r
+    return getMinimumSize();\r
+  }\r
+\r
+}\r
+\r
diff --git a/src/jalview/gui/ScalePanel.java b/src/jalview/gui/ScalePanel.java
new file mode 100755 (executable)
index 0000000..e25a4bb
--- /dev/null
@@ -0,0 +1,52 @@
+package jalview.gui;\r
+\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+\r
+import javax.swing.*;\r
+\r
+public class ScalePanel extends JPanel\r
+{\r
+\r
+  protected ScaleCanvas scaleCanvas;\r
+\r
+  protected int offy;\r
+  public    int width;\r
+\r
+  protected AlignViewport av;\r
+\r
+  public ScalePanel(AlignViewport av) {\r
+    this.av         = av;\r
+\r
+    scaleCanvas = new ScaleCanvas(av);\r
+    setLayout(new BorderLayout());\r
+    add(scaleCanvas, BorderLayout.CENTER);\r
+    addMouseListener(new MouseAdapter()\r
+    {\r
+      public void mousePressed(MouseEvent evt)\r
+      {\r
+        doMousePressed(evt);\r
+      }\r
+    });\r
+  }\r
+\r
+  public Dimension getMinimumSize() {\r
+    return scaleCanvas.getMinimumSize();\r
+  }\r
+\r
+  public Dimension getPreferredSize() {\r
+    return scaleCanvas.getPreferredSize();\r
+  }\r
+\r
+  public void doMousePressed(MouseEvent evt) {\r
+    int x = evt.getX();\r
+    int res = x/(int)av.getCharWidth() + av.getStartRes();\r
+\r
+    if (! av.getColumnSelection().contains(res))\r
+      av.getColumnSelection().addElement(res);\r
+     else\r
+      av.getColumnSelection().removeElement(res);\r
+\r
+    repaint();\r
+  }\r
+}\r
diff --git a/src/jalview/gui/ScorePanel.java b/src/jalview/gui/ScorePanel.java
new file mode 100755 (executable)
index 0000000..d2b472c
--- /dev/null
@@ -0,0 +1,97 @@
+package jalview.gui;\r
+\r
+import jalview.jbgui.*;\r
+import java.util.*;\r
+import javax.swing.*;\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+\r
+public class ScorePanel extends JPanel\r
+{\r
+  AlignViewport av;\r
+\r
+  public ScorePanel(AlignViewport a)\r
+  {\r
+    av = a;\r
+    setPreferredSize(new Dimension(500,80));\r
+    addMouseMotionListener(new MouseMotionAdapter()\r
+    { public void mouseMoved(MouseEvent evt)\r
+      {\r
+        doMouseMoved(evt);\r
+      }\r
+    });\r
+\r
+    ToolTipManager.sharedInstance().registerComponent(this);\r
+  }\r
+\r
+  public void doMouseMoved(MouseEvent evt)\r
+  {\r
+     Vector freq = av.getConsensus(false);\r
+\r
+     int col = (int)(evt.getX()/av.charWidth) +av.getStartRes();\r
+\r
+     if(col >= av.getEndRes() || col >= freq.size())\r
+       return;\r
+\r
+     Hashtable hash = (Hashtable) freq.elementAt( col );\r
+\r
+     String characters = hash.get("maxResidue").toString();\r
+\r
+     if (characters.length()>1)\r
+       this.setToolTipText(characters);\r
+     else\r
+       this.setToolTipText(null);\r
+  }\r
+\r
+  public void paintComponent(Graphics g)\r
+  {\r
+    setPreferredSize(new Dimension( this.getWidth(), 80));\r
+   g.setColor(Color.white);\r
+   g.fillRect(0, 0, this.getWidth(), 80);\r
+   g.setColor(Color.blue);\r
+   g.setFont(av.getFont());\r
+\r
+   Vector freq = av.getConsensus(false);\r
+\r
+   int value, charOffset;\r
+   String characters;\r
+   char character;\r
+\r
+\r
+   int i=0, iSize = av.getChunkWidth();\r
+   if(iSize > freq.size())\r
+     iSize=freq.size();\r
+\r
+   for (i = 0; i < iSize; i++)\r
+   {\r
+     g.setColor(Color.blue);\r
+\r
+     Hashtable hash = (Hashtable) freq.elementAt(i+av.getStartRes());\r
+     if(hash.containsKey("maxResidue"))\r
+            characters = hash.get("maxResidue").toString();\r
+     else\r
+       characters="@";\r
+     character = characters.charAt(0);\r
+     value = Integer.parseInt(hash.get("maxCount").toString());\r
+\r
+     if (characters.length() > 1)\r
+       character = '+';\r
+\r
+     charOffset = (int) (av.charWidth -\r
+                         g.getFontMetrics().charWidth(character)) / 2;\r
+     g.drawString(character + "", charOffset + (int) (i * av.charWidth),\r
+                  60 + (int) av.charWidth);\r
+\r
+     value = (int) ( (float) value /\r
+                    Float.parseFloat(hash.get("size").toString()) * 55);\r
+\r
+     if (character != ' ' && character != '.' && character != '-')\r
+       g.fillRect( (int) (i * av.charWidth),\r
+                  60 - value,\r
+                  (int) av.charWidth,\r
+                  value\r
+                  );\r
+   }\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/Selection.java b/src/jalview/gui/Selection.java
new file mode 100755 (executable)
index 0000000..6f73f5d
--- /dev/null
@@ -0,0 +1,60 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+\r
+import java.util.*;\r
+\r
+public class Selection {\r
+  Vector selected = new Vector();\r
+\r
+  public void addElement(DrawableSequence seq) {\r
+    addElement((SequenceI)seq);\r
+  }\r
+  public void addElement(SequenceI seq) {\r
+    selected.addElement(seq);\r
+  }\r
+\r
+  public void removeElement(DrawableSequence seq) {\r
+    removeElement((SequenceI)seq);\r
+  }\r
+\r
+  public void clear() {\r
+    selected.removeAllElements();\r
+  }\r
+\r
+  public void removeElement(SequenceI seq) {\r
+    if (selected.contains(seq)) {\r
+      selected.removeElement(seq);\r
+    } else {\r
+      System.err.println("WARNING: Tried to remove SequenceI NOT in Selection");\r
+    }\r
+  }\r
+\r
+  public boolean contains(DrawableSequence seq) {\r
+    return contains((SequenceI)seq);\r
+  }\r
+  public boolean contains(SequenceI seq) {\r
+    return selected.contains(seq);\r
+  }\r
+\r
+  public SequenceI sequenceAt(int i) {\r
+    return (SequenceI)selected.elementAt(i);\r
+  }\r
+\r
+  public int size() {\r
+    return selected.size();\r
+  }\r
+\r
+  public Vector asVector() {\r
+    return selected;\r
+  }\r
+\r
+  public void selectAll(AlignmentI align) {\r
+    for (int i=0;i<align.getSequences().size();i++) {\r
+      SequenceI seq = align.getSequenceAt(i);\r
+      if (!contains(seq)) {\r
+        addElement(seq);\r
+      }\r
+    }\r
+  }\r
+}\r
diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java
new file mode 100755 (executable)
index 0000000..c697d1e
--- /dev/null
@@ -0,0 +1,359 @@
+package jalview.gui;\r
+\r
+import java.awt.*;\r
+import javax.swing.*;\r
+import java.util.*;\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+import jalview.analysis.*;\r
+\r
+\r
+public class SeqCanvas extends JPanel\r
+{\r
+    Image             img;\r
+    Graphics          gg;\r
+    int               imgWidth;\r
+    int               imgHeight;\r
+\r
+    AlignViewport     av;\r
+    int pady = 2;\r
+    int oldstartx;\r
+    int oldstarty;\r
+    int oldendx;\r
+    int oldendy;\r
+\r
+    public boolean paintFlag = false;\r
+    boolean showScores = false;\r
+\r
+    int chunkHeight;\r
+    int chunkWidth;\r
+\r
+    Graphics debugG;\r
+    FeatureRenderer fr = new FeatureRenderer();\r
+    BlockRenderer   br = new BlockRenderer();\r
+    CpGRenderer     cgr = new CpGRenderer();\r
+\r
+    ColourSchemeI    cs = new ZappoColourScheme();\r
+\r
+    public SeqCanvas(AlignViewport av)\r
+    {\r
+       this.av         = av;\r
+       setLayout(new BorderLayout());\r
+    }\r
+\r
+  public void drawScale(int startx, int endx,double charWidth, int charHeight,int ypos) {\r
+      int scalestartx = startx - startx%10 + 10;\r
+\r
+      gg.setColor(Color.black);\r
+\r
+      for (int i=scalestartx;i < endx;i+= 10) {\r
+         String string = String.valueOf(i);\r
+         gg.drawString(string,(int)((i-startx-1)*charWidth),ypos+15 - charHeight*(2));\r
+      }\r
+  }\r
+\r
+\r
+/**\r
+ * Definitions of startx and endx (hopefully):\r
+ * SMJS This is what I'm working towards!\r
+ *   startx is the first residue (starting at 0) to display.\r
+ *   endx   is the last residue to display (starting at 0).\r
+ *   starty is the first sequence to display (starting at 0).\r
+ *   endy   is the last sequence to display (starting at 0).\r
+ * NOTE 1: The av limits are set in setFont in this class and\r
+ * in the adjustment listener in SeqPanel when the scrollbars move.\r
+ */\r
+\r
+  public void paintComponent(Graphics g) {\r
+    debugG = g;\r
+\r
+    AlignmentI da = av.getAlignment();\r
+\r
+    if (img == null ||\r
+        imgWidth  !=  getWidth()  ||\r
+        imgHeight !=  getHeight() ||\r
+        paintFlag == true) {\r
+\r
+      imgWidth  = (getWidth() > 0 ? getWidth() : 1);\r
+      imgHeight = (getHeight() > 0 ? getHeight() : 1);\r
+\r
+      img = createImage(imgWidth,imgHeight);\r
+      gg  = img.getGraphics();\r
+\r
+     // SMJS I added this in to update the AV when the size changes\r
+      //      until I figure out how this should be done\r
+      setFont(av.getFont());\r
+\r
+      gg.setFont(av.getFont());\r
+\r
+      paintFlag = false;\r
+\r
+      oldstartx = -1;\r
+      oldendx   = -1;\r
+      oldstarty = -1;\r
+      oldendy   = -1;\r
+    }\r
+\r
+    int startx = av.getStartRes();\r
+    int starty = av.getStartSeq();\r
+\r
+    int endx   = av.getEndRes();\r
+    int endy   = av.getEndSeq();\r
+\r
+    double charWidth  = av.getCharWidth();\r
+    int charHeight    = av.getCharHeight();\r
+\r
+    chunkWidth = (int)(getWidth()/charWidth);\r
+    chunkHeight =  (da.getHeight() + 2)*charHeight;\r
+\r
+    av.setChunkHeight(chunkHeight);\r
+    av.setChunkWidth(chunkWidth);\r
+\r
+    int offy = av.getStartSeq();\r
+\r
+    if (oldendx == -1) {\r
+      fillBackground(gg,Color.WHITE,0,0,imgWidth,imgHeight);\r
+\r
+     /* if (av.getWrapAlignment() == true) {\r
+         startx = (int)(offy/chunkWidth)*chunkWidth;\r
+         endx   = startx + chunkWidth;\r
+         starty = offy%chunkHeight;\r
+         endy   = starty + da.getHeight();\r
+\r
+         int ypos     = 0;\r
+         int rowstart = starty;\r
+\r
+         if (starty == 0) {\r
+             ypos = 2*charHeight;\r
+         } else if (starty == 1) {\r
+             starty = 0;\r
+             ypos = charHeight;\r
+         }\r
+\r
+         if (endy > da.getHeight()) {\r
+             endy = da.getHeight();\r
+         }\r
+\r
+         if (endx > da.getWidth()) {\r
+             endx = da.getWidth();\r
+         }\r
+\r
+         if (rowstart < 2) {\r
+             drawScale(startx,endx,charWidth,charHeight,ypos);\r
+         }\r
+\r
+         drawPanel(gg,startx,endx,starty,endy,startx,starty,ypos);\r
+\r
+         if (rowstart == 0) {\r
+             ypos = ypos + chunkHeight;\r
+         } else if (rowstart == 1) {\r
+             ypos = ypos + chunkHeight;\r
+         } else {\r
+             ypos   = ypos + chunkHeight - rowstart*charHeight;\r
+         }\r
+\r
+         startx += chunkWidth;\r
+         endx   = startx + chunkWidth;\r
+         starty = 0;\r
+\r
+         if (endx > da.getWidth()) {\r
+             endx = da.getWidth();\r
+         }\r
+         // Draw the rest of the panels\r
+\r
+         while (ypos <= getHeight()) {\r
+             drawScale(startx,endx,charWidth,charHeight,ypos);\r
+             drawPanel(gg,startx,endx,0,da.getHeight(),startx,starty,ypos);\r
+\r
+             ypos   += chunkHeight;\r
+             startx += chunkWidth;\r
+             endx   = startx + chunkWidth;\r
+\r
+             if (endy > da.getHeight()) {\r
+                 endy = da.getHeight();\r
+             }\r
+\r
+             if (endx > da.getWidth()) {\r
+                 endx = da.getWidth();\r
+             }\r
+\r
+         }\r
+      } else*/ {\r
+         drawPanel(gg,startx,endx,starty,endy,startx,starty,0);\r
+\r
+         oldstartx = startx;\r
+         oldendx   = endx;\r
+         oldstarty = starty;\r
+         oldendy   = endy;\r
+\r
+      }\r
+    }\r
+\r
+    else if (oldstartx < startx)\r
+    {\r
+      // This is dragging horizontal scrollbar to the right\r
+\r
+      int delx  = (int)((startx - oldstartx) * charWidth);\r
+      int delx2 = (int)((oldendx - startx + 1)   * charWidth);\r
+\r
+      gg.copyArea(delx,0,delx2,AlignmentUtil.getPixelHeight(starty,endy,charHeight),-delx,0);\r
+\r
+      if (startx > oldendx)\r
+       drawPanel(gg,startx,endx,starty,endy,startx,starty,0);\r
+      else\r
+       drawPanel(gg,oldendx+1,endx,starty,endy,startx,starty,0);\r
+\r
+\r
+      oldstartx = startx;\r
+      oldendx   = endx;\r
+\r
+    } else if (oldstartx > startx)\r
+    {\r
+     // Horizontal scrollbar pulled to the left\r
+\r
+      int delx  = (int)((oldstartx - startx) * charWidth);\r
+      int delx2 = (int)((endx - oldstartx +1)   * charWidth);\r
+\r
+      gg.copyArea(0,0,delx2,AlignmentUtil.getPixelHeight(starty,endy,charHeight),delx,0);\r
+\r
+      if (oldstartx > endx) {\r
+       drawPanel(gg,startx,endx,starty,endy,startx,starty,0);\r
+      } else {\r
+       drawPanel(gg,startx,oldstartx-1,starty,endy,startx,starty,0);\r
+      }\r
+\r
+      oldstartx = startx;\r
+      oldendx   = endx;\r
+\r
+    }  else if (oldstarty < starty) {\r
+      // Vertical scrollbar down\r
+      int dely  = AlignmentUtil.getPixelHeight(oldstarty,starty,charHeight);\r
+      int dely2 = AlignmentUtil.getPixelHeight(starty,oldendy,charHeight);\r
+\r
+      gg.copyArea(0,dely,(int)((endx-startx+1)*charWidth),dely2,0,-dely);\r
+\r
+      if (starty > oldendy) {\r
+       drawPanel(gg,startx,endx,starty,endy,startx,starty,0);\r
+      } else {\r
+       drawPanel(gg,startx,endx,oldendy,endy,startx,starty,0);\r
+      }\r
+\r
+      oldstarty = starty;\r
+      oldendy   = endy;\r
+\r
+    } else if (oldstarty > starty) {\r
+\r
+      // Vertical scrollbar up\r
+      int dely  = AlignmentUtil.getPixelHeight(endy,oldendy,charHeight);\r
+      int dely2 = AlignmentUtil.getPixelHeight(oldstarty,endy,charHeight);\r
+\r
+      gg.copyArea(0,0,(int)((endx-startx+1)*charWidth),dely2,0,dely);\r
+\r
+      if (oldstarty > endy) {\r
+       drawPanel(gg,startx,endx,starty,endy,startx,starty,0);\r
+      } else {\r
+       drawPanel(gg,startx,endx,starty,oldstarty,startx,starty,0);\r
+      }\r
+\r
+      oldstarty = starty;\r
+      oldendy   = endy;\r
+    }\r
+\r
+    if ((oldendy -oldstarty) > (int)((getWidth() / av.getCharWidth()))) {\r
+      System.out.println("LIMITS ERROR LIMITS ERROR");\r
+      System.out.println("Corrds " + (oldendy-oldstarty) + " " + (int)(getWidth()/av.getCharWidth()) + " " + getWidth() + " " + av.getCharWidth());\r
+    }\r
+\r
+\r
+    g.drawImage(img,0,0,this);\r
+\r
+  }\r
+\r
+\r
+\r
+\r
+  public void drawPanel(Graphics g,int x1,int x2, int y1, int y2,int startx, int starty,int offset) {\r
+\r
+/*\r
+    System.out.println("drawPanel called with g      = " + g);\r
+    System.out.println("                      x1     = " + x1);\r
+    System.out.println("                      x2     = " + x2);\r
+    System.out.println("                      y1     = " + y1);\r
+    System.out.println("                      y2     = " + y2);\r
+    System.out.println("                      startx = " + startx);\r
+    System.out.println("                      starty = " + starty);\r
+*/\r
+\r
+    g.setFont(av.getFont());\r
+    double            charWidth  = av.getCharWidth();\r
+    int               charHeight = av.getCharHeight();\r
+\r
+ //   Vector    pid    = av.calcNewConsensus();\r
+\r
+    RendererI sr = av.getRenderer();\r
+\r
+/*    Vector tmpseq = new Vector();\r
+\r
+    for (int i = 0; i < av.getAlignment().getHeight(); i++) {\r
+       if (!av.getSelection().contains(av.getAlignment().getSequenceAt(i))) {\r
+           tmpseq.addElement(av.getAlignment().getSequenceAt(i));\r
+       }\r
+    }\r
+\r
+    if (sr instanceof SequenceRenderer) {\r
+       pid    = AAFrequency.calculate(tmpseq,x1,x2);\r
+\r
+    } else if (sr instanceof GraphRenderer) {\r
+       pid = AAFrequency.calculatePID(av.getAlignment().getSequenceAt(0),\r
+                                      av.getAlignment().getSequences(),\r
+                                      av.getPIDWindow(),x1,x2);\r
+\r
+    }*/\r
+\r
+    if (y2 > starty && y1 < av.getEndSeq()) {\r
+\r
+    fillBackground(g,\r
+                   Color.white,\r
+                   (int)((x1-startx)*charWidth),\r
+                   offset + AlignmentUtil.getPixelHeight(starty,y1,av.getCharHeight()),\r
+                   (int)((x2-x1+1)*charWidth),\r
+                   offset + AlignmentUtil.getPixelHeight(y1,y2,av.getCharHeight()));\r
+    }\r
+\r
+    for (int i = y1 ; i < y2 ;i++) {\r
+\r
+      RendererI r = sr;\r
+\r
+    /*  if (av.getSelection().contains(av.getAlignment().getSequenceAt(i))) {\r
+          r = fr;\r
+          System.out.println("use feature renderer");\r
+    //  } else if ( i == 0) {\r
+       //   r = br;\r
+      } else if (av.getAlignment().getSequenceAt(i).getName().equals("CpG")) {\r
+          r = cgr;\r
+          System.out.println("cg renderer");\r
+      }*/\r
+\r
+      r.drawSequence(g,cs,av.getAlignment().getSequenceAt(i),\r
+                      x1,\r
+                      x2,\r
+                      (int)((x1-startx)*charWidth),\r
+                      offset + AlignmentUtil.getPixelHeight(starty,i,av.getCharHeight()),\r
+                      charWidth,\r
+                      charHeight,showScores,av.getShowBoxes(),av.getShowText(),null,i,av);\r
+\r
+    }\r
+  }\r
+\r
+\r
+\r
+  public void fillBackground(Graphics g,Color c, int x1,int y1,int width,int height) {\r
+    g.setColor(c);\r
+    g.fillRect(x1,y1,width,height);\r
+  }\r
+\r
+  public int getChunkWidth() {\r
+    return chunkWidth;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java
new file mode 100755 (executable)
index 0000000..120a062
--- /dev/null
@@ -0,0 +1,277 @@
+package jalview.gui;\r
+\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+import jalview.datamodel.*;\r
+import javax.swing.*;\r
+import jalview.schemes.*;\r
+\r
+\r
+public class SeqPanel extends JPanel\r
+{\r
+\r
+  public    AlignmentI        align;\r
+  public    SeqCanvas         seqCanvas;\r
+  public    AlignmentPanel    parent;\r
+\r
+  protected int startres;\r
+  protected int lastres;\r
+  protected int endres;\r
+\r
+  protected int startseq;\r
+  protected int padseq;\r
+\r
+  public    boolean editFlag;\r
+  protected AlignViewport av;\r
+\r
+  public SeqPanel(AlignViewport av, AlignmentPanel p) {\r
+    this.av         = av;\r
+    this.align      = av.getAlignment();\r
+\r
+    seqCanvas  = new SeqCanvas(av);\r
+    setLayout(new BorderLayout());\r
+    add(seqCanvas, BorderLayout.CENTER);\r
+\r
+    parent = p;\r
+\r
+    addMouseMotionListener( new MouseMotionAdapter()\r
+    {\r
+      public void mouseMoved(MouseEvent evt)\r
+      {  doMouseMoved(evt);   }\r
+      public void mouseDragged(MouseEvent evt)\r
+      { doMouseDragged(evt);  }\r
+    });\r
+\r
+    addMouseListener( new MouseAdapter()\r
+    {\r
+      public void mouseReleased(MouseEvent evt)\r
+      { doMouseReleased(evt);  }\r
+      public void mousePressed(MouseEvent evt)\r
+      { doMousePressed(evt);   }\r
+\r
+    });\r
+    repaint();\r
+  }\r
+\r
+\r
+  public void doMouseReleased(MouseEvent evt) {\r
+\r
+    int x = evt.getX();\r
+      int res = (int)(x/av.getCharWidth()) + av.getStartRes();\r
+\r
+      endres = res;\r
+\r
+      // This is to detect edits - we're at the end of an edit if mouse is up\r
+      editFlag = false;\r
+      startseq = -1;\r
+      startres = -1;\r
+      lastres  = -1;\r
+\r
+    parent.RefreshPanels();\r
+    repaint();\r
+\r
+  }\r
+\r
+  public void doMousePressed(MouseEvent evt) {\r
+    int seq;\r
+    int res;\r
+\r
+    int x = evt.getX();\r
+    int y = evt.getY();\r
+\r
+    res = (int)(x/av.getCharWidth()) + av.getStartRes();\r
+    seq = (y)/av.getCharHeight() + av.getStartSeq();\r
+\r
+    if (seq < align.getHeight() && res < align.getSequenceAt(seq).getLength())\r
+    {\r
+      //char resstr = align.getSequenceAt(seq).getSequence().charAt(res);\r
+      // Find the residue's position in the sequence (res is the position\r
+      // in the alignment\r
+\r
+      startseq = seq;\r
+\r
+      if (startseq == (align.getHeight()-1)) {\r
+        padseq = 1;\r
+      } else {\r
+        padseq = 1;\r
+      }\r
+\r
+      startres = res;\r
+      lastres = res;\r
+\r
+      } else {\r
+      startseq = -1;\r
+      startres = -1;\r
+      lastres = -1;\r
+    }\r
+\r
+    return;\r
+  }\r
+\r
+  public void doMouseMoved(MouseEvent evt)\r
+  {\r
+\r
+    int res = (int)(evt.getX()/av.getCharWidth()) + av.getStartRes();\r
+    int seq = (evt.getY())/av.getCharHeight() + av.getStartSeq();\r
+    if(seq>=av.getAlignment().getHeight())\r
+      return;\r
+\r
+    Object obj = ResidueProperties.aa2Triplet.get( av.getAlignment().getSequenceAt(seq).getCharAt(res)+"" ) ;\r
+    String aa = "";\r
+    if(obj!=null)\r
+         aa = obj.toString();\r
+\r
+    StringBuffer text = new StringBuffer("Sequence ID: "+av.getAlignment().getSequenceAt(seq).getName());\r
+    if(aa!="")\r
+      text.append("  Residue: "+aa+" ("+  av.getAlignment().getSequenceAt(seq).findPosition(res)+")");\r
+\r
+    parent.alignFrame.statusBar.setText(text.toString());\r
+\r
+  }\r
+\r
+  public void doMouseDragged(MouseEvent evt) {\r
+    // If we're dragging we're editing\r
+    editFlag = true;\r
+\r
+    int x = evt.getX();\r
+\r
+    int res = (int)(x/av.getCharWidth()) + av.getStartRes();\r
+    if (res < 0) {res = 0;}\r
+\r
+    if (res  != lastres) {\r
+      if (startseq != -1) {\r
+\r
+       // Group editing\r
+       if (av.getGroupEdit()) {\r
+         SequenceGroup sg = align.findGroup(startseq);\r
+\r
+         if (res < align.getWidth() && res < lastres) {\r
+           boolean flag = false;\r
+           for (int i= 0 ; i < sg.getSize(); i++) {\r
+             SequenceI s = (SequenceI)sg.getSequenceAt(i);\r
+             for (int j=lastres-1; j >= res; j--) {\r
+               if (!flag) {\r
+                 if (!s.getSequence().substring(j,j+1).equals(align.getGapCharacter()) &&\r
+                     !s.getSequence().substring(j,j+1).equals(" ")) {\r
+                   res = j+1;\r
+                   System.out.print("\07");\r
+                   System.out.flush();\r
+                   flag = true;\r
+                 }\r
+               }\r
+             }\r
+           }\r
+         }\r
+\r
+         for (int i= 0 ; i < sg.getSize(); i++)\r
+          {\r
+           SequenceI s = (SequenceI)sg.getSequenceAt(i);\r
+           boolean found = false;\r
+           int sno = -1;\r
+           for (int k = 0; k < align.getHeight(); k++)\r
+            {\r
+             if (align.getSequenceAt(k) == s)\r
+              {\r
+               found = true;\r
+               sno = k;\r
+               break;\r
+             }\r
+           }\r
+           if (found && sno != -1) {\r
+             if (res < align.getWidth() && res > lastres)\r
+              {\r
+               for (int j = lastres; j < res; j++)\r
+                 insertChar(j,sno);\r
+\r
+               int index = align.findIndex(s);\r
+               if (index != -1)\r
+                 drawChars(index,index+1,lastres);\r
+\r
+\r
+             } else if (res < align.getWidth() && res < lastres)\r
+              {\r
+               for (int j = res; j < lastres; j++)\r
+                {\r
+                 deleteChar(j,res,sno);\r
+                 startres = res;\r
+               }\r
+               int index = align.findIndex(s);\r
+               if (index != -1)\r
+                 drawChars(index,index+1,res);\r
+\r
+             }\r
+           }\r
+\r
+         }\r
+         lastres = res;\r
+       } else {\r
+\r
+\r
+         if (res < align.getWidth() && res > lastres) {\r
+            // dragging to the right\r
+           for (int j = lastres; j < res; j++)\r
+            {\r
+             insertChar(j,startseq);\r
+           }\r
+           drawChars(startseq,startseq+1,lastres);\r
+\r
+         } else if (res < align.getWidth() && res < lastres) {\r
+\r
+            // dragging to the left\r
+           for (int j = res; j < lastres; j++) {\r
+             deleteChar(j,res,startseq);\r
+             startres = res;\r
+           }\r
+           drawChars(startseq,startseq+1,res);\r
+         }\r
+       }\r
+      }\r
+      lastres = res;\r
+    }\r
+\r
+    repaint();\r
+    return;\r
+  }\r
+\r
+  public void drawChars(int seqstart, int seqend, int start) {\r
+    seqCanvas.drawPanel(seqCanvas.gg, start,av.getEndRes(),seqstart,seqend,av.getStartRes(),av.getStartSeq(),0);\r
+    repaint();\r
+  }\r
+\r
+  public void insertChar(int j, int seq)\r
+  {\r
+    align.getSequenceAt(seq).insertCharAt(j, av.getGapCharacter().charAt(0));\r
+  }\r
+\r
+  public void deleteChar(int j, int res, int sno)\r
+  {\r
+\r
+    if (align.getSequenceAt(sno).getSequence().substring(j,j+1).equals(".") ||\r
+        align.getSequenceAt(sno).getSequence().substring(j,j+1).equals("-") ||\r
+        align.getSequenceAt(sno).getSequence().substring(j,j+1).equals(" ") )\r
+    {\r
+        align.getSequenceAt(sno).deleteCharAt(j);\r
+    }\r
+\r
+    align.getWidth();\r
+    repaint();\r
+  }\r
+\r
+  public void setColourScheme(ColourSchemeI cs)\r
+  {\r
+   seqCanvas.cs = cs;\r
+   seqCanvas.paintFlag = true;\r
+   repaint();\r
+  }\r
+\r
+  public ColourSchemeI getColourScheme()\r
+  {\r
+    return seqCanvas.cs;\r
+  }\r
+\r
+\r
+}\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/gui/SequenceRenderer.java b/src/jalview/gui/SequenceRenderer.java
new file mode 100755 (executable)
index 0000000..7df9149
--- /dev/null
@@ -0,0 +1,130 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+\r
+import java.awt.*;\r
+import java.util.*;\r
+\r
+public class SequenceRenderer implements RendererI\r
+{\r
+  FontMetrics fm;\r
+  AlignViewport av;\r
+\r
+  public Color getResidueBoxColour(ColourSchemeI cs, SequenceI seq, int i) {\r
+    Color c = Color.WHITE;\r
+\r
+    try{\r
+      if (cs != null)\r
+        c = cs.findColour(seq, seq.getSequence(i, i + 1), i, null);\r
+    }catch(Exception ex)\r
+    {    }\r
+\r
+    return c;\r
+  }\r
+\r
+  public void drawSequence(Graphics g,ColourSchemeI cs,SequenceI seq,int start, int end, int x1, int y1, double width, int height,boolean showScores, boolean displayBoxes, boolean displayText,Vector freq, int seqnum,AlignViewport av) {\r
+\r
+    this.av = av;\r
+\r
+    if (displayBoxes == true) {\r
+        drawBoxes(g,cs,seq,start,end,x1,y1,(int)width, height,freq);\r
+    }\r
+    if (displayText == true) {\r
+        fm = g.getFontMetrics();\r
+        drawText(g,cs,seq,start,end,x1,y1,(int)width,height);\r
+    }\r
+  }\r
+\r
+  public void drawBoxes(Graphics g,ColourSchemeI cs, SequenceI seq,int start, int end, int x1, int y1, int width, int height,Vector freq) {\r
+    int i      = start;\r
+    int length = seq.getLength();\r
+\r
+    Color currentColor = Color.WHITE;\r
+\r
+    int curStart = x1;\r
+    int curWidth = width;\r
+\r
+  //  int threshold = 80;\r
+\r
+    while (i <= end && i < length) {\r
+      Color c = getResidueBoxColour(cs,seq,i);\r
+\r
+    //  Hashtable hash  = (Hashtable)freq.elementAt(i-start);\r
+    //  String    s     = (String)hash.get("maxResidue");\r
+    //  int       count = ((Integer)hash.get("maxCount")).intValue();\r
+  //    int       max   = ((Integer)hash.get("size")).intValue();\r
+   //   int       nongap = ((Integer)hash.get("nongap")).intValue();\r
+   //   float     frac  = (float)(count*1.0/(1.0*nongap));\r
+\r
+      //System.out.println("Frac/count/nongap " + frac + " " + count + " " + nongap);\r
+    /*  if (!seq.getSequence().substring(i,i+1).equals(s) ||\r
+         s.equals("-") ||\r
+         s.equals(".") ||\r
+         s.equals(" "))\r
+      {\r
+       c = Color.white;\r
+      } else {\r
+       if (frac > 0.9) {\r
+         c = Color.red;\r
+       } else if (frac > 0.8) {\r
+         c = Color.orange;\r
+       } else if (frac > 0.7) {\r
+         c = Color.pink;\r
+       } else if (frac > 0.5) {\r
+         c = Color.yellow;\r
+       } else if (frac> 0.3) {\r
+           c = Color.lightGray;\r
+       }\r
+      }*/\r
+\r
+      if (c != currentColor || c != null)\r
+      {\r
+        g.fillRect(x1+width*(curStart-start),y1,curWidth,height);\r
+\r
+        currentColor = c;\r
+        g.setColor(c);\r
+\r
+        curStart = i;\r
+        curWidth = width;\r
+      }\r
+      else\r
+        curWidth += width;\r
+\r
+      i++;\r
+    }\r
+    g.fillRect(x1+width*(curStart-start),y1,curWidth,height);\r
+  }\r
+\r
+  public void drawText(Graphics g, ColourSchemeI cs, SequenceI seq,int start, int end, int x1, int y1, int width, int height)\r
+  {\r
+    int pady = height/5;\r
+    int charOffset=0;\r
+    g.setColor(Color.black);\r
+    boolean colourText = av.getColourText();\r
+    Color c;\r
+    char s;\r
+    // Need to find the sequence position here.\r
+    for (int i = start; i <= end; i++)\r
+    {\r
+        if (i < end && i < seq.getLength())\r
+          s = seq.getSequence().charAt(i);\r
+        else if(i<seq.getLength())\r
+          s = seq.getSequence().charAt(i);\r
+        else\r
+          s = ' ';\r
+\r
+        if (colourText)\r
+        {\r
+            c = getResidueBoxColour(cs, seq, i);\r
+            g.setColor(c.darker());\r
+        }\r
+\r
+      charOffset =  (width - fm.charWidth(s))/2;\r
+\r
+\r
+      g.drawString(String.valueOf(s), charOffset + x1 + width * (i - start), y1 + height - pady);\r
+    }\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/TreeCanvas.java b/src/jalview/gui/TreeCanvas.java
new file mode 100755 (executable)
index 0000000..1a11630
--- /dev/null
@@ -0,0 +1,382 @@
+package jalview.gui;\r
+\r
+\r
+import jalview.analysis.*;\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+import javax.swing.*;\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+import java.util.*;\r
+import java.io.*;\r
+\r
+public class TreeCanvas extends JPanel implements MouseListener\r
+{\r
+  NJTree tree;\r
+  JScrollPane scrollPane;\r
+  AlignViewport av;\r
+\r
+  Font font;\r
+  int  fontSize = 12;\r
+\r
+  boolean showDistances = false;\r
+  boolean showBootstrap = false;\r
+\r
+  int offx = 20;\r
+  int offy = 20;\r
+\r
+  int threshold;\r
+\r
+  String longestName;\r
+  int labelLength=-1;\r
+\r
+  //RubberbandRectangle rubberband;\r
+\r
+  Selection selected;\r
+  Vector    listeners;\r
+\r
+  Hashtable nameHash = new Hashtable();\r
+  Hashtable nodeHash = new Hashtable();\r
+\r
+  public TreeCanvas(AlignViewport av, NJTree tree, JScrollPane scroller, String label)\r
+  {\r
+    this.av = av;\r
+    this.tree     = tree;\r
+    selected = av.getSelection();\r
+    scrollPane = scroller;\r
+    addMouseListener(this);\r
+    tree.findHeight(tree.getTopNode());\r
+    longestName = label;\r
+\r
+    PaintRefresher.Register(this);\r
+  }\r
+  public void TreeSelectionChanged(Sequence sequence)\r
+ {\r
+    selected = av.getSelection();\r
+\r
+    if (selected.contains(sequence))\r
+        selected.removeElement(sequence);\r
+    else\r
+        selected.addElement(sequence);\r
+\r
+    setSelected(selected);\r
+    PaintRefresher.Refresh(this);\r
+    repaint();\r
+ }\r
+\r
+\r
+  public void setSelected(Selection selected)\r
+  {\r
+        this.selected = selected;\r
+  }\r
+\r
+  public void setTree(NJTree tree) {\r
+    this.tree = tree;\r
+    tree.findHeight(tree.getTopNode());\r
+  }\r
+\r
+    public void drawNode(Graphics g,SequenceNode node, float chunk, float scale, int width,int offx, int offy) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+\r
+    if (node.left() == null && node.right() == null) {\r
+      // Drawing leaf node\r
+\r
+      float height = node.height;\r
+      float dist   = node.dist;\r
+\r
+      int xstart = (int)((height-dist)*scale) + offx;\r
+      int xend =   (int)(height*scale)        + offx;\r
+\r
+      int ypos = (int)(node.ycount * chunk) + offy;\r
+\r
+      if (node.element() instanceof SequenceI) {\r
+          g.setColor(((SequenceI)((SequenceNode)node).element()).getColor().darker());\r
+      } else {\r
+          g.setColor(Color.black);\r
+      }\r
+\r
+      // Draw horizontal line\r
+      g.drawLine(xstart,ypos,xend,ypos);\r
+\r
+      String nodeLabel = "";\r
+      if (showDistances && node.dist > 0) {\r
+        nodeLabel = new Format("%5.2f").form(node.dist);\r
+      }\r
+      if (showBootstrap) {\r
+        if (showDistances) {\r
+          nodeLabel = nodeLabel + " : ";\r
+        }\r
+        nodeLabel = nodeLabel + String.valueOf(node.getBootstrap());\r
+      }\r
+      if (! nodeLabel.equals("")) {\r
+      g.drawString(nodeLabel,xstart,ypos - 10);\r
+      }\r
+\r
+      // Colour selected leaves differently\r
+      String name    = node.getName();\r
+      FontMetrics fm = g.getFontMetrics(font);\r
+      int charWidth  = fm.stringWidth(node.getName()) + 3;\r
+      int charHeight = fm.getHeight();\r
+\r
+      Rectangle rect = new Rectangle(xend+20,ypos-charHeight,\r
+                                     charWidth,charHeight);\r
+\r
+      nameHash.put((SequenceI)node.element(),rect);\r
+\r
+      if (selected.contains((SequenceI)node.element())) {\r
+        g.setColor(Color.gray);\r
+\r
+        g.fillRect(xend + 10, ypos - charHeight + 3,charWidth,charHeight);\r
+        g.setColor(Color.white);\r
+      }\r
+      g.drawString(node.getName(),xend+10,ypos);\r
+      g.setColor(Color.black);\r
+    } else {\r
+      drawNode(g,(SequenceNode)node.left(), chunk,scale,width,offx,offy);\r
+      drawNode(g,(SequenceNode)node.right(),chunk,scale,width,offx,offy);\r
+\r
+      float height = node.height;\r
+      float dist   = node.dist;\r
+\r
+      int xstart = (int)((height-dist)*scale) + offx;\r
+      int xend   = (int)(height       *scale) + offx;\r
+      int ypos   = (int)(node.ycount  *chunk) + offy;\r
+\r
+      g.setColor(((SequenceNode)node).color.darker());\r
+\r
+      // Draw horizontal line\r
+      g.drawLine(xstart,ypos,xend,ypos);\r
+      g.fillRect(xend-2, ypos-2, 4,4);\r
+\r
+      int ystart = (int)(((SequenceNode)node.left()) .ycount * chunk) + offy;\r
+      int yend   = (int)(((SequenceNode)node.right()).ycount * chunk) + offy;\r
+\r
+      Rectangle pos = new Rectangle(xend-2,ypos-2,5,5);\r
+      nodeHash.put(node,pos);\r
+\r
+      g.drawLine((int)(height*scale) + offx, ystart,\r
+                 (int)(height*scale) + offx, yend);\r
+\r
+      if (showDistances && node.dist > 0) {\r
+        g.drawString(new Format("%5.2f").form(node.dist),xstart,ypos - 5);\r
+      }\r
+\r
+    }\r
+  }\r
+  public Object findElement(int x, int y) {\r
+       Enumeration keys = nameHash.keys();\r
+\r
+    while (keys.hasMoreElements()) {\r
+            Object ob = keys.nextElement();\r
+            Rectangle rect = (Rectangle)nameHash.get(ob);\r
+\r
+            if (x >= rect.x && x <= (rect.x + rect.width) &&\r
+              y >= rect.y && y <= (rect.y + rect.height)) {\r
+              return ob;\r
+            }\r
+  }\r
+  keys = nodeHash.keys();\r
+\r
+    while (keys.hasMoreElements()) {\r
+            Object ob = keys.nextElement();\r
+            Rectangle rect = (Rectangle)nodeHash.get(ob);\r
+\r
+            if (x >= rect.x && x <= (rect.x + rect.width) &&\r
+              y >= rect.y && y <= (rect.y + rect.height)) {\r
+              return ob;\r
+            }\r
+    }\r
+      return null;\r
+\r
+  }\r
+\r
+  public void pickNodes(Rectangle pickBox, Selection sel) {\r
+    int width  = getWidth();\r
+    int height = getHeight();\r
+\r
+    SequenceNode top = tree.getTopNode();\r
+\r
+    float wscale = (float)(width*.8-offx*2)/tree.getMaxHeight()\r
+;\r
+    if (top.count == 0) {\r
+      top.count = ((SequenceNode)top.left()).count + ((SequenceNode)top.right()).count ;\r
+    }\r
+    float chunk = (float)(height-offy*2)/top.count;\r
+\r
+    pickNode(pickBox,sel,top,chunk,wscale,width,offx,offy);\r
+  }\r
+\r
+  public void pickNode(Rectangle pickBox, Selection sel, SequenceNode node, float chunk, float scale, int width,int offx, int offy) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+\r
+    if (node.left() == null && node.right() == null) {\r
+      float height = node.height;\r
+      float dist   = node.dist;\r
+\r
+      int xstart = (int)((height-dist)*scale) + offx;\r
+      int xend   = (int)(height*scale) + offx;\r
+\r
+      int ypos = (int)(node.ycount * chunk) + offy;\r
+\r
+      if (pickBox.contains(new Point(xend,ypos))) {\r
+        if (node.element() instanceof SequenceI) {\r
+          SequenceI seq = (SequenceI)node.element();\r
+          if (sel.contains(seq)) {\r
+            sel.removeElement(seq);\r
+          } else {\r
+            sel.addElement(seq);\r
+          }\r
+        }\r
+      }\r
+    } else {\r
+      pickNode(pickBox,sel,(SequenceNode)node.left(), chunk,scale,width,offx,offy);\r
+      pickNode(pickBox,sel,(SequenceNode)node.right(),chunk,scale,width,offx,offy);\r
+    }\r
+  }\r
+\r
+  public void setColor(SequenceNode node, Color c) {\r
+    if (node == null) {\r
+      return;\r
+    }\r
+\r
+    if (node.left() == null && node.right() == null) {\r
+      node.color = c;\r
+\r
+      if (node.element() instanceof SequenceI) {\r
+          ((SequenceI)node.element()).setColor(c);\r
+      }\r
+    } else {\r
+      node.color = c;\r
+      setColor((SequenceNode)node.left(),c);\r
+      setColor((SequenceNode)node.right(),c);\r
+    }\r
+  }\r
+\r
+\r
+  public void paintComponent(Graphics g) {\r
+\r
+\r
+    font = new Font("Verdana",Font.PLAIN,fontSize);\r
+    g.setFont(font);\r
+\r
+    FontMetrics fm = g.getFontMetrics(font);\r
+\r
+    if(nameHash.size()==0)\r
+      repaint();\r
+\r
+\r
+    if( scrollPane.getHeight() > fm.getHeight() * nameHash.size()+offy)\r
+     {\r
+         draw(g,scrollPane.getWidth(),scrollPane.getHeight());\r
+         setPreferredSize(new Dimension(scrollPane.getWidth(), scrollPane.getHeight()));\r
+     }\r
+    else\r
+     {\r
+         setPreferredSize(new Dimension(getWidth(), fm.getHeight() * nameHash.size()));\r
+         draw( g,getWidth(), fm.getHeight() * nameHash.size());\r
+     }\r
+\r
+\r
+    if (threshold != 0)\r
+    {\r
+        g.setColor(Color.red);\r
+        g.drawLine(threshold,0,threshold,getHeight());\r
+    }\r
+\r
+    scrollPane.revalidate();\r
+  }\r
+    public int getFontSize() {\r
+        return fontSize;\r
+    }\r
+    public void setFontSize(int fontSize) {\r
+        this.fontSize = fontSize;\r
+        repaint();\r
+    }\r
+  public void draw(Graphics g, int width, int height) {\r
+      g.setColor(Color.white);\r
+      g.fillRect(0,0,width,height);\r
+\r
+\r
+      labelLength = g.getFontMetrics(font).stringWidth(longestName)+ 20;//20 allows for scrollbar\r
+\r
+      float wscale =(float)(width - labelLength -offx*2)/tree.getMaxHeight();\r
+\r
+      SequenceNode top = tree.getTopNode();\r
+\r
+      if (top.count == 0) {\r
+          top.count = ((SequenceNode)top.left()).count + ((SequenceNode)top.right()).count ;\r
+      }\r
+      float chunk = (float)(height-offy*2)/top.count ;\r
+\r
+      drawNode(g,tree.getTopNode(),chunk,wscale,width,offx,offy);\r
+  }\r
+\r
+  public void mouseReleased(MouseEvent e) { }\r
+  public void mouseEntered(MouseEvent e) { }\r
+  public void mouseExited(MouseEvent e) { }\r
+  public void mouseClicked(MouseEvent e) {\r
+  }\r
+\r
+  public void mousePressed(MouseEvent e) {\r
+      int x = e.getX();\r
+      int y = e.getY();\r
+\r
+      Object ob = findElement(x,y);\r
+\r
+      if (ob instanceof SequenceI)\r
+      {\r
+          TreeSelectionChanged((Sequence)ob);\r
+          repaint();\r
+          return;\r
+\r
+      } else if (ob instanceof SequenceNode) {\r
+          SequenceNode tmpnode = (SequenceNode)ob;\r
+          tree.swapNodes(tmpnode);\r
+          tree.reCount(tree.getTopNode());\r
+          tree.findHeight(tree.getTopNode());\r
+      } else {\r
+          // Find threshold\r
+\r
+          if (tree.getMaxHeight() != 0) {\r
+              float fthreshold = (float)(x - offx)/(float)(getWidth()-labelLength - 2*offx);\r
+              this.threshold = x;\r
+              tree.getGroups().removeAllElements();\r
+              tree.groupNodes(tree.getTopNode(),fthreshold);\r
+              setColor(tree.getTopNode(),Color.black);\r
+\r
+              for (int i=0; i < tree.getGroups().size(); i++) {\r
+\r
+                  int tmp = i%(7);\r
+                  Color col = new Color((int)(Math.random()*255),\r
+                                        (int)(Math.random()*255),\r
+                                        (int)(Math.random()*255));\r
+\r
+                  setColor((SequenceNode)tree.getGroups().elementAt(i),col.brighter());\r
+\r
+                  // l is vector of Objects\r
+                  Vector l = tree.findLeaves((SequenceNode)tree.getGroups().elementAt(i),new Vector());\r
+\r
+              }\r
+          }\r
+      }\r
+\r
+      repaint();\r
+\r
+  }\r
+\r
+    public void setShowDistances(boolean state) {\r
+        this.showDistances = state;\r
+        repaint();\r
+    }\r
+\r
+    public void setShowBootstrap(boolean state) {\r
+      this.showBootstrap = state;\r
+      repaint();\r
+    }\r
+\r
+}\r
+\r
diff --git a/src/jalview/gui/TreePanel.java b/src/jalview/gui/TreePanel.java
new file mode 100755 (executable)
index 0000000..9e9e70b
--- /dev/null
@@ -0,0 +1,274 @@
+package jalview.gui;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.analysis.*;\r
+import jalview.jbgui.GTreePanel;\r
+import jalview.io.*;\r
+import java.awt.event.*;\r
+import java.util.*;\r
+import java.io.*;\r
+import jalview.util.*;\r
+import javax.swing.*;\r
+\r
+\r
+public class TreePanel extends GTreePanel\r
+{\r
+  SequenceI[] seq;\r
+  String type;\r
+  String pwtype;\r
+  AlignViewport av;\r
+  int start;\r
+  int end;\r
+  TreeCanvas treeCanvas;\r
+  NJTree tree;\r
+\r
+  FileProperties       fp;\r
+  PostscriptProperties pp;\r
+\r
+  PrintWriter bw;\r
+  PrintStream ps;\r
+  boolean makeString = false;\r
+  StringBuffer out;\r
+\r
+\r
+\r
+  public TreePanel(AlignViewport av, Vector seqVector, String type, String pwtype, int s, int e)\r
+  {\r
+    super();\r
+\r
+    this.type = type;\r
+    this.pwtype = pwtype;\r
+\r
+    start = s;\r
+    end = e;\r
+\r
+    String longestName = "";\r
+    seq = new Sequence [seqVector.size()];\r
+    for (int i=0;i < seqVector.size();i++)\r
+    {\r
+      seq[i] = (Sequence) seqVector.elementAt(i);\r
+      if(seq[i].getName().length()>longestName.length())\r
+        longestName = seq[i].getName();\r
+    }\r
+\r
+    tree = new NJTree(seq, type, pwtype, start, end);\r
+    av.setCurrentTree(tree);\r
+\r
+    propertiesInit();\r
+\r
+    treeCanvas = new TreeCanvas(av, tree, scrollPane, longestName);\r
+\r
+    tree.reCount(tree.getTopNode());\r
+    tree.findHeight(tree.getTopNode());\r
+    scrollPane.setViewportView(treeCanvas);\r
+\r
+  }\r
+\r
+\r
+public void drawPostscript(PostscriptProperties pp) {\r
+  try {\r
+    int width = 0;\r
+    int height = 0;\r
+\r
+    printout("%!\n");\r
+\r
+    printout("/" + pp.font + " findfont\n");\r
+    printout(pp.fsize + " scalefont setfont\n");\r
+\r
+    int offx = pp.xoffset;\r
+    int offy = pp.yoffset;\r
+\r
+    if (pp.orientation == PostscriptProperties.PORTRAIT) {\r
+      width = PostscriptProperties.SHORTSIDE;\r
+      height = PostscriptProperties.LONGSIDE;\r
+    } else {\r
+      height = PostscriptProperties.SHORTSIDE;\r
+      width = PostscriptProperties.LONGSIDE;\r
+      printout(height + " 0 translate\n90 rotate\n");\r
+    }\r
+    float wscale = (float)(width*.8-offx*2)/tree.getMaxHeight();\r
+    SequenceNode top = tree.getTopNode();\r
+\r
+    if (top.count == 0) {\r
+        top.count = ((SequenceNode)top.left()).count + ((SequenceNode)top.right()).count ;\r
+    }\r
+\r
+    float chunk = (float)(height-offy*2)/(((SequenceNode)top).count+1);\r
+\r
+    drawPostscriptNode(top,chunk,wscale,width,offx,offy);\r
+\r
+    printout("showpage\n");\r
+  } catch (java.io.IOException e) {\r
+    System.out.println("Exception " + e);\r
+  }\r
+}\r
+\r
+public void drawPostscriptNode(SequenceNode node, float chunk, float scale, int width, int offx, int offy) throws java.io.IOException {\r
+  if (node == null) {\r
+    return;\r
+  }\r
+\r
+  if (node.left() == null && node.right() == null) {\r
+    // Drawing leaf node\r
+\r
+    float height = node.height;\r
+    float dist = node.dist;\r
+\r
+    int xstart = (int)((height-dist)*scale) + offx;\r
+    int xend =   (int)(height*scale) + offx;\r
+\r
+    int ypos = (int)(node.ycount * chunk) + offy;\r
+\r
+    // g.setColor(Color.black);\r
+    printout("\n" + new Format("%5.3f").form((double)node.color.getRed()/255) + " " +\r
+             new Format("%5.3f").form((double)node.color.getGreen()/255) + " " +\r
+             new Format("%5.3f").form((double)node.color.getBlue()/255) + " setrgbcolor\n");\r
+\r
+    // Draw horizontal line\r
+    //  g.drawLine(xstart,ypos,xend,ypos);\r
+    printout(xstart + " " + ypos + " moveto " + xend + " " + ypos + " lineto stroke \n");\r
+\r
+    if (treeCanvas.showDistances && node.dist > 0) {\r
+      //       g.drawString(new Format("%5.2f").form(node.dist),xstart,ypos - 5);\r
+      printout("(" + new Format("%5.2f").form(node.dist) + ") " + xstart + " " + (ypos+5) + " moveto show\n");\r
+    }\r
+    //g.drawString((String)node.element(),xend+20,ypos);\r
+    printout("(" + (((SequenceI)node.element()).getName()) + ") " + (xend+20) + " " + (ypos) + " moveto show\n");\r
+  } else {\r
+    drawPostscriptNode((SequenceNode)node.left(),chunk,scale,width,offx,offy);\r
+    drawPostscriptNode((SequenceNode)node.right(),chunk,scale,width,offx,offy);\r
+\r
+\r
+    float height = node.height;\r
+    float dist = node.dist;\r
+\r
+    int xstart = (int)((height-dist)*scale) + offx;\r
+    int xend =   (int)(height*scale) + offx;\r
+    int ypos = (int)(node.ycount * chunk) + offy;\r
+\r
+    printout("\n" + new Format("%5.3f").form((double)node.color.getRed()/255) + " " +\r
+             new Format("%5.3f").form((double)node.color.getGreen()/255) + " " +\r
+             new Format("%5.3f").form((double)node.color.getBlue()/255) + " setrgbcolor\n");\r
+    //      g.setColor(Color.black);\r
+    //      bw.append("\nblack setrgbcolor\n");\r
+    // Draw horizontal line\r
+    //      g.drawLine(xstart,ypos,xend,ypos);\r
+    printout(xstart + " " + ypos + " moveto " + xend + " " + ypos + " lineto stroke\n");\r
+    int ystart = (int)(((SequenceNode)node.left()).ycount * chunk) + offy;\r
+    int yend = (int)(((SequenceNode)node.right()).ycount * chunk) + offy;\r
+\r
+    //      g.drawLine((int)(height*scale) + offx, ystart,\r
+    //          (int)(height*scale) + offx, yend);\r
+    printout\r
+    (((int)(height*scale) + offx) + " " + ystart + " moveto " +  ((int)(height*scale) + offx) + " " +\r
+     yend + " lineto stroke\n");\r
+    if (treeCanvas.showDistances && node.dist > 0) {\r
+      //       g.drawString(new Format("%5.2f").form(node.dist),xstart,ypos - 5);\r
+      printout("(" +new Format("%5.2f").form(node.dist) + ") " + (xstart) + " " + (ypos+5) + " moveto show\n");\r
+    }\r
+  }\r
+}\r
+\r
+public void printout(String s) throws IOException {\r
+  if (bw != null) {\r
+    bw.write(s);\r
+  }\r
+  if (ps != null) {\r
+    ps.print(s);\r
+  }\r
+  if (makeString == true) {\r
+    out.append(s);\r
+  }\r
+}\r
+\r
+\r
+public PostscriptProperties getPostscriptProperties() {\r
+  return pp;\r
+}\r
+\r
+public FileProperties getFileProperties() {\r
+  return fp;\r
+}\r
+\r
+public void setPostscriptProperties(PostscriptProperties pp) {\r
+  this.pp = pp;\r
+}\r
+\r
+public void setFileProperties(FileProperties fp) {\r
+  this.fp = fp;\r
+}\r
+\r
+public String getText(String format) {\r
+  return null;\r
+}\r
+\r
+public void getPostscript(PrintWriter bw) {\r
+  this.bw = bw;\r
+  drawPostscript(pp);\r
+\r
+}\r
+\r
+public void getPostscript(PrintStream bw) {\r
+  this.ps = bw;\r
+  drawPostscript(pp);\r
+  bw.flush();\r
+}\r
+\r
+public StringBuffer getPostscript() {\r
+  makeString = true;\r
+  out = new StringBuffer();\r
+  drawPostscript(pp);\r
+  return out;\r
+}\r
+\r
+public void propertiesInit() {\r
+  this.pp = new PostscriptProperties();\r
+  this.fp = new FileProperties();\r
+}\r
+\r
+\r
+  public void saveButton_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+    try{\r
+      JFileChooser chooser = new JFileChooser(jalview.bin.Cache.LAST_DIRECTORY);\r
+      chooser.setDialogTitle("Save Tree as postscript file");\r
+      chooser.setToolTipText("Save");\r
+      int value = chooser.showSaveDialog(this);\r
+      if (value == JFileChooser.APPROVE_OPTION)\r
+      {\r
+        String choice = chooser.getSelectedFile().getPath();\r
+        jalview.bin.Cache.LAST_DIRECTORY = choice;\r
+\r
+        bw = new PrintWriter(new FileWriter(choice));\r
+        getPostscript(bw);\r
+        bw.close();\r
+\r
+      }\r
+\r
+    }catch(Exception ex){ex.printStackTrace();}\r
+\r
+  }\r
+\r
+  public void showDistanceCheckbox_actionPerformed(ActionEvent e)\r
+  {\r
+    treeCanvas.setShowDistances(showDistanceCheckbox.isSelected());\r
+  }\r
+\r
+  public void fontSizeCombobox_actionPerformed(ActionEvent e)\r
+  {\r
+    if( treeCanvas==null )\r
+     return;\r
+\r
+    int size = Integer.parseInt( fontSizeCombobox.getSelectedItem().toString() );\r
+        treeCanvas.setFontSize( size );\r
+\r
+    scrollPane.setViewportView(treeCanvas);\r
+  }\r
+\r
+  public void bootStrapCheckBox_actionPerformed(ActionEvent e)\r
+  {\r
+    treeCanvas.setShowBootstrap(bootStrapCheckBox.isSelected());\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/gui/UserDefinedColours.java b/src/jalview/gui/UserDefinedColours.java
new file mode 100755 (executable)
index 0000000..0c181b0
--- /dev/null
@@ -0,0 +1,165 @@
+package jalview.gui;\r
+\r
+import jalview.jbgui.GUserDefinedColours;\r
+import javax.swing.*;\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+import javax.swing.event.*;\r
+import jalview.schemes.*;\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+\r
+public class UserDefinedColours extends GUserDefinedColours implements ChangeListener\r
+{\r
+\r
+  SeqPanel seqPanel;\r
+  ColourSchemeI colourScheme;\r
+  JButton selectedButton;\r
+  Vector oldColours = new Vector();\r
+  JInternalFrame frame;\r
+\r
+  public UserDefinedColours(JInternalFrame f, SeqPanel sp)\r
+  {\r
+    super();\r
+    colorChooser.getSelectionModel().addChangeListener(this);\r
+    seqPanel = sp;\r
+    frame = f;\r
+    colourScheme = seqPanel.getColourScheme();\r
+   // colourScheme.\r
+\r
+    for(int i=0; i<20; i++)\r
+      makeButton(ResidueProperties.aa2Triplet.get( ResidueProperties.aa[i] )+"", ResidueProperties.aa[i]);\r
+\r
+    makeButton("B","B");\r
+    makeButton("Z","Z");\r
+    makeButton("X","X");\r
+    makeButton("'.','-',' '", "-");\r
+\r
+  }\r
+\r
+ public void stateChanged(ChangeEvent evt)\r
+ {\r
+   if(selectedButton!=null)\r
+     selectedButton.setBackground( colorChooser.getColor() );\r
+ }\r
+\r
+  public void colourButtonPressed(MouseEvent e)\r
+  {\r
+     selectedButton = (JButton)e.getSource();\r
+     colorChooser.setColor(selectedButton.getBackground());\r
+  }\r
+\r
+  void makeButton(String label, String aa)\r
+  {\r
+    final JButton button = new JButton();\r
+    button.setBackground( colourScheme.findColour(null,aa,-1,null) );\r
+    oldColours.addElement( colourScheme.findColour(null,aa,-1,null) );\r
+    button.setText( label );\r
+    button.setFont(new java.awt.Font("Verdana", 1, 10));\r
+    button.addMouseListener(new java.awt.event.MouseAdapter()\r
+    {\r
+      public void mouseClicked(MouseEvent e)\r
+      {\r
+        colourButtonPressed(e);\r
+      }\r
+    });\r
+\r
+    buttonPanel.add(button);\r
+  }\r
+\r
+\r
+  protected void okButton_actionPerformed(ActionEvent e)\r
+  {\r
+    applyButton_actionPerformed(null);\r
+    try{\r
+      frame.setClosed(true);\r
+    }catch(Exception ex){}\r
+  }\r
+\r
+  protected void applyButton_actionPerformed(ActionEvent e)\r
+  {\r
+    UserColourScheme ucs = new UserColourScheme();\r
+    Color [] newColours = new Color[24];\r
+    for(int i=0; i<24; i++)\r
+    {\r
+          JButton button = (JButton)buttonPanel.getComponent(i);\r
+          newColours[i] = button.getBackground();\r
+    }\r
+\r
+    ucs.setThreshold(0);\r
+    ucs.setColourScheme( newColours );\r
+    seqPanel.setColourScheme( ucs );\r
+  }\r
+\r
+  protected void loadbutton_actionPerformed(ActionEvent e)\r
+  {\r
+    JFileChooser chooser = new JFileChooser(jalview.bin.Cache.LAST_DIRECTORY);\r
+    chooser.setDialogTitle("Load colour scheme");\r
+    chooser.setToolTipText("Load");\r
+    int value = chooser.showOpenDialog(this);\r
+    if (value == JFileChooser.APPROVE_OPTION)\r
+    {\r
+      String choice = chooser.getSelectedFile().getPath();\r
+      jalview.bin.Cache.LAST_DIRECTORY = choice;\r
+\r
+      try{\r
+        BufferedReader in = new BufferedReader(new FileReader(choice));\r
+        for(int i=0; i<24; i++)\r
+        {\r
+          JButton button = (JButton)buttonPanel.getComponent(i);\r
+          Color c = new Color(Integer.parseInt(in.readLine()));\r
+          button.setBackground(c);\r
+        }\r
+\r
+      }\r
+      catch(Exception ex)\r
+      {}\r
+    }\r
+\r
+  }\r
+\r
+  protected void savebutton_actionPerformed(ActionEvent e)\r
+  {\r
+    JFileChooser chooser = new JFileChooser(jalview.bin.Cache.LAST_DIRECTORY);\r
+    chooser.setDialogTitle("Save colour scheme");\r
+    chooser.setToolTipText("Save");\r
+    int value = chooser.showSaveDialog(this);\r
+    if (value == JFileChooser.APPROVE_OPTION)\r
+    {\r
+      String choice = chooser.getSelectedFile().getPath();\r
+      jalview.bin.Cache.LAST_DIRECTORY = choice;\r
+\r
+      try{\r
+        PrintWriter out = new PrintWriter(new FileWriter(choice));\r
+        for(int i=0; i<24; i++)\r
+        {\r
+          JButton button = (JButton)buttonPanel.getComponent(i);\r
+          out.println(button.getBackground().getRGB() + "");\r
+        }\r
+\r
+        out.close();\r
+      }\r
+      catch(Exception ex)\r
+      {ex.printStackTrace();}\r
+    }\r
+\r
+  }\r
+\r
+  protected void cancelButton_actionPerformed(ActionEvent e)\r
+  {\r
+    UserColourScheme ucs = new UserColourScheme();\r
+    Color [] newColours = new Color[24];\r
+    for(int i=0; i<24; i++)\r
+    {\r
+          newColours[i] = (Color)oldColours.elementAt(i);\r
+          buttonPanel.getComponent(i).setBackground(newColours[i]);\r
+    }\r
+\r
+    ucs.setColourScheme( newColours );\r
+    seqPanel.setColourScheme( ucs );\r
+\r
+  }\r
+\r
+\r
+}\r
diff --git a/src/jalview/io/AlignFile.java b/src/jalview/io/AlignFile.java
new file mode 100755 (executable)
index 0000000..77002cf
--- /dev/null
@@ -0,0 +1,98 @@
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+public abstract class AlignFile extends FileParse {\r
+  int noSeqs    = 0;\r
+  int maxLength = 0;\r
+\r
+  Vector    seqs;\r
+  Vector    headers;\r
+\r
+  long start;\r
+  long end;\r
+\r
+  public AlignFile()\r
+  {}\r
+\r
+  public AlignFile(String inStr) {\r
+    initData();\r
+System.out.println("is this ever called??");\r
+    try{\r
+      parse();\r
+    }catch(Exception ex){}\r
+  }\r
+\r
+/**\r
+ * Constructor which parses the data from a file of some specified type.\r
+ * @param inFile Filename to read from.\r
+ * @param type   What type of file to read from (File, URL)\r
+ */\r
+  public AlignFile(String inFile, String type) throws IOException {\r
+    super(inFile,type);\r
+\r
+    initData();\r
+\r
+    parse();\r
+\r
+  }\r
+\r
+/**\r
+ * Return the seqs Vector\r
+ */\r
+  public Vector getSeqs() {\r
+    return seqs;\r
+  }\r
+\r
+/**\r
+ * Return the Sequences in the seqs Vector as an array of Sequences\r
+ */\r
+  public SequenceI [] getSeqsAsArray() {\r
+    SequenceI [] s = new SequenceI[seqs.size()];\r
+    for (int i=0;i < seqs.size();i++) {\r
+      s[i] = (SequenceI)seqs.elementAt(i);\r
+    }\r
+    return s;\r
+  }\r
+\r
+\r
+/**\r
+ * Initialise objects to store sequence data in.\r
+ */\r
+  protected void initData() {\r
+    seqs    = new Vector();\r
+    headers = new Vector();\r
+  }\r
+\r
+  protected void setSeqs(SequenceI [] s) {\r
+    seqs = new Vector();\r
+    for (int i=0; i<s.length; i++) {\r
+      seqs.addElement(s[i]);\r
+    }\r
+  }\r
+\r
+  // Checks whether sequence is valid aa characters\r
+  protected boolean isValidProteinSequence(String sequence)\r
+  {\r
+    for (int i = 0; i < sequence.length(); i++)\r
+      if (!jalview.schemes.ResidueProperties.aaHash.containsKey(String.valueOf(sequence.charAt(i))))\r
+        return false;\r
+\r
+    return true;\r
+  }\r
+\r
+\r
+/**\r
+ * This method must be implemented to parse the contents of the file.\r
+ */\r
+  public abstract void parse() throws IOException;\r
+\r
+\r
+/**\r
+ * Print out in alignment file format the Sequences in the seqs Vector.\r
+ */\r
+  public abstract String print();\r
+}\r
diff --git a/src/jalview/io/BLCFile.java b/src/jalview/io/BLCFile.java
new file mode 100755 (executable)
index 0000000..5f45aec
--- /dev/null
@@ -0,0 +1,153 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+import java.net.*;\r
+import java.awt.Font;\r
+\r
+public class BLCFile extends AlignFile {\r
+\r
+  Vector titles;\r
+\r
+  public BLCFile()\r
+  {}\r
+\r
+  public BLCFile(String inStr) {\r
+    super(inStr);\r
+  }\r
+\r
+  public void initData() {\r
+    super.initData();\r
+    titles = new Vector();\r
+  }\r
+\r
+  public BLCFile(String inFile, String type) throws IOException {\r
+    super(inFile,type);\r
+  }\r
+\r
+\r
+  public void parse()\r
+  {\r
+    boolean idsFound=false;\r
+    Vector ids = new Vector();\r
+    StringBuffer seqstrings [];\r
+    Vector starts = new Vector();\r
+    Vector ends = new Vector();\r
+\r
+   String line=null;\r
+   try{\r
+     do{\r
+      line = nextLine();\r
+\r
+      // seek end of ids\r
+      if (line.indexOf("*") > -1)\r
+      {\r
+        idsFound=true;\r
+        break;\r
+      }\r
+\r
+      if (line.indexOf(">") > -1)\r
+      {\r
+\r
+        if(line.indexOf(" ")>-1 )\r
+        {\r
+          //>54402046         0             1   137   137: immunog\r
+          ids.addElement(line.substring(1, line.indexOf(" ")));\r
+\r
+          // remove p Value\r
+          line = line.substring(line.indexOf(" ") + 1);\r
+          line = line.trim();\r
+\r
+          line = line.substring(line.indexOf(" ") + 1);\r
+          line = line.trim();\r
+          starts.addElement(line.substring(0, line.indexOf(" ")));\r
+          line = line.substring(line.indexOf(" ") + 1);\r
+          line = line.trim();\r
+          ends.addElement(line.substring(0, line.indexOf(" ")));\r
+        }\r
+        else\r
+        {\r
+          ids.addElement( line.substring(line.indexOf(">") + 1, line.indexOf("/")));\r
+          line = line.substring(line.indexOf("/") + 1);\r
+          starts.addElement(line.substring(0, line.indexOf("-")));\r
+          ends.addElement(line.substring(line.indexOf("-")+1));\r
+        }\r
+      }\r
+    }while(!idsFound);\r
+\r
+    int starCol = line.indexOf("*");\r
+    seqstrings = new StringBuffer[ids.size()];\r
+    for(int i=0; i<ids.size(); i++)\r
+    {\r
+      if(seqstrings[i]==null)\r
+        seqstrings[i] = new StringBuffer();\r
+    }\r
+\r
+    while ((line = nextLine()).indexOf("*")==-1)\r
+    {\r
+      for(int i=0; i<ids.size(); i++)\r
+        seqstrings[i].append( line.charAt(i+starCol) );\r
+    }\r
+\r
+    for(int i=0; i<ids.size(); i++)\r
+    {\r
+      Sequence newSeq = new Sequence(ids.elementAt(i).toString(),\r
+                                     seqstrings[i].toString(),\r
+                                     Integer.parseInt(starts.elementAt(i).toString()),\r
+                                     Integer.parseInt(ends.elementAt(i).toString()));\r
+      seqs.addElement(newSeq);\r
+    }\r
+\r
+   }catch(Exception ex){ex.printStackTrace();}\r
+  }\r
+\r
+  public String print() {\r
+    return print(getSeqsAsArray());\r
+  }\r
+  public static String print(SequenceI[] s) {\r
+    StringBuffer out = new StringBuffer();\r
+\r
+    int i=0;\r
+    int max = -1;\r
+    while (i < s.length && s[i] != null) {\r
+      out.append(">" + s[i].getName() + "/" + s[i].getStart() + "-" + s[i].getEnd() + "\n");\r
+      if (s[i].getSequence().length() > max) { max = s[i].getSequence().length();}\r
+      i++;\r
+    }\r
+\r
+      out.append("* iteration 1\n");\r
+      for (int j = 0; j < max; j++) {\r
+        i=0;\r
+        while (i < s.length && s[i] != null) {\r
+          if(s[i].getSequence().length()>j )\r
+            out.append(s[i].getSequence().substring(j,j+1));\r
+          else\r
+            out.append("-");\r
+          i++;\r
+        }\r
+        out.append("\n");\r
+      }\r
+    out.append("*\n");\r
+    return out.toString();\r
+\r
+  }\r
+}\r
diff --git a/src/jalview/io/ClustalFile.java b/src/jalview/io/ClustalFile.java
new file mode 100755 (executable)
index 0000000..98c500a
--- /dev/null
@@ -0,0 +1,174 @@
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+public class ClustalFile extends AlignFile {\r
+\r
+  Vector ids;\r
+\r
+  public ClustalFile()\r
+  {}\r
+\r
+  public ClustalFile(String inStr) {\r
+    super(inStr);\r
+  }\r
+\r
+\r
+  public void initData() {\r
+    super.initData();\r
+    ids = new Vector();\r
+  }\r
+\r
+  public ClustalFile(String inFile, String type) throws IOException {\r
+    super(inFile,type);\r
+  }\r
+\r
+  public void parse() {\r
+    int     i    = 0;\r
+    boolean flag = false;\r
+\r
+    Vector    headers = new Vector();\r
+    Hashtable seqhash = new Hashtable();\r
+\r
+    String line;\r
+\r
+    try {\r
+      while ((line = nextLine()) != null) {\r
+       if (line.indexOf(" ") != 0) {\r
+         StringTokenizer str = new StringTokenizer(line," ");\r
+         String id = "";\r
+\r
+         if (str.hasMoreTokens()) {\r
+           id = str.nextToken();\r
+           if (id.equals("CLUSTAL")) {\r
+             flag = true;\r
+           } else {\r
+             if (flag) {\r
+               StringBuffer tempseq;\r
+               if (seqhash.containsKey(id)) {\r
+                 tempseq = (StringBuffer)seqhash.get(id);\r
+               } else {\r
+                 tempseq = new StringBuffer();\r
+                 seqhash.put(id,tempseq);\r
+               }\r
+\r
+               if (!(headers.contains(id))) {\r
+                 headers.addElement(id);\r
+               }\r
+\r
+               tempseq.append(str.nextToken());\r
+             }\r
+           }\r
+         }\r
+       }\r
+      }\r
+    } catch (IOException e) {\r
+      System.out.println("Exception parsing clustal file " + e);\r
+    }\r
+\r
+    if (flag) {\r
+      this.noSeqs = headers.size();\r
+\r
+      //Add sequences to the hash\r
+      for (i = 0; i < headers.size(); i++ ) {\r
+        int start = -1;\r
+        int end   = -1;\r
+\r
+        if ( seqhash.get(headers.elementAt(i)) != null) {\r
+          if (maxLength <  seqhash.get(headers.elementAt(i)).toString().length() ) {\r
+            maxLength =  seqhash.get(headers.elementAt(i)).toString().length();\r
+          }\r
+          String head =  headers.elementAt(i).toString();\r
+          start = 1;\r
+          end   =  seqhash.get(headers.elementAt(i)).toString().length();\r
+\r
+          if (head.indexOf("/") > 0 ) {\r
+            StringTokenizer st = new StringTokenizer(head,"/");\r
+            if (st.countTokens() == 2) {\r
+\r
+              ids.addElement(st.nextToken());\r
+\r
+              String tmp = st.nextToken();\r
+              st = new StringTokenizer(tmp,"-");\r
+              if (st.countTokens() == 2) {\r
+                start = Integer.valueOf(st.nextToken()).intValue();\r
+                end = Integer.valueOf(st.nextToken()).intValue();\r
+              }\r
+            } else {\r
+              ids.addElement(headers.elementAt(i));\r
+            }\r
+          }  else {\r
+            ids.addElement(headers.elementAt(i));\r
+\r
+          }\r
+          Sequence newSeq = new Sequence(ids.elementAt(i).toString(),\r
+                                         seqhash.get(headers.elementAt(i).toString()).toString(),start,end);\r
+\r
+          seqs.addElement(newSeq);\r
+\r
+        } else {\r
+          System.out.println("Can't find sequence for " + headers.elementAt(i));\r
+        }\r
+      }\r
+    }\r
+\r
+  }\r
+\r
+  public String print() {\r
+    return print(getSeqsAsArray());\r
+  }\r
+  public static String print(SequenceI[] s) {\r
+    StringBuffer out = new StringBuffer("CLUSTAL\n\n");\r
+\r
+    int max = 0;\r
+    int maxid = 0;\r
+\r
+    int i = 0;\r
+\r
+    while (i < s.length && s[i] != null) {\r
+      String tmp = s[i].getName() + "/" + s[i].getStart() + "-" + s[i].getEnd();\r
+\r
+      if (s[i].getSequence().length() > max) {\r
+        max = s[i].getSequence().length();\r
+      }\r
+      if (tmp.length() > maxid) {\r
+        maxid = tmp.length();\r
+      }\r
+      i++;\r
+    }\r
+\r
+    if (maxid < 15) {\r
+      maxid = 15;\r
+    }\r
+    maxid++;\r
+    int len = 60;\r
+    int nochunks =  max / len + 1;\r
+\r
+    for (i = 0; i < nochunks; i++) {\r
+      int j = 0;\r
+      while ( j < s.length && s[j] != null) {\r
+        out.append( new Format("%-" + maxid + "s").form(s[j].getName() + "/" + s[j].getStart() + "-" + s[j].getEnd()) + " ");\r
+        int start = i*len;\r
+        int end = start + len;\r
+\r
+        if (end < s[j].getSequence().length() && start < s[j].getSequence().length() ) {\r
+          out.append(s[j].getSequence().substring(start,end) + "\n");\r
+        } else {\r
+          if (start < s[j].getSequence().length()) {\r
+            out.append(s[j].getSequence().substring(start) + "\n");\r
+          }\r
+        }\r
+        j++;\r
+      }\r
+      out.append("\n");\r
+\r
+    }\r
+    return out.toString();\r
+  }\r
+\r
+\r
+}\r
diff --git a/src/jalview/io/FastaFile.java b/src/jalview/io/FastaFile.java
new file mode 100755 (executable)
index 0000000..28109d5
--- /dev/null
@@ -0,0 +1,139 @@
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.analysis.*;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+public class FastaFile extends AlignFile {\r
+\r
+  public FastaFile()\r
+  {}\r
+\r
+  public FastaFile(String inStr) {\r
+    super(inStr);\r
+  }\r
+\r
+  public FastaFile(String inFile, String type) throws IOException {\r
+    super(inFile,type);\r
+  }\r
+\r
+  public void parse() throws IOException\r
+  {\r
+\r
+    String       id    = "";\r
+    StringBuffer seq   = new StringBuffer();\r
+    int          count = 0;\r
+    boolean      flag  = false;\r
+\r
+    int          sstart = 0;\r
+    int          send   = 0;\r
+\r
+    String line;\r
+\r
+      while ((line = nextLine()) != null) {\r
+\r
+       if (line.length() > 0) {\r
+\r
+         // Do we have an id line?\r
+\r
+         if (line.substring(0,1).equals(">")) {\r
+\r
+           if (count != 0) {\r
+             if (sstart != 0) {\r
+               seqs.addElement(new Sequence(id,seq.toString().toUpperCase(),sstart,send));\r
+             } else {\r
+               seqs.addElement(new Sequence(id,seq.toString().toUpperCase(),1,seq.length()));\r
+             }\r
+           }\r
+\r
+           count++;\r
+\r
+           StringTokenizer str = new StringTokenizer(line," ");\r
+\r
+           id = str.nextToken();\r
+           id = id.substring(1);\r
+\r
+           if (id.indexOf("/") > 0 ) {\r
+\r
+             StringTokenizer st = new StringTokenizer(id,"/");\r
+             if (st.countTokens() == 2) {\r
+               id = st.nextToken();\r
+               String tmp = st.nextToken();\r
+\r
+               st = new StringTokenizer(tmp,"-");\r
+\r
+               if (st.countTokens() == 2) {\r
+                 sstart = Integer.valueOf(st.nextToken()).intValue();\r
+                 send   = Integer.valueOf(st.nextToken()).intValue();\r
+               }\r
+             }\r
+           }\r
+\r
+           seq = new StringBuffer();\r
+\r
+         } else {\r
+           seq = seq.append(line);\r
+         }\r
+       }\r
+      }\r
+      if (count > 0) {\r
+\r
+        if(!isValidProteinSequence(seq.toString().toUpperCase()))\r
+          throw new IOException("Invalid protein sequence");\r
+\r
+       if (sstart != 0) {\r
+         seqs.addElement(new Sequence(id,seq.toString().toUpperCase(),sstart,send));\r
+       } else {\r
+         seqs.addElement(new Sequence(id,seq.toString().toUpperCase(),1,seq.length()));\r
+       }\r
+      }\r
+\r
+  }\r
+\r
+  public static String print(SequenceI[] s) {\r
+    return print(s,72);\r
+  }\r
+  public static String print(SequenceI[] s, int len) {\r
+    return print(s,len,true);\r
+  }\r
+  public static String print(SequenceI[] s, int len,boolean gaps) {\r
+    StringBuffer out = new StringBuffer();\r
+    int i = 0;\r
+    while (i < s.length && s[i] != null) {\r
+      String seq = "";\r
+      if (gaps) {\r
+        seq = s[i].getSequence();\r
+      } else {\r
+        seq = AlignSeq.extractGaps(s[i].getSequence(),"-");\r
+        seq = AlignSeq.extractGaps(seq,".");\r
+        seq = AlignSeq.extractGaps(seq," ");\r
+      }\r
+\r
+      out.append(">" + s[i].getName() + "/" + s[i].getStart() + "-" + s[i].getEnd() + "\n");\r
+\r
+      int nochunks = seq.length() / len + 1;\r
+\r
+      for (int j = 0; j < nochunks; j++) {\r
+        int start = j*len;\r
+        int end = start + len;\r
+\r
+        if (end < seq.length()) {\r
+          out.append(seq.substring(start,end) + "\n");\r
+        } else if (start < seq.length()) {\r
+          out.append(seq.substring(start) + "\n");\r
+        }\r
+      }\r
+      i++;\r
+    }\r
+    return out.toString();\r
+  }\r
+\r
+  public String print() {\r
+    return print(getSeqsAsArray());\r
+  }\r
+}\r
+\r
+\r
+\r
diff --git a/src/jalview/io/FileParse.java b/src/jalview/io/FileParse.java
new file mode 100755 (executable)
index 0000000..5f2e856
--- /dev/null
@@ -0,0 +1,46 @@
+package jalview.io;\r
+\r
+import java.io.*;\r
+import java.net.*;\r
+\r
+public class FileParse {\r
+\r
+  public File   inFile;\r
+  public int    fileSize;\r
+  public int    noLines;\r
+\r
+  protected String          type;\r
+  protected BufferedReader dataIn;\r
+\r
+  public FileParse() {}\r
+\r
+  public FileParse(String fileStr, String type) throws MalformedURLException, IOException\r
+  {\r
+\r
+    this.type = type;\r
+\r
+    if (type.equals("File")) {\r
+      this.inFile = new File(fileStr);\r
+      this.fileSize = (int)inFile.length();\r
+\r
+      dataIn = new BufferedReader(new FileReader( fileStr ));\r
+\r
+    } else if (type.equals("URL")) {\r
+      URL url = new URL(fileStr);\r
+      this.fileSize = 0;\r
+      dataIn = new BufferedReader(new InputStreamReader( url.openStream() ));\r
+    } else if(type.equals("Paste"))\r
+    {\r
+      dataIn = new BufferedReader(new StringReader(fileStr));\r
+    }\r
+  }\r
+\r
+  public String nextLine() throws IOException {\r
+    String next = dataIn.readLine();\r
+    if (next != null) {\r
+      noLines++;\r
+    }\r
+    return next;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/io/FileProperties.java b/src/jalview/io/FileProperties.java
new file mode 100755 (executable)
index 0000000..9921d70
--- /dev/null
@@ -0,0 +1,33 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.io;\r
+\r
+import java.util.*;\r
+\r
+public class FileProperties {\r
+  public String directory = "./";\r
+  public String extension = ".seq";\r
+\r
+  public FileProperties() {}\r
+\r
+  public FileProperties(String directory, String extension) {\r
+    this.directory = directory;\r
+    this.extension = extension;\r
+  }\r
+}\r
diff --git a/src/jalview/io/FormatAdapter.java b/src/jalview/io/FormatAdapter.java
new file mode 100755 (executable)
index 0000000..d4179b6
--- /dev/null
@@ -0,0 +1,46 @@
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+import java.util.*;\r
+\r
+public class FormatAdapter {\r
+\r
+  public static String get(String format,Vector seqs) {\r
+\r
+    SequenceI [] s = new SequenceI[seqs.size()];\r
+\r
+    for (int i=0;i<seqs.size(); i++)\r
+      s[i] = (SequenceI)seqs.elementAt(i);\r
+\r
+\r
+    if (FormatProperties.contains(format))\r
+    {\r
+      AlignFile afile = FormatFactory.get(format);\r
+      afile.setSeqs(s);\r
+      return afile.print();\r
+    }\r
+    else\r
+       return null;\r
+  }\r
+\r
+  public static SequenceI[] read(String format,String inStr) {\r
+    if (FormatProperties.contains(format)) {\r
+      AlignFile afile = FormatFactory.get(format,inStr);\r
+      return afile.getSeqsAsArray();\r
+    } else {\r
+    // Should throw exception\r
+      return null;\r
+    }\r
+  }\r
+\r
+\r
+  public static SequenceI[] read(String inFile, String type, String format) {\r
+      try {\r
+        AlignFile afile = FormatFactory.get(format,inFile,type);\r
+        return afile.getSeqsAsArray();\r
+      } catch (Exception e) {    }\r
+\r
+    return null;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/io/FormatFactory.java b/src/jalview/io/FormatFactory.java
new file mode 100755 (executable)
index 0000000..64abc11
--- /dev/null
@@ -0,0 +1,71 @@
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+\r
+import java.lang.reflect.*;\r
+\r
+public class FormatFactory {\r
+\r
+  public static AlignFile get(int index) {\r
+    try {\r
+      Class c = Class.forName(FormatProperties.getClassName(index));\r
+      Class [] paramTypes = new Class[1];\r
+      paramTypes[0] = SequenceI[].class;\r
+\r
+      Constructor cons = c.getConstructor(null);\r
+\r
+      return (AlignFile)cons.newInstance(null);\r
+    } catch (Exception e) {\r
+      System.err.println("Errore FFactory:"+e);\r
+      return null;\r
+    }\r
+  }\r
+\r
+  public static AlignFile get(int index,String inStr) {\r
+    try {\r
+      Class c = Class.forName(FormatProperties.getClassName(index));\r
+      Class [] paramTypes = new Class[1];\r
+      paramTypes[0] = String.class;\r
+      Constructor cons = c.getConstructor(paramTypes);\r
+\r
+      Object [] params = new Object[1];\r
+      params[0] = inStr;\r
+      return (AlignFile)cons.newInstance(params);\r
+    } catch (Exception e) {\r
+      System.err.println("error2"+e);\r
+      return null;\r
+    }\r
+  }\r
+\r
+  public static AlignFile get(int index,String inFile,String type) {\r
+    try {\r
+\r
+      Class c = Class.forName(FormatProperties.getClassName(index));\r
+      Class [] paramTypes = new Class[2];\r
+      paramTypes[0] = String.class;\r
+      paramTypes[1] = String.class;\r
+      Constructor cons = c.getConstructor(paramTypes);\r
+      Object [] params = new Object[2];\r
+      params[0] = inFile;\r
+      params[1] = type;\r
+\r
+      AlignFile af = (AlignFile)cons.newInstance(params);\r
+\r
+      return af;\r
+    } catch (Exception e) {\r
+      System.err.println("FormatFactory "+e);\r
+      return null;\r
+    }\r
+  }\r
+\r
+  public static AlignFile get(String format) {\r
+    return get(FormatProperties.indexOf(format));\r
+  }\r
+\r
+  public static AlignFile get(String format,String inStr) {\r
+    return get(FormatProperties.indexOf(format),inStr);\r
+  }\r
+  public static AlignFile get(String format,String inFile,String type) {\r
+    return get(FormatProperties.indexOf(format),inFile,type);\r
+  }\r
+}\r
diff --git a/src/jalview/io/FormatProperties.java b/src/jalview/io/FormatProperties.java
new file mode 100755 (executable)
index 0000000..ca79f72
--- /dev/null
@@ -0,0 +1,89 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.io;\r
+\r
+import java.util.*;\r
+\r
+public class FormatProperties {\r
+\r
+  static final int FASTA   = 0;\r
+  static final int MSF     = 1;\r
+  static final int CLUSTAL = 2;\r
+  static final int BLC     = 3;\r
+  static final int PIR     = 4;\r
+ //static final int MSP     = 5;\r
+  static final int PFAM    = 5;\r
+ // static final int POSTAL  = 7;\r
+//  static final int JNET    = 8;\r
+\r
+  static FormatPropertyVector formats = new FormatPropertyVector();\r
+\r
+  static {\r
+    String prefix = getDefaultClassPrefix();\r
+\r
+    formats.add("FASTA",  prefix + "FastaFile");\r
+    formats.add("MSF",    prefix + "MSFfile");\r
+    formats.add("CLUSTAL",prefix + "ClustalFile");\r
+    formats.add("BLC",    prefix + "BLCFile");\r
+    formats.add("PIR",    prefix + "PIRFile");\r
+  //  formats.add("MSP",    prefix + "MSPFile");\r
+    formats.add("PFAM",   prefix + "PfamFile");\r
+   //formats.add("POSTAL", prefix + "PostalFile");\r
+   // formats.add("JNET",   prefix + "JnetFile");\r
+  }\r
+\r
+  public static String getDefaultClassPrefix() {\r
+    return "jalview.io.";\r
+  }\r
+\r
+  static int indexOf(String format) {\r
+\r
+    if (format != null) {\r
+       format.toUpperCase();\r
+       if (formats.contains(format)) {\r
+         return formats.indexOf(format);\r
+       }\r
+    }\r
+    return -1;\r
+  }\r
+\r
+  public static String getClassName(int index) {\r
+    return formats.getClassName(index);\r
+  }\r
+\r
+  public static boolean contains(String format) {\r
+\r
+    if (format != null) {\r
+      format.toUpperCase();\r
+\r
+      if (formats.contains(format)) {\r
+        return true;\r
+      }\r
+    }\r
+    return false;\r
+  }\r
+\r
+  public static Vector getFormatNames() {\r
+    return formats.getFormatNames();\r
+  }\r
+\r
+  public static Vector getFormats() {\r
+    return formats.getFormatNames();\r
+  }\r
+}\r
diff --git a/src/jalview/io/FormatProperty.java b/src/jalview/io/FormatProperty.java
new file mode 100755 (executable)
index 0000000..2e72ee4
--- /dev/null
@@ -0,0 +1,18 @@
+package jalview.io;\r
+\r
+public class FormatProperty {\r
+  String description;\r
+  String className;\r
+\r
+  public FormatProperty(String description, String className) {\r
+    this.description = new String(description);\r
+    this.className   = new String(className);\r
+  }\r
+\r
+  public String getClassName() {\r
+    return className;\r
+  }\r
+  public String getDescription() {\r
+    return description;\r
+  }\r
+}\r
diff --git a/src/jalview/io/FormatPropertyVector.java b/src/jalview/io/FormatPropertyVector.java
new file mode 100755 (executable)
index 0000000..5fc97b3
--- /dev/null
@@ -0,0 +1,32 @@
+package jalview.io;\r
+\r
+import java.util.*;\r
+\r
+public class FormatPropertyVector {\r
+  Vector formatProps = new Vector();\r
+  Vector formatDescs = new Vector();\r
+\r
+  public void add(String description,String className) {\r
+    formatProps.addElement(new FormatProperty(description,className));\r
+    formatDescs.addElement(description);\r
+  }\r
+  public Vector getFormatNames() {\r
+    return formatDescs;\r
+  }\r
+\r
+  public String getClassName(int ind) {\r
+    return ((FormatProperty)formatProps.elementAt(ind)).getClassName();\r
+  }\r
+\r
+  public String getSchemeName(int ind) {\r
+    return ((FormatProperty)formatProps.elementAt(ind)).getDescription();\r
+  }\r
+\r
+  public boolean contains(String description) {\r
+    return formatDescs.contains(description);\r
+  }\r
+\r
+  public int indexOf(String description) {\r
+    return formatDescs.indexOf(description);\r
+  }\r
+}\r
diff --git a/src/jalview/io/HTMLOutput.java b/src/jalview/io/HTMLOutput.java
new file mode 100755 (executable)
index 0000000..8eef36f
--- /dev/null
@@ -0,0 +1,70 @@
+package jalview.io;\r
+\r
+import jalview.gui.*;\r
+import jalview.datamodel.*;\r
+import jalview.schemes.*;\r
+import java.awt.*;\r
+import javax.swing.*;\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+\r
+public class HTMLOutput\r
+{\r
+  SequenceRenderer sr = new SequenceRenderer();\r
+\r
+  public HTMLOutput(AlignmentI alignment, ColourSchemeI cs)\r
+  {\r
+    Color color;\r
+    JFileChooser chooser = new JFileChooser(jalview.bin.Cache.LAST_DIRECTORY);\r
+    chooser.setDialogTitle("Save as HTML");\r
+    chooser.setToolTipText("Save");\r
+    int value = chooser.showSaveDialog(null);\r
+    if(value == JFileChooser.APPROVE_OPTION)\r
+    {\r
+      String choice =  chooser.getSelectedFile().getPath();\r
+      jalview.bin.Cache.LAST_DIRECTORY = choice;\r
+      try{\r
+        PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(choice));\r
+        out.println("<HTML>");\r
+        out.println("<style type=\"text/css\">");\r
+        out.println("<!--");\r
+        out.println("td {font-family: \"Courier New\", Courier, mono; font-size: medium;}");\r
+        out.println("-->");\r
+        out.println("</style>");\r
+        out.println("<BODY>");\r
+        out.println("<table border=\"1\"><tr><td>\n");\r
+        out.println("<table border=\"0\"  cellpadding=\"0\" cellspacing=\"0\">\n");\r
+\r
+\r
+        //////////////\r
+        for (int i = 0; i < alignment.getHeight(); i++)\r
+        {\r
+          SequenceI seq = alignment.getSequenceAt(i);\r
+          out.println("<tr><td>"+seq.getName()+"&nbsp;&nbsp;</td>");\r
+          for (int res = 0; res < seq.getLength(); res++)\r
+          {\r
+            color = sr.getResidueBoxColour(cs, seq, res);\r
+            Integer.toHexString(color.getRed());\r
+\r
+            out.println("<td bgcolor=\"#"\r
+                        + Integer.toHexString(color.getRed())\r
+                        + Integer.toHexString(color.getGreen())\r
+                        + Integer.toHexString(color.getBlue())\r
+                        +"\"><center>"+seq.getCharAt(res)+"</center></td>");\r
+          }\r
+\r
+          out.println("</tr>");\r
+        }\r
+        //////////////\r
+        out.println("</td></tr></table>");\r
+        out.println("</table>\n</body>\n</html>");\r
+\r
+        out.close();\r
+      }\r
+      catch(Exception ex){}\r
+    }\r
+  }\r
+\r
+\r
+}\r
diff --git a/src/jalview/io/IdentifyFile.java b/src/jalview/io/IdentifyFile.java
new file mode 100755 (executable)
index 0000000..2baf323
--- /dev/null
@@ -0,0 +1,85 @@
+/********************\r
+ * 2004 Jalview Reengineered\r
+ * Barton Group\r
+ * Dundee University\r
+ *\r
+ * AM Waterhouse\r
+ *******************/\r
+\r
+package jalview.io;\r
+\r
+import java.io.*;\r
+import java.net.*;\r
+\r
+public class IdentifyFile\r
+{\r
+  public static String Identify(String file, String protocol)\r
+  {\r
+    String reply = "error";\r
+    try{\r
+\r
+      BufferedReader reader = null;\r
+\r
+      if(protocol.equals("File"))\r
+        reader = new BufferedReader(new FileReader(file));\r
+\r
+      else if (protocol.equals("URL"))\r
+      {\r
+        reply = "URL NOT FOUND";\r
+        URL url = new URL(file);\r
+        reader = new BufferedReader(new InputStreamReader( url.openStream() ) );\r
+        reply = "error";\r
+      }\r
+      else if( protocol.equals("Paste"))\r
+        reader = new BufferedReader( new StringReader(file) );\r
+\r
+\r
+      String data;\r
+      while( (data=reader.readLine())!=null)\r
+      {\r
+        data = data.toUpperCase();\r
+        if(data.indexOf("#")==0 || data.length()<1)\r
+          continue;\r
+\r
+        if(data.indexOf("PILEUP")>-1)\r
+        {\r
+          reply = "MSF";\r
+          break;\r
+        }\r
+        else if(data.indexOf("CLUSTAL")>-1)\r
+        {\r
+          reply = "CLUSTAL";\r
+          break;\r
+        }\r
+        else if(data.indexOf(">P1;")>-1 || data.indexOf(">DL;")>-1)\r
+        {\r
+          reply = "PIR";\r
+          break;\r
+        }\r
+        else if(data.indexOf(">")==0)\r
+        {\r
+          // could be BLC file\r
+          data = reader.readLine();\r
+          if(data.indexOf(">")==0)\r
+            reply = "BLC";\r
+          else\r
+            reply = "FASTA";\r
+\r
+            break;\r
+        }\r
+        else\r
+        {\r
+           reply = "PFAM";\r
+           break;\r
+         }\r
+\r
+      }\r
+      reader.close();\r
+    }\r
+    catch(Exception ex){ex.printStackTrace();}\r
+\r
+    return reply;\r
+  }\r
+\r
+\r
+}\r
diff --git a/src/jalview/io/MSFfile.java b/src/jalview/io/MSFfile.java
new file mode 100755 (executable)
index 0000000..b9cad0a
--- /dev/null
@@ -0,0 +1,230 @@
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+public class MSFfile extends AlignFile {\r
+\r
+  public MSFfile()\r
+  {}\r
+\r
+  public MSFfile(String inStr) {\r
+    super(inStr);\r
+  }\r
+\r
+  public MSFfile(String inFile, String type) throws IOException {\r
+    super(inFile,type);\r
+  }\r
+\r
+  public void parse() {\r
+\r
+    int       i       = 0;\r
+    boolean   seqFlag = false;\r
+    String    key     = new String();\r
+    Vector    headers = new Vector();\r
+    Hashtable seqhash = new Hashtable();\r
+    String    line;\r
+\r
+    try {\r
+    while ((line = nextLine()) != null) {\r
+\r
+      StringTokenizer str = new StringTokenizer(line);\r
+\r
+      while (str.hasMoreTokens()) {\r
+\r
+        String inStr = str.nextToken();\r
+\r
+        //If line has header information add to the headers vector\r
+        if (inStr.indexOf("Name:") != -1) {\r
+          key = str.nextToken();\r
+          headers.addElement(key);\r
+        }\r
+\r
+        //if line has // set SeqFlag to 1 so we know sequences are coming\r
+        if (inStr.indexOf("//") != -1) {\r
+          seqFlag = true;\r
+        }\r
+\r
+        //Process lines as sequence lines if seqFlag is set\r
+        if (( inStr.indexOf("//") == -1) && (seqFlag == true)) {\r
+          //seqeunce id is the first field\r
+          key = inStr;\r
+          StringBuffer tempseq;\r
+\r
+          //Get sequence from hash if it exists\r
+          if (seqhash.containsKey(key)) {\r
+            tempseq = (StringBuffer)seqhash.get(key);\r
+          } else {\r
+           tempseq = new StringBuffer();\r
+           seqhash.put(key,tempseq);\r
+         }\r
+\r
+          //loop through the rest of the words\r
+          while (str.hasMoreTokens()) {\r
+            //append the word to the sequence\r
+            tempseq.append(str.nextToken());\r
+          }\r
+        }\r
+      }\r
+    }\r
+    } catch (IOException e) {\r
+      System.out.println("Exception parsing MSFFile " + e);\r
+    }\r
+\r
+    this.noSeqs = headers.size();\r
+\r
+    //Add sequences to the hash\r
+    for (i = 0; i < headers.size(); i++ ) {\r
+\r
+      if ( seqhash.get(headers.elementAt(i)) != null) {\r
+        String head =  headers.elementAt(i).toString();\r
+        String seq  =  seqhash.get(head).toString();\r
+\r
+        int start = 1;\r
+        int end = seq.length();\r
+\r
+        if (maxLength <  head.length() ) {\r
+          maxLength =  head.length();\r
+        }\r
+\r
+        if (head.indexOf("/") > 0 ) {\r
+\r
+          StringTokenizer st = new StringTokenizer(head,"/");\r
+\r
+          if (st.countTokens() == 2) {\r
+\r
+            head = st.nextToken();\r
+            String tmp = st.nextToken();\r
+            st = new StringTokenizer(tmp,"-");\r
+            if (st.countTokens() == 2) {\r
+              start = Integer.valueOf(st.nextToken()).intValue();\r
+              end = Integer.valueOf(st.nextToken()).intValue();\r
+            }\r
+          }\r
+        }\r
+\r
+        Sequence newSeq = new Sequence(head,seq,start,end);\r
+\r
+        seqs.addElement(newSeq);\r
+\r
+      } else {\r
+        System.out.println("Can't find sequence for " + headers.elementAt(i));\r
+      }\r
+    }\r
+\r
+  }\r
+\r
+  public static int checkSum(String seq) {\r
+    //String chars =  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.*~&@";\r
+    int check = 0;\r
+\r
+    String index =  "--------------------------------------&---*---.-----------------@ABCDEFGHIJKLMNOPQRSTUVWXYZ------ABCDEFGHIJKLMNOPQRSTUVWXYZ----@";\r
+    index += "--------------------------------------------------------------------------------------------------------------------------------";\r
+\r
+    for(int i = 0; i < seq.length(); i++) {\r
+      try {\r
+        if (i <seq.length()) {\r
+          int pos = index.indexOf(seq.substring(i,i+1));\r
+          if (!index.substring(pos,pos+1).equals("_")) {\r
+            check += ((i % 57) + 1) * pos;\r
+          }\r
+        }\r
+      } catch (Exception e) {\r
+        System.err.println("Exception " + e);\r
+      }\r
+    }\r
+    return check % 10000;\r
+  }\r
+\r
+  public static String print(SequenceI[] s) {\r
+    StringBuffer out = new StringBuffer("PileUp\n\n");\r
+\r
+    int max = 0;\r
+    int maxid = 0;\r
+\r
+    int i = 0;\r
+    String big = "";\r
+    while (i < s.length && s[i] != null) {\r
+      big += s[i].getSequence();\r
+      i++;\r
+    }\r
+    i = 0;\r
+    int bigcheck = checkSum(big);\r
+\r
+    out.append("   MSF: " + s[0].getSequence().length() + "   Type: P    Check:  " + bigcheck + "   ..\n\n\n");\r
+\r
+    while (i < s.length && s[i] != null) {\r
+      String seq = s[i].getSequence();\r
+      String name =  s[i].getName()+ "/" + s[i].getStart() + "-" + s[i].getEnd();\r
+      int check = checkSum(s[i].getSequence());\r
+      out.append(" Name: " + name + " oo  Len:  " + s[i].getSequence().length() + "  Check:  " + check + "  Weight:  1.00\n");\r
+      if (seq.length() > max) {\r
+        max = seq.length();\r
+      }\r
+      if (name.length() > maxid) {\r
+        maxid = name.length();\r
+      }\r
+      i++;\r
+    }\r
+\r
+    if (maxid < 10) {\r
+      maxid = 10;\r
+    }\r
+    maxid++;\r
+    out.append( "\n\n//\n\n");\r
+\r
+    int len = 50;\r
+\r
+    int nochunks =  max / len + 1;\r
+    if (max%len == 0) {\r
+      nochunks--;\r
+    }\r
+    for (i = 0; i < nochunks; i++) {\r
+      int j = 0;\r
+      while (j < s.length && s[j] != null) {\r
+        String name =  s[j].getName();\r
+        out.append( new Format("%-" + maxid + "s").form(name + "/" + s[j].getStart() + "-" + s[j].getEnd()) + " ");\r
+        for (int k = 0; k < 5; k++) {\r
+\r
+          int start = i*50 + k*10;\r
+          int end = start + 10;\r
+\r
+          if (end < s[j].getSequence().length() && start < s[j].getSequence().length() ) {\r
+            out.append(s[j].getSequence().substring(start,end));\r
+            if (k < 4) {\r
+              out.append(" ");\r
+            } else {\r
+              out.append("\n");\r
+            }\r
+          } else {\r
+            if (start < s[j].getSequence().length()) {\r
+              out.append(s[j].getSequence().substring(start));\r
+              out.append("\n");\r
+            } else {\r
+              if (k == 0) {\r
+                out.append("\n");\r
+              }\r
+            }\r
+          }\r
+        }\r
+        j++;\r
+      }\r
+      out.append("\n");\r
+\r
+    }\r
+    return out.toString();\r
+  }\r
+  public String print() {\r
+    return print(getSeqsAsArray());\r
+  }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/io/OutputGenerator.java b/src/jalview/io/OutputGenerator.java
new file mode 100755 (executable)
index 0000000..c038e89
--- /dev/null
@@ -0,0 +1,20 @@
+package jalview.io;\r
+\r
+import java.io.*;\r
+\r
+public interface OutputGenerator {\r
+\r
+  public PostscriptProperties getPostscriptProperties();\r
+  //public MailProperties getMailProperties();\r
+  //    public FileProperties getFileProperties();\r
+\r
+  public void setPostscriptProperties(PostscriptProperties pp);\r
+  //    public void setFileProperties(FileProperties fp);\r
+  //public void setMailProperties(MailProperties mp);\r
+\r
+  public String getText(String format);\r
+  public void getPostscript(PrintWriter bw);\r
+  public void getPostscript(PrintStream ps);\r
+  public StringBuffer getPostscript();\r
+\r
+}\r
diff --git a/src/jalview/io/PIRFile.java b/src/jalview/io/PIRFile.java
new file mode 100755 (executable)
index 0000000..be60a43
--- /dev/null
@@ -0,0 +1,133 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.analysis.*;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+public class PIRFile extends AlignFile {\r
+\r
+  Vector words = new Vector();  //Stores the words in a line after splitting\r
+\r
+  public PIRFile()\r
+  {}\r
+\r
+  public PIRFile(String inStr) {\r
+    super(inStr);\r
+  }\r
+\r
+  public PIRFile(String inFile, String type) throws IOException {\r
+    super(inFile,type);\r
+  }\r
+\r
+  public void parse() {\r
+    try{\r
+      String id, start, end;\r
+      StringBuffer sequence;\r
+      String line = null;\r
+      while( (line = nextLine())!=null)\r
+      {\r
+        try{\r
+          id = line.substring(line.indexOf(";") + 1, line.indexOf("/"));\r
+          line = line.substring(line.indexOf("/") + 1);\r
+          start = line.substring(0, line.indexOf("-"));\r
+          end = line.substring(line.indexOf("-") + 1);\r
+        }catch(Exception ex)\r
+        {  id="No id"; start="0"; end="0"; }\r
+\r
+        sequence = new StringBuffer();\r
+\r
+        line = nextLine(); // this is the title line\r
+\r
+        boolean starFound = false;\r
+        do\r
+        {\r
+          line = nextLine();\r
+          sequence.append( line );\r
+          if(line.indexOf("*")>-1)\r
+            starFound = true;\r
+\r
+        }while(!starFound);\r
+\r
+        sequence.setLength( sequence.length()-1);\r
+\r
+       Sequence newSeq = new Sequence(id,\r
+                               sequence.toString(),\r
+                               Integer.parseInt(start),\r
+                               Integer.parseInt(end));\r
+         seqs.addElement(newSeq);\r
+      }\r
+\r
+    }\r
+    catch(Exception ex){ex.printStackTrace();}\r
+  }\r
+\r
+  public String print() {\r
+    return print(getSeqsAsArray());\r
+  }\r
+  public static String print(SequenceI[] s) {\r
+    return print(s,72,true);\r
+  }\r
+  public static String print(SequenceI[] s, int len) {\r
+    return print(s,len,true);\r
+  }\r
+  public static String print(SequenceI[] s, int len,boolean gaps) {\r
+    StringBuffer out = new StringBuffer();\r
+    int i = 0;\r
+\r
+    while (i < s.length && s[i] != null) {\r
+      String seq = "";\r
+      if (gaps) {\r
+        seq = s[i].getSequence() + "*";\r
+      } else {\r
+        seq = AlignSeq.extractGaps(s[i].getSequence(),"-");\r
+        seq = AlignSeq.extractGaps(seq,".");\r
+        seq = AlignSeq.extractGaps(seq," ");\r
+        seq = seq + "*";\r
+      }\r
+\r
+      out.append(">P1;" + s[i].getName() + "/" + s[i].getStart()+ "-" + s[i].getEnd() + "\n");\r
+      out.append(" Dummy title\n");\r
+      int nochunks = seq.length() / len + 1;\r
+\r
+      for (int j = 0; j < nochunks; j++) {\r
+        int start = j*len;\r
+        int end = start + len;\r
+\r
+        if (end < seq.length()) {\r
+          out.append(seq.substring(start,end) + "\n");\r
+        } else if (start < seq.length()) {\r
+          out.append(seq.substring(start) + "\n");\r
+        }\r
+      }\r
+      i++;\r
+    }\r
+    return out.toString();\r
+  }\r
+\r
+  public static void main(String[] args) {\r
+    String inStr = ">P1;LCAT_MOUSE_90.35\nMGLPGSPWQRVLLLLGLLLPPATPFWLLNVLFPPHTTPKAELSNHTRPVILVPGCLGNRLEAKLDKPDVVNW\nMCYRKTEDFFTIWLDFNLFLPLGVDCWIDNTRIVYNHSSGRVSNAPGVQIRVPGFGKTESVEYVDDNKLAGY\n\n>LCAT_PAPAN_95.78\nMGPPGSPWQWVPLLLGLLLPPAAPFWLLNVLFPPHTTPKAELSNHTRPVILVPGCLGNQLEAKLDKPDVVNW\nMCYRKTEDFFTIWLDLNMFLPLGVDCWIDNTRVVYNRSSGLVSNAPGVQIRVPGFGKTYSVEYLDSSKLAGY\nLHTLVQNLVNNGYVRDETVRAAPYDWRLEPGQQEEYYHKLAGLVEEMHAAYGKPVFLIGHSLGCLHLLYFLL\n";\r
+    PIRFile fa = new PIRFile(inStr);\r
+  }\r
+}\r
+\r
+\r
+\r
diff --git a/src/jalview/io/PfamFile.java b/src/jalview/io/PfamFile.java
new file mode 100755 (executable)
index 0000000..e17f831
--- /dev/null
@@ -0,0 +1,173 @@
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+public class PfamFile extends AlignFile {\r
+\r
+  Vector ids;\r
+\r
+  public PfamFile()\r
+  {}\r
+\r
+  public PfamFile(String inStr) {\r
+    super(inStr);\r
+  }\r
+\r
+  public void initData() {\r
+    super.initData();\r
+    ids = new Vector();\r
+  }\r
+\r
+  public PfamFile(String inFile, String type) throws IOException {\r
+    super(inFile,type);\r
+  }\r
+\r
+  public void parse() throws IOException{\r
+    int i = 0;\r
+    String line;\r
+\r
+\r
+    Hashtable seqhash = new Hashtable();\r
+    Vector    headers = new Vector();\r
+\r
+\r
+      while ((line = nextLine()) != null)\r
+      {\r
+\r
+      if (line.indexOf(" ") != 0)\r
+      {\r
+        if (line.indexOf("#") != 0)\r
+        {\r
+\r
+          StringTokenizer str = new StringTokenizer(line," ");\r
+          String id = "";\r
+\r
+          if (str.hasMoreTokens())\r
+          {\r
+            id = str.nextToken();\r
+\r
+            StringBuffer tempseq;\r
+\r
+            if (seqhash.containsKey(id))\r
+              tempseq = (StringBuffer)seqhash.get(id);\r
+           else\r
+           {\r
+             tempseq = new StringBuffer();\r
+             seqhash.put(id,tempseq);\r
+           }\r
+\r
+            if (!(headers.contains(id)))\r
+              headers.addElement(id);\r
+\r
+\r
+            tempseq.append(str.nextToken());\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    this.noSeqs = headers.size();\r
+    if(noSeqs<1)\r
+      throw new IOException("No sequences found (PFAM input)");\r
+\r
+    for (i = 0; i < headers.size(); i++ ) {\r
+\r
+      if ( seqhash.get(headers.elementAt(i)) != null) {\r
+        if (maxLength <  seqhash.get(headers.elementAt(i)).toString().length() )\r
+          maxLength =  seqhash.get(headers.elementAt(i)).toString().length();\r
+\r
+        String head =  headers.elementAt(i).toString();\r
+        int start = 1;\r
+        int end =  seqhash.get(headers.elementAt(i)).toString().length();\r
+\r
+        if (head.indexOf("/") > 0 ) {\r
+          StringTokenizer st = new StringTokenizer(head,"/");\r
+          if (st.countTokens() == 2) {\r
+            ids.addElement(st.nextToken());\r
+            String tmp = st.nextToken();\r
+            st = new StringTokenizer(tmp,"-");\r
+            if (st.countTokens() == 2) {\r
+              start = Integer.valueOf(st.nextToken()).intValue();\r
+              end = Integer.valueOf(st.nextToken()).intValue();\r
+            } else\r
+            {\r
+              start = -1;\r
+              end = -1;\r
+            }\r
+          } else\r
+            ids.addElement(headers.elementAt(i));\r
+\r
+        }\r
+        else\r
+          ids.addElement(headers.elementAt(i));\r
+\r
+\r
+        Sequence newSeq = null;\r
+        if (start != -1 && end != -1)\r
+        {\r
+          newSeq = new Sequence(ids.elementAt(i).toString(),\r
+                                         seqhash.get(headers.elementAt(i).toString()).toString(),start,end);\r
+          seqs.addElement(newSeq);\r
+        }\r
+        else\r
+        {\r
+          newSeq = new Sequence(ids.elementAt(i).toString(),\r
+                                         seqhash.get(headers.elementAt(i).toString()).toString(),1,\r
+                                         seqhash.get(headers.elementAt(i).toString()).toString().length());\r
+          seqs.addElement(newSeq);\r
+        }\r
+\r
+        if(!isValidProteinSequence(newSeq.getSequence()))\r
+          throw new IOException("Not a valid protein sequence - (PFAM input)");\r
+      }\r
+      else\r
+        System.out.println("Can't find sequence for " + headers.elementAt(i));\r
+\r
+    }\r
+\r
+  }\r
+\r
+  public static String print(SequenceI[] s) {\r
+    StringBuffer out = new StringBuffer("");\r
+\r
+    int max = 0;\r
+    int maxid = 0;\r
+\r
+    int i = 0;\r
+\r
+    while (i < s.length && s[i] != null) {\r
+      String tmp = s[i].getName() + "/" + s[i].getStart()+ "-" + s[i].getEnd();\r
+\r
+      if (s[i].getSequence().length() > max) {\r
+        max = s[i].getSequence().length();\r
+      }\r
+      if (tmp.length() > maxid) {\r
+        maxid = tmp.length();\r
+      }\r
+      i++;\r
+    }\r
+\r
+    if (maxid < 15) {\r
+      maxid = 15;\r
+    }\r
+\r
+    int j = 0;\r
+    while ( j < s.length && s[j] != null) {\r
+      out.append( new Format("%-" + maxid + "s").form(s[j].getName() + "/" + s[j].getStart() + "-" + s[j].getEnd() ) + " ");\r
+\r
+      out.append(s[j].getSequence() + "\n");\r
+      j++;\r
+    }\r
+    out.append("\n");\r
+\r
+    return out.toString();\r
+  }\r
+\r
+  public String print() {\r
+    return print(getSeqsAsArray());\r
+  }\r
+}\r
diff --git a/src/jalview/io/PostscriptProperties.java b/src/jalview/io/PostscriptProperties.java
new file mode 100755 (executable)
index 0000000..0aae0de
--- /dev/null
@@ -0,0 +1,75 @@
+package jalview.io;\r
+\r
+import java.util.*;\r
+\r
+public class PostscriptProperties {\r
+\r
+  public static final int PORTRAIT = 0;\r
+  public static final int LANDSCAPE = 1;\r
+\r
+  public static int SHORTSIDE = 612;\r
+  public static int LONGSIDE = 792;\r
+\r
+  static Vector fonts = new Vector();\r
+\r
+  static {\r
+    fonts.addElement("Helvetica");\r
+    fonts.addElement("Times-Roman");\r
+    fonts.addElement("Courier New");\r
+  }\r
+\r
+  static Vector fontsizes = new Vector();\r
+\r
+  static {\r
+    fontsizes.addElement("6");\r
+    fontsizes.addElement("8");\r
+    fontsizes.addElement("10");\r
+    fontsizes.addElement("12");\r
+    fontsizes.addElement("14");\r
+    fontsizes.addElement("16");\r
+  }\r
+\r
+  public int orientation = PORTRAIT;\r
+  public int width = SHORTSIDE;\r
+  public int height = LONGSIDE;\r
+\r
+  public int xoffset = 30;\r
+  public int yoffset = 30;\r
+  public int fsize = 8;\r
+  public String font = "Helvetica";\r
+\r
+  public PostscriptProperties() {}\r
+\r
+  public PostscriptProperties(int or, int w, int h, int xoff, int yoff, int fsize, String font) {\r
+\r
+    this.orientation = or;\r
+    this.width = w;\r
+    this.height = h;\r
+    this.xoffset = xoff;\r
+    this.yoffset = yoff;\r
+    this.fsize = fsize;\r
+    this.font = font;\r
+  }\r
+\r
+  public int getOrientation() {\r
+    return orientation;\r
+  }\r
+  public int getWidth() {\r
+    return width;\r
+  }\r
+  public int getHeight() {\r
+    return height;\r
+  }\r
+  public int getXOffset() {\r
+    return xoffset;\r
+  }\r
+  public int getYOffset() {\r
+    return yoffset;\r
+  }\r
+  public int getFSize() {\r
+    return fsize;\r
+  }\r
+  public String getFont() {\r
+    return font;\r
+  }\r
+}\r
diff --git a/src/jalview/io/SequenceFeatureSourceI.java b/src/jalview/io/SequenceFeatureSourceI.java
new file mode 100755 (executable)
index 0000000..90c8bd3
--- /dev/null
@@ -0,0 +1,13 @@
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+import java.util.*;\r
+\r
+public interface SequenceFeatureSourceI {\r
+  public Sequence getSequence();\r
+  public String   getSequenceString();\r
+  public String   getId();\r
+  public Vector   getFeatures();\r
+  public Vector   getPDBCode();\r
+  \r
+}\r
diff --git a/src/jalview/jbgui/GAlignFrame.java b/src/jalview/jbgui/GAlignFrame.java
new file mode 100755 (executable)
index 0000000..20df46f
--- /dev/null
@@ -0,0 +1,935 @@
+/********************\r
+ * 2004 Jalview Reengineered\r
+ * Barton Group\r
+ * Dundee University\r
+ *\r
+ * AM Waterhouse\r
+ *******************/\r
+\r
+package jalview.jbgui;\r
+\r
+import javax.swing.*;\r
+import java.awt.event.*;\r
+import java.awt.*;\r
+import javax.swing.event.*;\r
+\r
+\r
+public class GAlignFrame extends JInternalFrame\r
+{\r
+  protected JMenuBar alignFrameMenuBar = new JMenuBar();\r
+  protected JMenu fileMenu = new JMenu();\r
+  protected JMenuItem saveAsPostscriptMenuItem = new JMenuItem();\r
+  protected JMenuItem closeMenuItem = new JMenuItem();\r
+  protected JMenu editMenu = new JMenu();\r
+  protected JMenu fontMenu = new JMenu();\r
+  protected JMenu viewMenu = new JMenu();\r
+  protected JMenu colourMenu = new JMenu();\r
+  protected JMenu calculateMenu = new JMenu();\r
+  protected JMenu alignMenu = new JMenu();\r
+  protected JMenuItem groupsMenuItem = new JMenuItem();\r
+  protected JCheckBoxMenuItem groupEditingMenuItem = new JCheckBoxMenuItem();\r
+  protected JMenuItem selectAllSequenceMenuItem = new JMenuItem();\r
+  protected JMenuItem deselectAllSequenceMenuItem = new JMenuItem();\r
+  protected JMenuItem invertSequenceMenuItem = new JMenuItem();\r
+  protected JMenuItem deleteSelectedMenuItem = new JMenuItem();\r
+  protected JMenuItem moveSelectedMenuItem = new JMenuItem();\r
+  protected JMenuItem copySelectedMenuItem = new JMenuItem();\r
+  protected JMenuItem deselectAllColumnsMenuItem = new JMenuItem();\r
+  protected JMenuItem remove2LeftMenuItem = new JMenuItem();\r
+  protected JMenuItem remove2RightMenuItem = new JMenuItem();\r
+  protected JMenuItem removeGappedColumnMenuItem = new JMenuItem();\r
+  protected JMenuItem removeAllGapsMenuItem = new JMenuItem();\r
+  protected JMenuItem setGapCharMenuItem = new JMenuItem();\r
+  protected JMenuItem fontNameMenuItem = new JMenuItem();\r
+  protected JMenuItem fontSizeMenuItem = new JMenuItem();\r
+  protected JMenuItem fontStyleMenuItem = new JMenuItem();\r
+  protected JCheckBoxMenuItem viewBoxesMenuItem = new JCheckBoxMenuItem();\r
+  protected JCheckBoxMenuItem viewTextMenuItem = new JCheckBoxMenuItem();\r
+  protected JMenuItem sortPairwiseMenuItem = new JMenuItem();\r
+  protected JMenuItem sortIDMenuItem = new JMenuItem();\r
+  protected JMenuItem sortGroupMenuItem = new JMenuItem();\r
+  protected JMenuItem sortTreeOrderMenuItem = new JMenuItem();\r
+  protected JMenuItem removeRedundancyMenuItem = new JMenuItem();\r
+  protected JMenuItem pairwiseAlignmentMenuItem = new JMenuItem();\r
+  protected JMenuItem PCAMenuItem = new JMenuItem();\r
+  protected JMenuItem averageDistanceTreeMenuItem = new JMenuItem();\r
+  protected JMenuItem neighbourTreeMenuItem = new JMenuItem();\r
+  protected JMenuItem clustalAlignMenuItem = new JMenuItem();\r
+  BorderLayout borderLayout1 = new BorderLayout();\r
+  public JLabel statusBar = new JLabel();\r
+  protected JMenu saveAlignmentMenu = new JMenu();\r
+  protected JMenu outputTextboxMenu = new JMenu();\r
+  protected JRadioButtonMenuItem clustalColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem hydrophobicityColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem conservationColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem abovePIDColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem PIDColour = new JRadioButtonMenuItem();\r
+  protected JRadioButtonMenuItem BLOSUM62Colour = new JRadioButtonMenuItem();\r
+  JMenuItem njTreeBlosumMenuItem = new JMenuItem();\r
+  JMenuItem avDistanceTreeBlosumMenuItem = new JMenuItem();\r
+  JMenuItem conservationColourIncMenuItem = new JMenuItem();\r
+  protected JCheckBoxMenuItem consensusGraphMenuItem = new JCheckBoxMenuItem();\r
+  protected JCheckBoxMenuItem colourTextMenuItem = new JCheckBoxMenuItem();\r
+  JMenuItem htmlMenuItem = new JMenuItem();\r
+  JMenuItem schemeKeyMenuItem = new JMenuItem();\r
+  public GAlignFrame()\r
+  {\r
+    try\r
+    {\r
+      jbInit();\r
+      setJMenuBar(alignFrameMenuBar);\r
+\r
+      JMenuItem item;\r
+      // dynamically fill save as menu with available formats\r
+      for (int i = 0; i < jalview.io.FormatProperties.getFormats().size(); i++) {\r
+        item = new JMenuItem((String) jalview.io.FormatProperties.getFormats().elementAt(i));\r
+        saveAlignmentMenu.add( item );\r
+        item.addActionListener(new java.awt.event.ActionListener()\r
+        {\r
+          public void actionPerformed(ActionEvent e)\r
+          {\r
+            saveAs_actionPerformed(e);\r
+          }\r
+        });\r
+\r
+        item = new JMenuItem((String) jalview.io.FormatProperties.getFormats().elementAt(i));\r
+        item.addActionListener(new java.awt.event.ActionListener()\r
+        {\r
+          public void actionPerformed(ActionEvent e)\r
+          {\r
+            outputText_actionPerformed(e);\r
+          }\r
+        });\r
+\r
+        outputTextboxMenu.add( item );\r
+      }\r
+\r
+    }\r
+    catch(Exception e)\r
+    {\r
+      e.printStackTrace();\r
+    }\r
+\r
+    ButtonGroup colours = new ButtonGroup();\r
+    colours.add(clustalColour);\r
+    colours.add(zappoColour);\r
+    colours.add(taylorColour);\r
+    colours.add(hydrophobicityColour);\r
+    colours.add(helixColour);\r
+    colours.add(strandColour);\r
+    colours.add(turnColour);\r
+    colours.add(buriedColour);\r
+    colours.add(conservationColour);\r
+    colours.add(abovePIDColour);\r
+    colours.add(userDefinedColour);\r
+    colours.add(PIDColour);\r
+    colours.add(BLOSUM62Colour);\r
+  }\r
+  private void jbInit() throws Exception\r
+  {\r
+    fileMenu.setMnemonic('F');\r
+    fileMenu.setText("File");\r
+    saveAlignmentMenu.setMnemonic('L');\r
+    saveAlignmentMenu.setText("Save alignment to local file");\r
+    saveAsPostscriptMenuItem.setMnemonic('P');\r
+    saveAsPostscriptMenuItem.setText("Save alignment as postscript");\r
+    saveAsPostscriptMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        saveAsPostscriptMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    closeMenuItem.setMnemonic('C');\r
+    closeMenuItem.setText("Close");\r
+    closeMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        closeMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    editMenu.setText("Edit");\r
+    fontMenu.setText("Font");\r
+    viewMenu.setText("View");\r
+    colourMenu.setText("Colour");\r
+    calculateMenu.setText("Calculate");\r
+    alignMenu.setText("Web Service");\r
+    groupsMenuItem.setEnabled(false);\r
+    groupsMenuItem.setText("Groups");\r
+    groupsMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        groupsMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    groupEditingMenuItem.setEnabled(false);\r
+    groupEditingMenuItem.setText("Group editing mode");\r
+    groupEditingMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        groupEditingMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    selectAllSequenceMenuItem.setText("Select all sequences");\r
+    selectAllSequenceMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        selectAllSequenceMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    deselectAllSequenceMenuItem.setText("Deselect all sequences");\r
+    deselectAllSequenceMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        deselectAllSequenceMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    invertSequenceMenuItem.setText("Invert sequence selection");\r
+    invertSequenceMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        invertSequenceMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    deleteSelectedMenuItem.setText("Delete selected sequences");\r
+    deleteSelectedMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        deleteSelectedMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    moveSelectedMenuItem.setText("Move selected sequences to new alignment");\r
+    moveSelectedMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        moveSelectedMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    copySelectedMenuItem.setText("Copy selected sequences to new alignment");\r
+    copySelectedMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        copySelectedMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    deselectAllColumnsMenuItem.setText("Deselect all columns");\r
+    deselectAllColumnsMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        deselectAllColumnsMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    remove2LeftMenuItem.setText("Remove sequence <- left of selected column");\r
+    remove2LeftMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        remove2LeftMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    remove2RightMenuItem.setText("Remove sequence -> right of selected column");\r
+    remove2RightMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        remove2RightMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    removeGappedColumnMenuItem.setText("Remove gapped columns");\r
+    removeGappedColumnMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        removeGappedColumnMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    removeAllGapsMenuItem.setText("Remove all gaps");\r
+    removeAllGapsMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        removeAllGapsMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    setGapCharMenuItem.setText("Set gap character to \"-\"");\r
+    setGapCharMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        setGapCharMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    fontNameMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        fontNameMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    fontSizeMenuItem.setText("10");\r
+    fontSizeMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        fontSizeMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    fontStyleMenuItem.setText("Plain");\r
+    fontStyleMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        fontStyleMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    viewBoxesMenuItem.setText("Boxes");\r
+    viewBoxesMenuItem.setState(true);\r
+    viewBoxesMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        viewBoxesMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    viewTextMenuItem.setText("Text");\r
+    viewTextMenuItem.setState(true);\r
+    viewTextMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        viewTextMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    sortPairwiseMenuItem.setText("Sort by pairwise identity");\r
+    sortPairwiseMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        sortPairwiseMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    sortIDMenuItem.setText("Sort by ID");\r
+    sortIDMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        sortIDMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    sortGroupMenuItem.setText("Sort by group");\r
+    sortGroupMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        sortGroupMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    sortTreeOrderMenuItem.setText("Sort by tree order");\r
+    sortTreeOrderMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        sortTreeOrderMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    removeRedundancyMenuItem.setText("Remove redundancy");\r
+    removeRedundancyMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        removeRedundancyMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    pairwiseAlignmentMenuItem.setText("Pairwise alignments");\r
+    pairwiseAlignmentMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        pairwiseAlignmentMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    PCAMenuItem.setText("Principal component analysis");\r
+    PCAMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        PCAMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    averageDistanceTreeMenuItem.setText("Average distance tree using PID");\r
+    averageDistanceTreeMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        averageDistanceTreeMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    neighbourTreeMenuItem.setText("Neighbour joining tree using PID");\r
+    neighbourTreeMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        neighbourTreeMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    clustalAlignMenuItem.setText("Clustal alignment");\r
+    clustalAlignMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        clustalAlignMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    this.getContentPane().setLayout(borderLayout1);\r
+    alignFrameMenuBar.setFont(new java.awt.Font("Verdana", 0, 11));\r
+    statusBar.setBackground(Color.white);\r
+    statusBar.setFont(new java.awt.Font("Verdana", 0, 11));\r
+    statusBar.setBorder(BorderFactory.createLineBorder(Color.black));\r
+    statusBar.setText("Status bar");\r
+    outputTextboxMenu.setMnemonic('T');\r
+    outputTextboxMenu.setText("Output alignment via textbox");\r
+    clustalColour.setSelected(false);\r
+    clustalColour.setText("Clustalx colours");\r
+    clustalColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        clustalColour_actionPerformed(e);\r
+      }\r
+    });\r
+    zappoColour.setSelected(true);\r
+    zappoColour.setText("Zappo colour scheme");\r
+    zappoColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        zappoColour_actionPerformed(e);\r
+      }\r
+    });\r
+    taylorColour.setText("Taylor colour scheme");\r
+    taylorColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        taylorColour_actionPerformed(e);\r
+      }\r
+    });\r
+    hydrophobicityColour.setText("By hydrophobicity");\r
+    hydrophobicityColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        hydrophobicityColour_actionPerformed(e);\r
+      }\r
+    });\r
+    helixColour.setText("Helix propensity");\r
+    helixColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        helixColour_actionPerformed(e);\r
+      }\r
+    });\r
+    strandColour.setText("Strand propensity");\r
+    strandColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        strandColour_actionPerformed(e);\r
+      }\r
+    });\r
+    turnColour.setText("Turn propensity");\r
+    turnColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        turnColour_actionPerformed(e);\r
+      }\r
+    });\r
+    buriedColour.setText("Buried index");\r
+    buriedColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        buriedColour_actionPerformed(e);\r
+      }\r
+    });\r
+    conservationColour.setEnabled(false);\r
+    conservationColour.setText("By conservation");\r
+    conservationColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        conservationColour_actionPerformed(e);\r
+      }\r
+    });\r
+    abovePIDColour.setEnabled(false);\r
+    abovePIDColour.setText("Above PID threshold only");\r
+    abovePIDColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        abovePIDColour_actionPerformed(e);\r
+      }\r
+    });\r
+    userDefinedColour.setText("User defined colours");\r
+    userDefinedColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        userDefinedColour_actionPerformed(e);\r
+      }\r
+    });\r
+    PIDColour.setEnabled(false);\r
+    PIDColour.setText("By PID");\r
+    PIDColour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        PIDColour_actionPerformed(e);\r
+      }\r
+    });\r
+    BLOSUM62Colour.setText("By BLOSUM62 score");\r
+    BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        BLOSUM62Colour_actionPerformed(e);\r
+      }\r
+    });\r
+    avDistanceTreeBlosumMenuItem.setText("Average distance tree using BLOSUM62");\r
+    avDistanceTreeBlosumMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        avTreeBlosumMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    njTreeBlosumMenuItem.setText("Neighbour joining tree using BLOSUM62");\r
+    njTreeBlosumMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        njTreeBlosumMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    conservationColourIncMenuItem.setEnabled(false);\r
+    conservationColourIncMenuItem.setText("Conservation Colour Increment");\r
+    conservationColourIncMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        conservationColourIncMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    consensusGraphMenuItem.setActionCommand("");\r
+    consensusGraphMenuItem.setText("Consensus graph");\r
+    consensusGraphMenuItem.setState(true);\r
+    consensusGraphMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        consensusGraphMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    colourTextMenuItem.setText("Colour text");\r
+    colourTextMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        colourTextMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    htmlMenuItem.setText("Output as HTML");\r
+    htmlMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        htmlMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    schemeKeyMenuItem.setText("Colour Scheme Key");\r
+    schemeKeyMenuItem.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        schemeKeyMenuItem_actionPerformed(e);\r
+      }\r
+    });\r
+    alignFrameMenuBar.add(fileMenu);\r
+    alignFrameMenuBar.add(editMenu);\r
+    alignFrameMenuBar.add(fontMenu);\r
+    alignFrameMenuBar.add(viewMenu);\r
+    alignFrameMenuBar.add(colourMenu);\r
+    alignFrameMenuBar.add(calculateMenu);\r
+    alignFrameMenuBar.add(alignMenu);\r
+    fileMenu.add(saveAlignmentMenu);\r
+    fileMenu.add(saveAsPostscriptMenuItem);\r
+    fileMenu.add(outputTextboxMenu);\r
+    fileMenu.add(htmlMenuItem);\r
+    fileMenu.addSeparator();\r
+    fileMenu.add(closeMenuItem);\r
+    editMenu.add(groupsMenuItem);\r
+    editMenu.add(groupEditingMenuItem);\r
+    editMenu.addSeparator();\r
+    editMenu.add(selectAllSequenceMenuItem);\r
+    editMenu.add(deselectAllSequenceMenuItem);\r
+    editMenu.add(invertSequenceMenuItem);\r
+    editMenu.addSeparator();\r
+    editMenu.add(deleteSelectedMenuItem);\r
+    editMenu.add(moveSelectedMenuItem);\r
+    editMenu.add(copySelectedMenuItem);\r
+    editMenu.addSeparator();\r
+    editMenu.add(deselectAllColumnsMenuItem);\r
+    editMenu.add(remove2LeftMenuItem);\r
+    editMenu.add(remove2RightMenuItem);\r
+    editMenu.addSeparator();\r
+    editMenu.add(removeGappedColumnMenuItem);\r
+    editMenu.add(removeAllGapsMenuItem);\r
+    editMenu.add(setGapCharMenuItem);\r
+    fontMenu.add(fontNameMenuItem);\r
+    fontMenu.add(fontSizeMenuItem);\r
+    fontMenu.add(fontStyleMenuItem);\r
+    fontMenu.addSeparator();\r
+    fontMenu.add(colourTextMenuItem);\r
+    viewMenu.add(viewBoxesMenuItem);\r
+    viewMenu.add(viewTextMenuItem);\r
+    viewMenu.add(consensusGraphMenuItem);\r
+    colourMenu.add(clustalColour);\r
+    colourMenu.add(zappoColour);\r
+    colourMenu.add(taylorColour);\r
+    colourMenu.add(hydrophobicityColour);\r
+    colourMenu.add(helixColour);\r
+    colourMenu.add(strandColour);\r
+    colourMenu.add(turnColour);\r
+    colourMenu.add(buriedColour);\r
+    colourMenu.add(userDefinedColour);\r
+    colourMenu.addSeparator();\r
+    colourMenu.add(conservationColour);\r
+    colourMenu.add(conservationColourIncMenuItem);\r
+    colourMenu.addSeparator();\r
+    colourMenu.add(abovePIDColour);\r
+    colourMenu.add(PIDColour);\r
+    colourMenu.add(BLOSUM62Colour);\r
+    colourMenu.addSeparator();\r
+    colourMenu.add(schemeKeyMenuItem);\r
+    calculateMenu.add(sortPairwiseMenuItem);\r
+    calculateMenu.add(sortIDMenuItem);\r
+    calculateMenu.add(sortGroupMenuItem);\r
+    calculateMenu.add(sortTreeOrderMenuItem);\r
+    calculateMenu.add(removeRedundancyMenuItem);\r
+    calculateMenu.addSeparator();\r
+    calculateMenu.add(pairwiseAlignmentMenuItem);\r
+    calculateMenu.add(PCAMenuItem);\r
+    calculateMenu.addSeparator();\r
+    calculateMenu.add(averageDistanceTreeMenuItem);\r
+    calculateMenu.add(neighbourTreeMenuItem);\r
+    calculateMenu.add(avDistanceTreeBlosumMenuItem);\r
+    calculateMenu.add(njTreeBlosumMenuItem);\r
+    alignMenu.add(clustalAlignMenuItem);\r
+    this.getContentPane().add(statusBar, BorderLayout.SOUTH);\r
+  }\r
+\r
+  protected void saveAs_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void outputText_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void htmlMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+\r
+  protected void saveAsPostscriptMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+  protected void closeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void groupsMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void groupEditingMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void invertSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void deleteSelectedMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void moveSelectedMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void copySelectedMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void deselectAllColumnsMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void remove2LeftMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void remove2RightMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void removeAllGapsMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void setGapCharMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+  protected void fontNameMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void fontSizeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void fontStyleMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void viewBoxesMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void viewTextMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void colourTextMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+\r
+  protected void consensusGraphMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+\r
+\r
+\r
+\r
+  protected void sortPairwiseMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void sortIDMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void sortGroupMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void sortTreeOrderMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void removeRedundancyMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void PCAMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void neighbourTreeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+  protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+\r
+  protected void clustalAlignMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+\r
+\r
+  protected void clustalColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void zappoColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void taylorColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+  protected void hydrophobicityColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void helixColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void strandColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void turnColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void buriedColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void conservationColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void conservationColourIncMenuItem_actionPerformed(ActionEvent e)\r
+ {\r
+\r
+ }\r
+\r
+\r
+  protected void abovePIDColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+\r
+  protected void userDefinedColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void PIDColour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void BLOSUM62Colour_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+  protected void schemeKeyMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/jbgui/GAlignmentPanel.java b/src/jalview/jbgui/GAlignmentPanel.java
new file mode 100755 (executable)
index 0000000..c361c1e
--- /dev/null
@@ -0,0 +1,86 @@
+/********************
+ * 2004 Jalview Reengineered
+ * Barton Group
+ * Dundee University
+ *
+ * AM Waterhouse
+ *******************/
+
+package jalview.jbgui;
+
+import java.awt.*;
+import javax.swing.*;
+
+public class GAlignmentPanel extends JPanel
+{
+  protected JPanel sequenceHolderPanel = new JPanel();
+  protected JScrollBar vscroll = new JScrollBar();
+  protected  JScrollBar hscroll = new JScrollBar();
+  protected JPanel seqPanelHolder = new JPanel();
+  BorderLayout borderLayout1 = new BorderLayout();
+  BorderLayout borderLayout3 = new BorderLayout();
+  JPanel jPanel2 = new JPanel();
+  BorderLayout borderLayout2 = new BorderLayout();
+  protected JPanel scorePanelHolder = new JPanel();
+  protected JPanel scalePanelHolder = new JPanel();
+  protected JPanel idPanelHolder = new JPanel();
+  BorderLayout borderLayout5 = new BorderLayout();
+  JPanel jPanel3 = new JPanel();
+  protected JPanel idSpaceFillerPanel = new JPanel();
+  BorderLayout borderLayout4 = new BorderLayout();
+  BorderLayout borderLayout6 = new BorderLayout();
+  ButtonGroup buttonGroup1 = new ButtonGroup();
+  BorderLayout borderLayout7 = new BorderLayout();
+
+  public GAlignmentPanel()
+  {
+    try
+    {
+      jbInit();
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+  private void jbInit() throws Exception
+  {
+    idPanelHolder.setBorder(null);
+    idPanelHolder.setPreferredSize(new Dimension(70, 10));
+    this.setLayout(borderLayout7);
+    sequenceHolderPanel.setMaximumSize(new Dimension(2147483647, 2147483647));
+    sequenceHolderPanel.setMinimumSize(new Dimension(150, 150));
+    sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));
+    sequenceHolderPanel.setLayout(borderLayout3);
+    seqPanelHolder.setLayout(borderLayout1);
+    jPanel2.setBackground(new Color(212, 208, 230));
+    jPanel2.setBorder(null);
+    jPanel2.setLayout(borderLayout2);
+    scalePanelHolder.setBackground(Color.white);
+    scalePanelHolder.setMinimumSize(new Dimension(10, 80));
+    scalePanelHolder.setPreferredSize(new Dimension(10, 30));
+    scalePanelHolder.setLayout(borderLayout6);
+    scorePanelHolder.setBackground(Color.white);
+    scorePanelHolder.setPreferredSize(new Dimension(10, 80));
+    scorePanelHolder.setLayout(borderLayout4);
+    idPanelHolder.setLayout(borderLayout5);
+    jPanel3.setBackground(Color.white);
+    jPanel3.setPreferredSize(new Dimension(10, 30));
+    idSpaceFillerPanel.setBackground(Color.white);
+    idSpaceFillerPanel.setPreferredSize(new Dimension(10, 80));
+    hscroll.setOrientation(JScrollBar.HORIZONTAL);
+    vscroll.setEnabled(true);
+    sequenceHolderPanel.add(scorePanelHolder, BorderLayout.SOUTH);
+    sequenceHolderPanel.add(scalePanelHolder,  BorderLayout.NORTH);
+    sequenceHolderPanel.add(seqPanelHolder,  BorderLayout.CENTER);
+    this.add(jPanel2, BorderLayout.CENTER);
+    jPanel2.add(sequenceHolderPanel, BorderLayout.CENTER);
+    seqPanelHolder.add(vscroll, BorderLayout.EAST);
+    seqPanelHolder.add(hscroll, BorderLayout.SOUTH);
+    this.add(idPanelHolder, BorderLayout.WEST);
+    idPanelHolder.add(jPanel3,  BorderLayout.NORTH);
+    idPanelHolder.add(idSpaceFillerPanel,  BorderLayout.SOUTH);
+  }
+
+
+}
diff --git a/src/jalview/jbgui/GColourKey.java b/src/jalview/jbgui/GColourKey.java
new file mode 100755 (executable)
index 0000000..da4eb74
--- /dev/null
@@ -0,0 +1,201 @@
+package jalview.jbgui;
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.*;
+
+public class GColourKey extends JInternalFrame
+{
+  JMenuBar jMenuBar1 = new JMenuBar();
+  protected JMenu menu = new JMenu();
+  JRadioButtonMenuItem clustalMenuItem = new JRadioButtonMenuItem();
+  JRadioButtonMenuItem zappoMenuItem = new JRadioButtonMenuItem();
+  JRadioButtonMenuItem taylorMenuItem = new JRadioButtonMenuItem();
+  JRadioButtonMenuItem hydroMenuItem = new JRadioButtonMenuItem();
+  JRadioButtonMenuItem helixMenuItem = new JRadioButtonMenuItem();
+  JRadioButtonMenuItem strandMenuItem = new JRadioButtonMenuItem();
+  JRadioButtonMenuItem turnMenuItem = new JRadioButtonMenuItem();
+  JRadioButtonMenuItem buriedMenuItem = new JRadioButtonMenuItem();
+  JRadioButtonMenuItem blosumMenuItem = new JRadioButtonMenuItem();
+  FlowLayout flowLayout1 = new FlowLayout();
+
+  public GColourKey()
+  {
+    try
+    {
+      jbInit();
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+
+    this.setJMenuBar( jMenuBar1 );
+    ButtonGroup colours = new ButtonGroup();
+    colours.add(clustalMenuItem);
+    colours.add(zappoMenuItem);
+    colours.add(taylorMenuItem);
+    colours.add(hydroMenuItem);
+    colours.add(helixMenuItem);
+    colours.add(strandMenuItem);
+    colours.add(turnMenuItem);
+    colours.add(buriedMenuItem);
+    colours.add(blosumMenuItem);
+
+  }
+  private void jbInit() throws Exception
+  {
+    menu.setBackground(new Color(212, 208, 255));
+    menu.setActionCommand("Color Scheme");
+    menu.setText("Zappo Colour Scheme");
+    clustalMenuItem.setBackground(new Color(212, 208, 255));
+    clustalMenuItem.setText("ClustalX ");
+    clustalMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        clustalMenuItem_actionPerformed(e);
+      }
+    });
+    zappoMenuItem.setBackground(new Color(212, 208, 255));
+    zappoMenuItem.setSelected(true);
+    zappoMenuItem.setText("Zappo");
+    zappoMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        zappoMenuItem_actionPerformed(e);
+      }
+    });
+    taylorMenuItem.setBackground(new Color(212, 208, 255));
+    taylorMenuItem.setText("Taylor");
+    taylorMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        taylorMenuItem_actionPerformed(e);
+      }
+    });
+    hydroMenuItem.setBackground(new Color(212, 208, 255));
+    hydroMenuItem.setText("Hydrophobicity");
+    hydroMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        hydroMenuItem_actionPerformed(e);
+      }
+    });
+    helixMenuItem.setBackground(new Color(212, 208, 255));
+    helixMenuItem.setText("Helix Propensity");
+    helixMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        helixMenuItem_actionPerformed(e);
+      }
+    });
+    strandMenuItem.setBackground(new Color(212, 208, 255));
+    strandMenuItem.setText("Strand Propensity");
+    strandMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        strandMenuItem_actionPerformed(e);
+      }
+    });
+    turnMenuItem.setBackground(new Color(212, 208, 255));
+    turnMenuItem.setText("Turn Propensity");
+    turnMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        turnMenuItem_actionPerformed(e);
+      }
+    });
+    buriedMenuItem.setBackground(new Color(212, 208, 255));
+    buriedMenuItem.setText("Buried Index");
+    buriedMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        buriedMenuItem_actionPerformed(e);
+      }
+    });
+    blosumMenuItem.setBackground(new Color(212, 208, 255));
+    blosumMenuItem.setText("Blosum62");
+    blosumMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        blosumMenuItem_actionPerformed(e);
+      }
+    });
+    this.getContentPane().setLayout(flowLayout1);
+    this.getContentPane().setBackground(new Color(212, 208, 255));
+    jMenuBar1.setBackground(new Color(212, 208, 255));
+    jMenuBar1.add(menu);
+    menu.add(clustalMenuItem);
+    menu.add(zappoMenuItem);
+    menu.add(taylorMenuItem);
+    menu.add(hydroMenuItem);
+    menu.add(helixMenuItem);
+    menu.add(strandMenuItem);
+    menu.add(turnMenuItem);
+    menu.add(buriedMenuItem);
+    menu.add(blosumMenuItem);
+
+  }
+
+  protected void clustalMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void zappoMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void taylorMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void hydroMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void helixMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void strandMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void turnMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void buriedMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void blosumMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+
+
+
+
+
+
+
+}
diff --git a/src/jalview/jbgui/GCutAndPasteTransfer.java b/src/jalview/jbgui/GCutAndPasteTransfer.java
new file mode 100755 (executable)
index 0000000..6922fd3
--- /dev/null
@@ -0,0 +1,82 @@
+/********************
+ * 2004 Jalview Reengineered
+ * Barton Group
+ * Dundee University
+ *
+ * AM Waterhouse
+ *******************/
+
+package jalview.jbgui;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+
+
+public class GCutAndPasteTransfer extends JPanel
+{
+  protected JTextArea textarea = new JTextArea();
+  protected JComboBox formatChoice = new JComboBox();
+  protected JLabel formatLabel = new JLabel();
+  protected JScrollPane scrollPane = new JScrollPane();
+  public GCutAndPasteTransfer()
+  {
+    try
+    {
+      jbInit();
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+
+  }
+  private void jbInit() throws Exception
+  {
+    textarea.setFont(new java.awt.Font("Verdana", 0, 12));
+    textarea.setBorder(BorderFactory.createLineBorder(Color.black));
+    textarea.setText("Paste your alignment file here");
+    textarea.addMouseListener(new java.awt.event.MouseAdapter()
+    {
+      public void mousePressed(MouseEvent e)
+      {
+        textarea_mousePressed(e);
+      }
+    });
+    formatChoice.setFont(new java.awt.Font("Verdana", 0, 12));
+    formatChoice.setBounds(new Rectangle(194, 269, 159, 22));
+    formatChoice.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        formatChoice_actionPerformed(e);
+      }
+    });
+    formatLabel.setFont(new java.awt.Font("Verdana", 0, 12));
+    formatLabel.setHorizontalAlignment(SwingConstants.TRAILING);
+    formatLabel.setText("Alignment Format");
+    formatLabel.setBounds(new Rectangle(76, 272, 110, 16));
+    this.setLayout(null);
+    this.setPreferredSize(new Dimension(400, 300));
+    scrollPane.setBounds(new Rectangle(5, 5, 389, 256));
+    this.add(formatLabel, null);
+    this.add(formatChoice, null);
+    this.add(scrollPane, null);
+    scrollPane.getViewport().add(textarea, null);
+
+  }
+
+
+
+  protected void formatChoice_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  void textarea_mousePressed(MouseEvent e)
+  {
+    if(textarea.getText().equals("Paste your alignment file here"))
+      textarea.setText("");
+  }
+
+}
diff --git a/src/jalview/jbgui/GDesktop.java b/src/jalview/jbgui/GDesktop.java
new file mode 100755 (executable)
index 0000000..475153d
--- /dev/null
@@ -0,0 +1,145 @@
+/********************
+ * 2004 Jalview Reengineered
+ * Barton Group
+ * Dundee University
+ *
+ * AM Waterhouse
+ *******************/
+
+package jalview.jbgui;
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.*;
+
+
+public class GDesktop extends JFrame
+{
+  JMenuBar DesktopMenubar = new JMenuBar();
+  JMenu FileMenu = new JMenu();
+  JMenu HelpMenu = new JMenu();
+  JMenuItem inputLocalFileMenuItem = new JMenuItem();
+  JMenuItem inputURLMenuItem = new JMenuItem();
+  JMenuItem inputTextboxMenuItem = new JMenuItem();
+  JMenuItem quit = new JMenuItem();
+  JMenuItem aboutMenuItem = new JMenuItem();
+  JMenuItem documentationMenuItem = new JMenuItem();
+  JMenuItem colourIndexMenuItem = new JMenuItem();
+  FlowLayout flowLayout1 = new FlowLayout();
+  protected static JMenu windowMenu = new JMenu();
+  public GDesktop()
+  {
+    try
+    {
+      jbInit();
+      this.setJMenuBar(DesktopMenubar);
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+
+  }
+  private void jbInit() throws Exception
+  {
+    FileMenu.setMnemonic('F');
+    FileMenu.setText("File");
+    HelpMenu.setText("Help");
+    inputLocalFileMenuItem.setMnemonic('L');
+    inputLocalFileMenuItem.setText("Input Alignment From Local File");
+    inputLocalFileMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        inputLocalFileMenuItem_actionPerformed(e);
+      }
+    });
+    inputURLMenuItem.setMnemonic('U');
+    inputURLMenuItem.setText("Input Alignment From URL");
+    inputURLMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        inputURLMenuItem_actionPerformed(e);
+      }
+    });
+    inputTextboxMenuItem.setMnemonic('T');
+    inputTextboxMenuItem.setText("Input Alignment via Textbox");
+    inputTextboxMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        inputTextboxMenuItem_actionPerformed(e);
+      }
+    });
+    quit.setMnemonic('Q');
+    quit.setText("Quit");
+    quit.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        quit_actionPerformed(e);
+      }
+    });
+    aboutMenuItem.setText("About");
+    aboutMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        aboutMenuItem_actionPerformed(e);
+      }
+    });
+    documentationMenuItem.setText("Documentation");
+    documentationMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        documentationMenuItem_actionPerformed(e);
+      }
+    });
+    colourIndexMenuItem.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        colourIndexMenuItem_actionPerformed(e);
+      }
+    });
+    colourIndexMenuItem.setText("Colour Scheme Key");
+    this.getContentPane().setLayout(flowLayout1);
+    windowMenu.setText("Window");
+    DesktopMenubar.add(FileMenu);
+    DesktopMenubar.add(HelpMenu);
+    DesktopMenubar.add(windowMenu);
+    FileMenu.add(inputLocalFileMenuItem);
+    FileMenu.add(inputURLMenuItem);
+    FileMenu.add(inputTextboxMenuItem);
+    FileMenu.addSeparator();
+    FileMenu.add(quit);
+    HelpMenu.add(colourIndexMenuItem);
+    HelpMenu.add(aboutMenuItem);
+    HelpMenu.add(documentationMenuItem);
+  }
+
+  protected void inputLocalFileMenuItem_actionPerformed(ActionEvent e)
+  { }
+
+  protected void inputURLMenuItem_actionPerformed(ActionEvent e)
+  {  }
+
+  protected void inputTextboxMenuItem_actionPerformed(ActionEvent e)
+  { }
+
+  protected void quit_actionPerformed(ActionEvent e)
+  {  }
+
+  protected void aboutMenuItem_actionPerformed(ActionEvent e)
+  { }
+
+  protected void documentationMenuItem_actionPerformed(ActionEvent e)
+  {  }
+
+  protected void colourIndexMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+}
diff --git a/src/jalview/jbgui/GPCAPanel.java b/src/jalview/jbgui/GPCAPanel.java
new file mode 100755 (executable)
index 0000000..717c817
--- /dev/null
@@ -0,0 +1,97 @@
+package jalview.jbgui;
+
+import java.awt.*;
+import javax.swing.*;
+import java.awt.event.*;
+
+public class GPCAPanel extends JPanel
+{
+  JPanel jPanel2 = new JPanel();
+  JLabel jLabel1 = new JLabel();
+  JLabel jLabel2 = new JLabel();
+  JLabel jLabel3 = new JLabel();
+  protected JComboBox xCombobox = new JComboBox();
+  protected JComboBox yCombobox = new JComboBox();
+  protected JComboBox zCombobox = new JComboBox();
+  FlowLayout flowLayout1 = new FlowLayout();
+  BorderLayout borderLayout1 = new BorderLayout();
+
+  public GPCAPanel()
+  {
+    try
+    {
+      jbInit();
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+
+    for(int i=1; i<8; i++)
+    {
+      xCombobox.addItem("dim "+i);
+      yCombobox.addItem("dim "+i);
+      zCombobox.addItem("dim "+i);
+    }
+  }
+  private void jbInit() throws Exception
+  {
+    this.setLayout(borderLayout1);
+    jPanel2.setLayout(flowLayout1);
+    jLabel1.setFont(new java.awt.Font("Verdana", 0, 12));
+    jLabel1.setText("x=");
+    jLabel2.setFont(new java.awt.Font("Verdana", 0, 12));
+    jLabel2.setText("y=");
+    jLabel3.setFont(new java.awt.Font("Verdana", 0, 12));
+    jLabel3.setText("z=");
+    jPanel2.setBackground(Color.white);
+    jPanel2.setBorder(null);
+    zCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
+    zCombobox.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        zCombobox_actionPerformed(e);
+      }
+    });
+    yCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
+    yCombobox.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        yCombobox_actionPerformed(e);
+      }
+    });
+    xCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
+    xCombobox.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        xCombobox_actionPerformed(e);
+      }
+    });
+    this.add(jPanel2,  BorderLayout.SOUTH);
+    jPanel2.add(jLabel1, null);
+    jPanel2.add(xCombobox, null);
+    jPanel2.add(jLabel2, null);
+    jPanel2.add(yCombobox, null);
+    jPanel2.add(jLabel3, null);
+    jPanel2.add(zCombobox, null);
+  }
+
+  protected void xCombobox_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void yCombobox_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void zCombobox_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+}
diff --git a/src/jalview/jbgui/GPairwiseAlignPanel.java b/src/jalview/jbgui/GPairwiseAlignPanel.java
new file mode 100755 (executable)
index 0000000..77c0d79
--- /dev/null
@@ -0,0 +1,53 @@
+package jalview.jbgui;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+
+
+public class GPairwiseAlignPanel extends JPanel
+{
+  protected JScrollPane scrollPane = new JScrollPane();
+  protected JTextArea textarea = new JTextArea();
+  protected JButton viewInEditorButton = new JButton();
+  JPanel jPanel1 = new JPanel();
+  BorderLayout borderLayout1 = new BorderLayout();
+
+  public GPairwiseAlignPanel()
+  {
+    try
+    {
+      jbInit();
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+  private void jbInit() throws Exception
+  {
+    this.setLayout(borderLayout1);
+    textarea.setFont(new java.awt.Font("Monospaced", 0, 12));
+    textarea.setText("");
+    textarea.setWrapStyleWord(false);
+    viewInEditorButton.setFont(new java.awt.Font("Verdana", 0, 12));
+    viewInEditorButton.setText("View in alignment editor");
+    viewInEditorButton.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        viewInEditorButton_actionPerformed(e);
+      }
+    });
+    this.add(scrollPane, BorderLayout.CENTER);
+    scrollPane.getViewport().add(textarea, null);
+    this.add(jPanel1, BorderLayout.SOUTH);
+    jPanel1.add(viewInEditorButton, null);
+  }
+
+  protected void viewInEditorButton_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+}
diff --git a/src/jalview/jbgui/GTreePanel.java b/src/jalview/jbgui/GTreePanel.java
new file mode 100755 (executable)
index 0000000..43ee7c9
--- /dev/null
@@ -0,0 +1,108 @@
+package jalview.jbgui;
+
+import java.awt.*;
+import javax.swing.*;
+import java.awt.event.*;
+
+public class GTreePanel extends JPanel
+{
+  BorderLayout borderLayout1 = new BorderLayout();
+  JPanel jPanel1 = new JPanel();
+  JLabel jLabel1 = new JLabel();
+  protected JComboBox fontSizeCombobox = new JComboBox();
+  protected JCheckBox showDistanceCheckbox = new JCheckBox();
+  protected JButton saveButton = new JButton();
+  protected JCheckBox bootStrapCheckBox = new JCheckBox();
+  protected JScrollPane scrollPane = new JScrollPane();
+
+  public GTreePanel()
+  {
+    try
+    {
+      jbInit();
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+
+    for(int i=2; i<26; i+=2)
+       fontSizeCombobox.addItem(i+"");
+    fontSizeCombobox.setSelectedItem("12");
+
+  }
+  private void jbInit() throws Exception
+  {
+    this.setLayout(borderLayout1);
+    jLabel1.setFont(new java.awt.Font("Verdana", 0, 12));
+    jLabel1.setText("Font size");
+    showDistanceCheckbox.setFont(new java.awt.Font("Verdana", 0, 12));
+    showDistanceCheckbox.setText("Show distances");
+    showDistanceCheckbox.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        showDistanceCheckbox_actionPerformed(e);
+      }
+    });
+    saveButton.setFont(new java.awt.Font("Verdana", 0, 12));
+    saveButton.setToolTipText("");
+    saveButton.setText("Save as postscript");
+    saveButton.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        saveButton_actionPerformed(e);
+      }
+    });
+    this.setBackground(Color.white);
+    this.setFont(new java.awt.Font("Verdana", 0, 12));
+    this.setMinimumSize(new Dimension(530, 60));
+    fontSizeCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
+    fontSizeCombobox.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        fontSizeCombobox_actionPerformed(e);
+      }
+    });
+    bootStrapCheckBox.setFont(new java.awt.Font("Verdana", 0, 12));
+    bootStrapCheckBox.setText("Show bootstrap");
+    bootStrapCheckBox.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        bootStrapCheckBox_actionPerformed(e);
+      }
+    });
+    scrollPane.setOpaque(false);
+    this.add(jPanel1, BorderLayout.SOUTH);
+    jPanel1.add(jLabel1, null);
+    jPanel1.add(fontSizeCombobox, null);
+    jPanel1.add(showDistanceCheckbox, null);
+    jPanel1.add(bootStrapCheckBox, null);
+    jPanel1.add(saveButton, null);
+    this.add(scrollPane, BorderLayout.CENTER);
+  }
+
+
+  public void saveButton_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  public void showDistanceCheckbox_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  public void fontSizeCombobox_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  public void bootStrapCheckBox_actionPerformed(ActionEvent e)
+  {
+
+  }
+}
diff --git a/src/jalview/jbgui/GUserDefinedColours.java b/src/jalview/jbgui/GUserDefinedColours.java
new file mode 100755 (executable)
index 0000000..9086c39
--- /dev/null
@@ -0,0 +1,121 @@
+package jalview.jbgui;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+
+
+public class GUserDefinedColours extends JPanel
+{
+  protected JColorChooser colorChooser = new JColorChooser();
+  protected JPanel buttonPanel = new JPanel();
+  protected GridLayout gridLayout = new GridLayout();
+  JPanel jPanel2 = new JPanel();
+  protected JButton okButton = new JButton();
+  protected JButton applyButton = new JButton();
+  protected JButton loadbutton = new JButton();
+  protected JButton savebutton = new JButton();
+  protected JButton cancelButton = new JButton();
+  FlowLayout flowLayout1 = new FlowLayout();
+
+  public GUserDefinedColours()
+  {
+    try
+    {
+      jbInit();
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+  private void jbInit() throws Exception
+  {
+    this.setLayout(flowLayout1);
+    buttonPanel.setLayout(gridLayout);
+    gridLayout.setColumns(6);
+    gridLayout.setRows(4);
+    okButton.setFont(new java.awt.Font("Verdana", 0, 11));
+    okButton.setText("OK");
+    okButton.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        okButton_actionPerformed(e);
+      }
+    });
+    applyButton.setFont(new java.awt.Font("Verdana", 0, 11));
+    applyButton.setText("Apply");
+    applyButton.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        applyButton_actionPerformed(e);
+      }
+    });
+    loadbutton.setFont(new java.awt.Font("Verdana", 0, 11));
+    loadbutton.setText("Load scheme");
+    loadbutton.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        loadbutton_actionPerformed(e);
+      }
+    });
+    savebutton.setFont(new java.awt.Font("Verdana", 0, 11));
+    savebutton.setText("Save scheme");
+    savebutton.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        savebutton_actionPerformed(e);
+      }
+    });
+    cancelButton.setFont(new java.awt.Font("Verdana", 0, 11));
+    cancelButton.setText("Cancel");
+    cancelButton.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        cancelButton_actionPerformed(e);
+      }
+    });
+    this.setBackground(new Color(212, 208, 223));
+    jPanel2.setOpaque(false);
+    colorChooser.setOpaque(false);
+    this.add(colorChooser, null);
+    this.add(buttonPanel, null);
+     this.add(jPanel2, null);
+    jPanel2.add(okButton, null);
+    jPanel2.add(applyButton, null);
+    jPanel2.add(loadbutton, null);
+    jPanel2.add(savebutton, null);
+    jPanel2.add(cancelButton, null);
+  }
+
+
+  protected void okButton_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void applyButton_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void loadbutton_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void savebutton_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  protected void cancelButton_actionPerformed(ActionEvent e)
+  {
+
+  }
+}
diff --git a/src/jalview/math/Matrix.java b/src/jalview/math/Matrix.java
new file mode 100755 (executable)
index 0000000..d08fe22
--- /dev/null
@@ -0,0 +1,572 @@
+package jalview.math;\r
+\r
+import jalview.util.*;\r
+\r
+import java.io.*;\r
+\r
+public class Matrix {\r
+\r
+  /**\r
+   * SMJSPUBLIC\r
+   */\r
+  public double[][] value;\r
+  public int rows;\r
+  public int cols;\r
+  public double[] d;  // Diagonal\r
+  public double[] e;  // off diagonal\r
+\r
+  public Matrix(double[][] value, int rows, int cols) {\r
+    this.rows = rows;\r
+    this.cols = cols;\r
+    this.value = value;\r
+  }\r
+\r
+  public Matrix transpose() {\r
+    double[][] out = new double[cols][rows];\r
+\r
+    for (int i = 0; i < cols; i++) {\r
+      for (int j = 0; j < rows ; j++) {\r
+        out[i][j] = value[j][i];\r
+      }\r
+    }\r
+    return new Matrix(out,cols,rows);\r
+  }\r
+\r
+  public void print(PrintStream ps) {\r
+\r
+    for (int i = 0; i < rows; i++) {\r
+      for (int j = 0; j < cols; j++) {\r
+        Format.print(ps,"%8.2f",value[i][j]);\r
+      }\r
+      ps.println();\r
+    }\r
+  }\r
+\r
+\r
+  public Matrix  preMultiply(Matrix in) {\r
+    double[][] tmp = new double[in.rows][this.cols];\r
+\r
+    for (int i = 0; i < in.rows; i++) {\r
+      for (int j = 0; j < this.cols; j++ ) {\r
+        tmp[i][j] = 0.0;\r
+\r
+        for (int k = 0; k < in.cols; k++) {\r
+          tmp[i][j] += in.value[i][k]*this.value[k][j];\r
+        }\r
+\r
+      }\r
+    }\r
+\r
+    return new Matrix(tmp,in.rows,this.cols);\r
+  }\r
+\r
+  public double[] vectorPostMultiply(double[] in) {\r
+    double[] out = new double[in.length];\r
+    for (int i = 0; i < in.length; i++) {\r
+      out[i] = 0.0;\r
+      for (int k=0; k < in.length; k++) {\r
+        out[i] += value[i][k] * in[k];\r
+      }\r
+    }\r
+    return out;\r
+  }\r
+  public Matrix postMultiply(Matrix in) {\r
+\r
+    double[][] out = new double[this.rows][in.cols];\r
+    for (int i = 0; i < this.rows; i++) {\r
+      for (int j = 0; j < in.cols; j++ ) {\r
+\r
+        out[i][j] = 0.0;\r
+\r
+        for (int k = 0; k < rows; k++) {\r
+          out[i][j] = out[i][j] + value[i][k]*in.value[k][j];\r
+        }\r
+\r
+      }\r
+    }\r
+    return new Matrix(out,this.cols,in.rows);\r
+  }\r
+\r
+  public Matrix copy() {\r
+    double[][] newmat = new double[rows][cols];\r
+\r
+    for (int i = 0; i < rows; i++) {\r
+      for (int j = 0; j < cols; j++) {\r
+        newmat[i][j] = value[i][j];\r
+      }\r
+    }\r
+    return new Matrix(newmat,rows,cols);\r
+  }\r
+\r
+  public void tred() {\r
+    int n = rows;\r
+    int l;\r
+    int k;\r
+    int j;\r
+    int i;\r
+\r
+    double scale;\r
+    double hh;\r
+    double h;\r
+    double g;\r
+    double f;\r
+\r
+    this.d = new double[rows];\r
+    this.e = new double[rows];\r
+\r
+    for (i=n; i >= 2;i--) {\r
+      l=i-1;\r
+      h = 0.0;\r
+      scale = 0.0;\r
+\r
+      if (l > 1) {\r
+        for (k=1;k<=l;k++) {\r
+          scale += Math.abs(value[i-1][k-1]);\r
+        }\r
+        if (scale == 0.0) {\r
+          e[i-1] = value[i-1][l-1];\r
+        } else {\r
+          for (k=1; k <= l; k++) {\r
+            value[i-1][k-1] /= scale;\r
+            h += value[i-1][k-1]*value[i-1][k-1];\r
+          }\r
+          f = value[i-1][l-1];\r
+          if (f>0) {\r
+            g = -1.0*Math.sqrt(h);\r
+          } else {\r
+            g = Math.sqrt(h);\r
+          }\r
+          e[i-1] = scale*g;\r
+          h -= f*g;\r
+          value[i-1][l-1] = f-g;\r
+          f=0.0;\r
+          for (j=1; j <= l; j++) {\r
+            value[j-1][i-1] = value[i-1][j-1]/h;\r
+            g=0.0;\r
+            for (k= 1; k <= j; k++) {\r
+              g += value[j-1][k-1]*value[i-1][k-1];\r
+            }\r
+            for (k=j+1; k<=l;k++) {\r
+              g+= value[k-1][j-1]*value[i-1][k-1];\r
+            }\r
+            e[j-1] = g/h;\r
+            f+=e[j-1]*value[i-1][j-1];\r
+          }\r
+          hh=f/(h+h);\r
+          for (j=1;j<=l;j++) {\r
+            f=value[i-1][j-1];\r
+            g = e[j-1] - hh*f;\r
+            e[j-1] = g;\r
+            for (k=1;k<=j;k++) {\r
+              value[j-1][k-1] -= (f*e[k-1]+g*value[i-1][k-1]);\r
+            }\r
+          }\r
+        }\r
+      } else {\r
+        e[i-1] = value[i-1][l-1];\r
+      }\r
+      d[i-1] = h;\r
+    }\r
+    d[0] = 0.0;\r
+    e[0] = 0.0;\r
+    for (i=1;i<=n;i++) {\r
+      l=i-1;\r
+      if (d[i-1] != 0.0) {\r
+        for (j=1;j<=l;j++) {\r
+          g=0.0;\r
+          for (k=1;k<=l;k++) {\r
+            g+= value[i-1][k-1]*value[k-1][j-1];\r
+          }\r
+          for (k=1;k<=l;k++) {\r
+            value[k-1][j-1] -= g*value[k-1][i-1];\r
+          }\r
+        }\r
+      }\r
+      d[i-1] = value[i-1][i-1];\r
+      value[i-1][i-1] = 1.0;\r
+      for (j=1;j<=l;j++) {\r
+        value[j-1][i-1] = 0.0;\r
+        value[i-1][j-1] = 0.0;\r
+      }\r
+    }\r
+  }\r
+\r
+  public void tqli() {\r
+    int n = rows;\r
+\r
+    int m;\r
+    int l;\r
+    int iter;\r
+    int i;\r
+    int k;\r
+    double s;\r
+    double r;\r
+    double p;\r
+    ;\r
+    double g;\r
+    double f;\r
+    double dd;\r
+    double c;\r
+    double b;\r
+\r
+    for (i=2;i<=n;i++) {\r
+      e[i-2] = e[i-1];\r
+    }\r
+    e[n-1] = 0.0;\r
+    for (l=1;l<=n;l++) {\r
+      iter=0;\r
+      do {\r
+        for (m=l;m<=(n-1);m++) {\r
+          dd=Math.abs(d[m-1]) + Math.abs(d[m]);\r
+          if (Math.abs(e[m-1]) + dd == dd)\r
+            break;\r
+        }\r
+        if (m != l) {\r
+          iter++;\r
+          if (iter == 30) {\r
+            System.out.print("Too many iterations in tqli");\r
+            System.exit(0);\r
+          } else {\r
+            //     System.out.println("Iteration " + iter);\r
+          }\r
+          g=(d[l]-d[l-1])/(2.0*e[l-1]);\r
+          r = Math.sqrt((g*g) + 1.0);\r
+          g=d[m-1]-d[l-1]+e[l-1]/(g + sign(r,g));\r
+          c = 1.0;\r
+          s = c;\r
+          p=0.0;\r
+          for (i=m-1;i>=l;i--) {\r
+            f = s*e[i-1];\r
+            b = c*e[i-1];\r
+            if (Math.abs(f) >= Math.abs(g)) {\r
+              c=g/f;\r
+              r = Math.sqrt((c*c)+1.0);\r
+              e[i] = f*r;\r
+              s = 1.0/r;\r
+              c *= s;\r
+            } else {\r
+              s=f/g;\r
+              r = Math.sqrt((s*s)+1.0);\r
+              e[i] = g*r;\r
+              c = 1.0/r;\r
+              s *= c;\r
+            }\r
+            g=d[i] -p;\r
+            r=(d[i-1]-g)*s + 2.0*c*b;\r
+            p=s*r;\r
+            d[i] = g + p;\r
+            g = c * r - b;\r
+            for (k=1; k <= n; k++) {\r
+              f=value[k-1][i];\r
+              value[k-1][i] = s*value[k-1][i-1] + c*f;\r
+              value[k-1][i-1] = c*value[k-1][i-1] - s*f;\r
+            }\r
+          }\r
+          d[l-1] = d[l-1] - p;\r
+          e[l-1] = g;\r
+          e[m-1] = 0.0;\r
+        }\r
+      } while ( m != l);\r
+    }\r
+  }\r
+  public void tred2() {\r
+    int n = rows;\r
+    int l;\r
+    int k;\r
+    int j;\r
+    int i;\r
+\r
+    double scale;\r
+    double hh;\r
+    double h;\r
+    double g;\r
+    double f;\r
+\r
+    this.d = new double[rows];\r
+    this.e = new double[rows];\r
+\r
+    for (i=n-1; i >= 1;i--) {\r
+      l=i-1;\r
+      h = 0.0;\r
+      scale = 0.0;\r
+\r
+      if (l > 0) {\r
+        for (k=0;k<l;k++) {\r
+          scale += Math.abs(value[i][k]);\r
+        }\r
+        if (scale == 0.0) {\r
+          e[i] = value[i][l];\r
+        } else {\r
+          for (k=0; k < l; k++) {\r
+            value[i][k] /= scale;\r
+            h += value[i][k]*value[i][k];\r
+          }\r
+          f = value[i][l];\r
+          if (f>0) {\r
+            g = -1.0*Math.sqrt(h);\r
+          } else {\r
+            g = Math.sqrt(h);\r
+          }\r
+          e[i] = scale*g;\r
+          h -= f*g;\r
+          value[i][l] = f-g;\r
+          f=0.0;\r
+          for (j=0; j < l; j++) {\r
+            value[j][i] = value[i][j]/h;\r
+            g=0.0;\r
+            for (k= 0; k < j; k++) {\r
+              g += value[j][k]*value[i][k];\r
+            }\r
+            for (k=j; k<l;k++) {\r
+              g+= value[k][j]*value[i][k];\r
+            }\r
+            e[j] = g/h;\r
+            f+=e[j]*value[i][j];\r
+          }\r
+          hh=f/(h+h);\r
+          for (j=0;j<l;j++) {\r
+            f=value[i][j];\r
+            g = e[j] - hh*f;\r
+            e[j] = g;\r
+            for (k=0;k<j;k++) {\r
+              value[j][k] -= (f*e[k]+g*value[i][k]);\r
+            }\r
+          }\r
+        }\r
+      } else {\r
+        e[i] = value[i][l];\r
+      }\r
+      d[i] = h;\r
+    }\r
+    d[0] = 0.0;\r
+    e[0] = 0.0;\r
+    for (i=0;i<n;i++) {\r
+      l=i-1;\r
+      if (d[i] != 0.0) {\r
+        for (j=0;j<l;j++) {\r
+          g=0.0;\r
+          for (k=0;k<l;k++) {\r
+            g+= value[i][k]*value[k][j];\r
+          }\r
+          for (k=0;k<l;k++) {\r
+            value[k][j] -= g*value[k][i];\r
+          }\r
+        }\r
+      }\r
+      d[i] = value[i][i];\r
+      value[i][i] = 1.0;\r
+      for (j=0;j<l;j++) {\r
+        value[j][i] = 0.0;\r
+        value[i][j] = 0.0;\r
+      }\r
+    }\r
+  }\r
+\r
+  public void tqli2() {\r
+    int n = rows;\r
+\r
+    int m;\r
+    int l;\r
+    int iter;\r
+    int i;\r
+    int k;\r
+    double s;\r
+    double r;\r
+    double p;\r
+    ;\r
+    double g;\r
+    double f;\r
+    double dd;\r
+    double c;\r
+    double b;\r
+\r
+    for (i=2;i<=n;i++) {\r
+      e[i-2] = e[i-1];\r
+    }\r
+    e[n-1] = 0.0;\r
+    for (l=1;l<=n;l++) {\r
+      iter=0;\r
+      do {\r
+        for (m=l;m<=(n-1);m++) {\r
+          dd=Math.abs(d[m-1]) + Math.abs(d[m]);\r
+          if (Math.abs(e[m-1]) + dd == dd)\r
+            break;\r
+        }\r
+        if (m != l) {\r
+          iter++;\r
+          if (iter == 30) {\r
+            System.out.print("Too many iterations in tqli");\r
+            System.exit(0);\r
+          } else {\r
+            //     System.out.println("Iteration " + iter);\r
+          }\r
+          g=(d[l]-d[l-1])/(2.0*e[l-1]);\r
+          r = Math.sqrt((g*g) + 1.0);\r
+          g=d[m-1]-d[l-1]+e[l-1]/(g + sign(r,g));\r
+          c = 1.0;\r
+          s = c;\r
+          p=0.0;\r
+          for (i=m-1;i>=l;i--) {\r
+            f = s*e[i-1];\r
+            b = c*e[i-1];\r
+            if (Math.abs(f) >= Math.abs(g)) {\r
+              c=g/f;\r
+              r = Math.sqrt((c*c)+1.0);\r
+              e[i] = f*r;\r
+              s = 1.0/r;\r
+              c *= s;\r
+            } else {\r
+              s=f/g;\r
+              r = Math.sqrt((s*s)+1.0);\r
+              e[i] = g*r;\r
+              c = 1.0/r;\r
+              s *= c;\r
+            }\r
+            g=d[i] -p;\r
+            r=(d[i-1]-g)*s + 2.0*c*b;\r
+            p=s*r;\r
+            d[i] = g + p;\r
+            g = c * r - b;\r
+            for (k=1; k <= n; k++) {\r
+              f=value[k-1][i];\r
+              value[k-1][i] = s*value[k-1][i-1] + c*f;\r
+              value[k-1][i-1] = c*value[k-1][i-1] - s*f;\r
+            }\r
+          }\r
+          d[l-1] = d[l-1] - p;\r
+          e[l-1] = g;\r
+          e[m-1] = 0.0;\r
+        }\r
+      } while ( m != l);\r
+    }\r
+  }\r
+\r
+  public double sign(double a, double b) {\r
+    if (b < 0) {\r
+      return -Math.abs(a);\r
+    } else {\r
+      return Math.abs(a);\r
+    }\r
+  }\r
+\r
+  public double[] getColumn(int n) {\r
+    double[] out  = new double[rows];\r
+    for (int i=0;i<rows;i++) {\r
+      out[i] = value[i][n];\r
+    }\r
+    return out;\r
+  }\r
+\r
+\r
+  public void printD(PrintStream ps) {\r
+\r
+    for (int j = 0; j < rows;j++) {\r
+      Format.print(ps,"%15.4e",d[j]);\r
+    }\r
+  }\r
+  public void printE(PrintStream ps) {\r
+\r
+    for (int j = 0; j < rows;j++) {\r
+      Format.print(ps,"%15.4e",e[j]);\r
+    }\r
+  }\r
+\r
+  public static void main(String[] args) {\r
+    int n = Integer.parseInt(args[0]);\r
+    double[][] in = new double[n][n];\r
+\r
+    for (int i = 0;i < n;i++) {\r
+      for (int j = 0; j < n; j++) {\r
+        in[i][j] = (double)Math.random();\r
+      }\r
+    }\r
+\r
+    Matrix origmat = new Matrix(in,n,n);\r
+    //    System.out.println(" --- Original matrix ---- ");\r
+    ///    origmat.print(System.out);\r
+    //System.out.println();\r
+\r
+    //System.out.println(" --- transpose matrix ---- ");\r
+    Matrix trans = origmat.transpose();\r
+    //trans.print(System.out);\r
+    //System.out.println();\r
+\r
+    //System.out.println(" --- OrigT * Orig ---- ");\r
+\r
+    Matrix symm = trans.postMultiply(origmat);\r
+    //symm.print(System.out);\r
+    //System.out.println();\r
+\r
+    // Copy the symmetric matrix for later\r
+    Matrix origsymm = symm.copy();\r
+\r
+\r
+    // This produces the tridiagonal transformation matrix\r
+    long tstart = System.currentTimeMillis();\r
+    symm.tred();\r
+    long tend = System.currentTimeMillis();\r
+    //System.out.println("Time take for tred = " + (tend-tstart) + "ms");\r
+    //System.out.println(" ---Tridiag transform matrix ---");\r
+    //symm.print(System.out);\r
+    //System.out.println();\r
+\r
+    //System.out.println(" --- D vector ---");\r
+    //symm.printD(System.out);\r
+    //System.out.println();\r
+    //System.out.println(" --- E vector ---");\r
+    //symm.printE(System.out);\r
+    //System.out.println();\r
+\r
+\r
+    // Now produce the diagonalization matrix\r
+    tstart = System.currentTimeMillis();\r
+    symm.tqli();\r
+    tend = System.currentTimeMillis();\r
+    //System.out.println("Time take for tqli = " + (tend-tstart) + " ms");\r
+\r
+    //System.out.println(" --- New diagonalization matrix ---");\r
+    //symm.print(System.out);\r
+    //System.out.println();\r
+\r
+    //System.out.println(" --- D vector ---");\r
+    //symm.printD(System.out);\r
+    //System.out.println();\r
+    //System.out.println(" --- E vector ---");\r
+    //symm.printE(System.out);\r
+    //System.out.println();\r
+\r
+    //System.out.println(" --- First eigenvector --- ");\r
+    //double[] eigenv = symm.getColumn(0);\r
+    //for (int i=0; i < eigenv.length;i++) {\r
+    //  Format.print(System.out,"%15.4f",eigenv[i]);\r
+    // }\r
+    //System.out.println();\r
+\r
+    //double[] neigenv = origsymm.vectorPostMultiply(eigenv);\r
+\r
+    //for (int i=0; i < neigenv.length;i++) {\r
+    //  Format.print(System.out,"%15.4f",neigenv[i]/symm.d[0]);\r
+    //}\r
+\r
+    //System.out.println();\r
+  }\r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/math/RotatableMatrix.java b/src/jalview/math/RotatableMatrix.java
new file mode 100755 (executable)
index 0000000..dfe09f1
--- /dev/null
@@ -0,0 +1,370 @@
+package jalview.math;\r
+\r
+\r
+\r
+public class RotatableMatrix {\r
+\r
+  float matrix[][];\r
+\r
+  float[] temp;\r
+\r
+  float[][] rot;\r
+\r
+\r
+\r
+  public RotatableMatrix(int rows, int cols) {\r
+\r
+    matrix = new float[rows][cols];\r
+\r
+    temp = new float[3];\r
+\r
+    rot = new float[3][3];\r
+\r
+  }\r
+\r
+\r
+\r
+  public void addElement(int i, int j, float value) {\r
+\r
+    matrix[i][j] = value;\r
+\r
+  }\r
+\r
+\r
+\r
+  public void print() {\r
+\r
+    System.out.println(matrix[0][0] + " " + matrix[0][1] + " " + matrix[0][2]);\r
+\r
+    System.out.println(matrix[1][0] + " " + matrix[1][1] + " " + matrix[1][2]);\r
+\r
+    System.out.println(matrix[2][0] + " " + matrix[2][1] + " " + matrix[2][2]);\r
+\r
+  }\r
+\r
+\r
+\r
+  public void rotate (float degrees, char axis) {\r
+\r
+\r
+\r
+    float costheta = (float)Math.cos(degrees*Math.PI/(float)180.0);\r
+\r
+    float sintheta = (float)Math.sin(degrees*Math.PI/(float)180.0);\r
+\r
+\r
+\r
+    if (axis == 'z') {\r
+\r
+\r
+\r
+      rot[0][0] = (float)costheta;\r
+\r
+      rot[0][1] = (float)-sintheta;\r
+\r
+      rot[0][2] = (float)0.0;\r
+\r
+\r
+\r
+      rot[1][0] = (float)sintheta;\r
+\r
+      rot[1][1] = (float)costheta;\r
+\r
+      rot[1][2] = (float)0.0;\r
+\r
+\r
+\r
+      rot[2][0] = (float)0.0;\r
+\r
+      rot[2][1] = (float)0.0;\r
+\r
+      rot[2][2] = (float)1.0;\r
+\r
+\r
+\r
+      preMultiply(rot);\r
+\r
+    }\r
+\r
+    if (axis == 'x') {\r
+\r
+      rot[0][0] = (float)1.0;\r
+\r
+      rot[0][1] = (float)0.0;\r
+\r
+      rot[0][2] = (float)0.0;\r
+\r
+\r
+\r
+      rot[1][0] = (float)0.0;\r
+\r
+      rot[1][1] = (float)costheta;\r
+\r
+      rot[1][2] = (float)sintheta;\r
+\r
+\r
+\r
+      rot[2][0] = (float)0.0;\r
+\r
+      rot[2][1] = (float)-sintheta;\r
+\r
+      rot[2][2] = (float)costheta;\r
+\r
+\r
+\r
+      preMultiply(rot);\r
+\r
+\r
+\r
+    }\r
+\r
+    if (axis == 'y') {\r
+\r
+      rot[0][0] = (float)costheta;\r
+\r
+      rot[0][1] = (float)0.0;\r
+\r
+      rot[0][2] = (float)-sintheta;\r
+\r
+\r
+\r
+      rot[1][0] = (float)0.0;\r
+\r
+      rot[1][1] = (float)1.0;\r
+\r
+      rot[1][2] = (float)0.0;\r
+\r
+\r
+\r
+      rot[2][0] = (float)sintheta;\r
+\r
+      rot[2][1] = (float)0.0;\r
+\r
+      rot[2][2] = (float)costheta;\r
+\r
+\r
+\r
+      preMultiply(rot);\r
+\r
+\r
+\r
+    }\r
+\r
+\r
+\r
+  }\r
+\r
+\r
+\r
+  public float[] vectorMultiply(float[] vect) {\r
+\r
+    temp[0] = vect[0];\r
+\r
+    temp[1] = vect[1];\r
+\r
+    temp[2] = vect[2];\r
+\r
+\r
+\r
+    for (int i = 0; i < 3; i++) {\r
+\r
+      temp[i] = matrix[i][0]*vect[0] + matrix[i][1]*vect[1] + matrix[i][2]*vect[2];\r
+\r
+    }\r
+\r
+\r
+\r
+    vect[0] = temp[0];\r
+\r
+    vect[1] = temp[1];\r
+\r
+    vect[2] = temp[2];\r
+\r
+\r
+\r
+    return vect;\r
+\r
+  }\r
+\r
+\r
+\r
+  public void preMultiply(float mat[][]) {\r
+\r
+    float tmp[][]  = new float[3][3];\r
+\r
+\r
+\r
+    for (int i = 0; i < 3 ; i++) {\r
+\r
+      for (int j = 0; j < 3; j++ ) {\r
+\r
+        tmp[i][j] = mat[i][0]*matrix[0][j] +\r
+\r
+                    mat[i][1]*matrix[1][j] +\r
+\r
+                    mat[i][2]*matrix[2][j];\r
+\r
+      }\r
+\r
+    }\r
+\r
+\r
+\r
+    for (int i = 0; i < 3 ; i++) {\r
+\r
+      for (int j = 0; j < 3; j++ ) {\r
+\r
+        matrix[i][j] = tmp[i][j];\r
+\r
+      }\r
+\r
+    }\r
+\r
+  }\r
+\r
+\r
+\r
+  public void postMultiply(float mat[][]) {\r
+\r
+    float tmp[][]  = new float[3][3];\r
+\r
+\r
+\r
+    for (int i = 0; i < 3 ; i++) {\r
+\r
+      for (int j = 0; j < 3; j++ ) {\r
+\r
+        tmp[i][j] = matrix[i][0]*mat[0][j] +\r
+\r
+                    matrix[i][1]*mat[1][j] +\r
+\r
+                    matrix[i][2]*mat[2][j];\r
+\r
+      }\r
+\r
+    }\r
+\r
+\r
+\r
+    for (int i = 0; i < 3 ; i++) {\r
+\r
+      for (int j = 0; j < 3; j++ ) {\r
+\r
+        matrix[i][j] = tmp[i][j];\r
+\r
+      }\r
+\r
+    }\r
+\r
+  }\r
+\r
+\r
+\r
+  public static void main(String[] args) {\r
+\r
+\r
+\r
+    RotatableMatrix m = new  RotatableMatrix(3,3);\r
+\r
+    m.addElement(0,0,1);\r
+\r
+    m.addElement(0,1,0);\r
+\r
+    m.addElement(0,2,0);\r
+\r
+    m.addElement(1,0,0);\r
+\r
+    m.addElement(1,1,2);\r
+\r
+    m.addElement(1,2,0);\r
+\r
+    m.addElement(2,0,0);\r
+\r
+    m.addElement(2,1,0);\r
+\r
+    m.addElement(2,2,1);\r
+\r
+\r
+\r
+    m.print();\r
+\r
+\r
+\r
+    RotatableMatrix n = new  RotatableMatrix(3,3);\r
+\r
+    n.addElement(0,0,2);\r
+\r
+    n.addElement(0,1,1);\r
+\r
+    n.addElement(0,2,1);\r
+\r
+    n.addElement(1,0,2);\r
+\r
+    n.addElement(1,1,1);\r
+\r
+    n.addElement(1,2,1);\r
+\r
+    n.addElement(2,0,2);\r
+\r
+    n.addElement(2,1,1);\r
+\r
+    n.addElement(2,2,1);\r
+\r
+\r
+\r
+    n.print();\r
+\r
+\r
+\r
+    //m.postMultiply(n.matrix);\r
+\r
+    //m.print();\r
+\r
+    //     m.rotate(45,'z',new RotatableMatrix(3,3));\r
+\r
+\r
+\r
+    float vect[] = new float[3];\r
+\r
+    vect[0] = 2;\r
+\r
+    vect[1] = 4;\r
+\r
+    vect[2] = 6;\r
+\r
+\r
+\r
+    vect = m.vectorMultiply(vect);\r
+\r
+    System.out.println(vect[0] + " " + vect[1] + " " + vect[2]);\r
+\r
+\r
+\r
+  }\r
+\r
+  public void setIdentity() {\r
+\r
+    matrix[0][0] = (float)1.0;\r
+\r
+    matrix[1][1] = (float)1.0;\r
+\r
+    matrix[2][2] = (float)1.0;\r
+\r
+    matrix[0][1] = (float)0.0;\r
+\r
+    matrix[0][2] = (float)0.0;\r
+\r
+    matrix[1][0] = (float)0.0;\r
+\r
+    matrix[1][2] = (float) 0.0;\r
+\r
+    matrix[2][0] = (float)0.0;\r
+\r
+    matrix[2][1] = (float)0.0;\r
+\r
+  }\r
+\r
+}\r
+\r
+\r
+\r
diff --git a/src/jalview/schemes/Blosum62ColourScheme.java b/src/jalview/schemes/Blosum62ColourScheme.java
new file mode 100755 (executable)
index 0000000..d91d49f
--- /dev/null
@@ -0,0 +1,63 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.schemes;\r
+\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+import jalview.gui.*;\r
+import jalview.datamodel.*;\r
+\r
+public class Blosum62ColourScheme extends ResidueColourScheme\r
+{\r
+\r
+  // need to keep an eye on the changing visible consensus sequence\r
+  AlignViewport av;\r
+\r
+  public Blosum62ColourScheme(AlignViewport av)\r
+  {\r
+    super();\r
+    this.av = av;\r
+  }\r
+\r
+  public Color findColour(SequenceI seq, String s, int j, Vector aa)\r
+  {\r
+      if (!s.equals("-") && !s.equals(".") && !s.equals(" "))\r
+      {\r
+        String max = av.getVisibleConsensus().charAt(j) + "";\r
+\r
+        if (s.equals(max))\r
+          return new Color(154, 154, 255);\r
+        else if (ResidueProperties.getBLOSUM62(max, s) > 0)\r
+          return new Color(204, 204, 255);\r
+        else\r
+          return Color.white;\r
+\r
+      }\r
+      else\r
+        return Color.white;\r
+\r
+  }\r
+\r
+  public boolean canThreshold()\r
+  {\r
+    return false;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/schemes/BuriedColourScheme.java b/src/jalview/schemes/BuriedColourScheme.java
new file mode 100755 (executable)
index 0000000..66a9ce5
--- /dev/null
@@ -0,0 +1,15 @@
+package jalview.schemes;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class BuriedColourScheme extends ScoreColourScheme {\r
+\r
+  public BuriedColourScheme() {\r
+    super(ResidueProperties.buried,ResidueProperties.buriedmin,ResidueProperties.buriedmax);\r
+  }\r
+\r
+  public Color makeColour(float c) {\r
+    return new Color(0,(float)(1.0-c),c);\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/ClustalxColourScheme.java b/src/jalview/schemes/ClustalxColourScheme.java
new file mode 100755 (executable)
index 0000000..0479e5c
--- /dev/null
@@ -0,0 +1,247 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+/*\r
+package jalview.schemes;\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class ClustalxColourScheme implements ColourSchemeI\r
+{\r
+  Hashtable[] cons;\r
+  int[][] cons2;\r
+  ConsensusColour[] colours;\r
+  ConsensusColour[] ResidueColour;\r
+  int size;\r
+    Consensus[] conses = new Consensus[32];\r
+    public static Hashtable colhash = new Hashtable();\r
+\r
+    {\r
+        colhash.put("RED",new Color((float)0.9,(float)0.2,(float)0.1));\r
+        colhash.put("BLUE",new Color((float)0.5,(float)0.7,(float)0.9));\r
+        colhash.put("GREEN",new Color((float)0.1,(float)0.8,(float)0.1));\r
+        colhash.put("ORANGE",new Color((float)0.9,(float)0.6,(float)0.3));\r
+        colhash.put("CYAN",new Color((float)0.1,(float)0.7,(float)0.7));\r
+        colhash.put("PINK",new Color((float)0.9,(float)0.5,(float)0.5));\r
+        colhash.put("MAGENTA",new Color((float)0.8,(float)0.3,(float)0.8));\r
+        colhash.put("YELLOW",new Color((float)0.8,(float)0.8,(float)0.0));\r
+\r
+    }\r
+  Vector colourTable = new Vector();\r
+  public ClustalxColourScheme() {\r
+    this.cons2 = null;\r
+    this.size = 0;\r
+    makeColours();\r
+  }\r
+  public ClustalxColourScheme(int[][] cons2, int size) {\r
+    this.cons2 = cons2;\r
+    this.size = size;\r
+    makeColours();\r
+  }\r
+  public void makeColours() {\r
+    conses[0] = new Consensus("WLVIMAFCYHP",60);\r
+    conses[1] = new Consensus("WLVIMAFCYHP",80);\r
+    conses[2] = new Consensus("ED",50);\r
+    conses[3] = new Consensus("KR",60);\r
+    conses[4] = new Consensus("G",50);\r
+    conses[5] = new Consensus("N",50);\r
+    conses[6] = new Consensus("QE",50);\r
+    conses[7] = new Consensus("P",50);\r
+    conses[8] = new Consensus("TS",50);\r
+\r
+    conses[26] = new Consensus("A",85);\r
+    conses[27] = new Consensus("C",85);\r
+    conses[10] = new Consensus("E",85);\r
+    conses[11] = new Consensus("F",85);\r
+    conses[12] = new Consensus("G",85);\r
+    conses[13] = new Consensus("H",85);\r
+    conses[14] = new Consensus("I",85);\r
+    conses[15] = new Consensus("L",85);\r
+    conses[16] = new Consensus("M",85);\r
+    conses[17] = new Consensus("N",85);\r
+    conses[18] = new Consensus("P",85);\r
+    conses[19] = new Consensus("Q",85);\r
+    conses[20] = new Consensus("R",85);\r
+    conses[21] = new Consensus("S",85);\r
+    conses[22] = new Consensus("T",85);\r
+    conses[23] = new Consensus("V",85);\r
+    conses[24] = new Consensus("W",85);\r
+    conses[25] = new Consensus("Y",85);\r
+    conses[28] = new Consensus("K",85);\r
+    conses[29] = new Consensus("D",85);\r
+\r
+    conses[30] = new Consensus("G",0);\r
+    conses[31] = new Consensus("P",0);\r
+\r
+    // We now construct the colours\r
+    colours = new ConsensusColour[11];\r
+\r
+\r
+    Consensus[] tmp8 = new Consensus[1];\r
+    tmp8[0] = conses[30];//G\r
+    colours[7] =new ConsensusColour((Color)colhash.get("ORANGE"),tmp8);\r
+\r
+    Consensus[] tmp9 = new Consensus[1];\r
+    tmp9[0] = conses[31];//P\r
+    colours[8] =new ConsensusColour((Color)colhash.get("YELLOW"),tmp9);\r
+\r
+    Consensus[] tmp10 = new Consensus[1];\r
+    tmp10[0] = conses[27];//C\r
+    colours[9] =new ConsensusColour((Color)colhash.get("PINK"),tmp8);\r
+\r
+    Consensus[] tmp1 = new Consensus[14];\r
+    tmp1[0] = conses[0]; //%\r
+    tmp1[1] = conses[1]; //#\r
+    tmp1[2] = conses[26]; //A\r
+    tmp1[3] = conses[27]; //C\r
+    tmp1[4] = conses[11]; //F\r
+    tmp1[5] = conses[13]; //H\r
+    tmp1[6] = conses[14]; //I\r
+    tmp1[7] = conses[15]; //L\r
+    tmp1[8] = conses[16]; //M\r
+    tmp1[9] = conses[23]; //V\r
+    tmp1[10] = conses[24]; //W\r
+    tmp1[11] = conses[25]; //Y\r
+    tmp1[12] = conses[18]; //P\r
+    tmp1[13] = conses[19]; //p\r
+    colours[0] = new ConsensusColour((Color)colhash.get("BLUE"),tmp1);\r
+\r
+    colours[10] = new ConsensusColour((Color)colhash.get("CYAN"),tmp1);\r
+\r
+    Consensus[] tmp2 = new Consensus[5];\r
+    tmp2[0] = conses[8];  //t\r
+    tmp2[1] = conses[21]; //S\r
+    tmp2[2] = conses[22]; //T\r
+    tmp2[3] = conses[0];  //%\r
+    tmp2[4] = conses[1];  //#\r
+    colours[1] = new ConsensusColour((Color)colhash.get("GREEN"),tmp2);\r
+\r
+    Consensus[] tmp3 = new Consensus[3];\r
+\r
+    tmp3[0] = conses[17]; //N\r
+    tmp3[1] = conses[29]; //D\r
+    tmp3[2] = conses[5];  //n\r
+    colours[2] = new ConsensusColour((Color)colhash.get("GREEN"),tmp3);\r
+\r
+    Consensus[] tmp4 = new Consensus[6];\r
+    tmp4[0] = conses[6];  // q = QE\r
+    tmp4[1] = conses[19]; //Q\r
+    tmp4[2] = conses[22]; //E\r
+    tmp4[3] = conses[3];  //+\r
+    tmp4[4] = conses[28]; //K\r
+    tmp4[5] = conses[20]; //R\r
+    colours[3] = new ConsensusColour((Color)colhash.get("GREEN"),tmp4);\r
+    Consensus[] tmp5 = new Consensus[4];\r
+    tmp5[0] = conses[3];  //+\r
+    tmp5[1] = conses[28]; //K\r
+    tmp5[2] = conses[20]; //R\r
+    tmp5[3] = conses[19]; //Q\r
+    colours[4] = new ConsensusColour((Color)colhash.get("RED"),tmp5);\r
+    Consensus[] tmp6 = new Consensus[5];\r
+    tmp6[0] = conses[3];  //-\r
+    tmp6[1] = conses[29]; //D\r
+    tmp6[2] = conses[10]; //E\r
+    tmp6[3] = conses[6];  //q\r
+    tmp6[4] = conses[19]; //Q\r
+    colours[5] = new ConsensusColour((Color)colhash.get("MAGENTA"),tmp6);\r
+\r
+    Consensus[] tmp7 = new Consensus[5];\r
+    tmp7[0] = conses[3];  //-\r
+    tmp7[1] = conses[29]; //D\r
+    tmp7[2] = conses[10]; //E\r
+    tmp7[3] = conses[17];  //N\r
+    tmp7[4] = conses[2]; //DE\r
+    colours[6] = new ConsensusColour((Color)colhash.get("MAGENTA"),tmp7);\r
+\r
+    // Now attach the ConsensusColours to the residue letters\r
+    ResidueColour = new ConsensusColour[20];\r
+    ResidueColour[0] = colours[0]; // A\r
+    ResidueColour[1] = colours[4]; // R\r
+    ResidueColour[2] = colours[2]; // N\r
+    ResidueColour[3] = colours[6]; // D\r
+    ResidueColour[4] = colours[0]; // C\r
+    ResidueColour[5] = colours[3]; // Q\r
+    ResidueColour[6] = colours[5]; // E\r
+    ResidueColour[7] = colours[7]; // G\r
+    ResidueColour[8] = colours[10]; // H\r
+    ResidueColour[9] = colours[0]; // I\r
+    ResidueColour[10] = colours[0]; // L\r
+    ResidueColour[11] = colours[4]; // K\r
+    ResidueColour[12] = colours[0]; // M\r
+    ResidueColour[13] = colours[0]; // F\r
+    ResidueColour[14] = colours[8]; // P\r
+    ResidueColour[15] = colours[1]; // S\r
+    ResidueColour[16] = colours[1]; // T\r
+    ResidueColour[17] = colours[0]; // W\r
+    ResidueColour[18] = colours[10]; // Y\r
+    ResidueColour[19] = colours[0]; // V\r
+  }\r
+\r
+  public Color findColour(DrawableSequence seq, String s, int j) {\r
+    // System.out.println("Finding colour for " + s + " " + j);\r
+    int i = seq.num[j];\r
+    Color c = Color.white;\r
+    for (int k=0; k < ResidueColour[i].conses.length ; k++) {\r
+      if (ResidueColour[i].conses[k].isConserved(cons2,j,seq.num[j],size)) {\r
+        c =  ResidueColour[i].c;\r
+      }\r
+    }\r
+    if (i ==4) {\r
+      if (conses[27].isConserved(cons2,j,seq.num[j],size)) {\r
+        c = (Color)colhash.get("PINK");\r
+      }\r
+    }\r
+    return c;\r
+  }\r
+\r
+  public void setColours(DrawableSequence seq, int j) {\r
+    Color c = Color.white;\r
+\r
+    String s = seq.getSequence().substring(j,j+1);\r
+    try {\r
+      c = findColour(seq,s,j);\r
+      seq.setResidueBoxColour(j,c);\r
+    } catch (Exception e) {\r
+      seq.setResidueBoxColour(j,Color.white);\r
+    }\r
+  }\r
+\r
+  public void setColours(DrawableSequence s) {\r
+    for (int j = 0; j < s.sequence.length(); j++) {\r
+      setColours(s,j);\r
+    }\r
+  }\r
+\r
+  public void setColours(SequenceGroup sg) {\r
+    for (int j = 0; j < sg.sequences.size(); j++) {\r
+\r
+      DrawableSequence s = (DrawableSequence)sg.sequences.elementAt(j);\r
+      for (int i = 0; i < s.getSequence().length();i++) {\r
+        setColours(s,i);\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+}\r
+\r
+*/\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/schemes/ColourProperties.java b/src/jalview/schemes/ColourProperties.java
new file mode 100755 (executable)
index 0000000..ff2c6bc
--- /dev/null
@@ -0,0 +1,120 @@
+package jalview.schemes;\r
+\r
+import java.util.*;\r
+\r
+public class ColourProperties {\r
+\r
+  public static final int ZAPPO        = 0;\r
+  public static final int TAYLOR       = 1;\r
+  public static final int PID          = 2;\r
+  public static final int BLOSUM62     = 3;\r
+  public static final int SECONDARY    = 4;\r
+  public static final int USER         = 5;\r
+  public static final int HYDROPHOBIC  = 6;\r
+  public static final int CONSERVATION = 7;\r
+  public static final int HELIX        = 8;\r
+  public static final int STRAND       = 9;\r
+  public static final int TURN         = 10;\r
+  public static final int BURIED       = 11;\r
+  public static final int FEATURES     = 12;\r
+  public static final int CLUSTALX     = 13;\r
+\r
+  static ColourSchemePropertyVector colourSchemes = new ColourSchemePropertyVector();\r
+\r
+  static {\r
+    String prefix = getDefaultClassPrefix();\r
+\r
+    // MC 27/03/02 These should be read in from a file\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Zappo",\r
+                                              prefix + "ZappoColourScheme",\r
+                                              "Zappo colours"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Taylor",\r
+                                              prefix + "TaylorColourScheme",\r
+                                              "Taylor colours"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("PID",\r
+                                              prefix + "PIDColourScheme",\r
+                                              "By PID"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("BLOSUM62",\r
+                                              prefix + "Blosum62ColourScheme",\r
+                                              "By BLOSUM62 Score"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Secondary structure",\r
+                                              prefix + "SecondaryColourScheme",\r
+                                              "By Secondary Structure"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("User defined",\r
+                                              prefix + "ZappoColourScheme",\r
+                                              "User defined colours"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Hydrophobic",\r
+                                              prefix + "HydrophobicColourScheme",\r
+                                              "By Hydrophobicity"));\r
+\r
+   colourSchemes.add(new ColourSchemeProperty("Conservation",\r
+                                                   prefix + "ZappoColourScheme",\r
+                                                   null));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Helix",\r
+                                              prefix + "HelixColourScheme",\r
+                                              "Helix propensity"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Strand",\r
+                                              prefix + "StrandColourScheme",\r
+                                              "Strand propensity"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Turn",\r
+                                              prefix + "TurnColourScheme",\r
+                                              "Turn propensity"));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Buried",\r
+                                              prefix + "BuriedColourScheme",\r
+                                              "Buried index"));\r
+\r
+    //    colourSchemes.add(new ColourSchemeProperty("Features",\r
+    //                                               prefix + "FeatureColourScheme",\r
+    //                                               null));\r
+\r
+    colourSchemes.add(new ColourSchemeProperty("Clustalx",\r
+                                               prefix + "ClustalXColourScheme",\r
+                                               "ClustalX colours"));\r
+  }\r
+\r
+  static int indexOf(String scheme) {\r
+    if (colourSchemes.contains(scheme)) {\r
+      return colourSchemes.indexOf(scheme);\r
+    } else {\r
+      return -1;\r
+    }\r
+  }\r
+\r
+  static int indexOfClass(ColourSchemeI scheme) {\r
+    return colourSchemes.indexOfClass(scheme);\r
+  }\r
+\r
+  public static String getClassName(int index) {\r
+    return colourSchemes.getClassName(index);\r
+  }\r
+\r
+  public static String getMenuString(int index) {\r
+    return colourSchemes.getMenuString(index);\r
+  }\r
+\r
+  static boolean contains(String scheme) {\r
+    return colourSchemes.contains(scheme);\r
+  }\r
+\r
+  public static Vector getColourSchemeNames() {\r
+    return colourSchemes.getColourSchemeNames();\r
+  }\r
+\r
+  protected static String getDefaultClassPrefix() {\r
+    return "jalview.schemes.";\r
+  }\r
+}\r
+\r
+\r
+\r
diff --git a/src/jalview/schemes/ColourSchemeFactory.java b/src/jalview/schemes/ColourSchemeFactory.java
new file mode 100755 (executable)
index 0000000..7cc59b9
--- /dev/null
@@ -0,0 +1,29 @@
+package jalview.schemes;\r
+\r
+import java.lang.reflect.*;\r
+import java.util.*;\r
+\r
+public class ColourSchemeFactory {\r
+\r
+  public static ColourSchemeI get(int index) {\r
+    try {\r
+      System.out.println("Getting " + index);\r
+      String name = ColourProperties.getClassName(index);\r
+      System.out.println("Name " + name);\r
+      Class c = Class.forName(name);\r
+\r
+      return (ColourSchemeI)c.newInstance();\r
+    } catch (Exception e) {\r
+      System.err.println(e);\r
+      return null;\r
+    }\r
+  }\r
+\r
+  public static ColourSchemeI get(String scheme) {\r
+    return get(ColourProperties.indexOf(scheme));\r
+  }\r
+\r
+  public static int get(ColourSchemeI cs) {\r
+    return ColourProperties.indexOfClass(cs);\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/ColourSchemeI.java b/src/jalview/schemes/ColourSchemeI.java
new file mode 100755 (executable)
index 0000000..0c66da3
--- /dev/null
@@ -0,0 +1,18 @@
+package jalview.schemes;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.jbgui.*;\r
+import java.awt.*;\r
+import java.util.*;\r
+\r
+public interface ColourSchemeI\r
+{\r
+  public Color   findColour(String aa);\r
+  public Vector  getColours(SequenceI s, Vector aa);\r
+  public Color   getColour (SequenceI s, int pos, Vector aa);\r
+  public Vector  getColours(SequenceGroup sg, Vector aa);\r
+  public Color   findColour(SequenceI seq, String s,int j, Vector aa);\r
+\r
+  public boolean canThreshold();\r
+  public boolean isUserDefinable();\r
+}\r
diff --git a/src/jalview/schemes/ColourSchemeProperty.java b/src/jalview/schemes/ColourSchemeProperty.java
new file mode 100755 (executable)
index 0000000..518f7ab
--- /dev/null
@@ -0,0 +1,28 @@
+package jalview.schemes;\r
+\r
+public class ColourSchemeProperty {\r
+  String description;\r
+  String className;\r
+  String menuString = null;\r
+\r
+  public ColourSchemeProperty(String description, String className, String menuString) {\r
+    this.description = new String(description);\r
+    this.className   = new String(className);\r
+    if (menuString != null) {\r
+      this.menuString = new String(menuString);\r
+    }\r
+  }\r
+\r
+  public String getClassName() {\r
+    return className;\r
+  }\r
+  public String getDescription() {\r
+    return description;\r
+  }\r
+  public String getMenuString() {\r
+    return menuString;\r
+  }\r
+  public boolean isMenuItem() {\r
+    return (menuString != null);\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/ColourSchemePropertyVector.java b/src/jalview/schemes/ColourSchemePropertyVector.java
new file mode 100755 (executable)
index 0000000..0fb028b
--- /dev/null
@@ -0,0 +1,46 @@
+package jalview.schemes;\r
+\r
+import java.util.*;\r
+\r
+public class ColourSchemePropertyVector {\r
+  Vector schemeProps = new Vector();\r
+  Vector schemeDescs = new Vector();\r
+\r
+  public void add(ColourSchemeProperty prop) {\r
+    schemeProps.addElement(prop);\r
+    schemeDescs.addElement(prop.getDescription());\r
+  }\r
+  public Vector getColourSchemeNames() {\r
+    return schemeDescs;\r
+  }\r
+  public String getClassName(int ind) {\r
+    return get(ind).getClassName();\r
+  }\r
+  public String getMenuString(int ind) {\r
+    return get(ind).getMenuString();\r
+  }\r
+  public String getSchemeName(int ind) {\r
+    return get(ind).getDescription();\r
+  }\r
+  public boolean contains(String description) {\r
+    return schemeDescs.contains(description);\r
+  }\r
+  public int indexOf(String description) {\r
+    return schemeDescs.indexOf(description);\r
+  }\r
+  public ColourSchemeProperty get(int index) {\r
+    return (ColourSchemeProperty)schemeProps.elementAt(index);\r
+  }\r
+\r
+  public int indexOfClass(ColourSchemeI cs) {\r
+    if (cs != null) {\r
+      String className = cs.getClass().getName();\r
+      for (int i=0; i<schemeProps.size(); i++) {\r
+        if (get(i).getClassName().equals(className)) {\r
+          return i;\r
+        }\r
+      }\r
+    }\r
+    return -1;\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/HelixColourScheme.java b/src/jalview/schemes/HelixColourScheme.java
new file mode 100755 (executable)
index 0000000..7fdba76
--- /dev/null
@@ -0,0 +1,35 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.schemes;\r
+\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class HelixColourScheme extends ScoreColourScheme {\r
+\r
+\r
+  public HelixColourScheme() {\r
+    super(ResidueProperties.helix,ResidueProperties.helixmin,ResidueProperties.helixmax);\r
+  }\r
+\r
+  public Color makeColour(float c) {\r
+    return new Color(c,(float)1.0-c,c);\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/HydrophobicColourScheme.java b/src/jalview/schemes/HydrophobicColourScheme.java
new file mode 100755 (executable)
index 0000000..575d1b2
--- /dev/null
@@ -0,0 +1,32 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.schemes;\r
+\r
+import java.awt.*;\r
+\r
+public class HydrophobicColourScheme extends ScoreColourScheme {\r
+\r
+  public HydrophobicColourScheme() {\r
+    super(ResidueProperties.hyd,ResidueProperties.hydmin,ResidueProperties.hydmax);\r
+  }\r
+\r
+  public Color makeColour(float c) {\r
+    return new Color(c,(float)0.0,(float)1.0-c);\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/PIDColourScheme.java b/src/jalview/schemes/PIDColourScheme.java
new file mode 100755 (executable)
index 0000000..312ae7d
--- /dev/null
@@ -0,0 +1,61 @@
+package jalview.schemes;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.jbgui.*;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class PIDColourScheme extends ResidueColourScheme {\r
+    public Color[] pidColours;\r
+    public float[] thresholds;\r
+\r
+    SequenceGroup group;\r
+\r
+    public PIDColourScheme() {\r
+       this.pidColours = ResidueProperties.pidColours;\r
+       this.thresholds = ResidueProperties.pidThresholds;\r
+    }\r
+  public Color getColour(SequenceI seq, int j,Vector aa) {\r
+    Color c = Color.white;\r
+\r
+    String       s = seq.getSequence(j,j+1);\r
+\r
+    if (aa != null && j < aa.size()) {\r
+       c = findColour(seq,s,j,aa);\r
+    }\r
+\r
+    return c;\r
+  }\r
+\r
+  public Color findColour(SequenceI seq,String s, int j,Vector aa) {\r
+      Color     c    = Color.white;\r
+      Hashtable hash = null;\r
+\r
+      if (aa != null) {\r
+         hash = (Hashtable)aa.elementAt(j);\r
+      }\r
+      else\r
+        return c;\r
+\r
+      String    max  = (String)hash.get("maxResidue");\r
+\r
+      double sc = 0;\r
+      if (((Integer)hash.get("maxCount")).intValue() != -1  && hash.contains(s)) {\r
+         sc = ((Integer)hash.get(s)).intValue()*100.0/Integer.parseInt((String)hash.get("maxResidue"));\r
+\r
+         // MC Should be isGap\r
+         if  ( !s.equals("-")  && !s.equals(".") && !s.equals(" ")) {\r
+             for (int i=0; i < thresholds.length; i++) {\r
+                 if (sc > thresholds[i]) {\r
+                     c = pidColours[i];\r
+                     break;\r
+                 }\r
+             }\r
+         } else {\r
+             c = Color.white;\r
+         }\r
+      }\r
+      return c;\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/ResidueColourScheme.java b/src/jalview/schemes/ResidueColourScheme.java
new file mode 100755 (executable)
index 0000000..f90f475
--- /dev/null
@@ -0,0 +1,113 @@
+package jalview.schemes;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.jbgui.*;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class ResidueColourScheme implements ColourSchemeI {\r
+    Color    [] colors;\r
+    int         threshold = 90;\r
+\r
+    public ResidueColourScheme(Color[] colors, int threshold) {\r
+       this.colors    = colors;\r
+       this.threshold = threshold;\r
+    }\r
+\r
+    public ResidueColourScheme() {\r
+    }\r
+\r
+    public Color findColour(String aa)\r
+    {\r
+      return colors[((Integer)(ResidueProperties.aaHash.get(aa))).intValue()];\r
+    }\r
+\r
+    public Color findColour(SequenceI seq,String s, int j, Vector aa) {\r
+       try {\r
+           return colors[((Integer)(ResidueProperties.aaHash.get(s))).intValue()];\r
+       } catch (Exception e) {\r
+           return Color.white;\r
+       }\r
+    }\r
+\r
+    // aa should maybe be a class\r
+    public Color getColour(SequenceI seq, int j,Vector aa) {\r
+\r
+       Color  c       = Color.white;\r
+       String s       = seq.getSequence(j,j+1);\r
+\r
+       if (threshold > 0 && aa != null)\r
+        {\r
+           if (aboveThreshold(aa,seq,j,threshold))\r
+               c = findColour(seq,s,j,aa);\r
+       }\r
+        else\r
+           c = findColour(seq,s,j,aa);\r
+\r
+\r
+      return c;\r
+    }\r
+    public int getThreshold() {\r
+       return threshold;\r
+    }\r
+\r
+    public void setThreshold(int ct) {\r
+       threshold = ct;\r
+    }\r
+\r
+    public Vector  getColours(SequenceI s, Vector aa) {\r
+       Vector colours = new Vector();\r
+\r
+       for (int j = 0; j < s.getLength(); j++)\r
+           colours.addElement(getColour(s,j,aa));\r
+\r
+       return colours;\r
+    }\r
+\r
+    public Vector getColours(SequenceGroup sg, Vector aa) {\r
+       Vector colours = new Vector();\r
+\r
+       for (int j = 0; j < sg.getSize(); j++) {\r
+           SequenceI s = sg.getSequenceAt(j);\r
+\r
+           for (int i = 0; i < s.getLength();i++) {\r
+               colours.addElement(getColour(s,i,aa));\r
+           }\r
+       }\r
+       return colours;\r
+    }\r
+\r
+    public boolean aboveThreshold(Vector aa,SequenceI seq, int j, int threshold) {\r
+       String    s    = seq.getSequence(j,j+1);\r
+       Hashtable hash = (Hashtable)aa.elementAt(j);\r
+\r
+       if (j < aa.size()) {\r
+           String maxRes = (String)hash.get("maxResidue");\r
+\r
+           double sc = 0;\r
+\r
+           if (((Integer)hash.get("maxCount")).intValue() != -1  && hash.contains(s)) {\r
+               int maxCount = ((Integer)hash.get("maxCount")).intValue();\r
+               int resCount = ((Integer)hash.get(s)).intValue();\r
+\r
+               sc = resCount * 100.0 / resCount;\r
+\r
+               // This should be isGap somewhere\r
+               if  ( !s.equals("-")  && !s.equals(".") && !s.equals(" ")) {\r
+                   if (sc >= (double)threshold) {\r
+                       return true;\r
+                   }\r
+               }\r
+           }\r
+       }\r
+       return false;\r
+    }\r
+\r
+    public boolean canThreshold() {\r
+       return true;\r
+    }\r
+    public boolean isUserDefinable() {\r
+       return false;\r
+    }\r
+}\r
diff --git a/src/jalview/schemes/ResidueProperties.java b/src/jalview/schemes/ResidueProperties.java
new file mode 100755 (executable)
index 0000000..aa0297e
--- /dev/null
@@ -0,0 +1,995 @@
+\r
+/* Copyright (C) 1998  Michele Clamp\r
+*\r
+* This program is free software; you can redistribute it and/or\r
+* modify it under the terms of the GNU General Public License\r
+* as published by the Free Software Foundation; either version 2\r
+* of the License, or (at your option) any later version.\r
+*\r
+* This program is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with this program; if not, write to the Free Software\r
+* Foundation, Inc, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+*/\r
+package jalview.schemes;\r
+\r
+import java.awt.Color;\r
+import java.util.*;\r
+import jalview.jbgui.*;\r
+import jalview.datamodel.*;\r
+\r
+public class ResidueProperties {\r
+\r
+  //Stores residue codes/names and colours and other things\r
+  public static Hashtable aaHash = new Hashtable();  // stores the number value of the aa\r
+  public static Hashtable aa3Hash = new Hashtable();\r
+  public static Hashtable aa2Triplet = new Hashtable();\r
+\r
+  static {\r
+    aaHash.put("A", new Integer(0));\r
+    aaHash.put("R", new Integer(1));\r
+    aaHash.put("N", new Integer(2));\r
+    aaHash.put("D", new Integer(3));\r
+    aaHash.put("C", new Integer(4));\r
+    aaHash.put("Q", new Integer(5));\r
+    aaHash.put("E", new Integer(6));\r
+    aaHash.put("G", new Integer(7));\r
+    aaHash.put("H", new Integer(8));\r
+    aaHash.put("I", new Integer(9));\r
+    aaHash.put("L", new Integer(10));\r
+    aaHash.put("K", new Integer(11));\r
+    aaHash.put("M", new Integer(12));\r
+    aaHash.put("F", new Integer(13));\r
+    aaHash.put("P", new Integer(14));\r
+    aaHash.put("S", new Integer(15));\r
+    aaHash.put("T", new Integer(16));\r
+    aaHash.put("W", new Integer(17));\r
+    aaHash.put("Y", new Integer(18));\r
+    aaHash.put("V", new Integer(19));\r
+    aaHash.put("B", new Integer(20));\r
+    aaHash.put("Z", new Integer(21));\r
+    aaHash.put("X", new Integer(22));\r
+    aaHash.put("-", new Integer(23));\r
+    aaHash.put("*", new Integer(23));\r
+    aaHash.put(".", new Integer(23));\r
+    aaHash.put(" ", new Integer(23));\r
+  }\r
+\r
+  // These numbers should correspond to the indices in the Color hashes\r
+  public static Hashtable aaSpecialsHash = new Hashtable();\r
+  static {\r
+    aaSpecialsHash.put("-", new Integer(23));\r
+    aaSpecialsHash.put("*", new Integer(24));\r
+    aaSpecialsHash.put(".", new Integer(25));\r
+    aaSpecialsHash.put(" ", new Integer(26));\r
+  }\r
+\r
+  static {\r
+    aa3Hash.put("ALA", new Integer(0));\r
+    aa3Hash.put("ARG", new Integer(1));\r
+    aa3Hash.put("ASN", new Integer(2));\r
+    aa3Hash.put("ASP", new Integer(3)); //D\r
+    aa3Hash.put("CYS", new Integer(4));\r
+    aa3Hash.put("GLN", new Integer(5)); //Q\r
+    aa3Hash.put("GLU", new Integer(6));   // E\r
+    aa3Hash.put("GLY", new Integer(7));\r
+    aa3Hash.put("HIS", new Integer(8));\r
+    aa3Hash.put("ILE", new Integer(9));\r
+    aa3Hash.put("LEU", new Integer(10));\r
+    aa3Hash.put("LYS", new Integer(11));\r
+    aa3Hash.put("MET", new Integer(12));\r
+    aa3Hash.put("PHE", new Integer(13));\r
+    aa3Hash.put("PRO", new Integer(14));\r
+    aa3Hash.put("SER", new Integer(15));\r
+    aa3Hash.put("THR", new Integer(16));\r
+    aa3Hash.put("TRP", new Integer(17));\r
+    aa3Hash.put("TYR", new Integer(18));\r
+    aa3Hash.put("VAL", new Integer(19));\r
+    aa3Hash.put("B", new Integer(20));\r
+    aa3Hash.put("Z", new Integer(21));\r
+    aa3Hash.put("X", new Integer(22));\r
+    aa3Hash.put("-", new Integer(23));\r
+    aa3Hash.put("*", new Integer(23));\r
+    aa3Hash.put(".", new Integer(23));\r
+    aa3Hash.put(" ", new Integer(23));\r
+  }\r
+\r
+  static{\r
+     aa2Triplet.put("A", "ALA");\r
+     aa2Triplet.put("R", "ARG");\r
+     aa2Triplet.put("N", "ASN");\r
+     aa2Triplet.put("D", "ASP");\r
+     aa2Triplet.put("C", "CYS");\r
+     aa2Triplet.put("Q", "GLN");\r
+     aa2Triplet.put("E", "GLU");\r
+     aa2Triplet.put("G", "GLY");\r
+     aa2Triplet.put("H", "HIS");\r
+     aa2Triplet.put("I", "ILE");\r
+     aa2Triplet.put("L", "LEU");\r
+     aa2Triplet.put("K", "LYS");\r
+     aa2Triplet.put("M", "MET");\r
+     aa2Triplet.put("F", "PHE");\r
+     aa2Triplet.put("P", "PRO");\r
+     aa2Triplet.put("S", "SER");\r
+     aa2Triplet.put("T", "THR");\r
+     aa2Triplet.put("W", "TRP");\r
+     aa2Triplet.put("Y", "TYR");\r
+     aa2Triplet.put("V", "VAL");\r
+  }\r
+\r
+  public static String aa[] = {\r
+    "A","R","N","D","C","Q","E","G","H","I","L","K","M","F","P","S","T","W","Y","V","B","Z","X","_","*","."," "\r
+  };\r
+  public static Color midBlue = new Color(100,100,255);\r
+  public static Vector scaleColours = new Vector();\r
+  static {\r
+    scaleColours.addElement(new Color(114,0,147));\r
+    scaleColours.addElement(new Color(156,0,98));\r
+    scaleColours.addElement(new Color(190,0,0));\r
+    scaleColours.addElement(Color.red);\r
+    scaleColours.addElement(new Color(255,125,0));\r
+    scaleColours.addElement(Color.orange);\r
+    scaleColours.addElement(new Color(255,194,85));\r
+    scaleColours.addElement(Color.yellow);\r
+    scaleColours.addElement(new Color(255,255,181));\r
+    scaleColours.addElement(Color.white);\r
+  }\r
+\r
+  public static Color[] taylor = {\r
+    new Color(204,255,0),          // A  Greenish-yellowy-yellow\r
+    new Color(0,0,255),            // R  Blueish-bluey-blue\r
+    new Color(204,0,255),          // N  Blueish-reddy-blue\r
+    new Color(255,0,0),            // D  Reddish-reddy-red\r
+    new Color(255,255,0),          // C  Yellowish-yellowy-yellow\r
+    new Color(255,0,204),          // Q  Reddish-bluey-red\r
+    new Color(255,0,102),          // E  Blueish-reddy-red\r
+    new Color(255,153,0),          // G  Yellowy-reddy-yellow\r
+    new Color(0,102,255),          // H  Greenish-bluey-blue\r
+    new Color(102,255,0),          // I  Greenish-yellowy-green\r
+    new Color(51,255,0),           // L  Yellowish-greeny-green\r
+    new Color(102,0,255),          // K  Reddish-bluey-blue\r
+    new Color(0,255,0),            // M  Greenish-greeny-green\r
+    new Color(0,255,102),          // F  Blueish-greeny-green\r
+    new Color(255,204,0),          // P  Reddish-yellowy-yellow\r
+    new Color(255,51,0),           // S  Yellowish-reddy-red\r
+    new Color(255,102,0),          // T  Reddish-yellowy-red\r
+    new Color(0,204,255),          // W  Blueish-greeny-green\r
+    new Color(0,255,204),          // Y  Greenish-bluey-green\r
+    new Color(153,255,0),          // V  Yellowish-greeny-yellow\r
+    Color.white,         // B\r
+    Color.white,         // Z\r
+    Color.white,         // X\r
+    Color.white,         // -\r
+    Color.white,         // *\r
+    Color.white          // .\r
+  };\r
+\r
+  public static Color[] color = {\r
+    Color.pink,          // A\r
+    midBlue,             // R\r
+    Color.green,         // N\r
+    Color.red,           // D\r
+    Color.yellow,        // C\r
+    Color.green,         // Q\r
+    Color.red,           // E\r
+    Color.magenta,       // G\r
+    Color.red,           // H\r
+    Color.pink,          // I\r
+    Color.pink,          // L\r
+    midBlue,             // K\r
+    Color.pink,          // M\r
+    Color.orange,        // F\r
+    Color.magenta,       // P\r
+    Color.green,         // S\r
+    Color.green,         // T\r
+    Color.orange,        // W\r
+    Color.orange,        // Y\r
+    Color.pink,          // V\r
+    Color.white,         // B\r
+    Color.white,         // Z\r
+    Color.white,         // X\r
+    Color.white,         // -\r
+    Color.white,         // *\r
+    Color.white,          // .\r
+    Color.white          // ' '\r
+  };\r
+\r
+  // Dunno where I got these numbers from\r
+  public static double[] hyd2 = {\r
+    0.62,  //A\r
+    0.29,  //R\r
+    -0.90,  //N\r
+    -0.74,  //D\r
+    1.19,  //C\r
+    0.48,  //Q\r
+    -0.40, //E\r
+    1.38,  //G\r
+    -1.50, //H\r
+    1.06,  //I\r
+    0.64,  //L\r
+    -0.78, //K\r
+    0.12,  //M\r
+    -0.85, //F\r
+    -2.53, //P\r
+    -0.18, //S\r
+    -0.05, //T\r
+    1.08,  //W\r
+    0.81,  //Y\r
+    0.0,   //V\r
+    0.26,  //B\r
+    0.0,   //Z\r
+    0.0   //X\r
+  };\r
+  public static double[] helix = {\r
+    1.42,\r
+    0.98,\r
+    0.67,\r
+    1.01,\r
+    0.70,\r
+    1.11,\r
+    1.51,\r
+    0.57,\r
+    1.00,\r
+    1.08,\r
+    1.21,\r
+    1.16,\r
+    1.45,\r
+    1.13,\r
+    0.57,\r
+    0.77,\r
+    0.83,\r
+    1.08,\r
+    0.69,\r
+    1.06,\r
+    0.84,\r
+    1.31,\r
+    1.00,\r
+    0.0\r
+  };\r
+  public static double helixmin = 0.57;\r
+  public static double helixmax = 1.51;\r
+\r
+  public static double[] strand = {\r
+    0.83,0.93,0.89,0.54,1.19,1.10,0.37,\r
+    0.75,0.87,1.60,1.30,0.74,1.05,1.38,0.55,\r
+    0.75,1.19,1.37,1.47,1.70,0.72,0.74,1.0,0.0};\r
+\r
+  public static double strandmin = 0.37;\r
+  public static double strandmax = 1.7;\r
+\r
+  public static double[] turn = {\r
+    0.66,0.95,1.56,1.46,1.19,0.98,0.74,\r
+    1.56,0.95,0.47,0.59,1.01,0.60,0.60,1.52,\r
+    1.43,0.96,0.96,1.14,0.50,1.51,0.86,1.00,0,0};\r
+\r
+  public static double turnmin = 0.47;\r
+  public static double turnmax = 1.56;\r
+\r
+  public static double[] buried = {\r
+    1.7,\r
+    0.1,\r
+    0.4,\r
+    0.4,\r
+    4.6,\r
+    0.3,\r
+    0.3,\r
+    1.8,\r
+    0.8,\r
+    3.1,\r
+    2.4,\r
+    0.05,\r
+    1.9,\r
+    2.2,\r
+    0.6,\r
+    0.8,0.7,1.6,0.5,2.9,0.4,0.3,\r
+    1.358,\r
+    0.00\r
+  };\r
+\r
+  public static double buriedmin = 0.05;\r
+  public static double buriedmax = 4.6;\r
+\r
+  // This is hydropathy index\r
+  // Kyte, J., and Doolittle, R.F., J. Mol. Biol.\r
+  // 1157, 105-132, 1982\r
+\r
+  public static double hyd[] = {\r
+    1.8,\r
+    -4.5,\r
+    -3.5,\r
+    -3.5,\r
+    2.5,\r
+    -3.5,\r
+    -3.5,\r
+    -0.4,\r
+    -3.2,\r
+    4.5,\r
+    3.8,\r
+    -3.9,\r
+    1.9,\r
+    2.8,\r
+    -1.6,\r
+    -0.8,\r
+    -0.7,\r
+    -0.9,\r
+    -1.3,\r
+    4.2,\r
+    -3.5,\r
+    -3.5,\r
+    -0.49,\r
+    0.0\r
+  };\r
+\r
+  public static final double hydmax = 4.5;\r
+  public static final double hydmin = -3.9;\r
+\r
+  public static double getHydmax() {\r
+    return hydmax;\r
+  }\r
+  public static double getHydmin() {\r
+    return hydmin;\r
+  }\r
+  public static double[] getHyd() {\r
+    return hyd;\r
+  }\r
+  //public static final double hydmax = 1.38;\r
+  //public static final double hydmin = -2.53;\r
+\r
+  static final int[][] BLOSUM62 = {\r
+    //A   R   N   D   C   Q   E   G   H   I   L   K   M   F   P   S   T   W   Y   V   B   Z   X  -\r
+    { 4 ,-1, -2 ,-2 , 0 ,-1 ,-1 , 0 ,-2 ,-1 ,-1 ,-1 ,-1 ,-2 ,-1 , 1 , 0 ,-3 ,-2 , 0 ,-2, -1 , 0 ,-4},\r
+    {-1 , 5 , 0 ,-2 ,-3 , 1 , 0 ,-2 , 0 ,-3 ,-2 , 2 ,-1 ,-3 ,-2 ,-1 ,-1 ,-3 ,-2 ,-3 ,-1 , 0 ,-1 ,-4 },\r
+    {-2 , 0 , 6 , 1 ,-3 , 0 , 0 , 0 , 1 ,-3 ,-3 , 0 ,-2 ,-3 ,-2 , 1 , 0 ,-4 ,-2 ,-3 , 3 , 0 ,-1 ,-4 },\r
+    {-2 ,-2 , 1 , 6 ,-3 , 0 , 2 ,-1 ,-1 ,-3 ,-4 ,-1 ,-3 ,-3 ,-1 , 0 ,-1 ,-4 ,-3 ,-3 , 4 , 1 ,-1 ,-4 },\r
+    { 0 , 3 ,-3 ,-3 , 9 ,-3 ,-4 ,-3 ,-3 ,-1 ,-1 ,-3 ,-1 ,-2 ,-3 ,-1 ,-1 ,-2 ,-2 ,-1 ,-3 ,-3 ,-2 ,-4 },\r
+    {-1 , 1 , 0 , 0 ,-3 , 5 , 2 ,-2 , 0 ,-3 ,-2 , 1 , 0 ,-3 ,-1 , 0 ,-1 ,-2 ,-1 ,-2 , 0 , 3 ,-1 ,-4 },\r
+    {-1 , 0 , 0 , 2 ,-4 , 2 , 5 ,-2 , 0 ,-3 ,-3 , 1 ,-2 ,-3 ,-1 , 0 ,-1 ,-3 ,-2 ,-2 , 1 , 4 ,-1 ,-4 },\r
+    { 0 ,-2 , 0 ,-1 ,-3 ,-2 ,-2 , 6 ,-2 ,-4 ,-4 ,-2 ,-3 ,-3 ,-2 , 0 ,-2 ,-2 ,-3 ,-3 ,-1 ,-2 ,-1 ,-4 },\r
+    {-2 , 0 , 1 ,-1 ,-3 , 0 , 0 ,-2 , 8 ,-3 ,-3 ,-1 ,-2 ,-1 ,-2 ,-1 ,-2 ,-2 , 2 ,-3 , 0 , 0 ,-1 ,-4 },\r
+    {-1 ,-3 ,-3 ,-3 ,-1 ,-3 ,-3 ,-4 ,-3 , 4 , 2 ,-3 , 1 , 0 ,-3 ,-2 ,-1 ,-3 ,-1 , 3 ,-3 ,-3 ,-1 ,-4 },\r
+    {-1 ,-2 ,-3 ,-4 ,-1 ,-2 ,-3 ,-4 ,-3 , 2 , 4 ,-2 , 2 , 0 ,-3 ,-2 ,-1 ,-2 ,-1 , 1 ,-4 ,-3 ,-1 ,-4 },\r
+    {-1 , 2 , 0 ,-1 ,-3 , 1 , 1 ,-2 ,-1 ,-3 ,-2 , 5 ,-1 ,-3 ,-1 , 0 ,-1 ,-3 ,-2 ,-2 , 0 , 1 ,-1 ,-4 },\r
+    {-1 ,-1 ,-2 ,-3 ,-1 , 0 ,-2 ,-3 ,-2 , 1 , 2 ,-1 , 5 , 0 ,-2 ,-1 ,-1 ,-1 ,-1 , 1 ,-3 ,-1 ,-1 ,-4 },\r
+    {-2 ,-3 ,-3 ,-3 ,-2 ,-3 ,-3 ,-3 ,-1 , 0 , 0 ,-3 , 0 , 6 ,-4 ,-2 ,-2 , 1 , 3 ,-1 ,-3 ,-3 ,-1 ,-4 },\r
+    {-1 ,-2 ,-2 ,-1 ,-3 ,-1 ,-1 ,-2 ,-2 ,-3 ,-3 ,-1 ,-2 ,-4 , 7 ,-1 ,-1 ,-4 ,-3 ,-2 ,-2 ,-1 ,-2 ,-4 },\r
+    { 1 ,-1 , 1 , 0 ,-1 , 0 , 0 , 0 ,-1 ,-2 ,-2 , 0 ,-1 ,-2 ,-1 , 4 , 1 ,-3 ,-2 ,-2 , 0 , 0 , 0 ,-4 },\r
+    { 0 ,-1 , 0 ,-1 ,-1 ,-1 ,-1 ,-2 ,-2 ,-1 ,-1 ,-1 ,-1 ,-2 ,-1 , 1 , 5 ,-2 ,-2 , 0 ,-1 ,-1 , 0 ,-4 },\r
+    {-3 ,-3 ,-4 ,-4 ,-2 ,-2 ,-3 ,-2 ,-2 ,-3 ,-2 ,-3 ,-1 , 1 ,-4 ,-3 ,-2 ,11 , 2 ,-3 ,-4 ,-3 ,-2 ,-4 },\r
+    {-2 ,-2 ,-2 ,-3 ,-2 ,-1 ,-2 ,-3 , 2 ,-1 ,-1 ,-2 ,-1 , 3 ,-3 ,-2 ,-2 , 2 , 7 ,-1 ,-3 ,-2 ,-1 ,-4 },\r
+    { 0 ,-3 ,-3 ,-3 ,-1 ,-2 ,-2 ,-3 ,-3 , 3 , 1 ,-2 , 1 ,-1 ,-2 ,-2 , 0 ,-3 ,-1 , 4 ,-3 ,-2 ,-1 ,-4 },\r
+    {-2 ,-1 , 3 , 4 ,-3 , 0 , 1 ,-1 , 0 ,-3 ,-4 , 0 ,-3 ,-3 ,-2 , 0 ,-1 ,-4 ,-3 ,-3 , 4 , 1 ,-1 ,-4 },\r
+    {-1 , 0 , 0 , 1 ,-3 , 3 , 4 ,-2 , 0 ,-3 ,-3 , 1 ,-1 ,-3 ,-1 , 0 ,-1 ,-3 ,-2 ,-2 , 1 , 4 ,-1 ,-4 },\r
+    { 0 ,-1 ,-1 ,-1 ,-2 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-2 , 0 , 0 ,-2 ,-1 ,-1 ,-1 ,-1 ,-1 ,-4 },\r
+    {-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 ,-4 , 1 },\r
+  };\r
+  static final int[][] PAM250 = {\r
+    {  2,-2 ,0 ,0,-2 ,0 ,0 ,1,-1,-1,-2,-1,-1,-3 ,1 ,1 ,1,-6,-3 ,0 ,0 ,0 ,0,-8},\r
+    { -2 ,6 ,0,-1,-4 ,1,-1,-3 ,2,-2,-3 ,3 ,0,-4 ,0 ,0,-1 ,2,-4,-2,-1 ,0,-1,-8},\r
+    {  0 ,0 ,2 ,2,-4 ,1 ,1 ,0 ,2,-2,-3 ,1,-2,-3 ,0 ,1 ,0,-4,-2,-2 ,2 ,1 ,0,-8},\r
+    {  0,-1 ,2 ,4,-5 ,2 ,3 ,1 ,1,-2,-4 ,0,-3,-6,-1 ,0 ,0,-7,-4,-2 ,3 ,3,-1,-8},\r
+    { -2,-4,-4,-5,12,-5,-5,-3,-3,-2,-6,-5,-5,-4,-3 ,0,-2,-8 ,0,-2,-4,-5,-3,-8},\r
+    {  0 ,1 ,1 ,2,-5 ,4 ,2,-1 ,3,-2,-2 ,1,-1,-5 ,0,-1,-1,-5,-4,-2 ,1 ,3,-1,-8},\r
+    {  0,-1 ,1 ,3,-5 ,2 ,4 ,0 ,1,-2,-3 ,0,-2,-5,-1 ,0 ,0,-7,-4,-2 ,3 ,3,-1,-8},\r
+    {  1,-3 ,0 ,1,-3,-1 ,0 ,5,-2,-3,-4,-2,-3,-5 ,0 ,1 ,0,-7,-5,-1 ,0 ,0,-1,-8},\r
+    { -1 ,2 ,2 ,1,-3 ,3 ,1,-2 ,6,-2,-2 ,0,-2,-2 ,0,-1,-1,-3 ,0,-2 ,1 ,2,-1,-8},\r
+    { -1,-2,-2,-2,-2,-2,-2,-3,-2 ,5 ,2,-2 ,2 ,1,-2,-1 ,0,-5,-1 ,4,-2,-2,-1,-8},\r
+    { -2,-3,-3,-4,-6,-2,-3,-4,-2 ,2 ,6,-3 ,4 ,2,-3,-3,-2,-2,-1 ,2,-3,-3,-1,-8},\r
+    { -1 ,3 ,1 ,0,-5 ,1 ,0,-2 ,0,-2,-3 ,5 ,0,-5,-1 ,0 ,0,-3,-4,-2 ,1 ,0,-1,-8},\r
+    { -1 ,0,-2,-3,-5,-1,-2,-3,-2 ,2 ,4 ,0 ,6 ,0,-2,-2,-1,-4,-2 ,2,-2,-2,-1,-8},\r
+    { -3,-4,-3,-6,-4,-5,-5,-5,-2 ,1 ,2,-5 ,0 ,9,-5,-3,-3 ,0 ,7,-1,-4,-5,-2,-8},\r
+    {  1 ,0 ,0,-1,-3 ,0,-1 ,0 ,0,-2,-3,-1,-2,-5 ,6 ,1 ,0,-6,-5,-1,-1 ,0,-1,-8},\r
+    {  1 ,0 ,1 ,0 ,0,-1 ,0 ,1,-1,-1,-3 ,0,-2,-3 ,1 ,2 ,1,-2,-3,-1 ,0 ,0 ,0,-8},\r
+    {  1,-1 ,0 ,0,-2,-1 ,0 ,0,-1 ,0,-2 ,0,-1,-3 ,0 ,1 ,3,-5,-3 ,0 ,0,-1 ,0,-8},\r
+    { -6 ,2,-4,-7,-8,-5,-7,-7,-3,-5,-2,-3,-4 ,0,-6,-2,-5,17 ,0,-6,-5,-6,-4,-8},\r
+    { -3,-4,-2,-4 ,0,-4,-4,-5 ,0,-1,-1,-4,-2 ,7,-5,-3,-3 ,0,10,-2,-3,-4,-2,-8},\r
+    {  0,-2,-2,-2,-2,-2,-2,-1,-2 ,4 ,2,-2 ,2,-1,-1,-1 ,0,-6,-2 ,4,-2,-2,-1,-8},\r
+    {  0,-1 ,2 ,3,-4 ,1 ,3 ,0 ,1,-2,-3 ,1,-2,-4,-1 ,0 ,0,-5,-3,-2 ,3 ,2,-1,-8},\r
+    {  0 ,0 ,1 ,3,-5 ,3 ,3 ,0 ,2,-2,-3 ,0,-2,-5 ,0 ,0,-1,-6,-4,-2 ,2 ,3,-1,-8},\r
+    {  0,-1 ,0,-1,-3,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1 ,0 ,0,-4,-2,-1,-1,-1,-1,-8},\r
+    { -8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8 ,1},\r
+  };\r
+\r
+  public static Hashtable ssHash = new Hashtable();  // stores the number value of the aa\r
+\r
+  static {\r
+    ssHash.put("H", Color.magenta);\r
+    ssHash.put("E", Color.yellow);\r
+    ssHash.put("-", Color.white);\r
+    ssHash.put(".", Color.white);\r
+    ssHash.put("S", Color.cyan);\r
+    ssHash.put("T", Color.blue);\r
+    ssHash.put("G", Color.pink);\r
+    ssHash.put("I", Color.pink);\r
+    ssHash.put("B", Color.yellow);\r
+  }\r
+  static final int[][] DNA = {\r
+    //  C  T  A  G  -\r
+    { 5,-4,-4,-4, 1},// C\r
+    {-4, 5,-4,-4, 1},// T\r
+    {-4,-4, 5,-4, 1},// A\r
+    {-4,-4,-4, 5, 1},// G\r
+    { 1, 1, 1, 1, 1},// -\r
+  };\r
+  public static Hashtable getAAHash() {\r
+    return aaHash;\r
+  }\r
+  public static Hashtable getAA3Hash() {\r
+    return aa3Hash;\r
+  }\r
+  public static int[][] getDNA() {\r
+    return ResidueProperties.DNA;\r
+  }\r
+  public static int[][] getBLOSUM62() {\r
+    return ResidueProperties.BLOSUM62;\r
+  }\r
+  public static int getPAM250(String A1, String A2) {\r
+    Integer pog1  = (Integer)aaHash.get(A1);\r
+    Integer pog2  = (Integer)aaHash.get(A2);\r
+    int pog = ResidueProperties.PAM250[pog1.intValue()][pog2.intValue()];\r
+    return pog ;\r
+  }\r
+  public static int getBLOSUM62(String A1, String A2) {\r
+    int pog = 0;\r
+    try {\r
+      Integer pog1  = (Integer)aaHash.get(A1);\r
+      Integer pog2  = (Integer)aaHash.get(A2);\r
+      pog = ResidueProperties.BLOSUM62[pog1.intValue()][pog2.intValue()];\r
+    } catch (Exception e) {\r
+      //System.out.println("Unknown residue in " + A1 + " " + A2);\r
+    }\r
+    return pog ;\r
+  }\r
+\r
+  public static Color[] pidColours = {\r
+    midBlue,\r
+    new Color(153,153,255),\r
+    //    Color.lightGray,\r
+    new Color(204,204,255),\r
+  };\r
+  public static float[] pidThresholds = {\r
+    80,\r
+    60,\r
+    40,\r
+  } ;\r
+  private ResidueProperties() {}\r
+\r
+  public static Hashtable codonHash = new Hashtable();\r
+\r
+  public static Vector Lys = new Vector();\r
+  public static Vector Asn = new Vector();\r
+  public static Vector Gln = new Vector();\r
+  public static Vector His = new Vector();\r
+  public static Vector Glu = new Vector();\r
+  public static Vector Asp = new Vector();\r
+  public static Vector Tyr = new Vector();\r
+  public static Vector Thr = new Vector();\r
+  public static Vector Pro = new Vector();\r
+  public static Vector Ala = new Vector();\r
+  public static Vector Ser = new Vector();\r
+  public static Vector Arg = new Vector();\r
+  public static Vector Gly = new Vector();\r
+  public static Vector Trp = new Vector();\r
+  public static Vector Cys = new Vector();\r
+  public static Vector Ile = new Vector();\r
+  public static Vector Met = new Vector();\r
+  public static Vector Leu = new Vector();\r
+  public static Vector Val = new Vector();\r
+  public static Vector Phe = new Vector();\r
+  public static Vector STOP = new Vector();\r
+\r
+  static {\r
+    codonHash.put("K",Lys);\r
+    codonHash.put("N",Asn);\r
+    codonHash.put("Q",Gln);\r
+    codonHash.put("H",His);\r
+    codonHash.put("E",Glu);\r
+    codonHash.put("D",Asp);\r
+    codonHash.put("Y",Tyr);\r
+    codonHash.put("T",Thr);\r
+    codonHash.put("P",Pro);\r
+    codonHash.put("A",Ala);\r
+    codonHash.put("S",Ser);\r
+    codonHash.put("R",Arg);\r
+    codonHash.put("G",Gly);\r
+    codonHash.put("W",Trp);\r
+    codonHash.put("C",Cys);\r
+    codonHash.put("I",Ile);\r
+    codonHash.put("M",Met);\r
+    codonHash.put("L",Leu);\r
+    codonHash.put("V",Val);\r
+    codonHash.put("F",Phe);\r
+    codonHash.put("STOP",STOP);\r
+  }\r
+\r
+  public static Vector getCodons(String res) {\r
+    if (codonHash.containsKey(res))\r
+      return (Vector)codonHash.get(res);\r
+    return null;\r
+  }\r
+\r
+  public static String codonTranslate(String codon) {\r
+    Enumeration e = codonHash.keys();\r
+    while (e.hasMoreElements()) {\r
+      String key = (String)e.nextElement();\r
+      Vector tmp = (Vector)codonHash.get(key);\r
+      if (tmp.contains(codon)) {\r
+        return key;\r
+      }\r
+    }\r
+    return null;\r
+  }\r
+  public static Hashtable codonHash2 = new Hashtable();\r
+  static {\r
+    codonHash2.put("AAA","K");\r
+    codonHash2.put("AAG","K");\r
+    codonHash2.put("AAC","N");\r
+    codonHash2.put("AAT","N");\r
+\r
+    codonHash2.put("CAA","E");\r
+    codonHash2.put("CAG","E");\r
+    codonHash2.put("CAC","H");\r
+    codonHash2.put("CAT","H");\r
+\r
+    codonHash2.put("GAA","Q");\r
+    codonHash2.put("GAG","Q");\r
+    codonHash2.put("GAC","D");\r
+    codonHash2.put("GAT","D");\r
+\r
+    codonHash2.put("TAC","Y");\r
+    codonHash2.put("TAT","Y");\r
+\r
+    codonHash2.put("ACA","T");\r
+    codonHash2.put("AAG","T");\r
+    codonHash2.put("ACC","T");\r
+    codonHash2.put("ACT","T");\r
+\r
+    codonHash2.put("CCA","P");\r
+    codonHash2.put("CCG","P");\r
+    codonHash2.put("CCC","P");\r
+    codonHash2.put("CCT","P");\r
+\r
+    codonHash2.put("GCA","A");\r
+    codonHash2.put("GCG","A");\r
+    codonHash2.put("GCC","A");\r
+    codonHash2.put("GCT","A");\r
+\r
+    codonHash2.put("TCA","S");\r
+    codonHash2.put("TCG","S");\r
+    codonHash2.put("TCC","S");\r
+    codonHash2.put("TCT","S");\r
+    codonHash2.put("AGC","S");\r
+    codonHash2.put("AGT","S");\r
+\r
+    codonHash2.put("AGA","R");\r
+    codonHash2.put("AGG","R");\r
+    codonHash2.put("CGA","R");\r
+    codonHash2.put("CGG","R");\r
+    codonHash2.put("CGC","R");\r
+    codonHash2.put("CGT","R");\r
+\r
+    codonHash2.put("GGA","G");\r
+    codonHash2.put("GGG","G");\r
+    codonHash2.put("GGC","G");\r
+    codonHash2.put("GGT","G");\r
+\r
+    codonHash2.put("TGA","*");\r
+    codonHash2.put("TAA","*");\r
+    codonHash2.put("TAG","*");\r
+\r
+    codonHash2.put("TGG","W");\r
+\r
+    codonHash2.put("TGC","C");\r
+    codonHash2.put("TGT","C");\r
+\r
+    codonHash2.put("ATA","I");\r
+    codonHash2.put("ATC","I");\r
+    codonHash2.put("ATT","I");\r
+\r
+    codonHash2.put("ATG","M");\r
+\r
+    codonHash2.put("CTA","L");\r
+    codonHash2.put("CTG","L");\r
+    codonHash2.put("CTC","L");\r
+    codonHash2.put("CTT","L");\r
+    codonHash2.put("TTA","L");\r
+    codonHash2.put("TTG","L");\r
+\r
+    codonHash2.put("GTA","V");\r
+    codonHash2.put("GTG","V");\r
+    codonHash2.put("GTC","V");\r
+    codonHash2.put("GTT","V");\r
+\r
+    codonHash2.put("TTC","F");\r
+    codonHash2.put("TTT","F");\r
+\r
+  }\r
+\r
+  static {\r
+    Lys.addElement("AAA");\r
+    Lys.addElement("AAG");\r
+    Asn.addElement("AAC");\r
+    Asn.addElement("AAT");\r
+\r
+    Gln.addElement("CAA");\r
+    Gln.addElement("CAG");\r
+    His.addElement("CAC");\r
+    His.addElement("CAT");\r
+\r
+    Glu.addElement("GAA");\r
+    Glu.addElement("GAG");\r
+    Asp.addElement("GAC");\r
+    Asp.addElement("GAT");\r
+\r
+    Tyr.addElement("TAC");\r
+    Tyr.addElement("TAT");\r
+\r
+    Thr.addElement("ACA");\r
+    Thr.addElement("ACG");\r
+    Thr.addElement("ACC");\r
+    Thr.addElement("ACT");\r
+\r
+    Pro.addElement("CCA");\r
+    Pro.addElement("CCG");\r
+    Pro.addElement("CCC");\r
+    Pro.addElement("CCT");\r
+\r
+    Ala.addElement("GCA");\r
+    Ala.addElement("GCG");\r
+    Ala.addElement("GCC");\r
+    Ala.addElement("GCT");\r
+\r
+    Ser.addElement("TCA");\r
+    Ser.addElement("TCG");\r
+    Ser.addElement("TCC");\r
+    Ser.addElement("TCT");\r
+    Ser.addElement("AGC");\r
+    Ser.addElement("AGT");\r
+\r
+    Arg.addElement("AGA");\r
+    Arg.addElement("AGG");\r
+    Arg.addElement("CGA");\r
+    Arg.addElement("CGG");\r
+    Arg.addElement("CGC");\r
+    Arg.addElement("CGT");\r
+\r
+    Gly.addElement("GGA");\r
+    Gly.addElement("GGG");\r
+    Gly.addElement("GGC");\r
+    Gly.addElement("GGT");\r
+\r
+    STOP.addElement("TGA");\r
+    STOP.addElement("TAA");\r
+    STOP.addElement("TAG");\r
+\r
+    Trp.addElement("TGG");\r
+\r
+    Cys.addElement("TGC");\r
+    Cys.addElement("TGT");\r
+\r
+    Ile.addElement("ATA");\r
+    Ile.addElement("ATC");\r
+    Ile.addElement("ATT");\r
+\r
+    Met.addElement("ATG");\r
+\r
+    Leu.addElement("CTA");\r
+    Leu.addElement("CTG");\r
+    Leu.addElement("CTC");\r
+    Leu.addElement("CTT");\r
+    Leu.addElement("TTA");\r
+    Leu.addElement("TTG");\r
+\r
+    Val.addElement("GTA");\r
+    Val.addElement("GTG");\r
+    Val.addElement("GTC");\r
+    Val.addElement("GTT");\r
+\r
+    Phe.addElement("TTC");\r
+    Phe.addElement("TTT");\r
+  }\r
+\r
+  public static Color[][] groupColors = {\r
+    {Color.red,Color.red.brighter(),Color.red.brighter().brighter()},\r
+    {Color.orange,Color.orange.brighter(),Color.orange.brighter().brighter()},\r
+    {Color.green,Color.green.brighter(),Color.green.brighter().brighter()},\r
+    {Color.blue,Color.blue.brighter(),Color.blue.brighter().brighter()},\r
+    {Color.magenta,Color.magenta.brighter(),Color.magenta.brighter().brighter()},\r
+    {Color.cyan,Color.cyan.brighter(),Color.cyan.brighter().brighter()},\r
+    {Color.pink,Color.pink.brighter(),Color.pink.brighter().brighter()},\r
+\r
+  };\r
+\r
+\r
+\r
+  //Stores residue codes/names and colours and other things\r
+  public static Hashtable propHash = new Hashtable();\r
+  public static Hashtable hydrophobic = new Hashtable();\r
+  public static Hashtable polar = new Hashtable();\r
+  public static Hashtable small = new Hashtable();\r
+  public static Hashtable positive = new Hashtable();\r
+  public static Hashtable negative = new Hashtable();\r
+  public static Hashtable charged = new Hashtable();\r
+  public static Hashtable aromatic = new Hashtable();\r
+  public static Hashtable aliphatic = new Hashtable();\r
+  public static Hashtable tiny = new Hashtable();\r
+  public static Hashtable proline = new Hashtable();\r
+\r
+  static {\r
+    hydrophobic.put("I",new Integer(1));\r
+    hydrophobic.put("L",new Integer(1));\r
+    hydrophobic.put("V",new Integer(1));\r
+    hydrophobic.put("C",new Integer(1));\r
+    hydrophobic.put("A",new Integer(1));\r
+    hydrophobic.put("G",new Integer(1));\r
+    hydrophobic.put("M",new Integer(1));\r
+    hydrophobic.put("F",new Integer(1));\r
+    hydrophobic.put("Y",new Integer(1));\r
+    hydrophobic.put("W",new Integer(1));\r
+    hydrophobic.put("H",new Integer(1));\r
+    hydrophobic.put("K",new Integer(1));\r
+    hydrophobic.put("X",new Integer(1));\r
+    hydrophobic.put("-",new Integer(1));\r
+    hydrophobic.put("*",new Integer(1));\r
+    hydrophobic.put("R",new Integer(0));\r
+    hydrophobic.put("E",new Integer(0));\r
+    hydrophobic.put("Q",new Integer(0));\r
+    hydrophobic.put("D",new Integer(0));\r
+    hydrophobic.put("N",new Integer(0));\r
+    hydrophobic.put("S",new Integer(0));\r
+    hydrophobic.put("T",new Integer(0));\r
+    hydrophobic.put("P",new Integer(0));\r
+  }\r
+  static {\r
+    polar.put("Y",new Integer(1));\r
+    polar.put("W",new Integer(1));\r
+    polar.put("H",new Integer(1));\r
+    polar.put("K",new Integer(1));\r
+    polar.put("R",new Integer(1));\r
+    polar.put("E",new Integer(1));\r
+    polar.put("Q",new Integer(1));\r
+    polar.put("D",new Integer(1));\r
+    polar.put("N",new Integer(1));\r
+    polar.put("S",new Integer(1));\r
+    polar.put("T",new Integer(1));\r
+    polar.put("X",new Integer(1));\r
+    polar.put("-",new Integer(1));\r
+    polar.put("*",new Integer(1));\r
+    polar.put("I",new Integer(0));\r
+    polar.put("L",new Integer(0));\r
+    polar.put("V",new Integer(0));\r
+    polar.put("C",new Integer(0));\r
+    polar.put("A",new Integer(0));\r
+    polar.put("G",new Integer(0));\r
+    polar.put("M",new Integer(0));\r
+    polar.put("F",new Integer(0));\r
+    polar.put("P",new Integer(0));\r
+\r
+  }\r
+  static {\r
+    small.put("I",new Integer(0));\r
+    small.put("L",new Integer(0));\r
+    small.put("V",new Integer(1));\r
+    small.put("C",new Integer(1));\r
+    small.put("A",new Integer(1));\r
+    small.put("G",new Integer(1));\r
+    small.put("M",new Integer(0));\r
+    small.put("F",new Integer(0));\r
+    small.put("Y",new Integer(0));\r
+    small.put("W",new Integer(0));\r
+    small.put("H",new Integer(0));\r
+    small.put("K",new Integer(0));\r
+    small.put("R",new Integer(0));\r
+    small.put("E",new Integer(0));\r
+    small.put("Q",new Integer(0));\r
+    small.put("D",new Integer(1));\r
+    small.put("N",new Integer(1));\r
+    small.put("S",new Integer(1));\r
+    small.put("T",new Integer(1));\r
+    small.put("P",new Integer(1));\r
+    small.put("-",new Integer(1));\r
+    small.put("*",new Integer(1));\r
+  }\r
+  static {\r
+    positive.put("I",new Integer(0));\r
+    positive.put("L",new Integer(0));\r
+    positive.put("V",new Integer(0));\r
+    positive.put("C",new Integer(0));\r
+    positive.put("A",new Integer(0));\r
+    positive.put("G",new Integer(0));\r
+    positive.put("M",new Integer(0));\r
+    positive.put("F",new Integer(0));\r
+    positive.put("Y",new Integer(0));\r
+    positive.put("W",new Integer(0));\r
+    positive.put("H",new Integer(1));\r
+    positive.put("K",new Integer(1));\r
+    positive.put("R",new Integer(1));\r
+    positive.put("E",new Integer(0));\r
+    positive.put("Q",new Integer(0));\r
+    positive.put("D",new Integer(0));\r
+    positive.put("N",new Integer(0));\r
+    positive.put("S",new Integer(0));\r
+    positive.put("T",new Integer(0));\r
+    positive.put("P",new Integer(0));\r
+    positive.put("-",new Integer(1));\r
+    positive.put("*",new Integer(1));\r
+  }\r
+  static {\r
+    negative.put("I",new Integer(0));\r
+    negative.put("L",new Integer(0));\r
+    negative.put("V",new Integer(0));\r
+    negative.put("C",new Integer(0));\r
+    negative.put("A",new Integer(0));\r
+    negative.put("G",new Integer(0));\r
+    negative.put("M",new Integer(0));\r
+    negative.put("F",new Integer(0));\r
+    negative.put("Y",new Integer(0));\r
+    negative.put("W",new Integer(0));\r
+    negative.put("H",new Integer(0));\r
+    negative.put("K",new Integer(0));\r
+    negative.put("R",new Integer(0));\r
+    negative.put("E",new Integer(1));\r
+    negative.put("Q",new Integer(0));\r
+    negative.put("D",new Integer(1));\r
+    negative.put("N",new Integer(0));\r
+    negative.put("S",new Integer(0));\r
+    negative.put("T",new Integer(0));\r
+    negative.put("P",new Integer(0));\r
+    negative.put("-",new Integer(1));\r
+    negative.put("*",new Integer(1));\r
+  }\r
+  static {\r
+    charged.put("I",new Integer(0));\r
+    charged.put("L",new Integer(0));\r
+    charged.put("V",new Integer(0));\r
+    charged.put("C",new Integer(0));\r
+    charged.put("A",new Integer(0));\r
+    charged.put("G",new Integer(0));\r
+    charged.put("M",new Integer(0));\r
+    charged.put("F",new Integer(0));\r
+    charged.put("Y",new Integer(0));\r
+    charged.put("W",new Integer(0));\r
+    charged.put("H",new Integer(1));\r
+    charged.put("K",new Integer(1));\r
+    charged.put("R",new Integer(1));\r
+    charged.put("E",new Integer(1));\r
+    charged.put("Q",new Integer(0));\r
+    charged.put("D",new Integer(1));\r
+    charged.put("N",new Integer(1));\r
+    charged.put("S",new Integer(0));\r
+    charged.put("T",new Integer(0));\r
+    charged.put("P",new Integer(0));\r
+    charged.put("-",new Integer(1));\r
+    charged.put("*",new Integer(1));\r
+  }\r
+  static {\r
+    aromatic.put("I",new Integer(0));\r
+    aromatic.put("L",new Integer(0));\r
+    aromatic.put("V",new Integer(0));\r
+    aromatic.put("C",new Integer(0));\r
+    aromatic.put("A",new Integer(0));\r
+    aromatic.put("G",new Integer(0));\r
+    aromatic.put("M",new Integer(0));\r
+    aromatic.put("F",new Integer(1));\r
+    aromatic.put("Y",new Integer(1));\r
+    aromatic.put("W",new Integer(1));\r
+    aromatic.put("H",new Integer(1));\r
+    aromatic.put("K",new Integer(0));\r
+    aromatic.put("R",new Integer(0));\r
+    aromatic.put("E",new Integer(0));\r
+    aromatic.put("Q",new Integer(0));\r
+    aromatic.put("D",new Integer(0));\r
+    aromatic.put("N",new Integer(0));\r
+    aromatic.put("S",new Integer(0));\r
+    aromatic.put("T",new Integer(0));\r
+    aromatic.put("P",new Integer(0));\r
+    aromatic.put("-",new Integer(1));\r
+    aromatic.put("*",new Integer(1));\r
+  }\r
+  static {\r
+    aliphatic.put("I",new Integer(1));\r
+    aliphatic.put("L",new Integer(1));\r
+    aliphatic.put("V",new Integer(1));\r
+    aliphatic.put("C",new Integer(0));\r
+    aliphatic.put("A",new Integer(0));\r
+    aliphatic.put("G",new Integer(0));\r
+    aliphatic.put("M",new Integer(0));\r
+    aliphatic.put("F",new Integer(0));\r
+    aliphatic.put("Y",new Integer(0));\r
+    aliphatic.put("W",new Integer(0));\r
+    aliphatic.put("H",new Integer(0));\r
+    aliphatic.put("K",new Integer(0));\r
+    aliphatic.put("R",new Integer(0));\r
+    aliphatic.put("E",new Integer(0));\r
+    aliphatic.put("Q",new Integer(0));\r
+    aliphatic.put("D",new Integer(0));\r
+    aliphatic.put("N",new Integer(0));\r
+    aliphatic.put("S",new Integer(0));\r
+    aliphatic.put("T",new Integer(0));\r
+    aliphatic.put("P",new Integer(0));\r
+    aliphatic.put("-",new Integer(1));\r
+    aliphatic.put("*",new Integer(1));\r
+  }\r
+\r
+  static {\r
+    tiny.put("I",new Integer(0));\r
+    tiny.put("L",new Integer(0));\r
+    tiny.put("V",new Integer(0));\r
+    tiny.put("C",new Integer(0));\r
+    tiny.put("A",new Integer(1));\r
+    tiny.put("G",new Integer(1));\r
+    tiny.put("M",new Integer(0));\r
+    tiny.put("F",new Integer(0));\r
+    tiny.put("Y",new Integer(0));\r
+    tiny.put("W",new Integer(0));\r
+    tiny.put("H",new Integer(0));\r
+    tiny.put("K",new Integer(0));\r
+    tiny.put("R",new Integer(0));\r
+    tiny.put("E",new Integer(0));\r
+    tiny.put("Q",new Integer(0));\r
+    tiny.put("D",new Integer(0));\r
+    tiny.put("N",new Integer(0));\r
+    tiny.put("S",new Integer(1));\r
+    tiny.put("T",new Integer(0));\r
+    tiny.put("P",new Integer(0));\r
+    tiny.put("-",new Integer(1));\r
+    tiny.put("*",new Integer(1));\r
+  }\r
+\r
+  static {\r
+    proline.put("I",new Integer(0));\r
+    proline.put("L",new Integer(0));\r
+    proline.put("V",new Integer(0));\r
+    proline.put("C",new Integer(0));\r
+    proline.put("A",new Integer(0));\r
+    proline.put("G",new Integer(0));\r
+    proline.put("M",new Integer(0));\r
+    proline.put("F",new Integer(0));\r
+    proline.put("Y",new Integer(0));\r
+    proline.put("W",new Integer(0));\r
+    proline.put("H",new Integer(0));\r
+    proline.put("K",new Integer(0));\r
+    proline.put("R",new Integer(0));\r
+    proline.put("E",new Integer(0));\r
+    proline.put("Q",new Integer(0));\r
+    proline.put("D",new Integer(0));\r
+    proline.put("N",new Integer(0));\r
+    proline.put("S",new Integer(0));\r
+    proline.put("T",new Integer(0));\r
+    proline.put("P",new Integer(1));\r
+    proline.put("-",new Integer(1));\r
+    proline.put("*",new Integer(1));\r
+  }\r
+\r
+\r
+  static {\r
+    propHash.put("hydrophobic",hydrophobic);\r
+    propHash.put("small",small);\r
+    propHash.put("positive",positive);\r
+    propHash.put("negative",negative);\r
+    propHash.put("charged",charged);\r
+    propHash.put("aromatic",aromatic);\r
+    propHash.put("aliphatic",aliphatic);\r
+    propHash.put("tiny",tiny);\r
+    propHash.put("proline",proline);\r
+    propHash.put("polar",polar);\r
+  }\r
+\r
+  public static Hashtable chainColours = new Hashtable();\r
+  static {\r
+    chainColours.put("A",Color.red);\r
+    chainColours.put("B",Color.orange);\r
+    chainColours.put("C",Color.yellow);\r
+    chainColours.put("D",Color.green);\r
+    chainColours.put("E",Color.cyan);\r
+    chainColours.put("F",Color.blue);\r
+    chainColours.put("G",Color.magenta);\r
+    chainColours.put("H",Color.pink);\r
+  }\r
+  public static Hashtable getChainColours() {\r
+    return chainColours;\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/ScoreColourScheme.java b/src/jalview/schemes/ScoreColourScheme.java
new file mode 100755 (executable)
index 0000000..e8d7156
--- /dev/null
@@ -0,0 +1,63 @@
+package jalview.schemes;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.jbgui.*;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class ScoreColourScheme extends ResidueColourScheme {\r
+  public double min;\r
+  public double max;\r
+  public double[] scores;\r
+\r
+  public ScoreColourScheme( double[] scores,\r
+                          double min,\r
+                          double max) {\r
+\r
+    super();\r
+\r
+    this.scores = scores;\r
+    this.min = min;\r
+    this.max = max;\r
+  }\r
+\r
+  public Color getColour(SequenceI seq, int j, Vector aa) {\r
+      Color c = Color.white;\r
+      String s = seq.getSequence(j,j+1);\r
+\r
+      if (threshold > 0)\r
+      {\r
+         if (aboveThreshold(aa,seq,j,threshold))\r
+             c = findColour(seq,s,j,aa);\r
+      }\r
+      else if ( !s.equals("-")  && !s.equals(".") && !s.equals(" ") )\r
+         c = findColour(seq,s,j,aa);\r
+     //  else\r
+       //  c = Color.white;\r
+\r
+      return c;\r
+  }\r
+\r
+    public Color findColour(SequenceI seq,String s,int j,Vector aa)\r
+    {\r
+\r
+       float red = (float)(scores[((Integer)ResidueProperties.aaHash.get(s)).intValue()]\r
+                           - (float)min)/(float)(max - min);\r
+       if (red > (float)1.0)\r
+           red = (float)1.0;\r
+\r
+       if (red < (float)0.0)\r
+           red = (float)0.0;\r
+\r
+    if(s.equals(" ")|| s.equals(".")  || s.equals("-"))\r
+        return Color.white;\r
+\r
+       // This isn';t great - pool of colours in here?\r
+       return makeColour(red);\r
+    }\r
+    public Color makeColour(float c) {\r
+       return new Color(c,(float)0.0,(float)1.0-c);\r
+    }\r
+}\r
+\r
diff --git a/src/jalview/schemes/SecondaryColourScheme.java b/src/jalview/schemes/SecondaryColourScheme.java
new file mode 100755 (executable)
index 0000000..ddf205c
--- /dev/null
@@ -0,0 +1,28 @@
+package jalview.schemes;\r
+\r
+import jalview.gui.DrawableSequence;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+\r
+public class SecondaryColourScheme extends ResidueColourScheme {\r
+\r
+  public Color getColor(DrawableSequence seq, int j, Vector aa) {\r
+    Color c = Color.white;\r
+\r
+    String s = seq.getSequence().substring(j,j+1);\r
+\r
+    if (ResidueProperties.ssHash.containsKey(s)) {\r
+       c = (Color)ResidueProperties.ssHash.get(s);\r
+    } else {\r
+        c = Color.white;\r
+    }\r
+    return c;\r
+  }\r
+}\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/schemes/StrandColourScheme.java b/src/jalview/schemes/StrandColourScheme.java
new file mode 100755 (executable)
index 0000000..9ffed08
--- /dev/null
@@ -0,0 +1,36 @@
+\r
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.schemes;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class StrandColourScheme extends ScoreColourScheme {\r
+\r
+\r
+  public StrandColourScheme() {\r
+    super(ResidueProperties.strand,ResidueProperties.strandmin,ResidueProperties.strandmax);\r
+  }\r
+\r
+  public Color makeColour(float c) {\r
+    return new Color(c,c,(float)1.0-c);\r
+  }\r
+}\r
+\r
diff --git a/src/jalview/schemes/TaylorColourScheme.java b/src/jalview/schemes/TaylorColourScheme.java
new file mode 100755 (executable)
index 0000000..b13a312
--- /dev/null
@@ -0,0 +1,15 @@
+package jalview.schemes;\r
+\r
+import jalview.jbgui.*;\r
+import jalview.datamodel.*;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class TaylorColourScheme extends ResidueColourScheme {\r
+\r
+  public TaylorColourScheme() {\r
+    super(ResidueProperties.taylor,0);\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/schemes/TurnColourScheme.java b/src/jalview/schemes/TurnColourScheme.java
new file mode 100755 (executable)
index 0000000..b251c76
--- /dev/null
@@ -0,0 +1,35 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.schemes;\r
+\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class TurnColourScheme extends ScoreColourScheme {\r
+\r
+  public TurnColourScheme() {\r
+    super(ResidueProperties.turn,ResidueProperties.turnmin,ResidueProperties.turnmax);\r
+  }\r
+\r
+  public Color makeColour(float c) {\r
+    return new Color(c,1-c,1-c);\r
+  }\r
+}\r
+\r
diff --git a/src/jalview/schemes/UserColourScheme.java b/src/jalview/schemes/UserColourScheme.java
new file mode 100755 (executable)
index 0000000..24e35bb
--- /dev/null
@@ -0,0 +1,30 @@
+/* Jalview - a java multiple alignment editor\r
+ * Copyright (C) 1998  Michele Clamp\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+ */\r
+\r
+package jalview.schemes;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class UserColourScheme extends ResidueColourScheme\r
+{\r
+  public void setColourScheme(Color [] newColors)\r
+  {\r
+    colors = newColors;\r
+  }\r
+}\r
diff --git a/src/jalview/schemes/ZappoColourScheme.java b/src/jalview/schemes/ZappoColourScheme.java
new file mode 100755 (executable)
index 0000000..b72ff02
--- /dev/null
@@ -0,0 +1,19 @@
+package jalview.schemes;\r
+\r
+import jalview.jbgui.*;\r
+import jalview.datamodel.*;\r
+\r
+import java.util.*;\r
+import java.awt.*;\r
+\r
+public class ZappoColourScheme extends ResidueColourScheme {\r
+\r
+  public ZappoColourScheme() {\r
+    super(ResidueProperties.color,0);\r
+  }\r
+\r
+  public boolean isUserDefinable() {\r
+    return true;\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/util/BrowserLauncher.java b/src/jalview/util/BrowserLauncher.java
new file mode 100755 (executable)
index 0000000..b169dc4
--- /dev/null
@@ -0,0 +1,591 @@
+/********************
+ * 2004 Jalview Reengineered
+ * Barton Group
+ * Dundee University
+ *
+ * AM Waterhouse
+ *******************/
+
+package jalview.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * BrowserLauncher is a class that provides one static method, openURL, which opens the default
+ * web browser for the current user of the system to the given URL.  It may support other
+ * protocols depending on the system -- mailto, ftp, etc. -- but that has not been rigorously
+ * tested and is not guaranteed to work.
+ * <p>
+ * Yes, this is platform-specific code, and yes, it may rely on classes on certain platforms
+ * that are not part of the standard JDK.  What we're trying to do, though, is to take something
+ * that's frequently desirable but inherently platform-specific -- opening a default browser --
+ * and allow programmers (you, for example) to do so without worrying about dropping into native
+ * code or doing anything else similarly evil.
+ * <p>
+ * Anyway, this code is completely in Java and will run on all JDK 1.1-compliant systems without
+ * modification or a need for additional libraries.  All classes that are required on certain
+ * platforms to allow this to run are dynamically loaded at runtime via reflection and, if not
+ * found, will not cause this to do anything other than returning an error when opening the
+ * browser.
+ * <p>
+ * There are certain system requirements for this class, as it's running through Runtime.exec(),
+ * which is Java's way of making a native system call.  Currently, this requires that a Macintosh
+ * have a Finder which supports the GURL event, which is true for Mac OS 8.0 and 8.1 systems that
+ * have the Internet Scripting AppleScript dictionary installed in the Scripting Additions folder
+ * in the Extensions folder (which is installed by default as far as I know under Mac OS 8.0 and
+ * 8.1), and for all Mac OS 8.5 and later systems.  On Windows, it only runs under Win32 systems
+ * (Windows 95, 98, and NT 4.0, as well as later versions of all).  On other systems, this drops
+ * back from the inherently platform-sensitive concept of a default browser and simply attempts
+ * to launch Netscape via a shell command.
+ * <p>
+ * This code is Copyright 1999-2001 by Eric Albert (ejalbert@cs.stanford.edu) and may be
+ * redistributed or modified in any form without restrictions as long as the portion of this
+ * comment from this paragraph through the end of the comment is not removed.  The author
+ * requests that he be notified of any application, applet, or other binary that makes use of
+ * this code, but that's more out of curiosity than anything and is not required.  This software
+ * includes no warranty.  The author is not repsonsible for any loss of data or functionality
+ * or any adverse or unexpected effects of using this software.
+ * <p>
+ * Credits:
+ * <br>Steven Spencer, JavaWorld magazine (<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html">Java Tip 66</a>)
+ * <br>Thanks also to Ron B. Yeh, Eric Shapiro, Ben Engber, Paul Teitlebaum, Andrea Cantatore,
+ * Larry Barowski, Trevor Bedzek, Frank Miedrich, and Ron Rabakukk
+ *
+ * @author Eric Albert (<a href="mailto:ejalbert@cs.stanford.edu">ejalbert@cs.stanford.edu</a>)
+ * @version 1.4b1 (Released June 20, 2001)
+ */
+public class BrowserLauncher {
+
+        /**
+         * The Java virtual machine that we are running on.  Actually, in most cases we only care
+         * about the operating system, but some operating systems require us to switch on the VM. */
+        private static int jvm;
+
+        /** The browser for the system */
+        private static Object browser;
+
+        /**
+         * Caches whether any classes, methods, and fields that are not part of the JDK and need to
+         * be dynamically loaded at runtime loaded successfully.
+         * <p>
+         * Note that if this is <code>false</code>, <code>openURL()</code> will always return an
+         * IOException.
+         */
+        private static boolean loadedWithoutErrors;
+
+        /** The com.apple.mrj.MRJFileUtils class */
+        private static Class mrjFileUtilsClass;
+
+        /** The com.apple.mrj.MRJOSType class */
+        private static Class mrjOSTypeClass;
+
+        /** The com.apple.MacOS.AEDesc class */
+        private static Class aeDescClass;
+
+        /** The <init>(int) method of com.apple.MacOS.AETarget */
+        private static Constructor aeTargetConstructor;
+
+        /** The <init>(int, int, int) method of com.apple.MacOS.AppleEvent */
+        private static Constructor appleEventConstructor;
+
+        /** The <init>(String) method of com.apple.MacOS.AEDesc */
+        private static Constructor aeDescConstructor;
+
+        /** The findFolder method of com.apple.mrj.MRJFileUtils */
+        private static Method findFolder;
+
+        /** The getFileCreator method of com.apple.mrj.MRJFileUtils */
+        private static Method getFileCreator;
+
+        /** The getFileType method of com.apple.mrj.MRJFileUtils */
+        private static Method getFileType;
+
+        /** The openURL method of com.apple.mrj.MRJFileUtils */
+        private static Method openURL;
+
+        /** The makeOSType method of com.apple.MacOS.OSUtils */
+        private static Method makeOSType;
+
+        /** The putParameter method of com.apple.MacOS.AppleEvent */
+        private static Method putParameter;
+
+        /** The sendNoReply method of com.apple.MacOS.AppleEvent */
+        private static Method sendNoReply;
+
+        /** Actually an MRJOSType pointing to the System Folder on a Macintosh */
+        private static Object kSystemFolderType;
+
+        /** The keyDirectObject AppleEvent parameter type */
+        private static Integer keyDirectObject;
+
+        /** The kAutoGenerateReturnID AppleEvent code */
+        private static Integer kAutoGenerateReturnID;
+
+        /** The kAnyTransactionID AppleEvent code */
+        private static Integer kAnyTransactionID;
+
+        /** The linkage object required for JDirect 3 on Mac OS X. */
+        private static Object linkage;
+
+        /** The framework to reference on Mac OS X */
+        private static final String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox";
+
+        /** JVM constant for MRJ 2.0 */
+        private static final int MRJ_2_0 = 0;
+
+        /** JVM constant for MRJ 2.1 or later */
+        private static final int MRJ_2_1 = 1;
+
+        /** JVM constant for Java on Mac OS X 10.0 (MRJ 3.0) */
+        private static final int MRJ_3_0 = 3;
+
+        /** JVM constant for MRJ 3.1 */
+        private static final int MRJ_3_1 = 4;
+
+        /** JVM constant for any Windows NT JVM */
+        private static final int WINDOWS_NT = 5;
+
+        /** JVM constant for any Windows 9x JVM */
+        private static final int WINDOWS_9x = 6;
+
+        /** JVM constant for any other platform */
+        private static final int OTHER = -1;
+
+        /**
+         * The file type of the Finder on a Macintosh.  Hardcoding "Finder" would keep non-U.S. English
+         * systems from working properly.
+         */
+        private static final String FINDER_TYPE = "FNDR";
+
+        /**
+         * The creator code of the Finder on a Macintosh, which is needed to send AppleEvents to the
+         * application.
+         */
+        private static final String FINDER_CREATOR = "MACS";
+
+        /** The name for the AppleEvent type corresponding to a GetURL event. */
+        private static final String GURL_EVENT = "GURL";
+
+        /**
+         * The first parameter that needs to be passed into Runtime.exec() to open the default web
+         * browser on Windows.
+         */
+    private static final String FIRST_WINDOWS_PARAMETER = "/c";
+
+    /** The second parameter for Runtime.exec() on Windows. */
+    private static final String SECOND_WINDOWS_PARAMETER = "start";
+
+    /**
+     * The third parameter for Runtime.exec() on Windows.  This is a "title"
+     * parameter that the command line expects.  Setting this parameter allows
+     * URLs containing spaces to work.
+     */
+    private static final String THIRD_WINDOWS_PARAMETER = "\"\"";
+
+        /**
+         * The shell parameters for Netscape that opens a given URL in an already-open copy of Netscape
+         * on many command-line systems.
+         */
+        private static final String NETSCAPE_REMOTE_PARAMETER = "-remote";
+        private static final String NETSCAPE_OPEN_PARAMETER_START = "openURL(";
+        private static final String NETSCAPE_OPEN_PARAMETER_END = ")";
+
+        /**
+         * The message from any exception thrown throughout the initialization process.
+         */
+        private static String errorMessage;
+
+        /**
+         * An initialization block that determines the operating system and loads the necessary
+         * runtime data.
+         */
+        static {
+                loadedWithoutErrors = true;
+                String osName = System.getProperty("os.name");
+                if (osName.startsWith("Mac OS")) {
+                        String mrjVersion = System.getProperty("mrj.version");
+                        String majorMRJVersion = mrjVersion.substring(0, 3);
+                        try {
+                                double version = Double.valueOf(majorMRJVersion).doubleValue();
+                                if (version == 2) {
+                                        jvm = MRJ_2_0;
+                                } else if (version >= 2.1 && version < 3) {
+                                        // Assume that all 2.x versions of MRJ work the same.  MRJ 2.1 actually
+                                        // works via Runtime.exec() and 2.2 supports that but has an openURL() method
+                                        // as well that we currently ignore.
+                                        jvm = MRJ_2_1;
+                                } else if (version == 3.0) {
+                                        jvm = MRJ_3_0;
+                                } else if (version >= 3.1) {
+                                        // Assume that all 3.1 and later versions of MRJ work the same.
+                                        jvm = MRJ_3_1;
+                                } else {
+                                        loadedWithoutErrors = false;
+                                        errorMessage = "Unsupported MRJ version: " + version;
+                                }
+                        } catch (NumberFormatException nfe) {
+                                loadedWithoutErrors = false;
+                                errorMessage = "Invalid MRJ version: " + mrjVersion;
+                        }
+                } else if (osName.startsWith("Windows")) {
+                        if (osName.indexOf("9") != -1) {
+                                jvm = WINDOWS_9x;
+                        } else {
+                                jvm = WINDOWS_NT;
+                        }
+                } else {
+                        jvm = OTHER;
+                }
+
+                if (loadedWithoutErrors) {     // if we haven't hit any errors yet
+                        loadedWithoutErrors = loadClasses();
+                }
+        }
+
+        /**
+         * This class should be never be instantiated; this just ensures so.
+         */
+        private BrowserLauncher() { }
+
+        /**
+         * Called by a static initializer to load any classes, fields, and methods required at runtime
+         * to locate the user's web browser.
+         * @return <code>true</code> if all intialization succeeded
+         *                     <code>false</code> if any portion of the initialization failed
+         */
+        private static boolean loadClasses() {
+                switch (jvm) {
+                        case MRJ_2_0:
+                                try {
+                                        Class aeTargetClass = Class.forName("com.apple.MacOS.AETarget");
+                                        Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils");
+                                        Class appleEventClass = Class.forName("com.apple.MacOS.AppleEvent");
+                                        Class aeClass = Class.forName("com.apple.MacOS.ae");
+                                        aeDescClass = Class.forName("com.apple.MacOS.AEDesc");
+
+                                        aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class [] { int.class });
+                                        appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class[] { int.class, int.class, aeTargetClass, int.class, int.class });
+                                        aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class[] { String.class });
+
+                                        makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class [] { String.class });
+                                        putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class[] { int.class, aeDescClass });
+                                        sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class[] { });
+
+                                        Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject");
+                                        keyDirectObject = (Integer) keyDirectObjectField.get(null);
+                                        Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID");
+                                        kAutoGenerateReturnID = (Integer) autoGenerateReturnIDField.get(null);
+                                        Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID");
+                                        kAnyTransactionID = (Integer) anyTransactionIDField.get(null);
+                                } catch (ClassNotFoundException cnfe) {
+                                        errorMessage = cnfe.getMessage();
+                                        return false;
+                                } catch (NoSuchMethodException nsme) {
+                                        errorMessage = nsme.getMessage();
+                                        return false;
+                                } catch (NoSuchFieldException nsfe) {
+                                        errorMessage = nsfe.getMessage();
+                                        return false;
+                                } catch (IllegalAccessException iae) {
+                                        errorMessage = iae.getMessage();
+                                        return false;
+                                }
+                                break;
+                        case MRJ_2_1:
+                                try {
+                                        mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
+                                        mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType");
+                                        Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType");
+                                        kSystemFolderType = systemFolderField.get(null);
+                                        findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class[] { mrjOSTypeClass });
+                                        getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class[] { File.class });
+                                        getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class[] { File.class });
+                                } catch (ClassNotFoundException cnfe) {
+                                        errorMessage = cnfe.getMessage();
+                                        return false;
+                                } catch (NoSuchFieldException nsfe) {
+                                        errorMessage = nsfe.getMessage();
+                                        return false;
+                                } catch (NoSuchMethodException nsme) {
+                                        errorMessage = nsme.getMessage();
+                                        return false;
+                                } catch (SecurityException se) {
+                                        errorMessage = se.getMessage();
+                                        return false;
+                                } catch (IllegalAccessException iae) {
+                                        errorMessage = iae.getMessage();
+                                        return false;
+                                }
+                                break;
+                        case MRJ_3_0:
+                            try {
+                                        Class linker = Class.forName("com.apple.mrj.jdirect.Linker");
+                                        Constructor constructor = linker.getConstructor(new Class[]{ Class.class });
+                                        linkage = constructor.newInstance(new Object[] { BrowserLauncher.class });
+                                } catch (ClassNotFoundException cnfe) {
+                                        errorMessage = cnfe.getMessage();
+                                        return false;
+                                } catch (NoSuchMethodException nsme) {
+                                        errorMessage = nsme.getMessage();
+                                        return false;
+                                } catch (InvocationTargetException ite) {
+                                        errorMessage = ite.getMessage();
+                                        return false;
+                                } catch (InstantiationException ie) {
+                                        errorMessage = ie.getMessage();
+                                        return false;
+                                } catch (IllegalAccessException iae) {
+                                        errorMessage = iae.getMessage();
+                                        return false;
+                                }
+                                break;
+                        case MRJ_3_1:
+                                try {
+                                        mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
+                                        openURL = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class[] { String.class });
+                                } catch (ClassNotFoundException cnfe) {
+                                        errorMessage = cnfe.getMessage();
+                                        return false;
+                                } catch (NoSuchMethodException nsme) {
+                                        errorMessage = nsme.getMessage();
+                                        return false;
+                                }
+                                break;
+                        default:
+                            break;
+                }
+                return true;
+        }
+
+        /**
+         * Attempts to locate the default web browser on the local system.  Caches results so it
+         * only locates the browser once for each use of this class per JVM instance.
+         * @return The browser for the system.  Note that this may not be what you would consider
+         *                     to be a standard web browser; instead, it's the application that gets called to
+         *                     open the default web browser.  In some cases, this will be a non-String object
+         *                     that provides the means of calling the default browser.
+         */
+        private static Object locateBrowser() {
+                if (browser != null) {
+                        return browser;
+                }
+                switch (jvm) {
+                        case MRJ_2_0:
+                                try {
+                                        Integer finderCreatorCode = (Integer) makeOSType.invoke(null, new Object[] { FINDER_CREATOR });
+                                        Object aeTarget = aeTargetConstructor.newInstance(new Object[] { finderCreatorCode });
+                                        Integer gurlType = (Integer) makeOSType.invoke(null, new Object[] { GURL_EVENT });
+                                        Object appleEvent = appleEventConstructor.newInstance(new Object[] { gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID });
+                                        // Don't set browser = appleEvent because then the next time we call
+                                        // locateBrowser(), we'll get the same AppleEvent, to which we'll already have
+                                        // added the relevant parameter. Instead, regenerate the AppleEvent every time.
+                                        // There's probably a way to do this better; if any has any ideas, please let
+                                        // me know.
+                                        return appleEvent;
+                                } catch (IllegalAccessException iae) {
+                                        browser = null;
+                                        errorMessage = iae.getMessage();
+                                        return browser;
+                                } catch (InstantiationException ie) {
+                                        browser = null;
+                                        errorMessage = ie.getMessage();
+                                        return browser;
+                                } catch (InvocationTargetException ite) {
+                                        browser = null;
+                                        errorMessage = ite.getMessage();
+                                        return browser;
+                                }
+                        case MRJ_2_1:
+                                File systemFolder;
+                                try {
+                                        systemFolder = (File) findFolder.invoke(null, new Object[] { kSystemFolderType });
+                                } catch (IllegalArgumentException iare) {
+                                        browser = null;
+                                        errorMessage = iare.getMessage();
+                                        return browser;
+                                } catch (IllegalAccessException iae) {
+                                        browser = null;
+                                        errorMessage = iae.getMessage();
+                                        return browser;
+                                } catch (InvocationTargetException ite) {
+                                        browser = null;
+                                        errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
+                                        return browser;
+                                }
+                                String[] systemFolderFiles = systemFolder.list();
+                                // Avoid a FilenameFilter because that can't be stopped mid-list
+                                for(int i = 0; i < systemFolderFiles.length; i++) {
+                                        try {
+                                                File file = new File(systemFolder, systemFolderFiles[i]);
+                                                if (!file.isFile()) {
+                                                        continue;
+                                                }
+                                                // We're looking for a file with a creator code of 'MACS' and
+                                                // a type of 'FNDR'.  Only requiring the type results in non-Finder
+                                                // applications being picked up on certain Mac OS 9 systems,
+                                                // especially German ones, and sending a GURL event to those
+                                                // applications results in a logout under Multiple Users.
+                                                Object fileType = getFileType.invoke(null, new Object[] { file });
+                                                if (FINDER_TYPE.equals(fileType.toString())) {
+                                                        Object fileCreator = getFileCreator.invoke(null, new Object[] { file });
+                                                        if (FINDER_CREATOR.equals(fileCreator.toString())) {
+                                                                browser = file.toString();     // Actually the Finder, but that's OK
+                                                                return browser;
+                                                        }
+                                                }
+                                        } catch (IllegalArgumentException iare) {
+                                                browser = browser;
+                                                errorMessage = iare.getMessage();
+                                                return null;
+                                        } catch (IllegalAccessException iae) {
+                                                browser = null;
+                                                errorMessage = iae.getMessage();
+                                                return browser;
+                                        } catch (InvocationTargetException ite) {
+                                                browser = null;
+                                                errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
+                                                return browser;
+                                        }
+                                }
+                                browser = null;
+                                break;
+                        case MRJ_3_0:
+                        case MRJ_3_1:
+                                browser = "";  // Return something non-null
+                                break;
+                        case WINDOWS_NT:
+                                browser = "cmd.exe";
+                                break;
+                        case WINDOWS_9x:
+                                browser = "command.com";
+                                break;
+                        case OTHER:
+                        default:
+                                browser = "netscape";
+                                break;
+                }
+                return browser;
+        }
+
+        /**
+         * Attempts to open the default web browser to the given URL.
+         * @param url The URL to open
+         * @throws IOException If the web browser could not be located or does not run
+         */
+        public static void openURL(String url) throws IOException {
+                if (!loadedWithoutErrors) {
+                        throw new IOException("Exception in finding browser: " + errorMessage);
+                }
+                Object browser = locateBrowser();
+                if (browser == null) {
+                        throw new IOException("Unable to locate browser: " + errorMessage);
+                }
+
+                switch (jvm) {
+                        case MRJ_2_0:
+                                Object aeDesc = null;
+                                try {
+                                        aeDesc = aeDescConstructor.newInstance(new Object[] { url });
+                                        putParameter.invoke(browser, new Object[] { keyDirectObject, aeDesc });
+                                        sendNoReply.invoke(browser, new Object[] { });
+                                } catch (InvocationTargetException ite) {
+                                        throw new IOException("InvocationTargetException while creating AEDesc: " + ite.getMessage());
+                                } catch (IllegalAccessException iae) {
+                                        throw new IOException("IllegalAccessException while building AppleEvent: " + iae.getMessage());
+                                } catch (InstantiationException ie) {
+                                        throw new IOException("InstantiationException while creating AEDesc: " + ie.getMessage());
+                                } finally {
+                                        aeDesc = null; // Encourage it to get disposed if it was created
+                                        browser = null;        // Ditto
+                                }
+                                break;
+                        case MRJ_2_1:
+                                Runtime.getRuntime().exec(new String[] { (String) browser, url } );
+                                break;
+                        case MRJ_3_0:
+                                int[] instance = new int[1];
+                                int result = ICStart(instance, 0);
+                                if (result == 0) {
+                                        int[] selectionStart = new int[] { 0 };
+                                        byte[] urlBytes = url.getBytes();
+                                        int[] selectionEnd = new int[] { urlBytes.length };
+                                        result = ICLaunchURL(instance[0], new byte[] { 0 }, urlBytes,
+                                                                                        urlBytes.length, selectionStart,
+                                                                                        selectionEnd);
+                                        if (result == 0) {
+                                                // Ignore the return value; the URL was launched successfully
+                                                // regardless of what happens here.
+                                                ICStop(instance);
+                                        } else {
+                                                throw new IOException("Unable to launch URL: " + result);
+                                        }
+                                } else {
+                                        throw new IOException("Unable to create an Internet Config instance: " + result);
+                                }
+                                break;
+                        case MRJ_3_1:
+                                try {
+                                        openURL.invoke(null, new Object[] { url });
+                                } catch (InvocationTargetException ite) {
+                                        throw new IOException("InvocationTargetException while calling openURL: " + ite.getMessage());
+                                } catch (IllegalAccessException iae) {
+                                        throw new IOException("IllegalAccessException while calling openURL: " + iae.getMessage());
+                                }
+                                break;
+                    case WINDOWS_NT:
+                    case WINDOWS_9x:
+                            // Add quotes around the URL to allow ampersands and other special
+                            // characters to work.
+                                Process process = Runtime.getRuntime().exec(new String[] { (String) browser,
+                                                                                                                                FIRST_WINDOWS_PARAMETER,
+                                                                                                                                SECOND_WINDOWS_PARAMETER,
+                                                                                                                                THIRD_WINDOWS_PARAMETER,
+                                                                                                                                '"' + url + '"' });
+                                // This avoids a memory leak on some versions of Java on Windows.
+                                // That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>.
+                                try {
+                                        process.waitFor();
+                                        process.exitValue();
+                                } catch (InterruptedException ie) {
+                                        throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
+                                }
+                                break;
+                        case OTHER:
+                                // Assume that we're on Unix and that Netscape is installed
+
+                                // First, attempt to open the URL in a currently running session of Netscape
+                                process = Runtime.getRuntime().exec(new String[] { (String) browser,
+                                                                                                        NETSCAPE_REMOTE_PARAMETER,
+                                                                                                        NETSCAPE_OPEN_PARAMETER_START +
+                                                                                                        url +
+                                                                                                        NETSCAPE_OPEN_PARAMETER_END });
+                                try {
+                                        int exitCode = process.waitFor();
+                                        if (exitCode != 0) {   // if Netscape was not open
+                                                Runtime.getRuntime().exec(new String[] { (String) browser, url });
+                                        }
+                                } catch (InterruptedException ie) {
+                                        throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
+                                }
+                                break;
+                        default:
+                                // This should never occur, but if it does, we'll try the simplest thing possible
+                                Runtime.getRuntime().exec(new String[] { (String) browser, url });
+                                break;
+                }
+        }
+
+        /**
+         * Methods required for Mac OS X.  The presence of native methods does not cause
+         * any problems on other platforms.
+         */
+        private native static int ICStart(int[] instance, int signature);
+        private native static int ICStop(int[] instance);
+        private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len,
+                                                                                        int[] selectionStart, int[] selectionEnd);
+}
diff --git a/src/jalview/util/Comparison.java b/src/jalview/util/Comparison.java
new file mode 100755 (executable)
index 0000000..72fb1d1
--- /dev/null
@@ -0,0 +1,114 @@
+package jalview.util;\r
+\r
+import jalview.datamodel.*;\r
+\r
+public class Comparison {\r
+\r
+  public static float compare(SequenceI ii, SequenceI jj)\r
+  {\r
+    return Comparison.compare(ii,jj,0,ii.getLength()-1);\r
+  }\r
+  public static float compare(SequenceI ii, SequenceI jj, int start, int end) {\r
+\r
+     String si   = ii.getSequence();\r
+     String sj   = jj.getSequence();\r
+\r
+     int ilen = end-start+1;\r
+     int jlen = end-start+1;\r
+\r
+     if ( si.substring(start + ilen).equals("-") ||\r
+          si.substring(start + ilen).equals(".") ||\r
+          si.substring(start + ilen).equals(" ")) {\r
+\r
+       ilen--;\r
+\r
+       while (si.substring(start + ilen,start + ilen+1).equals("-")  ||\r
+              si.substring(start + ilen,start + ilen+1).equals(".")  ||\r
+              si.substring(start + ilen,start + ilen+1).equals(" ")) {\r
+         ilen--;\r
+       }\r
+     }\r
+\r
+     if ( sj.substring(start + jlen).equals("-")  ||\r
+          sj.substring(start + jlen).equals(".")  ||\r
+          sj.substring(start + jlen).equals(" ")) {\r
+       jlen--;\r
+\r
+       while (sj.substring(start + jlen,start + jlen+1).equals("-")  ||\r
+              sj.substring(start + jlen,start + jlen+1).equals(".")  ||\r
+              sj.substring(start + jlen,start + jlen+1).equals(" ")) {\r
+         jlen--;\r
+       }\r
+     }\r
+\r
+     int   count = 0;\r
+     int   match = 0;\r
+     float pid   = -1;\r
+\r
+     if (ilen > jlen) {\r
+\r
+       for (int j = 0; j < jlen; j++) {\r
+         if (si.substring(start + j,start + j+1).equals(sj.substring(start + j,start + j+1))) {\r
+           match++;\r
+         }\r
+         count++;\r
+       }\r
+       pid = (float)match/(float)ilen * 100;\r
+     } else {\r
+       for (int j = 0; j < jlen; j++) {\r
+         if (si.substring(start + j,start + j+1).equals(sj.substring(start + j,start + j+1))) {\r
+           match++;\r
+         }\r
+         count++;\r
+       }\r
+       pid = (float)match/(float)jlen * 100;\r
+     }\r
+\r
+    return pid;\r
+  }\r
+\r
+  /**    */\r
+  public static float PID(Sequence s1 , Sequence s2) {\r
+    int res = 0;\r
+    int len;\r
+\r
+    if (s1.getSequence().length() > s2.getSequence().length()) {\r
+      len = s1.getSequence().length();\r
+    } else {\r
+      len = s2.getSequence().length();\r
+    }\r
+\r
+    int bad = 0;\r
+\r
+    for (int i = 0; i < len; i++) {\r
+      String str1 = "";\r
+      String str2 = "";\r
+\r
+      if (i < s1.getSequence().length()) {\r
+        str1 = s1.getSequence().substring(i,i+1);\r
+      } else {\r
+        str1 = ".";\r
+      }\r
+\r
+      if (i < s2.getSequence().length()) {\r
+        str2 = s2.getSequence().substring(i,i+1);\r
+      } else {\r
+        str2 = ".";\r
+      }\r
+\r
+      if (!(str1.equals(".") ||\r
+            str1.equals("-") ||\r
+            str1.equals(" "))   &&\r
+          !(str2.equals(".") ||\r
+            str2.equals("-") ||\r
+            str2.equals(" "))) {\r
+\r
+        if (!str1.equals(str2)) {\r
+          bad++;\r
+        }\r
+      }\r
+    }\r
+\r
+    return (float)100*(len-bad)/len;\r
+  }\r
+}\r
diff --git a/src/jalview/util/ErrorLog.java b/src/jalview/util/ErrorLog.java
new file mode 100755 (executable)
index 0000000..dd95b06
--- /dev/null
@@ -0,0 +1,18 @@
+package jalview.util;\r
+\r
+import java.io.*;\r
+\r
+public class ErrorLog {\r
+  static PrintStream errStream = System.err;\r
+  static PrintStream teeFile = null;\r
+\r
+  private ErrorLog() {}\r
+\r
+  public static void println(String str) {\r
+    errStream.println("Error Logger: " + str);\r
+  }\r
+\r
+  public static void main(String [] argv) {\r
+    ErrorLog.println("ERROR");\r
+  }\r
+}\r
diff --git a/src/jalview/util/Format.java b/src/jalview/util/Format.java
new file mode 100755 (executable)
index 0000000..4acf29e
--- /dev/null
@@ -0,0 +1,612 @@
+/*\r
+ * Cay S. Horstmann & Gary Cornell, Core Java\r
+ * Published By Sun Microsystems Press/Prentice-Hall\r
+ * Copyright (C) 1997 Sun Microsystems Inc.\r
+ * All Rights Reserved.\r
+ *\r
+ * Permission to use, copy, modify, and distribute this \r
+ * software and its documentation for NON-COMMERCIAL purposes\r
+ * and without fee is hereby granted provided that this \r
+ * copyright notice appears in all copies. \r
+ * \r
+ * THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR \r
+ * WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER \r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE \r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A \r
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS\r
+ * AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED \r
+ * BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING \r
+ * THIS SOFTWARE OR ITS DERIVATIVES.\r
+ */\r
+\r
+/**\r
+ * A class for formatting numbers that follows printf conventions.\r
+ * Also implements C-like atoi and atof functions\r
+ * @version 1.03 25 Oct 1997\r
+ * @author Cay Horstmann\r
+ */\r
+\r
+package jalview.util;\r
+\r
+import java.io.*;\r
+\r
+public class Format { /**\r
+     * Formats the number following printf conventions.\r
+     * Main limitation: Can only handle one format parameter at a time\r
+     * Use multiple Format objects to format more than one number\r
+     * @param s the format string following printf conventions\r
+     * The string has a prefix, a format code and a suffix. The prefix and suffix\r
+     * become part of the formatted output. The format code directs the\r
+     * formatting of the (single) parameter to be formatted. The code has the\r
+     * following structure\r
+     * <ul>\r
+     * <li> a % (required)\r
+     * <li> a modifier (optional)\r
+     * <dl>\r
+     * <dt> + <dd> forces display of + for positive numbers\r
+     * <dt> 0 <dd> show leading zeroes\r
+     * <dt> - <dd> align left in the field\r
+     * <dt> space <dd> prepend a space in front of positive numbers\r
+     * <dt> # <dd> use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers. Don't suppress trailing zeroes in general floating point format.\r
+     * </dl>\r
+     * <li> an integer denoting field width (optional)\r
+     * <li> a period followed by an integer denoting precision (optional)\r
+     * <li> a format descriptor (required)\r
+     * <dl>\r
+     * <dt>f <dd> floating point number in fixed format\r
+     * <dt>e, E <dd> floating point number in exponential notation (scientific format). The E format results in an uppercase E for the exponent (1.14130E+003), the e format in a lowercase e.\r
+     * <dt>g, G <dd> floating point number in general format (fixed format for small numbers, exponential format for large numbers). Trailing zeroes are suppressed. The G format results in an uppercase E for the exponent (if any), the g format in a lowercase e.\r
+     * <dt>d, i <dd> integer in decimal\r
+     * <dt>x <dd> integer in hexadecimal\r
+     * <dt>o <dd> integer in octal\r
+     * <dt>s <dd> string\r
+     * <dt>c <dd> character\r
+     * </dl>\r
+     * </ul>\r
+     * @exception IllegalArgumentException if bad format\r
+     */\r
+\r
+  public Format(String s) {\r
+    width = 0;\r
+    precision = -1;\r
+    pre = "";\r
+    post = "";\r
+    leading_zeroes = false;\r
+    show_plus = false;\r
+    alternate = false;\r
+    show_space = false;\r
+    left_align = false;\r
+    fmt = ' ';\r
+\r
+    int state = 0;\r
+    int length = s.length();\r
+    int parse_state = 0;\r
+    // 0 = prefix, 1 = flags, 2 = width, 3 = precision,\r
+    // 4 = format, 5 = end\r
+    int i = 0;\r
+\r
+    while (parse_state == 0) {\r
+      if (i >= length)\r
+        parse_state = 5;\r
+      else if (s.charAt(i) == '%') {\r
+        if (i < length - 1) {\r
+          if (s.charAt(i + 1) == '%') {\r
+            pre = pre + '%';\r
+            i++;\r
+          } else\r
+            parse_state = 1;\r
+        } else\r
+          throw new java.lang.IllegalArgumentException();\r
+      } else\r
+        pre = pre + s.charAt(i);\r
+      i++;\r
+    }\r
+    while (parse_state == 1) {\r
+      if (i >= length)\r
+        parse_state = 5;\r
+      else if (s.charAt(i) == ' ')\r
+        show_space = true;\r
+      else if (s.charAt(i) == '-')\r
+        left_align = true;\r
+      else if (s.charAt(i) == '+')\r
+        show_plus = true;\r
+      else if (s.charAt(i) == '0')\r
+        leading_zeroes = true;\r
+      else if (s.charAt(i) == '#')\r
+        alternate = true;\r
+      else {\r
+        parse_state = 2;\r
+        i--;\r
+      }\r
+      i++;\r
+    }\r
+    while (parse_state == 2) {\r
+      if (i >= length)\r
+        parse_state = 5;\r
+      else if ('0' <= s.charAt(i) && s.charAt(i) <= '9') {\r
+        width = width * 10 + s.charAt(i) - '0';\r
+        i++;\r
+      } else if (s.charAt(i) == '.') {\r
+        parse_state = 3;\r
+        precision = 0;\r
+        i++;\r
+      } else\r
+        parse_state = 4;\r
+    }\r
+    while (parse_state == 3) {\r
+      if (i >= length)\r
+        parse_state = 5;\r
+      else if ('0' <= s.charAt(i) && s.charAt(i) <= '9') {\r
+        precision = precision * 10 + s.charAt(i) - '0';\r
+        i++;\r
+      } else\r
+        parse_state = 4;\r
+    }\r
+    if (parse_state == 4) {\r
+      if (i >= length)\r
+        parse_state = 5;\r
+      else\r
+        fmt = s.charAt(i);\r
+      i++;\r
+    }\r
+    if (i < length)\r
+      post = s.substring(i, length);\r
+  }\r
+\r
+  /**\r
+  * prints a formatted number following printf conventions\r
+  * @param s a PrintStream\r
+  * @param fmt the format string\r
+  * @param x the double to print\r
+  */\r
+\r
+  public static void print(java.io.PrintStream s, String fmt, double x) {\r
+    s.print(new Format(fmt).form(x));\r
+  }\r
+\r
+  /**\r
+  * prints a formatted number following printf conventions\r
+  * @param s a PrintStream\r
+  * @param fmt the format string\r
+  * @param x the long to print\r
+  */\r
+  public static void print(java.io.PrintStream s, String fmt, long x) {\r
+    s.print(new Format(fmt).form(x));\r
+  }\r
+\r
+  /**\r
+  * prints a formatted number following printf conventions\r
+  * @param s a PrintStream\r
+  * @param fmt the format string\r
+  * @param x the character to \r
+  */\r
+\r
+  public static void print(java.io.PrintStream s, String fmt, char x) {\r
+    s.print(new Format(fmt).form(x));\r
+  }\r
+\r
+  /**\r
+  * prints a formatted number following printf conventions\r
+  * @param s a PrintStream, fmt the format string\r
+  * @param x a string that represents the digits to print\r
+  */\r
+\r
+  public static void print(java.io.PrintStream s, String fmt, String x) {\r
+    s.print(new Format(fmt).form(x));\r
+  }\r
+\r
+  /**\r
+  * Converts a string of digits (decimal, octal or hex) to an integer\r
+  * @param s a string\r
+  * @return the numeric value of the prefix of s representing a base 10 integer\r
+  */\r
+\r
+  public static int atoi(String s) {\r
+    return (int)atol(s);\r
+  }\r
+\r
+  /**\r
+  * Converts a string of digits (decimal, octal or hex) to a long integer\r
+  * @param s a string\r
+  * @return the numeric value of the prefix of s representing a base 10 integer\r
+  */\r
+\r
+  public static long atol(String s) {\r
+    int i = 0;\r
+\r
+    while (i < s.length() && Character.isWhitespace(s.charAt(i)))\r
+      i++;\r
+    if (i < s.length() && s.charAt(i) == '0') {\r
+      if (i + 1 < s.length() && (s.charAt(i + 1) == 'x' || s.charAt(i + 1) == 'X'))\r
+        return parseLong(s.substring(i + 2), 16);\r
+      else\r
+        return parseLong(s, 8);\r
+    } else\r
+      return parseLong(s, 10);\r
+  }\r
+\r
+  private static long parseLong(String s, int base) {\r
+    int i = 0;\r
+    int sign = 1;\r
+    long r = 0;\r
+\r
+    while (i < s.length() && Character.isWhitespace(s.charAt(i)))\r
+      i++;\r
+    if (i < s.length() && s.charAt(i) == '-') {\r
+      sign = -1;\r
+      i++;\r
+    } else if (i < s.length() && s.charAt(i) == '+') {\r
+      i++;\r
+    }\r
+    while (i < s.length()) {\r
+      char ch = s.charAt(i);\r
+      if ('0' <= ch && ch < '0' + base)\r
+        r = r * base + ch - '0';\r
+      else if ('A' <= ch && ch < 'A' + base - 10)\r
+        r = r * base + ch - 'A' + 10 ;\r
+      else if ('a' <= ch && ch < 'a' + base - 10)\r
+        r = r * base + ch - 'a' + 10 ;\r
+      else\r
+        return r * sign;\r
+      i++;\r
+    }\r
+    return r * sign;\r
+  }\r
+\r
+  /**\r
+  * Converts a string of digits to an double\r
+  * @param s a string\r
+  */\r
+\r
+  public static double atof(String s) {\r
+    int i = 0;\r
+    int sign = 1;\r
+    double r = 0; // integer part\r
+    double f = 0; // fractional part\r
+    double p = 1; // exponent of fractional part\r
+    int state = 0; // 0 = int part, 1 = frac part\r
+\r
+    while (i < s.length() && Character.isWhitespace(s.charAt(i)))\r
+      i++;\r
+    if (i < s.length() && s.charAt(i) == '-') {\r
+      sign = -1;\r
+      i++;\r
+    } else if (i < s.length() && s.charAt(i) == '+') {\r
+      i++;\r
+    }\r
+    while (i < s.length()) {\r
+      char ch = s.charAt(i);\r
+      if ('0' <= ch && ch <= '9') {\r
+        if (state == 0)\r
+          r = r * 10 + ch - '0';\r
+        else if (state == 1) {\r
+          p = p / 10;\r
+          r = r + p * (ch - '0');\r
+        }\r
+      } else if (ch == '.') {\r
+        if (state == 0)\r
+          state = 1;\r
+        else\r
+          return sign * r;\r
+      } else if (ch == 'e' || ch == 'E') {\r
+        long e = (int)parseLong(s.substring(i + 1), 10);\r
+        return sign * r * Math.pow(10, e);\r
+      } else\r
+        return sign * r;\r
+      i++;\r
+    }\r
+    return sign * r;\r
+  }\r
+\r
+  /**\r
+  * Formats a double into a string (like sprintf in C)\r
+  * @param x the number to format\r
+  * @return the formatted string \r
+  * @exception IllegalArgumentException if bad argument\r
+  */\r
+\r
+  public String form(double x) {\r
+    String r;\r
+    if (precision < 0)\r
+      precision = 6;\r
+    int s = 1;\r
+    if (x < 0) {\r
+      x = -x;\r
+      s = -1;\r
+    }\r
+    if (fmt == 'f')\r
+      r = fixed_format(x);\r
+    else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G')\r
+      r = exp_format(x);\r
+    else\r
+      throw new java.lang.IllegalArgumentException();\r
+\r
+    return pad(sign(s, r));\r
+  }\r
+\r
+  /**\r
+  * Formats a long integer into a string (like sprintf in C)\r
+  * @param x the number to format\r
+  * @return the formatted string \r
+  */\r
+\r
+  public String form(long x) {\r
+    String r;\r
+    int s = 0;\r
+    if (fmt == 'd' || fmt == 'i') {\r
+      if (x < 0) {\r
+        r = ("" + x).substring(1);\r
+        s = -1;\r
+      } else {\r
+        r = "" + x;\r
+        s = 1;\r
+      }\r
+    } else if (fmt == 'o')\r
+      r = convert(x, 3, 7, "01234567");\r
+    else if (fmt == 'x')\r
+      r = convert(x, 4, 15, "0123456789abcdef");\r
+    else if (fmt == 'X')\r
+      r = convert(x, 4, 15, "0123456789ABCDEF");\r
+    else\r
+      throw new java.lang.IllegalArgumentException();\r
+\r
+    return pad(sign(s, r));\r
+  }\r
+\r
+  /**\r
+  * Formats a character into a string (like sprintf in C)\r
+  * @param x the value to format\r
+  * @return the formatted string \r
+  */\r
+\r
+  public String form(char c) {\r
+    if (fmt != 'c')\r
+      throw new java.lang.IllegalArgumentException();\r
+\r
+    String r = "" + c;\r
+    return pad(r);\r
+  }\r
+\r
+  /**\r
+  * Formats a string into a larger string (like sprintf in C)\r
+  * @param x the value to format\r
+  * @return the formatted string \r
+  */\r
+\r
+  public String form(String s) {\r
+    if (fmt != 's')\r
+      throw new java.lang.IllegalArgumentException();\r
+    if (precision >= 0)\r
+      s = s.substring(0, precision);\r
+    return pad(s);\r
+  }\r
+\r
+\r
+  /**\r
+  * a test stub for the format class\r
+  */\r
+\r
+  public static void main(String[] a) {\r
+    double x = 1.23456789012;\r
+    double y = 123;\r
+    double z = 1.2345e30;\r
+    double w = 1.02;\r
+    double u = 1.234e-5;\r
+    int d = 0xCAFE;\r
+    Format.print(System.out, "x = |%f|\n", x);\r
+    Format.print(System.out, "u = |%20f|\n", u);\r
+    Format.print(System.out, "x = |% .5f|\n", x);\r
+    Format.print(System.out, "w = |%20.5f|\n", w);\r
+    Format.print(System.out, "x = |%020.5f|\n", x);\r
+    Format.print(System.out, "x = |%+20.5f|\n", x);\r
+    Format.print(System.out, "x = |%+020.5f|\n", x);\r
+    Format.print(System.out, "x = |% 020.5f|\n", x);\r
+    Format.print(System.out, "y = |%#+20.5f|\n", y);\r
+    Format.print(System.out, "y = |%-+20.5f|\n", y);\r
+    Format.print(System.out, "z = |%20.5f|\n", z);\r
+\r
+    Format.print(System.out, "x = |%e|\n", x);\r
+    Format.print(System.out, "u = |%20e|\n", u);\r
+    Format.print(System.out, "x = |% .5e|\n", x);\r
+    Format.print(System.out, "w = |%20.5e|\n", w);\r
+    Format.print(System.out, "x = |%020.5e|\n", x);\r
+    Format.print(System.out, "x = |%+20.5e|\n", x);\r
+    Format.print(System.out, "x = |%+020.5e|\n", x);\r
+    Format.print(System.out, "x = |% 020.5e|\n", x);\r
+    Format.print(System.out, "y = |%#+20.5e|\n", y);\r
+    Format.print(System.out, "y = |%-+20.5e|\n", y);\r
+\r
+    Format.print(System.out, "x = |%g|\n", x);\r
+    Format.print(System.out, "z = |%g|\n", z);\r
+    Format.print(System.out, "w = |%g|\n", w);\r
+    Format.print(System.out, "u = |%g|\n", u);\r
+    Format.print(System.out, "y = |%.2g|\n", y);\r
+    Format.print(System.out, "y = |%#.2g|\n", y);\r
+\r
+    Format.print(System.out, "d = |%d|\n", d);\r
+    Format.print(System.out, "d = |%20d|\n", d);\r
+    Format.print(System.out, "d = |%020d|\n", d);\r
+    Format.print(System.out, "d = |%+20d|\n", d);\r
+    Format.print(System.out, "d = |% 020d|\n", d);\r
+    Format.print(System.out, "d = |%-20d|\n", d);\r
+    Format.print(System.out, "d = |%20.8d|\n", d);\r
+    Format.print(System.out, "d = |%x|\n", d);\r
+    Format.print(System.out, "d = |%20X|\n", d);\r
+    Format.print(System.out, "d = |%#20x|\n", d);\r
+    Format.print(System.out, "d = |%020X|\n", d);\r
+    Format.print(System.out, "d = |%20.8x|\n", d);\r
+    Format.print(System.out, "d = |%o|\n", d);\r
+    Format.print(System.out, "d = |%020o|\n", d);\r
+    Format.print(System.out, "d = |%#20o|\n", d);\r
+    Format.print(System.out, "d = |%#020o|\n", d);\r
+    Format.print(System.out, "d = |%20.12o|\n", d);\r
+\r
+    Format.print(System.out, "s = |%-20s|\n", "Hello");\r
+    Format.print(System.out, "s = |%-20c|\n", '!');\r
+\r
+    // regression test to confirm fix of reported bugs\r
+\r
+    Format.print(System.out, "|%i|\n", Long.MIN_VALUE);\r
+\r
+    Format.print(System.out, "|%6.2e|\n", 0.0);\r
+    Format.print(System.out, "|%6.2g|\n", 0.0);\r
+\r
+    Format.print(System.out, "|%6.2f|\n", 9.99);\r
+    Format.print(System.out, "|%6.2f|\n", 9.999);\r
+\r
+    Format.print(System.out, "|%6.0f|\n", 9.999);\r
+  }\r
+\r
+  private static String repeat(char c, int n) {\r
+    if (n <= 0)\r
+      return "";\r
+    StringBuffer s = new StringBuffer(n);\r
+    for (int i = 0; i < n; i++)\r
+      s.append(c);\r
+    return s.toString();\r
+  }\r
+\r
+  private static String convert(long x, int n, int m, String d) {\r
+    if (x == 0)\r
+      return "0";\r
+    String r = "";\r
+    while (x != 0) {\r
+      r = d.charAt((int)(x & m)) + r;\r
+      x = x >>> n;\r
+    }\r
+    return r;\r
+  }\r
+\r
+  private String pad(String r) {\r
+    String p = repeat(' ', width - r.length());\r
+    if (left_align)\r
+      return pre + r + p + post;\r
+    else\r
+      return pre + p + r + post;\r
+  }\r
+\r
+  private String sign(int s, String r) {\r
+    String p = "";\r
+    if (s < 0)\r
+      p = "-";\r
+    else if (s > 0) {\r
+      if (show_plus)\r
+        p = "+";\r
+      else if (show_space)\r
+        p = " ";\r
+    } else {\r
+      if (fmt == 'o' && alternate && r.length() > 0 && r.charAt(0) != '0')\r
+        p = "0";\r
+      else if (fmt == 'x' && alternate)\r
+        p = "0x";\r
+      else if (fmt == 'X' && alternate)\r
+        p = "0X";\r
+    }\r
+    int w = 0;\r
+    if (leading_zeroes)\r
+      w = width;\r
+    else if ((fmt == 'd' || fmt == 'i' || fmt == 'x' || fmt == 'X' || fmt == 'o')\r
+             && precision > 0)\r
+      w = precision;\r
+\r
+    return p + repeat('0', w - p.length() - r.length()) + r;\r
+  }\r
+\r
+  private String fixed_format(double d) {\r
+    boolean removeTrailing\r
+    = (fmt == 'G' || fmt == 'g') && !alternate;\r
+    // remove trailing zeroes and decimal point\r
+\r
+    if (d > 0x7FFFFFFFFFFFFFFFL)\r
+      return exp_format(d);\r
+    if (precision == 0)\r
+      return (long)(d + 0.5) + (removeTrailing ? "" : ".");\r
+\r
+    long whole = (long)d;\r
+    double fr = d - whole; // fractional part\r
+    if (fr >= 1 || fr < 0)\r
+      return exp_format(d);\r
+\r
+    double factor = 1;\r
+    String leading_zeroes = "";\r
+    for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL; i++) {\r
+      factor *= 10;\r
+      leading_zeroes = leading_zeroes + "0";\r
+    }\r
+    long l = (long) (factor * fr + 0.5);\r
+    if (l >= factor) {\r
+      l = 0;\r
+      whole++;\r
+    } // CSH 10-25-97\r
+\r
+    String z = leading_zeroes + l;\r
+    z = "." + z.substring(z.length() - precision, z.length());\r
+\r
+    if (removeTrailing) {\r
+      int t = z.length() - 1;\r
+      while (t >= 0 && z.charAt(t) == '0')\r
+        t--;\r
+      if (t >= 0 && z.charAt(t) == '.')\r
+        t--;\r
+      z = z.substring(0, t + 1);\r
+    }\r
+\r
+    return whole + z;\r
+  }\r
+\r
+  private String exp_format(double d) {\r
+    String f = "";\r
+    int e = 0;\r
+    double dd = d;\r
+    double factor = 1;\r
+    if (d != 0) {\r
+      while (dd > 10) {\r
+        e++;\r
+        factor /= 10;\r
+        dd = dd / 10;\r
+      }\r
+      while (dd < 1) {\r
+        e--;\r
+        factor *= 10;\r
+        dd = dd * 10;\r
+      }\r
+    }\r
+    if ((fmt == 'g' || fmt == 'G') && e >= -4 && e < precision)\r
+      return fixed_format(d);\r
+\r
+    d = d * factor;\r
+    f = f + fixed_format(d);\r
+\r
+    if (fmt == 'e' || fmt == 'g')\r
+      f = f + "e";\r
+    else\r
+      f = f + "E";\r
+\r
+    String p = "000";\r
+    if (e >= 0) {\r
+      f = f + "+";\r
+      p = p + e;\r
+    } else {\r
+      f = f + "-";\r
+      p = p + (-e);\r
+    }\r
+\r
+    return f + p.substring(p.length() - 3, p.length());\r
+  }\r
+\r
+  private int width;\r
+  private int precision;\r
+  private String pre;\r
+  private String post;\r
+  private boolean leading_zeroes;\r
+  private boolean show_plus;\r
+  private boolean alternate;\r
+  private boolean show_space;\r
+  private boolean left_align;\r
+  private char fmt; // one of cdeEfgGiosxXos\r
+}\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/util/Format.save b/src/jalview/util/Format.save
new file mode 100755 (executable)
index 0000000..5783670
--- /dev/null
@@ -0,0 +1,563 @@
+/*\r
+ * Cay S. Horstmann & Gary Cornell, Core Java\r
+ * Published By Sun Microsystems Press/Prentice-Hall\r
+ * Copyright (C) 1997 Sun Microsystems Inc.\r
+ * All Rights Reserved.\r
+ *\r
+ * Permission to use, copy, modify, and distribute this \r
+ * software and its documentation for NON-COMMERCIAL purposes\r
+ * and without fee is hereby granted provided that this \r
+ * copyright notice appears in all copies. \r
+ * \r
+ * THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR \r
+ * WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER \r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE \r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A \r
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS\r
+ * AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED \r
+ * BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING \r
+ * THIS SOFTWARE OR ITS DERIVATIVES.\r
+ */\r
\r
+/**\r
+ * A class for formatting numbers that follows printf conventions.\r
+ * Also implements C-like atoi and atof functions\r
+ * @version 1.03 25 Oct 1997\r
+ * @author Cay Horstmann\r
+ */\r
+\r
+package jalview.util;\r
+\r
+import java.io.*;\r
+\r
+public class Format\r
+\r
+{ /** \r
+  * Formats the number following printf conventions.\r
+  * Main limitation: Can only handle one format parameter at a time\r
+  * Use multiple Format objects to format more than one number\r
+  * @param s the format string following printf conventions\r
+  * The string has a prefix, a format code and a suffix. The prefix and suffix\r
+  * become part of the formatted output. The format code directs the\r
+  * formatting of the (single) parameter to be formatted. The code has the\r
+  * following structure\r
+  * <ul>\r
+  * <li> a % (required)\r
+  * <li> a modifier (optional)\r
+  * <dl>\r
+  * <dt> + <dd> forces display of + for positive numbers\r
+  * <dt> 0 <dd> show leading zeroes\r
+  * <dt> - <dd> align left in the field\r
+  * <dt> space <dd> prepend a space in front of positive numbers\r
+  * <dt> # <dd> use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers. Don't suppress trailing zeroes in general floating point format.\r
+  * </dl>\r
+  * <li> an integer denoting field width (optional)\r
+  * <li> a period followed by an integer denoting precision (optional)\r
+  * <li> a format descriptor (required)\r
+  * <dl>\r
+  * <dt>f <dd> floating point number in fixed format\r
+  * <dt>e, E <dd> floating point number in exponential notation (scientific format). The E format results in an uppercase E for the exponent (1.14130E+003), the e format in a lowercase e.\r
+  * <dt>g, G <dd> floating point number in general format (fixed format for small numbers, exponential format for large numbers). Trailing zeroes are suppressed. The G format results in an uppercase E for the exponent (if any), the g format in a lowercase e.\r
+  * <dt>d, i <dd> integer in decimal\r
+  * <dt>x <dd> integer in hexadecimal\r
+  * <dt>o <dd> integer in octal\r
+  * <dt>s <dd> string\r
+  * <dt>c <dd> character\r
+  * </dl>\r
+  * </ul>\r
+  * @exception IllegalArgumentException if bad format\r
+  */\r
+\r
+   public Format(String s)\r
+   {  width = 0;\r
+      precision = -1;\r
+      pre = "";\r
+      post = "";\r
+      leading_zeroes = false;\r
+      show_plus = false;\r
+      alternate = false;\r
+      show_space = false;\r
+      left_align = false;\r
+      fmt = ' '; \r
+      \r
+      int state = 0; \r
+      int length = s.length();\r
+      int parse_state = 0; \r
+      // 0 = prefix, 1 = flags, 2 = width, 3 = precision,\r
+      // 4 = format, 5 = end\r
+      int i = 0;\r
+      \r
+      while (parse_state == 0)\r
+      {  if (i >= length) parse_state = 5;\r
+         else if (s.charAt(i) == '%')\r
+         {  if (i < length - 1)\r
+            {  if (s.charAt(i + 1) == '%')\r
+               {  pre = pre + '%';\r
+                  i++;\r
+               }\r
+               else\r
+                  parse_state = 1;\r
+            }\r
+            else throw new java.lang.IllegalArgumentException();\r
+         }\r
+         else\r
+            pre = pre + s.charAt(i);\r
+         i++;\r
+      }\r
+      while (parse_state == 1)\r
+      {  if (i >= length) parse_state = 5;\r
+         else if (s.charAt(i) == ' ') show_space = true;\r
+         else if (s.charAt(i) == '-') left_align = true; \r
+         else if (s.charAt(i) == '+') show_plus = true;\r
+         else if (s.charAt(i) == '0') leading_zeroes = true;\r
+         else if (s.charAt(i) == '#') alternate = true;\r
+         else { parse_state = 2; i--; }\r
+         i++;\r
+      }      \r
+      while (parse_state == 2)\r
+      {  if (i >= length) parse_state = 5;\r
+         else if ('0' <= s.charAt(i) && s.charAt(i) <= '9')\r
+         {  width = width * 10 + s.charAt(i) - '0';\r
+            i++;\r
+         }\r
+         else if (s.charAt(i) == '.')\r
+         {  parse_state = 3;\r
+            precision = 0;\r
+            i++;\r
+         }\r
+         else \r
+            parse_state = 4;            \r
+      }\r
+      while (parse_state == 3)\r
+      {  if (i >= length) parse_state = 5;\r
+         else if ('0' <= s.charAt(i) && s.charAt(i) <= '9')\r
+         {  precision = precision * 10 + s.charAt(i) - '0';\r
+            i++;\r
+         }\r
+         else \r
+            parse_state = 4;                  \r
+      }\r
+      if (parse_state == 4) \r
+      {  if (i >= length) parse_state = 5;\r
+         else fmt = s.charAt(i);\r
+         i++;\r
+      }\r
+      if (i < length)\r
+         post = s.substring(i, length);\r
+   }      \r
+\r
+  /** \r
+  * prints a formatted number following printf conventions\r
+  * @param s a PrintStream\r
+  * @param fmt the format string\r
+  * @param x the double to print\r
+  */\r
+  \r
+   public static void print(java.io.PrintStream s, String fmt, double x)\r
+   {  s.print(new Format(fmt).form(x));\r
+   }\r
+\r
+  /** \r
+  * prints a formatted number following printf conventions\r
+  * @param s a PrintStream\r
+  * @param fmt the format string\r
+  * @param x the long to print\r
+  */\r
+  public static void print(java.io.PrintStream s, String fmt, long x)\r
+   {  s.print(new Format(fmt).form(x));\r
+   }\r
+\r
+  /** \r
+  * prints a formatted number following printf conventions\r
+  * @param s a PrintStream\r
+  * @param fmt the format string\r
+  * @param x the character to \r
+  */\r
+  \r
+   public static void print(java.io.PrintStream s, String fmt, char x)\r
+   {  s.print(new Format(fmt).form(x));\r
+   }\r
+\r
+  /** \r
+  * prints a formatted number following printf conventions\r
+  * @param s a PrintStream, fmt the format string\r
+  * @param x a string that represents the digits to print\r
+  */\r
+  \r
+   public static void print(java.io.PrintStream s, String fmt, String x)\r
+   {  s.print(new Format(fmt).form(x));\r
+   }\r
+   \r
+  /** \r
+  * Converts a string of digits (decimal, octal or hex) to an integer\r
+  * @param s a string\r
+  * @return the numeric value of the prefix of s representing a base 10 integer\r
+  */\r
+  \r
+   public static int atoi(String s)\r
+   {  return (int)atol(s);\r
+   } \r
+   \r
+  /** \r
+  * Converts a string of digits (decimal, octal or hex) to a long integer\r
+  * @param s a string\r
+  * @return the numeric value of the prefix of s representing a base 10 integer\r
+  */\r
+  \r
+   public static long atol(String s)\r
+   {  int i = 0;\r
+\r
+      while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;\r
+      if (i < s.length() && s.charAt(i) == '0')\r
+      {  if (i + 1 < s.length() && (s.charAt(i + 1) == 'x' || s.charAt(i + 1) == 'X'))\r
+            return parseLong(s.substring(i + 2), 16);\r
+         else return parseLong(s, 8);\r
+      }\r
+      else return parseLong(s, 10);\r
+   }\r
+\r
+   private static long parseLong(String s, int base)\r
+   {  int i = 0;\r
+      int sign = 1;\r
+      long r = 0;\r
+      \r
+      while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;\r
+      if (i < s.length() && s.charAt(i) == '-') { sign = -1; i++; }\r
+      else if (i < s.length() && s.charAt(i) == '+') { i++; }\r
+      while (i < s.length())\r
+      {  char ch = s.charAt(i);\r
+         if ('0' <= ch && ch < '0' + base)\r
+            r = r * base + ch - '0';\r
+         else if ('A' <= ch && ch < 'A' + base - 10)\r
+            r = r * base + ch - 'A' + 10 ;\r
+         else if ('a' <= ch && ch < 'a' + base - 10)\r
+            r = r * base + ch - 'a' + 10 ;\r
+         else \r
+            return r * sign;\r
+         i++;\r
+      }\r
+      return r * sign;      \r
+   }\r
+      \r
+   /** \r
+   * Converts a string of digits to an double\r
+   * @param s a string\r
+   */\r
+   \r
+   public static double atof(String s)\r
+   {  int i = 0;\r
+      int sign = 1;\r
+      double r = 0; // integer part\r
+      double f = 0; // fractional part\r
+      double p = 1; // exponent of fractional part\r
+      int state = 0; // 0 = int part, 1 = frac part\r
+      \r
+      while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;\r
+      if (i < s.length() && s.charAt(i) == '-') { sign = -1; i++; }\r
+      else if (i < s.length() && s.charAt(i) == '+') { i++; }\r
+      while (i < s.length())\r
+      {  char ch = s.charAt(i);\r
+         if ('0' <= ch && ch <= '9')\r
+         {  if (state == 0)\r
+               r = r * 10 + ch - '0';\r
+            else if (state == 1)\r
+            {  p = p / 10;\r
+               r = r + p * (ch - '0');\r
+            }\r
+         }\r
+         else if (ch == '.') \r
+         {  if (state == 0) state = 1; \r
+            else return sign * r;\r
+         }\r
+         else if (ch == 'e' || ch == 'E')\r
+         {  long e = (int)parseLong(s.substring(i + 1), 10);\r
+            return sign * r * Math.pow(10, e);\r
+         }\r
+         else return sign * r;\r
+         i++;\r
+      }\r
+      return sign * r;\r
+   }\r
+            \r
+   /** \r
+   * Formats a double into a string (like sprintf in C)\r
+   * @param x the number to format\r
+   * @return the formatted string \r
+   * @exception IllegalArgumentException if bad argument\r
+   */\r
+   \r
+   public String form(double x)\r
+   {  String r;\r
+      if (precision < 0) precision = 6;\r
+      int s = 1;\r
+      if (x < 0) { x = -x; s = -1; }\r
+      if (fmt == 'f')\r
+         r = fixed_format(x);\r
+      else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G')\r
+         r = exp_format(x);\r
+      else throw new java.lang.IllegalArgumentException();\r
+      \r
+      return pad(sign(s, r));\r
+   }\r
+   \r
+   /** \r
+   * Formats a long integer into a string (like sprintf in C)\r
+   * @param x the number to format\r
+   * @return the formatted string \r
+   */\r
+   \r
+   public String form(long x)\r
+   {  String r; \r
+      int s = 0;\r
+      if (fmt == 'd' || fmt == 'i')\r
+      {  if (x < 0) \r
+         {  r = ("" + x).substring(1);\r
+            s = -1; \r
+         }\r
+         else \r
+         {  r = "" + x; \r
+            s = 1;\r
+         }\r
+      }\r
+      else if (fmt == 'o')\r
+         r = convert(x, 3, 7, "01234567");\r
+      else if (fmt == 'x')\r
+         r = convert(x, 4, 15, "0123456789abcdef");\r
+      else if (fmt == 'X')\r
+         r = convert(x, 4, 15, "0123456789ABCDEF");\r
+      else throw new java.lang.IllegalArgumentException();\r
+         \r
+      return pad(sign(s, r));\r
+   }\r
+   \r
+   /** \r
+   * Formats a character into a string (like sprintf in C)\r
+   * @param x the value to format\r
+   * @return the formatted string \r
+   */\r
+   \r
+   public String form(char c)\r
+   {  if (fmt != 'c')\r
+         throw new java.lang.IllegalArgumentException();\r
+\r
+      String r = "" + c;\r
+      return pad(r);\r
+   }\r
+   \r
+   /** \r
+   * Formats a string into a larger string (like sprintf in C)\r
+   * @param x the value to format\r
+   * @return the formatted string \r
+   */\r
+   \r
+   public String form(String s)\r
+   {  if (fmt != 's')\r
+         throw new java.lang.IllegalArgumentException();\r
+      if (precision >= 0) s = s.substring(0, precision);\r
+      return pad(s);\r
+   }\r
+   \r
+    \r
+   /**\r
+   * a test stub for the format class\r
+   */\r
+   \r
+   public static void main(String[] a)\r
+   {  double x = 1.23456789012;\r
+      double y = 123;\r
+      double z = 1.2345e30;\r
+      double w = 1.02;\r
+      double u = 1.234e-5;\r
+      int d = 0xCAFE;\r
+      Format.print(System.out, "x = |%f|\n", x);\r
+      Format.print(System.out, "u = |%20f|\n", u);\r
+      Format.print(System.out, "x = |% .5f|\n", x);\r
+      Format.print(System.out, "w = |%20.5f|\n", w);\r
+      Format.print(System.out, "x = |%020.5f|\n", x);\r
+      Format.print(System.out, "x = |%+20.5f|\n", x);\r
+      Format.print(System.out, "x = |%+020.5f|\n", x);\r
+      Format.print(System.out, "x = |% 020.5f|\n", x);\r
+      Format.print(System.out, "y = |%#+20.5f|\n", y);\r
+      Format.print(System.out, "y = |%-+20.5f|\n", y);\r
+      Format.print(System.out, "z = |%20.5f|\n", z);\r
+      \r
+      Format.print(System.out, "x = |%e|\n", x);\r
+      Format.print(System.out, "u = |%20e|\n", u);\r
+      Format.print(System.out, "x = |% .5e|\n", x);\r
+      Format.print(System.out, "w = |%20.5e|\n", w);\r
+      Format.print(System.out, "x = |%020.5e|\n", x);\r
+      Format.print(System.out, "x = |%+20.5e|\n", x);\r
+      Format.print(System.out, "x = |%+020.5e|\n", x);\r
+      Format.print(System.out, "x = |% 020.5e|\n", x);\r
+      Format.print(System.out, "y = |%#+20.5e|\n", y);\r
+      Format.print(System.out, "y = |%-+20.5e|\n", y);\r
+      \r
+      Format.print(System.out, "x = |%g|\n", x);\r
+      Format.print(System.out, "z = |%g|\n", z);\r
+      Format.print(System.out, "w = |%g|\n", w);\r
+      Format.print(System.out, "u = |%g|\n", u);\r
+      Format.print(System.out, "y = |%.2g|\n", y);\r
+      Format.print(System.out, "y = |%#.2g|\n", y);\r
+\r
+      Format.print(System.out, "d = |%d|\n", d);\r
+      Format.print(System.out, "d = |%20d|\n", d);            \r
+      Format.print(System.out, "d = |%020d|\n", d);    \r
+      Format.print(System.out, "d = |%+20d|\n", d);\r
+      Format.print(System.out, "d = |% 020d|\n", d);\r
+      Format.print(System.out, "d = |%-20d|\n", d);\r
+      Format.print(System.out, "d = |%20.8d|\n", d);\r
+      Format.print(System.out, "d = |%x|\n", d);            \r
+      Format.print(System.out, "d = |%20X|\n", d);    \r
+      Format.print(System.out, "d = |%#20x|\n", d);\r
+      Format.print(System.out, "d = |%020X|\n", d);\r
+      Format.print(System.out, "d = |%20.8x|\n", d);\r
+      Format.print(System.out, "d = |%o|\n", d);            \r
+      Format.print(System.out, "d = |%020o|\n", d);    \r
+      Format.print(System.out, "d = |%#20o|\n", d);\r
+      Format.print(System.out, "d = |%#020o|\n", d);\r
+      Format.print(System.out, "d = |%20.12o|\n", d);\r
+      \r
+      Format.print(System.out, "s = |%-20s|\n", "Hello");      \r
+      Format.print(System.out, "s = |%-20c|\n", '!');      \r
+\r
+      // regression test to confirm fix of reported bugs\r
+\r
+      Format.print(System.out, "|%i|\n", Long.MIN_VALUE);\r
+\r
+      Format.print(System.out, "|%6.2e|\n", 0.0);\r
+      Format.print(System.out, "|%6.2g|\n", 0.0);\r
+\r
+      Format.print(System.out, "|%6.2f|\n", 9.99);\r
+      Format.print(System.out, "|%6.2f|\n", 9.999);\r
+\r
+      Format.print(System.out, "|%6.0f|\n", 9.999);\r
+   }\r
+   \r
+   private static String repeat(char c, int n)\r
+   {  if (n <= 0) return "";\r
+      StringBuffer s = new StringBuffer(n);\r
+      for (int i = 0; i < n; i++) s.append(c);\r
+      return s.toString();\r
+   }\r
+\r
+   private static String convert(long x, int n, int m, String d)\r
+   {  if (x == 0) return "0";\r
+      String r = "";\r
+      while (x != 0)\r
+      {  r = d.charAt((int)(x & m)) + r;\r
+         x = x >>> n;\r
+      }\r
+      return r;\r
+   }\r
+\r
+   private String pad(String r)\r
+   {  String p = repeat(' ', width - r.length());\r
+      if (left_align) return pre + r + p + post;\r
+      else return pre + p + r + post;\r
+   }\r
+   \r
+   private String sign(int s, String r)\r
+   {  String p = "";\r
+      if (s < 0) p = "-"; \r
+      else if (s > 0)\r
+      {  if (show_plus) p = "+";\r
+         else if (show_space) p = " ";\r
+      }\r
+      else\r
+      {  if (fmt == 'o' && alternate && r.length() > 0 && r.charAt(0) != '0') p = "0";\r
+         else if (fmt == 'x' && alternate) p = "0x";\r
+         else if (fmt == 'X' && alternate) p = "0X";\r
+      }\r
+      int w = 0;\r
+      if (leading_zeroes) \r
+         w = width;\r
+      else if ((fmt == 'd' || fmt == 'i' || fmt == 'x' || fmt == 'X' || fmt == 'o') \r
+         && precision > 0) w = precision;\r
+      \r
+      return p + repeat('0', w - p.length() - r.length()) + r;\r
+   }\r
+   \r
+   private String fixed_format(double d)\r
+   {  boolean removeTrailing\r
+         = (fmt == 'G' || fmt == 'g') && !alternate;\r
+         // remove trailing zeroes and decimal point\r
+\r
+      if (d > 0x7FFFFFFFFFFFFFFFL) return exp_format(d);\r
+      if (precision == 0) \r
+         return (long)(d + 0.5) + (removeTrailing ? "" : ".");\r
+\r
+      long whole = (long)d;\r
+      double fr = d - whole; // fractional part\r
+      if (fr >= 1 || fr < 0) return exp_format(d);\r
+\r
+      double factor = 1;\r
+      String leading_zeroes = "";\r
+      for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL; i++) \r
+      {  factor *= 10; \r
+         leading_zeroes = leading_zeroes + "0"; \r
+      }\r
+      long l = (long) (factor * fr + 0.5);\r
+      if (l >= factor) { l = 0; whole++; } // CSH 10-25-97\r
+      \r
+      String z = leading_zeroes + l;\r
+      z = "." + z.substring(z.length() - precision, z.length());\r
+\r
+      if (removeTrailing)\r
+      {  int t = z.length() - 1;\r
+         while (t >= 0 && z.charAt(t) == '0') t--;\r
+         if (t >= 0 && z.charAt(t) == '.') t--;\r
+         z = z.substring(0, t + 1);\r
+      }\r
+\r
+      return whole + z;\r
+   }\r
+\r
+   private String exp_format(double d)\r
+   {  String f = "";\r
+      int e = 0;\r
+      double dd = d;\r
+      double factor = 1;\r
+      if (d != 0)\r
+      {  while (dd > 10) { e++; factor /= 10; dd = dd / 10; }\r
+         while (dd < 1) { e--; factor *= 10; dd = dd * 10; }\r
+      }\r
+      if ((fmt == 'g' || fmt == 'G') && e >= -4 && e < precision) \r
+         return fixed_format(d);\r
+      \r
+      d = d * factor;\r
+      f = f + fixed_format(d);\r
+      \r
+      if (fmt == 'e' || fmt == 'g')\r
+         f = f + "e";\r
+      else\r
+         f = f + "E";\r
+\r
+      String p = "000";      \r
+      if (e >= 0) \r
+      {  f = f + "+";\r
+         p = p + e;\r
+      }\r
+      else\r
+      {  f = f + "-";\r
+         p = p + (-e);\r
+      }\r
+         \r
+      return f + p.substring(p.length() - 3, p.length());\r
+   }\r
+   \r
+   private int width;\r
+   private int precision;\r
+   private String pre;\r
+   private String post;\r
+   private boolean leading_zeroes;\r
+   private boolean show_plus;\r
+   private boolean alternate;\r
+   private boolean show_space;\r
+   private boolean left_align;\r
+   private char fmt; // one of cdeEfgGiosxXos\r
+}\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/jalview/util/ListenList.java b/src/jalview/util/ListenList.java
new file mode 100755 (executable)
index 0000000..cc0fc5a
--- /dev/null
@@ -0,0 +1,28 @@
+package jalview.util;\r
+\r
+import java.util.*;\r
+\r
+public class ListenList {\r
+  protected Vector listeners;\r
+  public ListenList() {\r
+    listeners = new Vector();\r
+  }\r
+\r
+  public void addListener(EventListener l) {\r
+    if (l == null) {\r
+      return;\r
+    }\r
+    if (!listeners.contains(l)) {\r
+      listeners.addElement(l);\r
+    }\r
+  }\r
+\r
+  public void removeListener(EventListener l) {\r
+    if (l == null) {\r
+      return;\r
+    }\r
+    if (listeners.contains(l)) {\r
+      listeners.removeElement(l);\r
+    }\r
+  }\r
+}\r
diff --git a/src/jalview/util/QuickSort.java b/src/jalview/util/QuickSort.java
new file mode 100755 (executable)
index 0000000..f81056a
--- /dev/null
@@ -0,0 +1,91 @@
+package jalview.util;\r
+\r
+\r
+public class QuickSort {\r
+\r
+  public static void sort(float[] arr,Object[] s) {\r
+    sort(arr,0,arr.length-1,s);\r
+  }\r
+\r
+  public static void sort(String[] arr,Object[] s) {\r
+    stringSort(arr,0,arr.length-1,s);\r
+  }\r
+\r
+  public static void stringSort(String[] arr,int p, int r,Object[] s) {\r
+    int q;\r
+\r
+    if (p < r) {\r
+      q = stringPartition(arr,p,r,s);\r
+      stringSort(arr,p,q,s);\r
+      stringSort(arr,q+1,r,s);\r
+    }\r
+  }\r
+\r
+  public static void sort(float[] arr,int p, int r,Object[] s) {\r
+    int q;\r
+\r
+    if (p < r) {\r
+      q = partition(arr,p,r,s);\r
+      sort(arr,p,q,s);\r
+      sort(arr,q+1,r,s);\r
+    }\r
+  }\r
+\r
+  private static int partition(float[] arr, int p, int r,Object[] s) {\r
+    float x = arr[p];\r
+    int i = p-1;\r
+    int j = r+1;\r
+\r
+    while(true) {\r
+      do {\r
+        j = j-1;\r
+      }        while (arr[j] > x);\r
+\r
+      do {\r
+        i = i+1;\r
+      } while (arr[i] < x);\r
+\r
+      if ( i < j) {\r
+        float tmp = arr[i];\r
+        arr[i] = arr[j];\r
+        arr[j] = tmp;\r
+\r
+        Object tmp2 = s[i];\r
+        s[i] = s[j];\r
+        s[j] = tmp2;\r
+      } else {\r
+        return j;\r
+      }\r
+    }\r
+  }\r
+  private static int stringPartition(String[] arr, int p, int r,Object[] s) {\r
+    String x = arr[p];\r
+    int i = p-1;\r
+    int j = r+1;\r
+\r
+    while(true) {\r
+      do {\r
+        j = j-1;\r
+      }        while (arr[j].compareTo(x) < 0);\r
+\r
+      do {\r
+        i = i+1;\r
+      } while (arr[i].compareTo(x) > 0);\r
+\r
+      if ( i < j) {\r
+        String tmp = arr[i];\r
+        arr[i] = arr[j];\r
+        arr[j] = tmp;\r
+\r
+        Object tmp2 = s[i];\r
+        s[i] = s[j];\r
+        s[j] = tmp2;\r
+      } else {\r
+        return j;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+\r
+\r
diff --git a/src/jalview/util/WindowUtil.java b/src/jalview/util/WindowUtil.java
new file mode 100755 (executable)
index 0000000..3f44167
--- /dev/null
@@ -0,0 +1,45 @@
+package jalview.util;\r
+\r
+import java.awt.*;\r
+import java.lang.reflect.*;\r
+\r
+public class WindowUtil {\r
+\r
+  public  static Window getWindowAncestor(Component c) {\r
+    for(Container p = c.getParent(); p != null; p = p.getParent()) {\r
+      if (p instanceof Window) {\r
+        return (Window)p;\r
+      }\r
+    }\r
+    return null;\r
+  }\r
+\r
+  public static void removeComponents(Container cont) {\r
+    Component[] components = cont.getComponents();\r
+    Component comp;\r
\r
+    for (int i = 0; i < components.length; i++) {\r
+      comp = components[i];\r
+      if (comp != null) {\r
+        cont.remove(comp);\r
+        if (comp instanceof Container)\r
+          removeComponents((Container) comp);\r
+      }\r
+    }\r
+  }\r
+  public static void invalidateComponents(Container cont) {\r
+    Component[] components = cont.getComponents();\r
+    Component comp;\r
\r
+    cont.invalidate();\r
+    for (int i = 0; i < components.length; i++) {\r
+      comp = components[i];\r
+      if (comp != null) {\r
+        if (comp instanceof Container)\r
+          invalidateComponents((Container) comp);\r
+        else \r
+          comp.invalidate();\r
+      }\r
+    }\r
+  }\r
+}\r