Merge branch 'develop' into features/hmmer
authorTZVanaalten <TZVanaalten@LS30916.ad.lifesci.dundee.ac.uk>
Fri, 18 Aug 2017 16:29:38 +0000 (17:29 +0100)
committerTZVanaalten <TZVanaalten@LS30916.ad.lifesci.dundee.ac.uk>
Fri, 18 Aug 2017 16:29:38 +0000 (17:29 +0100)
Conflicts:
src/jalview/datamodel/SequenceI.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/io/StockholmFile.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/schemes/JalviewColourScheme.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/workers/AlignCalcManager.java

35 files changed:
1  2 
resources/lang/Messages.properties
src/jalview/analysis/AAFrequency.java
src/jalview/analysis/SeqsetUtils.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/AlignViewport.java
src/jalview/bin/Cache.java
src/jalview/bin/Jalview.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentAnnotation.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/AlignmentOrder.java
src/jalview/datamodel/Sequence.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/datamodel/SequenceI.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/io/AlignFile.java
src/jalview/io/FileFormat.java
src/jalview/io/FileLoader.java
src/jalview/io/HMMFile.java
src/jalview/io/IdentifyFile.java
src/jalview/io/StockholmFile.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/jbgui/GPreferences.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/renderer/ResidueShader.java
src/jalview/renderer/ResidueShaderI.java
src/jalview/schemes/JalviewColourScheme.java
src/jalview/schemes/ResidueProperties.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/workers/AlignCalcManager.java
src/jalview/ws/jws2/MsaWSThread.java

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1263,11 -1251,13 +1251,13 @@@ public class AlignmentAnnotatio
        throw new Error(
                "liftOver currently not implemented for transfer of annotation between different types of seqeunce");
      }
-     boolean mapIsTo = (sp2sq != null) ? (sp2sq.getTo() == sq || sp2sq
-             .getTo() == sq.getDatasetSequence()) : false;
+     boolean mapIsTo = (sp2sq != null)
+             ? (sp2sq.getTo() == sq
+                     || sp2sq.getTo() == sq.getDatasetSequence())
+             : false;
  
      // TODO build a better annotation element map and get rid of annotations[]
 -    Map<Integer, Annotation> mapForsq = new HashMap<Integer, Annotation>();
 +    Map<Integer, Annotation> mapForsq = new HashMap<>();
      if (sequenceMapping != null)
      {
        if (sp2sq != null)
@@@ -580,36 -580,6 +580,27 @@@ public interface AlignmentI extends Ann
     */
    AlignedCodonFrame getMapping(SequenceI mapFrom, SequenceI mapTo);
  
-   /**
-    * Calculate the visible start and end index of an alignment. The result is
-    * returned an int array where: int[0] = startIndex, and int[1] = endIndex.
-    * 
-    * @param hiddenCols
-    * @return
-    */
-   public int[] getVisibleStartAndEndIndex(List<int[]> hiddenCols);
    public void setHiddenColumns(HiddenColumns cols);
 +  
 +  /**
 +   * Returns all HMM consensus sequences.
 +   * 
 +   * @param remove
 +   *          If true, remove all HMM consensus sequences from the alignment.
 +   * @return
 +   */
 +  public List<SequenceI> getHMMConsensusSequences(boolean remove);
 +
 +  /**
 +   * Insert a sequence at a position in an alignment
 +   * 
 +   * @param i
 +   *          The idnex of the position.
 +   * @param snew
 +   *          The new sequence.
 +   */
 +  void insertSequenceAt(int i, SequenceI snew);
 +
 +  
  
  }
Simple merge
@@@ -481,18 -478,10 +482,24 @@@ public interface SequenceI extends ASeq
     */
    public List<DBRefEntry> getPrimaryDBRefs();
  
 +  public void updateHMMMapping();
 +
 +  boolean isHMMConsensusSequence();
 +
 +  void setIsHMMConsensusSequence(boolean isHMMConsensusSequence);
 +
 +  boolean hasHMMAnnotation();
 +
 +  void setHasInfo(boolean status);
 +
 +  int getPreviousPosition();
 +
 +  void setPreviousPosition(int previousPosition);
 +
+   /**
+    * 
+    * @return BitSet corresponding to index [0,length) where Comparison.isGap()
+    *         returns true.
+    */
+   BitSet getInsertionsAsBits();
  }
