JAL-2599 fix for index issue on node lookup
authorTZVanaalten <TZVanaalten@LS30916.ad.lifesci.dundee.ac.uk>
Tue, 8 Aug 2017 16:55:56 +0000 (17:55 +0100)
committerTZVanaalten <TZVanaalten@LS30916.ad.lifesci.dundee.ac.uk>
Tue, 8 Aug 2017 16:55:56 +0000 (17:55 +0100)
src/jalview/datamodel/HMMNode.java
src/jalview/datamodel/HiddenMarkovModel.java
src/jalview/datamodel/Sequence.java
src/jalview/io/HMMFile.java

index cf95a1b..04e335f 100644 (file)
@@ -24,6 +24,23 @@ public class HMMNode
   char referenceAnnotation;
   char maskValue;
   char consensusStructure;
+
+  public HMMNode()
+  {
+  }
+
+  public HMMNode(HMMNode node)
+  {
+    matchEmissions = new ArrayList<>(node.getMatchEmissions());
+    insertEmissions = new ArrayList<>(node.getInsertEmissions());
+    stateTransitions = new ArrayList<>(node.getStateTransitions());
+    alignmentColumn = new Integer(node.getAlignmentColumn());
+    consensusResidue = node.getConsensusResidue();
+    referenceAnnotation = node.getReferenceAnnotation();
+    maskValue = node.getMaskValue();
+    consensusStructure = node.getConsensusStructure();
+  }
+
   public List<Double> getMatchEmissions()
   {
     return matchEmissions;
index 4ecdf53..c96ad8b 100644 (file)
@@ -33,7 +33,8 @@ public class HiddenMarkovModel
   // 0. Node 0 contains average emission probabilities for each symbol
   List<HMMNode> nodes = new ArrayList<>();
 
-  // contains the HMM node for each alignment column
+  // contains the HMM node for each alignment column, alignment columns start at
+  // index 0;
   Map<Integer, Integer> nodeLookup = new HashMap<>();
   
   // contains the symbol index for each symbol
@@ -124,11 +125,12 @@ public class HiddenMarkovModel
   public HiddenMarkovModel(HiddenMarkovModel hmm)
   {
     super();
-    this.fileProperties = hmm.fileProperties;
-    this.symbols = hmm.symbols;
-    this.nodes = hmm.nodes;
-    this.nodeLookup = hmm.nodeLookup;
-    this.symbolIndexLookup = hmm.symbolIndexLookup;
+    this.fileProperties = new HashMap<>(hmm.fileProperties);
+    this.symbols = new ArrayList<>(hmm.symbols);
+    this.nodes = new ArrayList<>(hmm.nodes);
+    this.nodeLookup = new HashMap<>(hmm.nodeLookup);
+    this.symbolIndexLookup = new HashMap<>(
+            hmm.symbolIndexLookup);
     this.numberOfSymbols = hmm.numberOfSymbols;
     this.fileHeader = new String(hmm.fileHeader);
   }
@@ -390,9 +392,9 @@ public class HiddenMarkovModel
       return 0d;
     }
     symbolIndex = symbolIndexLookup.get(symbol);
-    if (nodeLookup.containsKey(alignColumn + 1))
+    if (nodeLookup.containsKey(alignColumn))
     {
-      nodeIndex = nodeLookup.get(alignColumn + 1);
+      nodeIndex = nodeLookup.get(alignColumn);
       probability = getNode(nodeIndex).getMatchEmissions().get(symbolIndex);
       return probability;
     }
@@ -425,9 +427,9 @@ public class HiddenMarkovModel
       return 0d;
     }
     symbolIndex = symbolIndexLookup.get(symbol);
