From b48749857263e9c85c93fce54f764453fbce9696 Mon Sep 17 00:00:00 2001 From: TZVanaalten Date: Tue, 8 Aug 2017 17:55:56 +0100 Subject: [PATCH] JAL-2599 fix for index issue on node lookup --- src/jalview/datamodel/HMMNode.java | 17 +++++ src/jalview/datamodel/HiddenMarkovModel.java | 87 ++++++++++++++++++++------ src/jalview/datamodel/Sequence.java | 4 +- src/jalview/io/HMMFile.java | 4 +- 4 files changed, 89 insertions(+), 23 deletions(-) diff --git a/src/jalview/datamodel/HMMNode.java b/src/jalview/datamodel/HMMNode.java index cf95a1b..04e335f 100644 --- a/src/jalview/datamodel/HMMNode.java +++ b/src/jalview/datamodel/HMMNode.java @@ -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 getMatchEmissions() { return matchEmissions; diff --git a/src/jalview/datamodel/HiddenMarkovModel.java b/src/jalview/datamodel/HiddenMarkovModel.java index 4ecdf53..c96ad8b 100644 --- a/src/jalview/datamodel/HiddenMarkovModel.java +++ b/src/jalview/datamodel/HiddenMarkovModel.java @@ -33,7 +33,8 @@ public class HiddenMarkovModel // 0. Node 0 contains average emission probabilities for each symbol List 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 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); } } diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index 95c1bac..130af40 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -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++; } diff --git a/src/jalview/io/HMMFile.java b/src/jalview/io/HMMFile.java index 02d92296..234c108 100644 --- a/src/jalview/io/HMMFile.java +++ b/src/jalview/io/HMMFile.java @@ -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 { -- 1.7.10.2