@@@ -178,11 -166,6 +178,10 @@@ public class AlignFrame extends GAlignF
    ViewportRanges vpRanges;
  
    public AlignViewControllerI avc;
 +  /*
 +   * The selected HMM for this align frame
 +   */
 +  HiddenMarkovModel selectedHMM = null;
  
    List<AlignmentPanel> alignPanels = new ArrayList<>();
  
      if (viewport.hasHiddenColumns())
      {
        hiddenColumns = new ArrayList<>();
-       int hiddenOffset = viewport.getSelectionGroup().getStartRes(), hiddenCutoff = viewport
-               .getSelectionGroup().getEndRes();
-       for (int[] region : viewport.getAlignment().getHiddenColumns()
-               .getHiddenRegions())
++
+       int hiddenOffset = viewport.getSelectionGroup().getStartRes();
+       int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
+       ArrayList<int[]> hiddenRegions = viewport.getAlignment()
+               .getHiddenColumns().getHiddenColumnsCopy();
+       for (int[] region : hiddenRegions)
++
        {
          if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff)
          {
@@@ -285,9 -284,8 +284,11 @@@ public class AlignViewport extends Alig
        showOccupancy = Cache.getDefault(Preferences.SHOW_OCCUPANCY, true);
      }
      initAutoAnnotation();
 +    initInformation();
 +
-     String colourProperty = alignment.isNucleotide() ? Preferences.DEFAULT_COLOUR_NUC
++
+     String colourProperty = alignment.isNucleotide()
+             ? Preferences.DEFAULT_COLOUR_NUC
              : Preferences.DEFAULT_COLOUR_PROT;
      String schemeName = Cache.getProperty(colourProperty);
      if (schemeName == null)
@@@ -438,18 -436,14 +438,17 @@@ public class AnnotationLabels extends J
        }
        else if (label.indexOf("Consensus") > -1)
        {
 +
 +
          pop.addSeparator();
          // av and sequencegroup need to implement same interface for
-         final AlignmentAnnotation aaa = aa[selectedRow];
 +
          final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
-                   MessageManager.getString("label.ignore_gaps_consensus"),
-                 (aa[selectedRow].groupRef != null) ? aa[selectedRow].groupRef
-                         .getIgnoreGapsConsensus() : ap.av
-                         .isIgnoreGapsConsensus());
+                 MessageManager.getString("label.ignore_gaps_consensus"),
+                 (aa[selectedRow].groupRef != null)
+                         ? aa[selectedRow].groupRef.getIgnoreGapsConsensus()
+                         : ap.av.isIgnoreGapsConsensus());
+         final AlignmentAnnotation aaa = aa[selectedRow];
          cbmi.addActionListener(new ActionListener()
          {
            @Override
              .setContents(new StringSelection(output), Desktop.instance);
  
      ArrayList<int[]> hiddenColumns = null;
      if (av.hasHiddenColumns())
      {
-       hiddenColumns = new ArrayList<>();
-       for (int[] region : av.getAlignment().getHiddenColumns()
-               .getHiddenRegions())
-       {
-         hiddenColumns.add(new int[] { region[0], region[1] });
-       }
++
+       hiddenColumns = av.getAlignment().getHiddenColumns()
+               .getHiddenColumnsCopy();
++
      }
  
      Desktop.jalviewClipboard = new Object[] { seqs, ds, // what is the dataset
@@@ -231,7 -227,8 +232,8 @@@ public class PopupMenu extends JPopupMe
       * currently selected sequence (if there is one):
       */
      final List<SequenceI> selectedSequence = (seq == null
 -            ? Collections.<SequenceI> emptyList()
 -            : Arrays.asList(seq));
 +            ? Collections.<SequenceI> emptyList() : Arrays.asList(seq));
++
      buildAnnotationTypesMenus(seqShowAnnotationsMenu,
              seqHideAnnotationsMenu, selectedSequence);
      configureReferenceAnnotationsMenu(seqAddReferenceAnnotations,
@@@ -250,21 -213,18 +250,21 @@@ public class Preferences extends GPrefe
      showUnconserved
              .setSelected(Cache.getDefault("SHOW_UNCONSERVED", false));
      showOccupancy.setSelected(Cache.getDefault(SHOW_OCCUPANCY, false));
-     showGroupConsensus.setSelected(Cache.getDefault("SHOW_GROUP_CONSENSUS",
-             false));
-     showGroupConservation.setSelected(Cache.getDefault(
-             "SHOW_GROUP_CONSERVATION", false));
-     showConsensHistogram.setSelected(Cache.getDefault(
-             "SHOW_CONSENSUS_HISTOGRAM", true));
-     showConsensLogo.setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO",
-             false));
+     showGroupConsensus
+             .setSelected(Cache.getDefault("SHOW_GROUP_CONSENSUS", false));
+     showGroupConservation.setSelected(
+             Cache.getDefault("SHOW_GROUP_CONSERVATION", false));
+     showConsensHistogram.setSelected(
+             Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM", true));
+     showConsensLogo
+             .setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO", false));
 +    showInformationHistogram.setSelected(
 +            Cache.getDefault("SHOW_INFORMATION_HISTOGRAM", true));
 +    showHMMLogo.setSelected(Cache.getDefault("SHOW_HMM_LOGO", false));
-     showNpTooltip.setSelected(Cache
-             .getDefault("SHOW_NPFEATS_TOOLTIP", true));
-     showDbRefTooltip.setSelected(Cache.getDefault("SHOW_DBREFS_TOOLTIP",
-             true));
+     showNpTooltip
+             .setSelected(Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true));
+     showDbRefTooltip
+             .setSelected(Cache.getDefault("SHOW_DBREFS_TOOLTIP", true));
  
      String[] fonts = java.awt.GraphicsEnvironment
              .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
Simple merge
Simple merge
Simple merge
index e114f52,0000000..49d885c
mode 100644,000000..100644
--- /dev/null
@@@ -1,737 -1,0 +1,773 @@@
 +package jalview.io;
 +
++import jalview.api.AlignExportSettingI;
++import jalview.api.AlignmentViewPanel;
 +import jalview.datamodel.HMMNode;
 +import jalview.datamodel.HiddenMarkovModel;
 +import jalview.datamodel.SequenceI;
 +
 +import java.io.BufferedReader;
 +import java.io.IOException;
 +import java.util.ArrayList;
 +import java.util.List;
 +import java.util.Scanner;
 +
 +
 +/**
 + * Adds capability to read in and write out HMMER3 files. .
 + * 
 + * 
 + * @author TZVanaalten
 + *
 + */
 +public class HMMFile extends AlignFile
 +        implements AlignmentFileReaderI, AlignmentFileWriterI
 +{
 +  // HMM to store file data
 +  private HiddenMarkovModel hmm;
 +
 +  // number of possible transitions
 +  private static final int NUMBER_OF_TRANSITIONS = 7;
 +
-   private static final String NL = "\n";
++  private String NL = "\n";
 +
 +  //number of symbols in the alphabet used in the hidden Markov model
 +  int numberOfSymbols;
 +
 +  private final String SPACE = " ";
 +
 +  private final String COMPO = "COMPO";
 +
 +  private final String EMPTY = "";
 +
 +  //This is a line that needs to be added to each HMMER� file. It is purely for readability.
 +  private static final String TRANSITIONTYPELINE = "            m->m     m->i     m->d     i->m     i->i     d->m     d->d";
 +
 +  /**
 +   * Parses immediately.
 +   * 
 +   * @param inFile
 +   * @param type
 +   * @throws IOException
 +   */
 +  public HMMFile(String inFile, DataSourceType type) throws IOException
 +  {
 +    super(inFile, type);
 +  }
 +
 +  /**
 +   * Parses immediately.
 +   * 
 +   * @param source
 +   * @throws IOException
 +   */
 +  public HMMFile(FileParse source) throws IOException
 +  {
 +    super(source);
 +  }
 +
 +  /**
 +   * Default constructor, do not use!
 +   */
 +  public HMMFile()
 +  {
 +
 +  }
 +
 +  /**
 +   * Constructor for HMMFile used for exporting.
 +   * 
 +   * @param hmm
 +   * @param exportImmediately
 +   */
 +  public HMMFile(HiddenMarkovModel markov)
 +  {
 +    hmm = markov;
 +  }
 +
 +  /**
 +   * For testing, do not use.
 +   * 
 +   * @param br
 +   */
 +  HMMFile(BufferedReader br)
 +  {
 +    dataIn = br;
 +  }
 +
 +  /**
 +   * Returns the HMM produced by reading in a HMMER3 file.
 +   * 
 +   * @return
 +   */
 +  public HiddenMarkovModel getHMM()
 +  {
 +    return hmm;
 +  }
 +
 +  /**
 +   * Sets the HMM used in this file.
 +   * 
 +   * @param model
 +   */
 +  public void setHMM(HiddenMarkovModel model)
 +  {
 +    this.hmm = model;
 +  }
 +
 +  /**
 +   * Gets the name of the hidden Markov model.
 +   * 
 +   * @return
 +   */
 +  public String getName()
 +  {
 +    return hmm.getName();
 +  }
 +
 +  /**
 +   * Reads the data from HMM file into the HMM field on this object.
 +   * 
 +   * @throws IOException
 +   */
 +  @Override
 +  public void parse() throws IOException
 +  {
 +    hmm = new HiddenMarkovModel();
 +    parseFileProperties(dataIn);
 +    parseModel(dataIn);
 +  }
 +
 +  /**
 +   * Reads the data from HMM file into the HMM field on this object.
 +   * 
 +   * @throws IOException
 +   */
 +
 +  public void parse(BufferedReader br) throws IOException
 +  {
 +    hmm = new HiddenMarkovModel();
 +    parseFileProperties(br);
 +    parseModel(br);
 +  }
 +
 +
 +
 +  /**
 +   * Imports the file properties from a HMMER3 file.
 +   * 
 +   * @param input
 +   *          The buffered reader used to read in the file.
 +   * @throws IOException
 +   */
 +  void parseFileProperties(BufferedReader input) throws IOException
 +  {
 +    boolean readingFile = true;
 +    hmm.setFileHeader(input.readLine());
 +    String line = input.readLine();
 +    while (readingFile)
 +    {
 +      if (line != null)
 +      {
 +        Scanner parser = new Scanner(line);
 +        String next = parser.next();
 +        if ("HMM".equals(next)) // indicates start of HMM data (end of file
 +                              // properties)
 +        {
 +          readingFile = false;
 +          fillSymbols(parser);
 +          numberOfSymbols = hmm.getNumberOfSymbols();
 +        }
 +        else if ("STATS".equals(next))
 +        {
 +          parser.next();
 +          String key;
 +          String value;
 +          key = parser.next();
 +          value = parser.next() + SPACE + SPACE + parser.next();
 +          hmm.addFileProperty(key, value);
 +        }
 +        else
 +        {
 +          String key = next;
 +          String value = parser.next();
 +          while (parser.hasNext())
 +          {
 +            value = value + SPACE + parser.next();
 +          }
 +          hmm.addFileProperty(key, value);
 +        }
 +        parser.close();
 +      }
 +      line = input.readLine();
 +      if (line == null)
 +      {
 +        readingFile = false;
 +      }
 +    }
 +
 +  }
 +
 +  /**
 +   * Parses the model data from the HMMER3 file
 +   * 
 +   * @param input
 +   *          The buffered reader used to read the file.
 +   * @throws IOException
 +   */
 +  void parseModel(BufferedReader input) throws IOException
 +  {
 +    String line = input.readLine();
 +    int node = 0;
 +    while (!"//".equals(line))
 +    {
 +      hmm.getNodes().add(new HMMNode());
 +      String next;
 +      Scanner matchReader = new Scanner(line);
 +      next = matchReader.next();
 +      if (next.equals(COMPO) || node > 0)
 +      {
 +        // stores match emission line in list
 +        List<Double> matches = new ArrayList<>();
 +        matches = fillList(matchReader, numberOfSymbols);
 +        hmm.getNodes().get(node).setMatchEmissions(matches);
 +        if (node > 0)
 +        {
 +          parseAnnotations(matchReader, node);
 +        }
 +      }
 +      matchReader.close();
 +      // stores insert emission line in list
 +      line = input.readLine();
 +      Scanner insertReader = new Scanner(line);
 +      List<Double> inserts = new ArrayList<>();
 +      inserts = fillList(insertReader, numberOfSymbols);
 +      hmm.getNodes().get(node).setInsertEmissions(inserts);
 +      insertReader.close();
 +
 +      // stores state transition line in list
 +      line = input.readLine();
 +      Scanner transitionReader = new Scanner(line);
 +      List<Double> transitions = new ArrayList<>();
 +      transitions = fillList(transitionReader, NUMBER_OF_TRANSITIONS);
 +      hmm.getNodes().get(node).setStateTransitions(transitions);
 +      transitionReader.close();
 +      line = input.readLine();
 +      node++;
 +    }
 +
 +  }
 +
 +  /**
 +   * Parses the annotations on the match emission line.
 +   * 
 +   * @param scanner
 +   *          The scanner which is processing match emission line.
 +   * @param index
 +   *          The index of node which is being scanned.
 +   */
 +  void parseAnnotations(Scanner scanner, int index)
 +  {
 +    if (hmm.mapIsActive() && scanner.hasNext())
 +    {
 +      int column;
 +      column = scanner.nextInt();
 +      hmm.getNodes().get(index).setAlignmentColumn(column - 1);
 +      hmm.getNodeLookup().put(column - 1, index);
 +    }
 +    else
 +    {
 +      scanner.next();
 +    }
 +
 +    if (scanner.hasNext())
 +    {
 +      char consensusR;
 +      consensusR = charValue(scanner.next());
 +      hmm.getNodes().get(index).setConsensusResidue(consensusR);
 +    }
 +
 +    if (scanner.hasNext())
 +    {
 +      char reference;
 +      reference = charValue(scanner.next());
 +      hmm.getNodes().get(index).setReferenceAnnotation(reference);
 +    }
 +
 +    if (scanner.hasNext())
 +    {
 +      char value;
 +      value = charValue(scanner.next());
 +      hmm.getNodes().get(index).setMaskValue(value);
 +    }
 +    if (scanner.hasNext())
 +    {
 +      char consensusS;
 +      consensusS = charValue(scanner.next());
 +      hmm.getNodes().get(index).setConsensusStructure(consensusS);
 +    }
 +  }
 +
 +
 +
 +  /**
 +   * Fills a list of doubles based on an input line.
 +   * 
 +   * @param input
 +   *          The scanner for the line containing the data to be transferred to
 +   *          the list.
 +   * @param numberOfElements
 +   *          The number of elements in the list to be filled.
 +   * @return filled list Returns the list of doubles.
 +   * @throws IOException
 +   */
 +  static List<Double> fillList(Scanner input,
 +          int numberOfElements) throws IOException
 +  {
 +    List<Double> list = new ArrayList<>();
 +    for (int i = 0; i < numberOfElements; i++)
 +    {
 +
 +      String next = input.next();
 +      if (next.contains("*")) // state transitions to or from delete states
 +                              // occasionally have values of -infinity. These
 +                              // values are represented by an * in the .hmm
 +                              // file.
 +      {
 +        list.add(Double.NEGATIVE_INFINITY);
 +      }
 +      else
 +      {
 +        double prob = Double.valueOf(next);
 +        prob = Math.pow(Math.E, -prob);
 +        list.add(prob);
 +      }
 +    }
 +    if (list.size() < numberOfElements)
 +    {
 +      throw new IOException("Incomplete data");
 +    }
 +    return list;
 +  }
 +
 +  /**
 +   * Returns a string to be added to the StringBuilder containing the entire
 +   * output String.
 +   * 
 +   * @param initialColumnSeparation
 +   *          The initial whitespace separation between the left side of the
 +   *          file and first character.
 +   * @param columnSeparation
 +   *          The separation between subsequent data entries.
 +   * @param data
 +   *          The list fo data to be added to the String.
 +   * @return
 +   */
 +  String addData(int initialColumnSeparation,
 +          int columnSeparation, List<String> data)
 +  {
 +    String line = EMPTY;
 +    int index = 0;
 +    for (String value : data)
 +    {
 +      if (index == 0)
 +      {
 +        line += String.format("%" + initialColumnSeparation + "s", value);
 +      }
 +      else
 +      {
 +        line += String.format("%" + columnSeparation + "s", value);
 +      }
 +      index++;
 +    }
 +    return line;
 +  }
 +
 +  /**
 +   * Converts list of characters into a list of Strings.
 +   * 
 +   * @param list
 +   * @return Returns the list of Strings.
 +   */
 +  List<String> charListToStringList(List<Character> list)
 +  {
 +    List<String> strList = new ArrayList<>();
 +    for (char value : list)
 +    {
 +      String strValue = Character.toString(value);
 +      strList.add(strValue);
 +    }
 +    return strList;
 +  }
 +
 +  /**
 +   * Converts a list of doubles into a list of Strings, rounded to the nearest
 +   * 5th decimal place.
 +   * 
 +   * @param list
 +   * @param noOfDecimals
 +   * @return
 +   */
 +  List<String> doubleListToStringList(List<Double> list)
 +  {
 +    List<String> strList = new ArrayList<>();
 +    for (double value : list)
 +    {
 +      String strValue;
 +      if (value > 0)
 +      {
 +        strValue = String.format("%.5f", value);
 +
 +      }
 +      else if (value == -0.00000d)
 +      {
 +        strValue = "0.00000";
 +      }
 +      else
 +      {
 +        strValue = "*";
 +      }
 +
 +      strList.add(strValue);
 +    }
 +    return strList;
 +  }
 +
 +  /**
 +   * Converts a primitive array of Strings to a list of Strings.
 +   * 
 +   * @param array
 +   * @return
 +   */
 +  List<String> stringArrayToStringList(String[] array)
 +  {
 +    List<String> list = new ArrayList<>();
 +    for (String value : array)
 +    {
 +      list.add(value);
 +    }
 +
 +    return list;
 +  }
 +
 +  /**
 +   * Returns a string containing the model data.
 +   */
 +  String getModelAsString()
 +  {
 +    StringBuffer output = new StringBuffer();
 +    String symbolLine = "HMM";
 +    List<Character> charSymbols = hmm.getSymbols();
 +    List<String> strSymbols;
 +    strSymbols = charListToStringList(charSymbols);
 +    symbolLine += addData(11, 9, strSymbols);
 +    output.append(symbolLine);
 +    output.append(NL + TRANSITIONTYPELINE);
 +
 +    int length = hmm.getLength();
 +
 +    for (int node = 0; node <= length; node++)
 +    {
 +      String matchLine;
 +      if (node == 0)
 +      {
 +        matchLine = String.format("%7s", "COMPO");
 +      }
 +      else
 +      {
 +        matchLine = String.format("%7s", node);
 +      }
 +
 +      List<String> strMatches;
 +      List<Double> doubleMatches;
 +      doubleMatches = convertListToLogSpace(
 +              hmm.getNode(node).getMatchEmissions());
 +      strMatches = doubleListToStringList(doubleMatches);
 +      matchLine += addData(10, 9, strMatches);
 +
 +
 +      if (node != 0)
 +      {
 +        matchLine += SPACE + (hmm.getNodeAlignmentColumn(node) + 1);
 +        matchLine += SPACE + hmm.getConsensusResidue(node);
 +        matchLine += SPACE + hmm.getReferenceAnnotation(node);
 +        if (hmm.getFileHeader().contains("HMMER3/f"))
 +        {
 +          matchLine += SPACE + hmm.getMaskedValue(node);
 +          matchLine += SPACE + hmm.getConsensusStructure(node);
 +        }
 +
 +      }
 +
 +      output.append(NL + matchLine);
 +      
 +      String insertLine = EMPTY;
 +      List<String> strInserts;
 +      List<Double> doubleInserts;
 +      doubleInserts = convertListToLogSpace(
 +              hmm.getNode(node).getInsertEmissions());
 +      strInserts = doubleListToStringList(doubleInserts);
 +      insertLine += addData(17, 9, strInserts);
 +
 +      output.append(NL + insertLine);
 +
 +      String transitionLine = EMPTY;
 +      List<String> strTransitions;
 +      List<Double> doubleTransitions;
 +      doubleTransitions = convertListToLogSpace(
 +              hmm.getNode(node).getStateTransitions());
 +      strTransitions = doubleListToStringList(doubleTransitions);
 +      transitionLine += addData(17, 9, strTransitions);
 +
 +      output.append(NL + transitionLine);
 +    }
 +    return output.toString();
 +  }
 +
 +  /**
 +   * Returns a String containing the HMM file properties
 +   */
 +  String getFilePropertiesAsString()
 +  {
 +    StringBuffer output = new StringBuffer();
 +    String line;
 +
 +    output.append(hmm.getFileHeader());
 +    
 +    line = String.format("%-5s %1s", "NAME", hmm.getName());
 +    output.append(NL + line);
 +
 +    if (hmm.getAccessionNumber() != null)
 +    {
 +    line = String.format("%-5s %1s", "ACC", hmm.getAccessionNumber());
 +      output.append(NL + line);
 +    }
 +
 +    if (hmm.getDescription() != null)
 +    {
 +    line = String.format("%-5s %1s", "DESC", hmm.getDescription());
 +      output.append(NL + line);
 +    }
 +    line = String.format("%-5s %1s", "LENG", hmm.getLength());
 +    output.append(NL + line);
 +
 +    if (hmm.getMaxInstanceLength() != null)
 +    {
 +    line = String.format("%-5s %1s", "MAXL", hmm.getMaxInstanceLength());
 +      output.append(NL + line);
 +    }
 +    line = String.format("%-5s %1s", "ALPH", hmm.getAlphabetType());
 +    output.append(NL + line);
 +
 +    boolean status;
 +    String statusStr;
 +
 +    status = hmm.referenceAnnotationIsActive();
 +    statusStr = HiddenMarkovModel.findStringFromBoolean(status);
 +    line = String.format("%-5s %1s", "RF",
 +            statusStr);
 +    output.append(NL + line);
 +
 +    status = hmm.maskValueIsActive();
 +    statusStr = HiddenMarkovModel.findStringFromBoolean(status);
 +    line = String.format("%-5s %1s", "MM",
 +            statusStr);
 +    output.append(NL + line);
 +    
 +    status = hmm.consensusResidueIsActive();
 +    statusStr = HiddenMarkovModel.findStringFromBoolean(status);
 +    line = String.format("%-5s %1s", "CONS",
 +            statusStr);
 +    output.append(NL + line);
 +
 +    status = hmm.consensusStructureIsActive();
 +    statusStr = HiddenMarkovModel.findStringFromBoolean(status);
 +    line = String.format("%-5s %1s", "CS",
 +            statusStr);
 +    output.append(NL + line);
 +
 +    status = hmm.mapIsActive();
 +    statusStr = HiddenMarkovModel.findStringFromBoolean(status);
 +    line = String.format("%-5s %1s", "MAP",
 +            statusStr);
 +    output.append(NL + line);
 +
 +
 +    if (hmm.getDate() != null)
 +    {
 +    line = String.format("%-5s %1s", "DATE", hmm.getDate());
 +      output.append(NL + line);
 +    }
 +    if (hmm.getNumberOfSequences() != null)
 +    {
 +    line = String.format("%-5s %1s", "NSEQ", hmm.getNumberOfSequences());
 +      output.append(NL + line);
 +    }
 +    if (hmm.getEffectiveNumberOfSequences() != null)
 +    {
 +    line = String.format("%-5s %1s", "EFFN",
 +            hmm.getEffectiveNumberOfSequences());
 +      output.append(NL + line);
 +    }
 +    if (hmm.getCheckSum() != null)
 +    {
 +    line = String.format("%-5s %1s", "CKSUM", hmm.getCheckSum());
 +      output.append(NL + line);
 +    }
 +    if (hmm.getGatheringThreshold() != null)
 +    {
 +    line = String.format("%-5s %1s", "GA", hmm.getGatheringThreshold());
 +      output.append(NL + line);
 +    }
 +
 +    if (hmm.getTrustedCutoff() != null)
 +    {
 +    line = String.format("%-5s %1s", "TC", hmm.getTrustedCutoff());
 +      output.append(NL + line);
 +    }
 +    if (hmm.getNoiseCutoff() != null)
 +    {
 +    line = String.format("%-5s %1s", "NC", hmm.getNoiseCutoff());
 +      output.append(NL + line);
 +    }
 +    if (hmm.getMSV() != null)
 +    {
 +      line = String.format("%-19s %18s", "STATS LOCAL MSV", hmm.getMSV());
 +      output.append(NL + line);
 +
 +      line = String.format("%-19s %18s", "STATS LOCAL VITERBI",
 +              hmm.getViterbi());
 +      output.append(NL + line);
 +    
 +      line = String.format("%-19s %18s", "STATS LOCAL FORWARD",
 +              hmm.getForward());
 +      output.append(NL + line);
 +    }
 +    return output.toString();
 +  }
 +
 +
 +  /**
 +   * Returns the char value of a single lettered String.
 +   * 
 +   * @param string
 +   * @return
 +   */
 +  char charValue(String string)
 +  {
 +    char character;
 +    character = string.charAt(0);
 +    return character;
 +
 +  }
 +
 +  @Override
 +  public String print(SequenceI[] seqs, boolean jvsuffix)
 +  {
++    if (seqs[0].getHMM() != null)
++    {
++      hmm = seqs[0].getHMM();
++    }
 +    return print();
 +  }
 +
 +  /**
 +   * Prints the .hmm file to a String.
 +   * 
 +   * @return
 +   */
 +  public String print()
 +  {
 +    StringBuffer output = new StringBuffer();
 +    output.append(getFilePropertiesAsString());
 +    output.append(NL);
 +    output.append(getModelAsString());
 +    output.append(NL + "//");
 +    return output.toString();
 +  }
 +
 +  /**
 +   * Converts the probabilities contained in a list into log space.
 +   * 
 +   * @param list
 +   */
 +  List<Double> convertListToLogSpace(List<Double> list)
 +  {
 +
 +    List<Double> convertedList = new ArrayList<>();
 +    for (int i = 0; i < list.size(); i++)
 +    {
 +      double prob = list.get(i);
 +      double logProb = -1 * Math.log(prob);
 +
 +      convertedList.add(logProb);
 +    }
 +    return convertedList;
 +
 +
 +  }
 +
 +  /**
 +   * Returns the HMM sequence produced by reading a .hmm file.
 +   */
 +  @Override
 +  public SequenceI[] getSeqsAsArray()
 +  {
 +    SequenceI hmmSeq = hmm.initHMMSequence();
 +    SequenceI[] seq = new SequenceI[1];
 +    seq[0] = hmmSeq;
 +    return seq;
 +
 +  }
 +
 +  /**
 +   * Fills symbol array and adds each symbol to an index lookup
 +   * 
 +   * @param parser
 +   *          The scanner scanning the symbol line in the file.
 +   */
 +  public void fillSymbols(Scanner parser)
 +  {
 +    int i = 0;
 +    while (parser.hasNext())
 +    {
 +      String strSymbol = parser.next();
 +      char[] symbol = strSymbol.toCharArray();
 +      hmm.getSymbols().add(symbol[0]);
 +      hmm.setSymbolIndex(symbol[0], i);
 +      i++;
 +    }
 +  }
 +
++  @Override
++  public void setNewlineString(String newLine)
++  {
++    NL = newLine;
++  }
++
++  @Override
++  public void setExportSettings(AlignExportSettingI exportSettings)
++  {
++
++  }
++
++  @Override
++  public void configureForView(AlignmentViewPanel viewpanel)
++  {
++
++  }
++
++  @Override
++  public boolean hasWarningMessage()
++  {
++    return false;
++  }
++
++  @Override
++  public String getWarningMessage()
++  {
++    return "warning message";
++  }
++
 +}
 +
Simple merge
@@@ -995,53 -997,52 +997,53 @@@ public class StockholmFile extends Alig
        }
      }
  
 +