-    if (nodeLookup.containsKey(alignColumn + 1))
+    if (nodeLookup.containsKey(alignColumn))
     {
-      nodeIndex = nodeLookup.get(alignColumn + 1);
+      nodeIndex = nodeLookup.get(alignColumn);
       probability = getNode(nodeIndex).getInsertEmissions()
               .get(symbolIndex);
       return probability;
@@ -457,9 +459,9 @@ public class HiddenMarkovModel
     int transitionIndex;
     int nodeIndex;
     Double probability;
-    if (nodeLookup.containsKey(alignColumn + 1))
+    if (nodeLookup.containsKey(alignColumn))
     {
-      nodeIndex = nodeLookup.get(alignColumn + 1);
+      nodeIndex = nodeLookup.get(alignColumn);
       probability = getNode(nodeIndex).getStateTransitions()
               .get(transition);
       return probability;
@@ -482,7 +484,7 @@ public class HiddenMarkovModel
   public Integer getNodeAlignmentColumn(int nodeIndex)
   {
     Integer value = nodes.get(nodeIndex).getAlignmentColumn();
-    return value - 1;
+    return value;
   }
   
   /**
@@ -950,7 +952,7 @@ public class HiddenMarkovModel
   public Integer findNodeIndex(int alignmentColumn)
   {
     Integer index;
-    index = nodeLookup.get(alignmentColumn + 1);
+    index = nodeLookup.get(alignmentColumn);
     return index;
   }
 
@@ -1018,7 +1020,7 @@ public class HiddenMarkovModel
    * Maps the nodes of the hidden Markov model to the reference annotation and
    * then deletes this annotation.
    */
-  public void mapToReferenceAnnotation(AlignFrame af)
+  public void mapToReferenceAnnotation(AlignFrame af, SequenceI seq)
   {
     AlignmentAnnotation annotArray[] = af.getViewport().getAlignment()
             .getAlignmentAnnotation();
@@ -1037,10 +1039,56 @@ public class HiddenMarkovModel
       return;
     }
 
-    mapToReferenceAnnotation(reference);
+    mapToReferenceAnnotation(reference, seq);
     af.getViewport().getAlignment().deleteAnnotation(reference);
   }
 
+  public void mapToReferenceAnnotation(AlignmentAnnotation reference,
+          SequenceI seq)
+  {
+    HiddenMarkovModel hmm = seq.getHMM();
+    Annotation[] annots = reference.annotations;
+    {
+      int nodeIndex = 0;
+      for (int col = 0; col < annots.length; col++)
+      {
+        String character = annots[col].displayCharacter;
+        if ("x".equals(character) || "X".equals(character))
+        {
+          nodeIndex++;
+          if (nodeIndex < hmm.getNodes().size())
+          {
+            HMMNode node = hmm.getNode(nodeIndex);
+            int alignPos = getNodeAlignmentColumn(nodeIndex);
+            char seqCharacter = seq.getCharAt(alignPos);
+            if (alignPos >= seq.getLength() || col >= seq.getLength())
+            {
+              seq.insertCharAt(seq.getLength(),
+                      (alignPos + 1) - seq.getLength(),
+                      '-');
+            }
+            seq.getSequence()[alignPos] = '-';
+            seq.getSequence()[col] = seqCharacter;
+            node.setAlignmentColumn(col);
+            hmm.nodeLookup.put(col, nodeIndex);
+          }
+          else
+          {
+            System.out.println(
+                    "The reference annotation contains more consensus columns than the hidden Markov model");
+            break;
+          }
+        }
+        else
+        {
+          hmm.nodeLookup.remove(col);
+        }
+      }
+
+    }
+
+  }
+
   public void mapToReferenceAnnotation(AlignmentAnnotation reference)
   {
     Annotation[] annots = reference.annotations;
@@ -1054,8 +1102,9 @@ public class HiddenMarkovModel
           nodeIndex++;
           if (nodeIndex < nodes.size())
           {
-            nodes.get(nodeIndex).setAlignmentColumn(col + 1);
-            nodeLookup.put(col + 1, nodeIndex);
+            HMMNode node = nodes.get(nodeIndex);
+            node.setAlignmentColumn(col + 1);
+            nodeLookup.put(col, nodeIndex);
           }
           else
           {
@@ -1066,7 +1115,7 @@ public class HiddenMarkovModel
         }
         else
         {
-          nodeLookup.remove(col + 1);
+          nodeLookup.remove(col);
         }
       }
 
index 95c1bac..130af40 100755 (executable)
@@ -1497,7 +1497,7 @@ public class Sequence extends ASequence implements SequenceI
   public void updateHMMMapping()
   {
     int node = 1;
-    int column = 1;
+    int column = 0;
     for (char residue : sequence)
     {
       if (!Comparison.isGap(residue))
@@ -1508,7 +1508,7 @@ public class Sequence extends ASequence implements SequenceI
       }
       else
       {
-        hmm.getNodeLookup().remove(column + 1);
+        hmm.getNodeLookup().remove(column);
       }
       column++;
     }
index 02d9229..234c108 100644 (file)
@@ -250,8 +250,8 @@ public class HMMFile extends AlignFile
     {
       int column;
       column = scanner.nextInt();
-      hmm.getNodes().get(index).setAlignmentColumn(column);
-      hmm.getNodeLookup().put(column, index);
+      hmm.getNodes().get(index).setAlignmentColumn(column - 1);
+      hmm.getNodeLookup().put(column - 1, index);
     }
     else
     {