-       // output annotations
-       while (i < s.length && s[i] != null)
-       {
-         AlignmentAnnotation[] alAnot = s[i].getAnnotation();
+     // output annotations
+     while (i < s.length && s[i] != null)
+     {
+       AlignmentAnnotation[] alAnot = s[i].getAnnotation();
        if (alAnot != null)
+       {
+         Annotation[] ann;
+         for (int j = 0; j < alAnot.length; j++)
          {
-           Annotation[] ann;
-           for (int j = 0; j < alAnot.length; j++)
-           {
  
-             String key = type2id(alAnot[j].label);
-             boolean isrna = alAnot[j].isValidStruc();
+           String key = type2id(alAnot[j].label);
+           boolean isrna = alAnot[j].isValidStruc();
 -
+           if (isrna)
+           {
+             // hardwire to secondary structure if there is RNA secondary
+             // structure on the annotation
+             key = "SS";
+           }
+           if (key == null)
+           {
  
-             if (isrna)
-             {
-               // hardwire to secondary structure if there is RNA secondary
-               // structure on the annotation
-               key = "SS";
-             }
-             if (key == null)
-             {
+             continue;
+           }
  
-               continue;
-             }
+           // out.append("#=GR ");
+           out.append(new Format("%-" + maxid + "s").form(
+                   "#=GR " + printId(s[i], jvSuffix) + " " + key + " "));
+           ann = alAnot[j].annotations;
+           String seq = "";
+           for (int k = 0; k < ann.length; k++)
+           {
+             seq += outputCharacter(key, k, isrna, ann, s[i]);
 -          }
 +
-             // out.append("#=GR ");
-             out.append(new Format("%-" + maxid + "s").form(
-                     "#=GR " + printId(s[i], jvSuffix) + " " + key + " "));
-             ann = alAnot[j].annotations;
-             String seq = "";
-             for (int k = 0; k < ann.length; k++)
-             {
-               seq += outputCharacter(key, k, isrna, ann, s[i]);
-             }
-             out.append(seq);
-             out.append(newline);
-           }
 +        }
-         out.append(new Format("%-" + maxid + "s")
-                 .form(printId(s[i], jvSuffix) + " "));
-         out.append(s[i].getSequenceAsString());
-         out.append(newline);
-         i++;
+           out.append(seq);
+           out.append(newline);
+         }
        }
  
+       out.append(new Format("%-" + maxid + "s")
+               .form(printId(s[i], jvSuffix) + " "));
+       out.append(s[i].getSequenceAsString());
+       out.append(newline);
+       i++;
+     }
      // alignment annotation
      AlignmentAnnotation aa;
      if (al.getAlignmentAnnotation() != null)
          out.append(newline);
        }
      }
++    
 +
  
      out.append("//");
      out.append(newline);
      out.append("# STOCKHOLM 1.0");
      out.append(newline);
      print(getSeqsAsArray(), false);
--
++    
+     out.append("//");
      out.append(newline);
      return out.toString();
    }
@@@ -274,16 -258,17 +274,17 @@@ public class GAlignFrame extends JInter
          saveAs_actionPerformed(e);
        }
      };
 -
 +  
      // FIXME getDefaultToolkit throws an exception in Headless mode
-     KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask()
-             | KeyEvent.SHIFT_MASK, false);
+     KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                     | KeyEvent.SHIFT_MASK,
+             false);
      addMenuActionAndAccelerator(keyStroke, saveAs, al);
 -
 +  
      closeMenuItem.setText(MessageManager.getString("action.close"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_W,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
      JMenu calculateMenu = new JMenu(
              MessageManager.getString("action.calculate"));
      webService.setText(MessageManager.getString("action.web_service"));
 +    hmmerMenu.setText(MessageManager.getString("action.hmmer"));
 +    String status = Cache.getProperty("HMMER_FUNCTIONING");
 +    if ("false".equals(status) || status == null)
 +    {
 +      hmmerMenu.setEnabled(false);
 +    }
 +    else
 +    {
 +      hmmerMenu.setEnabled(true);
 +    }
 +    hmmerMenu.addActionListener(new ActionListener()
 +    {
 +      @Override
 +      public void actionPerformed(ActionEvent e)
 +      {
 +        hmmerMenu_actionPerformed(e);
 +      }
 +    });
      JMenuItem selectAllSequenceMenuItem = new JMenuItem(
              MessageManager.getString("action.select_all"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, deselectAllSequenceMenuItem, al);
 -
 +  
      JMenuItem invertSequenceMenuItem = new JMenuItem(
              MessageManager.getString("action.invert_sequence_selection"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, remove2LeftMenuItem, al);
 -
 +  
      JMenuItem remove2RightMenuItem = new JMenuItem(
              MessageManager.getString("action.remove_right"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_R, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_R,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, remove2RightMenuItem, al);
 -
 +  
      JMenuItem removeGappedColumnMenuItem = new JMenuItem(
              MessageManager.getString("action.remove_empty_columns"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, removeGappedColumnMenuItem, al);
 -
 +  
      JMenuItem removeAllGapsMenuItem = new JMenuItem(
              MessageManager.getString("action.remove_all_gaps"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask()
-             | KeyEvent.SHIFT_MASK, false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                     | KeyEvent.SHIFT_MASK,
+             false);
      al = new ActionListener()
      {
        @Override
          sortGroupMenuItem_actionPerformed(e);
        }
      });
 -
 +  
      JMenuItem removeRedundancyMenuItem = new JMenuItem(
              MessageManager.getString("action.remove_redundancy"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
      statusBar.setFont(new java.awt.Font("Verdana", 0, 11));
      statusBar.setBorder(BorderFactory.createLineBorder(Color.black));
      statusBar.setText(MessageManager.getString("label.status_bar"));
-     outputTextboxMenu.setText(MessageManager
-             .getString("label.out_to_textbox"));
-   
++
+     outputTextboxMenu
+             .setText(MessageManager.getString("label.out_to_textbox"));
++
      annotationPanelMenuItem.setActionCommand("");
-     annotationPanelMenuItem.setText(MessageManager
-             .getString("label.show_annotations"));
-     annotationPanelMenuItem.setState(Cache.getDefault("SHOW_ANNOTATIONS",
-             true));
+     annotationPanelMenuItem
+             .setText(MessageManager.getString("label.show_annotations"));
+     annotationPanelMenuItem
+             .setState(Cache.getDefault("SHOW_ANNOTATIONS", true));
      annotationPanelMenuItem.addActionListener(new ActionListener()
      {
        @Override
              MessageManager.getString("label.sort_annotations_by_sequence"));
      final JCheckBoxMenuItem sortAnnByLabel = new JCheckBoxMenuItem(
              MessageManager.getString("label.sort_annotations_by_label"));
-   
-     sortAnnBySequence
-             .setSelected(sortAnnotationsBy == SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
++
+     sortAnnBySequence.setSelected(
+             sortAnnotationsBy == SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
      sortAnnBySequence.addActionListener(new ActionListener()
      {
        @Override
          overviewMenuItem_actionPerformed(e);
        }
      });
 -
 +  
      undoMenuItem.setEnabled(false);
      undoMenuItem.setText(MessageManager.getString("action.undo"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, undoMenuItem, al);
 -
 +  
      redoMenuItem.setEnabled(false);
      redoMenuItem.setText(MessageManager.getString("action.redo"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
          wrapMenuItem_actionPerformed(e);
        }
      });
 -
 +  
      JMenuItem printMenuItem = new JMenuItem(
              MessageManager.getString("action.print"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_P, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_P,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
          renderGapsMenuItem_actionPerformed(e);
        }
      });
 -
 +  
      JMenuItem findMenuItem = new JMenuItem(
              MessageManager.getString("action.find"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      findMenuItem.setToolTipText(JvSwingUtils.wrapTooltip(true,
              MessageManager.getString("label.find_tip")));
      al = new ActionListener()
        }
      };
      addMenuActionAndAccelerator(keyStroke, findMenuItem, al);
-   
-     showSeqFeatures.setText(MessageManager
-             .getString("label.show_sequence_features"));
+     showSeqFeatures.setText(
+             MessageManager.getString("label.show_sequence_features"));
++
      showSeqFeatures.addActionListener(new ActionListener()
      {
        @Override
       * void actionPerformed(ActionEvent actionEvent) {
       * showSeqFeaturesHeight_actionPerformed(actionEvent); } });
       */
-     showDbRefsMenuitem.setText(MessageManager
-             .getString("label.show_database_refs"));
+     showDbRefsMenuitem
+             .setText(MessageManager.getString("label.show_database_refs"));
      showDbRefsMenuitem.addActionListener(new ActionListener()
      {
 -
 +  
        @Override
        public void actionPerformed(ActionEvent e)
        {
          showDbRefs_actionPerformed(e);
        }
 -
 +  
      });
-     showNpFeatsMenuitem.setText(MessageManager
-             .getString("label.show_non_positional_features"));
+     showNpFeatsMenuitem.setText(
+             MessageManager.getString("label.show_non_positional_features"));
      showNpFeatsMenuitem.addActionListener(new ActionListener()
      {
 -
 +  
        @Override
        public void actionPerformed(ActionEvent e)
        {
          showNpFeats_actionPerformed(e);
        }
 -
 +  
      });
-     showGroupConservation.setText(MessageManager
-             .getString("label.group_conservation"));
+     showGroupConservation
+             .setText(MessageManager.getString("label.group_conservation"));
      showGroupConservation.addActionListener(new ActionListener()
      {
 -
 +  
        @Override
        public void actionPerformed(ActionEvent e)
        {
          showGroupConservation_actionPerformed(e);
        }
 -
 +  
      });
-   
-     showGroupConsensus.setText(MessageManager
-             .getString("label.group_consensus"));
+     showGroupConsensus
+             .setText(MessageManager.getString("label.group_consensus"));
      showGroupConsensus.addActionListener(new ActionListener()
      {
 -
 +  
        @Override
        public void actionPerformed(ActionEvent e)
        {
          showGroupConsensus_actionPerformed(e);
        }
 -
 +  
      });
-     showConsensusHistogram.setText(MessageManager
-             .getString("label.show_consensus_histogram"));
+     showConsensusHistogram.setText(
+             MessageManager.getString("label.show_consensus_histogram"));
      showConsensusHistogram.addActionListener(new ActionListener()
      {
 -
 +  
        @Override
        public void actionPerformed(ActionEvent e)
        {
          showConsensusHistogram_actionPerformed(e);
        }
 -
 +  
      });
-     showSequenceLogo.setText(MessageManager
-             .getString("label.show_consensus_logo"));
+     showSequenceLogo
+             .setText(MessageManager.getString("label.show_consensus_logo"));
      showSequenceLogo.addActionListener(new ActionListener()
      {
 -
 +  
        @Override
        public void actionPerformed(ActionEvent e)
        {
          showSequenceLogo_actionPerformed(e);
        }
 -
 +  
      });
-     normaliseSequenceLogo.setText(MessageManager
-             .getString("label.norm_consensus_logo"));
+     normaliseSequenceLogo
+             .setText(MessageManager.getString("label.norm_consensus_logo"));
      normaliseSequenceLogo.addActionListener(new ActionListener()
      {
 -
 +  
        @Override
        public void actionPerformed(ActionEvent e)
        {
          normaliseSequenceLogo_actionPerformed(e);
        }
 -
 +  
      });
-     applyAutoAnnotationSettings.setText(MessageManager
-             .getString("label.apply_all_groups"));
+     applyAutoAnnotationSettings
+             .setText(MessageManager.getString("label.apply_all_groups"));
      applyAutoAnnotationSettings.setState(false);
      applyAutoAnnotationSettings.setVisible(true);
      applyAutoAnnotationSettings.addActionListener(new ActionListener()
          sortAnnotations_actionPerformed();
        }
      });
 -
 +  
      JMenuItem deleteGroups = new JMenuItem(
              MessageManager.getString("action.undefine_groups"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_U, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_U,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
          annotationColumn_actionPerformed(e);
        }
      });
 -
 +  
      JMenuItem createGroup = new JMenuItem(
              MessageManager.getString("action.create_group"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, createGroup, al);
 -
 +  
      JMenuItem unGroup = new JMenuItem(
              MessageManager.getString("action.remove_group"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask()
-             | KeyEvent.SHIFT_MASK, false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                     | KeyEvent.SHIFT_MASK,
+             false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, unGroup, al);
 -
 +  
      copy.setText(MessageManager.getString("action.copy"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
-   
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_C,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, copy, al);
 -
 +  
      cut.setText(MessageManager.getString("action.cut"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_X,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
        }
      };
      addMenuActionAndAccelerator(keyStroke, pasteNew, al);
 -
 +  
      JMenuItem pasteThis = new JMenuItem(
              MessageManager.getString("label.to_this_alignment"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
          createPNG(null);
        }
      });
-     createPNG.setActionCommand(MessageManager
-             .getString("label.save_png_image"));
-   
+     createPNG.setActionCommand(
+             MessageManager.getString("label.save_png_image"));
 -
      JMenuItem font = new JMenuItem(MessageManager.getString("action.font"));
      font.addActionListener(new ActionListener()
      {
          createSVG(null);
        }
      });
 -
 +  
      JMenuItem loadTreeMenuItem = new JMenuItem(
              MessageManager.getString("label.load_associated_tree"));
-     loadTreeMenuItem.setActionCommand(MessageManager
-             .getString("label.load_tree_for_sequence_set"));
+     loadTreeMenuItem.setActionCommand(
+             MessageManager.getString("label.load_tree_for_sequence_set"));
      loadTreeMenuItem.addActionListener(new ActionListener()
      {
        @Override
      });
      followHighlightMenuItem.setVisible(true);
      followHighlightMenuItem.setState(true);
-     followHighlightMenuItem.setText(MessageManager
-             .getString("label.automatic_scrolling"));
+     followHighlightMenuItem
+             .setText(MessageManager.getString("label.automatic_scrolling"));
      followHighlightMenuItem.addActionListener(new ActionListener()
      {
 -
 +  
        @Override
        public void actionPerformed(ActionEvent e)
        {
      });
      extractScores.setVisible(true);
      // JBPNote: TODO: make gui for regex based score extraction
 -
 +  
      // for show products actions see AlignFrame.canShowProducts
      showProducts.setText(MessageManager.getString("label.get_cross_refs"));
 -
 +  
      runGroovy.setText(MessageManager.getString("label.run_groovy"));
-     runGroovy.setToolTipText(MessageManager
-             .getString("label.run_groovy_tip"));
+     runGroovy.setToolTipText(
+             MessageManager.getString("label.run_groovy_tip"));
      runGroovy.addActionListener(new ActionListener()
      {
        @Override
        @Override
        public void actionPerformed(ActionEvent e)
        {
 -        associatedData_actionPerformed(e);
 +        try
 +        {
 +          associatedData_actionPerformed(e);
 +        } catch (IOException | InterruptedException e1)
 +        {
 +          // TODO Auto-generated catch block
 +          e1.printStackTrace();
 +        }
        }
      });
-     autoCalculate.setText(MessageManager
-             .getString("label.autocalculate_consensus"));
-     autoCalculate.setState(jalview.bin.Cache.getDefault(
-             "AUTO_CALC_CONSENSUS", true));
+     autoCalculate.setText(
+             MessageManager.getString("label.autocalculate_consensus"));
+     autoCalculate.setState(
+             jalview.bin.Cache.getDefault("AUTO_CALC_CONSENSUS", true));
      autoCalculate.addActionListener(new ActionListener()
      {
        @Override
          hiddenMarkers_actionPerformed(e);
        }
      });
 -
 +  
      JMenuItem invertColSel = new JMenuItem(
              MessageManager.getString("action.invert_column_selection"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask()
-             | KeyEvent.ALT_MASK, false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                     | KeyEvent.ALT_MASK,
+             false);
      al = new ActionListener()
      {
        @Override
          tabbedPane_focusGained(e);
        }
      });
 -
 +  
      JMenuItem save = new JMenuItem(MessageManager.getString("action.save"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
          reload_actionPerformed(e);
        }
      });
 -
 +  
      JMenuItem newView = new JMenuItem(
              MessageManager.getString("action.new_view"));
-     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit
-             .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_T,
+             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
      al = new ActionListener()
      {
        @Override
      tabbedPane.setToolTipText("<html><i>"
              + MessageManager.getString("label.rename_tab_eXpand_reGroup")
              + "</i></html>");
 -
 +  
      formatMenu.setText(MessageManager.getString("action.format"));
      JMenu selectMenu = new JMenu(MessageManager.getString("action.select"));
-   
-     idRightAlign.setText(MessageManager
-             .getString("label.right_align_sequence_id"));
+     idRightAlign.setText(
+             MessageManager.getString("label.right_align_sequence_id"));
      idRightAlign.addActionListener(new ActionListener()
      {
        @Override
@@@ -1244,14 -1120,10 +1256,14 @@@ public class GPreferences extends JPane
    {
      String choice = null;
      JFileChooser chooser = new JFileChooser();
 +    if (forFolder)
 +    {
 +      chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
 +    }
  
      // chooser.setFileView(new JalviewFileView());
-     chooser.setDialogTitle(MessageManager
-             .getString("label.open_local_file"));
+     chooser.setDialogTitle(
+             MessageManager.getString("label.open_local_file"));
      chooser.setToolTipText(MessageManager.getString("action.open"));
  
      int value = chooser.showOpenDialog(this);
     * Customer cell editor for JTable: supports column of radio buttons in
     * conjunction with renderer
     */
-   public class RadioButtonEditor extends AbstractCellEditor implements
-             TableCellEditor
-     {
-       private JRadioButton button = new JRadioButton();
+   public class RadioButtonEditor extends AbstractCellEditor
+           implements TableCellEditor
+   {
+     private JRadioButton button = new JRadioButton();
  
-       public RadioButtonEditor()
-       {
+     public RadioButtonEditor()
+     {
        button.setHorizontalAlignment(SwingConstants.CENTER);
        this.button.addActionListener(new ActionListener()
+       {
+         @Override
+         public void actionPerformed(ActionEvent e)
          {
-           @Override
-           public void actionPerformed(ActionEvent e)
-           {
-             fireEditingStopped();
-           }
-         });
-       }
+           fireEditingStopped();
+         }
+       });
+     }
  
-       @Override
-       public Component getTableCellEditorComponent(JTable table,
-               Object value, boolean isSelected, int row, int column)
-       {
+     @Override
+     public Component getTableCellEditorComponent(JTable table, Object value,
+             boolean isSelected, int row, int column)
+     {
        button.setSelected((boolean) value);
-         return button;
-       }
+       return button;
+     }
  
-       @Override
-       public Object getCellEditorValue()
-       {
+     @Override
+     public Object getCellEditorValue()
+     {
        return button.isSelected();
-       }
+     }
  
    }
 +
 +  public void hmmerPath_actionPerformed(ActionEvent e)
 +  {
 +
 +  }
  }
@@@ -10,20 -29,20 +29,21 @@@ public enum JalviewColourSchem
     * the order of declaration is the default order in which 
     * items are added to Colour menus
     */
-   Clustal("Clustal", ClustalxColourScheme.class), Blosum62("Blosum62",
-           Blosum62ColourScheme.class), PID("% Identity",
-           PIDColourScheme.class), Zappo("Zappo", ZappoColourScheme.class),
-   Taylor("Taylor", TaylorColourScheme.class), Hydrophobic("Hydrophobic",
-           HydrophobicColourScheme.class), Helix("Helix Propensity",
-           HelixColourScheme.class), Strand("Strand Propensity",
-           StrandColourScheme.class), Turn("Turn Propensity",
-           TurnColourScheme.class), Buried("Buried Index",
-           BuriedColourScheme.class), Nucleotide("Nucleotide",
-           NucleotideColourScheme.class), PurinePyrimidine(
-           "Purine/Pyrimidine", PurinePyrimidineColourScheme.class),
-   RNAHelices("RNA Helices", RNAHelicesColour.class), TCoffee(
-           "T-Coffee Scores", TCoffeeColourScheme.class),
+   Clustal("Clustal", ClustalxColourScheme.class),
+   Blosum62("Blosum62", Blosum62ColourScheme.class),
+   PID("% Identity", PIDColourScheme.class),
+   Zappo("Zappo", ZappoColourScheme.class),
+   Taylor("Taylor", TaylorColourScheme.class),
+   Hydrophobic("Hydrophobic", HydrophobicColourScheme.class),
+   Helix("Helix Propensity", HelixColourScheme.class),
+   Strand("Strand Propensity", StrandColourScheme.class),
+   Turn("Turn Propensity", TurnColourScheme.class),
+   Buried("Buried Index", BuriedColourScheme.class),
+   Nucleotide("Nucleotide", NucleotideColourScheme.class),
+   PurinePyrimidine("Purine/Pyrimidine", PurinePyrimidineColourScheme.class),
+   RNAHelices("RNA Helices", RNAHelicesColour.class),
 -  TCoffee("T-Coffee Scores", TCoffeeColourScheme.class);
++  TCoffee("T-Coffee Scores", TCoffeeColourScheme.class),
 +  HMMER("HMMER", HMMERColourScheme.class);
    // RNAInteraction("RNA Interaction type", RNAInteractionColourScheme.class)
  
    private String name;
@@@ -68,13 -68,13 +68,13 @@@ public class AlignCalcManager implement
    {
      restartable = Collections
              .synchronizedList(new ArrayList<AlignCalcWorkerI>());
-     blackList = Collections
-             .synchronizedList(new ArrayList<Class<? extends AlignCalcWorkerI>>());
+     blackList = Collections.synchronizedList(
+             new ArrayList<Class<? extends AlignCalcWorkerI>>());
      inProgress = Collections
              .synchronizedList(new ArrayList<AlignCalcWorkerI>());
-     updating = Collections
-             .synchronizedMap(new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
+     updating = Collections.synchronizedMap(
+             new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
 -    canUpdate = new HashSet<AlignCalcWorkerI>();
 +    canUpdate = new HashSet<>();
    }
  
    @Override
Simple merge