From: TZVanaalten Date: Wed, 2 Aug 2017 09:51:14 +0000 (+0100) Subject: JAL-2599 fix for information annotation buttons X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=c4160cf5c69643d0af950db63214b2067a04b061;p=jalview.git JAL-2599 fix for information annotation buttons --- diff --git a/src/jalview/analysis/AAFrequency.java b/src/jalview/analysis/AAFrequency.java index 900209d..d83f138 100755 --- a/src/jalview/analysis/AAFrequency.java +++ b/src/jalview/analysis/AAFrequency.java @@ -110,6 +110,7 @@ public class AAFrequency } + /** * Calculate the consensus symbol(s) for each column in the given range. * @@ -201,6 +202,38 @@ public class AAFrequency // System.out.println(elapsed); } + public static ProfilesI calculateInformation(final HiddenMarkovModel hmm, + int width, int start, int end, boolean saveFullProfile, + boolean removeBelowBackground) + { + ProfileI[] result = new ProfileI[width]; + int symbolCount = hmm.getNumberOfSymbols(); + String alph = hmm.getAlphabetType(); + for (int column = start; column < end; column++) + { + ResidueCount counts = new ResidueCount(); + for (char symbol : hmm.getSymbols()) + { + int value = getAnalogueCount(hmm, column, removeBelowBackground, + alph, symbol); + counts.put(symbol, value); + } + int maxCount = counts.getModalCount(); + String maxResidue = counts.getResiduesForCount(maxCount); + int gapCount = counts.getGapCount(); + ProfileI profile = new Profile(symbolCount, gapCount, maxCount, + maxResidue); + + if (saveFullProfile) + { + profile.setCounts(counts); + } + + result[column] = profile; + } + return new Profiles(result); + } + /** * Make an estimate of the profile size we are going to compute i.e. how many * different characters may be present in it. Overestimating has a cost of @@ -299,6 +332,82 @@ public class AAFrequency } /** + * Derive the information annotations to be added to the alignment for + * display. This does not recompute the raw data, but may be called on a + * change in display options, such as 'ignore below background frequency', + * which may in turn result in a change in the derived values. + * + * @param information + * the annotation row to add annotations to + * @param profiles + * the source information data + * @param startCol + * start column (inclusive) + * @param endCol + * end column (exclusive) + * @param ignoreGaps + * if true, normalise residue percentages + * @param showSequenceLogo + * if true include all information symbols, else just show modal + * residue + * @param nseq + * number of sequences + */ + public static void completeInformation(AlignmentAnnotation information, + ProfilesI profiles, int startCol, int endCol, + boolean ignoreBelowBackground, + boolean showSequenceLogo, long nseq) + { + // long now = System.currentTimeMillis(); + if (information == null || information.annotations == null + || information.annotations.length < endCol) + { + /* + * called with a bad alignment annotation row + * wait for it to be initialised properly + */ + return; + } + + Float max = 0f; + + for (int i = startCol; i < endCol; i++) + { + ProfileI profile = profiles.get(i); + if (profile == null) + { + /* + * happens if sequences calculated over were + * shorter than alignment width + */ + information.annotations[i] = null; + return; + } + + HiddenMarkovModel hmm; + + SequenceI hmmSeq = information.sequenceRef; + + hmm = hmmSeq.getHMM(); + + Float value = getInformationContent(i, hmm); + + if (value > max) + { + max = value; + } + + String description = value + " bits"; + + information.annotations[i] = new Annotation(" ", description, + ' ', value); + } + information.graphMax = max; + // long elapsed = System.currentTimeMillis() - now; + // System.out.println(-elapsed); + } + + /** * Derive the gap count annotation row. * * @param gaprow @@ -730,6 +839,42 @@ public class AAFrequency } /** + * Returns the information content at a specified column. + * + * @param column + * Index of the column, starting from 0. + * @return + */ + public static float getInformationContent(int column, + HiddenMarkovModel hmm) + { + float informationContent = 0f; + + for (char symbol : hmm.getSymbols()) + { + float freq = 0f; + if ("amino".equals(hmm.getAlphabetType())) + { + freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol); + } + if ("DNA".equals(hmm.getAlphabetType())) + { + freq = ResidueProperties.dnaBackgroundFrequencies.get(symbol); + } + if ("RNA".equals(hmm.getAlphabetType())) + { + freq = ResidueProperties.rnaBackgroundFrequencies.get(symbol); + } + Double hmmProb = hmm.getMatchEmissionProbability(column, symbol); + float prob = hmmProb.floatValue(); + informationContent += prob * (Math.log(prob / freq) / Math.log(2)); + + } + + return informationContent; + } + + /** * Produces a HMM profile for a column in an alignment * * @param aa @@ -741,7 +886,7 @@ public class AAFrequency * less than their background frequencies. * @return */ - public static int[] getHMMProfileFor(HiddenMarkovModel hmm, int column, + public static int[] extractHMMProfile(HiddenMarkovModel hmm, int column, boolean removeBelowBackground) { @@ -758,39 +903,10 @@ public class AAFrequency { char symbol = charList.get(i); symbols[i] = symbol; - Double value; - - value = hmm.getMatchEmissionProbability(column, symbol); - double freq; - - if (AMINO.equals(alph) && removeBelowBackground) - { - freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol); - if (value < freq) - { - value = 0d; - } - } - else if (DNA.equals(alph) && removeBelowBackground) - { - freq = ResidueProperties.dnaBackgroundFrequencies.get(symbol); - if (value < freq) - { - value = 0d; - } - } - else if (RNA.equals(alph) && removeBelowBackground) - { - freq = ResidueProperties.rnaBackgroundFrequencies - .get(symbol); - if (value < freq) - { - value = 0d; - } - } - value = value * 10000; - values[i] = value.intValue(); - totalCount += value.intValue(); + int value = getAnalogueCount(hmm, column, removeBelowBackground, + alph, symbol); + values[i] = value; + totalCount += value; } QuickSort.sort(values, symbols); @@ -819,4 +935,40 @@ public class AAFrequency } return null; } + + private static int getAnalogueCount(HiddenMarkovModel hmm, int column, + boolean removeBelowBackground, String alph, char symbol) + { + Double value; + + value = hmm.getMatchEmissionProbability(column, symbol); + double freq; + + if (AMINO.equals(alph) && removeBelowBackground) + { + freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol); + if (value < freq) + { + value = 0d; + } + } + else if (DNA.equals(alph) && removeBelowBackground) + { + freq = ResidueProperties.dnaBackgroundFrequencies.get(symbol); + if (value < freq) + { + value = 0d; + } + } + else if (RNA.equals(alph) && removeBelowBackground) + { + freq = ResidueProperties.rnaBackgroundFrequencies.get(symbol); + if (value < freq) + { + value = 0d; + } + } + value = value * 10000; + return value.intValue(); + } } diff --git a/src/jalview/api/AlignViewportI.java b/src/jalview/api/AlignViewportI.java index 6ebde3c..4b6dc4e 100644 --- a/src/jalview/api/AlignViewportI.java +++ b/src/jalview/api/AlignViewportI.java @@ -108,6 +108,8 @@ public interface AlignViewportI extends ViewStyleI ProfilesI getSequenceConsensusHash(); + ProfilesI getSequenceInformationHash(); + /** * Get consensus data table for the cDNA complement of this alignment (if any) * @@ -188,6 +190,13 @@ public interface AlignViewportI extends ViewStyleI void setSequenceConsensusHash(ProfilesI hconsensus); /** + * set the information result object for the viewport + * + * @param hconsensus + */ + void setSequenceInformationHash(ProfilesI hinformation); + + /** * Set the cDNA complement consensus for the viewport * * @param hconsensus @@ -511,4 +520,6 @@ public interface AlignViewportI extends ViewStyleI */ @Override void setProteinFontAsCdna(boolean b); + + ProfilesI setSequenceInformationHash(); } diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java index 02d30bb..f764be6 100644 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@ -234,6 +234,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, alignPanel); viewport.updateConservation(alignPanel); viewport.updateConsensus(alignPanel); + viewport.updateInformation(alignPanel); displayNonconservedMenuItem.setState(viewport.getShowUnconserved()); followMouseOverFlag.setState(viewport.isFollowHighlight()); diff --git a/src/jalview/appletgui/AlignViewport.java b/src/jalview/appletgui/AlignViewport.java index 6c7b39a..99059cf 100644 --- a/src/jalview/appletgui/AlignViewport.java +++ b/src/jalview/appletgui/AlignViewport.java @@ -28,6 +28,7 @@ import jalview.commands.CommandI; import jalview.datamodel.AlignmentI; import jalview.datamodel.ColumnSelection; import jalview.datamodel.HiddenColumns; +import jalview.datamodel.ProfilesI; import jalview.datamodel.SearchResults; import jalview.datamodel.SearchResultsI; import jalview.datamodel.Sequence; @@ -476,4 +477,18 @@ public class AlignViewport extends AlignmentViewport implements return normaliseHMMSequenceLogo; } + @Override + public ProfilesI getSequenceInformationHash() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setSequenceInformationHash(ProfilesI hinformation) + { + // TODO Auto-generated method stub + + } + } diff --git a/src/jalview/datamodel/AlignmentAnnotation.java b/src/jalview/datamodel/AlignmentAnnotation.java index e8e8d01..8f826f5 100755 --- a/src/jalview/datamodel/AlignmentAnnotation.java +++ b/src/jalview/datamodel/AlignmentAnnotation.java @@ -51,8 +51,6 @@ public class AlignmentAnnotation public static final int CDNA_PROFILE = 2; - HiddenMarkovModel hmm; - private static long counter = 0; /** @@ -1506,13 +1504,4 @@ public class AlignmentAnnotation return graphMin < graphMax; } - public void setHMM(HiddenMarkovModel markov) - { - hmm = markov; - } - - public HiddenMarkovModel getHMM() - { - return hmm; - } } diff --git a/src/jalview/datamodel/HiddenMarkovModel.java b/src/jalview/datamodel/HiddenMarkovModel.java index e0f13d8..2c1632d 100644 --- a/src/jalview/datamodel/HiddenMarkovModel.java +++ b/src/jalview/datamodel/HiddenMarkovModel.java @@ -1,7 +1,6 @@ package jalview.datamodel; import jalview.gui.AlignFrame; -import jalview.schemes.ResidueProperties; import java.util.ArrayList; import java.util.HashMap; @@ -973,81 +972,7 @@ public class HiddenMarkovModel } } - /** - * Creates the HMM Logo alignment annotation, and populates it with - * information content data. - * - * @return The alignment annotation. - */ - public AlignmentAnnotation createAnnotation(int length) - { - Annotation[] annotations = new Annotation[length]; - float max = 0f; - for (int alignPos = 0; alignPos < length; alignPos++) - { - Float content = getInformationContent(alignPos); - if (content > max) - { - max = content; - } - - Character cons; - - cons = getConsensusAtAlignColumn(alignPos); - - cons = Character.toUpperCase(cons); - - String description = String.format("%.3f", content); - description += " bits"; - annotations[alignPos] = new Annotation(cons.toString(), description, - ' ', - content); - - } - AlignmentAnnotation annotation = new AlignmentAnnotation( - "Information", - "The information content of each column, measured in bits", - annotations, - 0f, max, AlignmentAnnotation.BAR_GRAPH); - annotation.setHMM(this); - return annotation; - } - - /** - * Returns the information content at a specified column. - * - * @param column - * Index of the column, starting from 0. - * @return - */ - public float getInformationContent(int column) - { - float informationContent = 0f; - for (char symbol : symbols) - { - float freq = 0f; - if ("amino".equals(getAlphabetType())) - { - freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol); - } - if ("DNA".equals(getAlphabetType())) - { - freq = ResidueProperties.dnaBackgroundFrequencies.get(symbol); - } - if ("RNA".equals(getAlphabetType())) - { - freq = ResidueProperties.rnaBackgroundFrequencies - .get(symbol); - } - Double hmmProb = getMatchEmissionProbability(column, symbol); - float prob = hmmProb.floatValue(); - informationContent += prob * (Math.log(prob / freq) / Math.log(2)); - - } - - return informationContent; - } /** * Returns the consensus sequence based on the most probable symbol at each @@ -1112,6 +1037,12 @@ public class HiddenMarkovModel return; } + mapToReferenceAnnotation(reference); + af.getViewport().getAlignment().deleteAnnotation(reference); + } + + public void mapToReferenceAnnotation(AlignmentAnnotation reference) + { Annotation[] annots = reference.annotations; { int nodeIndex = 0; @@ -1140,10 +1071,10 @@ public class HiddenMarkovModel } } - af.getViewport().getAlignment().deleteAnnotation(reference); + } - public void initPlaceholder(AlignFrame af) + public SequenceI initPlaceholder(AlignFrame af) { AlignmentI alignment = af.getViewport().getAlignment(); int length = alignment.getWidth(); @@ -1153,6 +1084,7 @@ public class HiddenMarkovModel AlignmentI newAlignment = new Alignment(consensusArr); newAlignment.append(alignment); af.getViewport().setAlignment(newAlignment); + return consensus; } } diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index 39ee2cb..eeff135 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -128,7 +128,7 @@ public class SequenceGroup implements AnnotatedCollectionI AlignmentAnnotation conservation = null; - AlignmentAnnotation informationContent = null; + AlignmentAnnotation information = null; private boolean showConsensusHistogram; @@ -565,7 +565,7 @@ public class SequenceGroup implements AnnotatedCollectionI public boolean recalcConservation(boolean defer) { if (cs == null && consensus == null && conservation == null - && informationContent == null) + && information == null) { return false; } @@ -576,7 +576,7 @@ public class SequenceGroup implements AnnotatedCollectionI { ProfilesI cnsns = AAFrequency.calculate(sequences, startRes, endRes + 1, showSequenceLogo); - if (informationContent != null) + if (information != null) { // _updateInformationRow(cnsns, sequences.size()); TODO don't know what // to do here @@ -654,6 +654,8 @@ public class SequenceGroup implements AnnotatedCollectionI public ProfilesI consensusData = null; + public ProfilesI informationData = null; + private void _updateConsensusRow(ProfilesI cnsns, long nseq) { if (consensus == null) @@ -679,26 +681,28 @@ public class SequenceGroup implements AnnotatedCollectionI private void _updateInformationRow(ProfilesI cnsns, long nseq) { - if (consensus == null) + if (information == null) { - getConsensus(); + getInformation(); } - consensus.label = "Consensus for " + getName(); - consensus.description = "Percent Identity"; - consensusData = cnsns; + information.label = "Information for " + getName(); + information.description = "Percent Identity"; + informationData = cnsns; // preserve width if already set - int aWidth = (consensus.annotations != null) - ? (endRes < consensus.annotations.length - ? consensus.annotations.length : endRes + 1) + int aWidth = (information.annotations != null) + ? (endRes < information.annotations.length + ? information.annotations.length : endRes + 1) : endRes + 1; - consensus.annotations = null; - consensus.annotations = new Annotation[aWidth]; // should be alignment width + information.annotations = null; + information.annotations = new Annotation[aWidth]; // should be alignment + // width - AAFrequency.completeConsensus(consensus, cnsns, startRes, endRes + 1, - ignoreGapsInConsensus, showSequenceLogo, nseq); // TODO: setting + AAFrequency.completeInformation(information, cnsns, startRes, + endRes + 1, ignoreBelowBackground, showSequenceLogo, nseq); // TODO: + // setting // container // for - // ignoreGapsInConsensusCalculation); + // ignoreGapsInInformationCalculation); } /** @@ -1149,6 +1153,34 @@ public class SequenceGroup implements AnnotatedCollectionI } /** + * + * @return information content annotation. + */ + public AlignmentAnnotation getInformation() + { + // TODO get or calculate and get information annotation row for this group + int aWidth = this.getWidth(); + // pointer + // possibility + // here. + if (aWidth < 0) + { + return null; + } + if (information == null) + { + information = new AlignmentAnnotation("", "", new Annotation[1], 0f, + 100f, AlignmentAnnotation.BAR_GRAPH); + information.hasText = true; + information.autoCalculated = true; + information.groupRef = this; + information.label = "Consensus for " + getName(); + information.description = "Percent Identity"; + } + return information; + } + + /** * set this alignmentAnnotation object as the one used to render consensus * annotation * @@ -1526,7 +1558,7 @@ public class SequenceGroup implements AnnotatedCollectionI public void setShowInformationHistogram(boolean state) { - if (showInformationHistogram != state && informationContent != null) + if (showInformationHistogram != state && information != null) { this.showInformationHistogram = state; // recalcConservation(); TODO don't know what to do here next diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 6dccadc..2168bd1 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -92,6 +92,7 @@ import jalview.schemes.TCoffeeColourScheme; import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; import jalview.viewmodel.ViewportRanges; +import jalview.workers.InformationThread; import jalview.ws.DBRefFetcher; import jalview.ws.DBRefFetcher.FetchFinishedListenerI; import jalview.ws.jws1.Discoverer; @@ -800,6 +801,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, ap.av.updateConservation(ap); ap.av.updateConsensus(ap); ap.av.updateStrucConsensus(ap); + ap.av.updateInformation(ap); } } @@ -4712,12 +4714,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, HiddenMarkovModel hmm = hmmFile.getHMM(); hmm.mapToReferenceAnnotation(this); + SequenceI hmmSeq = hmm.initPlaceholder(this); + getViewport().initInformation(hmmSeq); + new Thread(new InformationThread(getViewport(), + getViewport().getAlignPanel()) + { + }).start(); - - AlignmentAnnotation annotation = hmm.createAnnotation( - getViewport().getAlignment().getWidth()); - getViewport().getAlignment().addAnnotation(annotation); - hmm.initPlaceholder(this); isAnnotation = true; alignPanel.repaint(); diff --git a/src/jalview/gui/AlignViewport.java b/src/jalview/gui/AlignViewport.java index 2005b91..f4ded5b 100644 --- a/src/jalview/gui/AlignViewport.java +++ b/src/jalview/gui/AlignViewport.java @@ -37,6 +37,7 @@ import jalview.datamodel.AlignmentI; import jalview.datamodel.ColumnSelection; import jalview.datamodel.HiddenColumns; import jalview.datamodel.PDBEntry; +import jalview.datamodel.ProfilesI; import jalview.datamodel.SearchResults; import jalview.datamodel.SearchResultsI; import jalview.datamodel.Sequence; @@ -703,6 +704,7 @@ public class AlignViewport extends AlignmentViewport implements return normaliseSequenceLogo; } + public void setNormaliseSequenceLogo(boolean state) { normaliseSequenceLogo = state; @@ -1157,8 +1159,20 @@ public class AlignViewport extends AlignmentViewport implements @Override public boolean isNormaliseHMMSequenceLogo() { - // TODO Auto-generated method stub return normaliseHMMSequenceLogo; } + @Override + public ProfilesI getSequenceInformationHash() + { + return hinformation; + } + + @Override + public void setSequenceInformationHash(ProfilesI hinformation) + { + this.hinformation = hinformation; + + } + } diff --git a/src/jalview/gui/AnnotationLabels.java b/src/jalview/gui/AnnotationLabels.java index 1834fc2..090a400 100755 --- a/src/jalview/gui/AnnotationLabels.java +++ b/src/jalview/gui/AnnotationLabels.java @@ -554,7 +554,6 @@ public class AnnotationLabels extends JPanel implements MouseListener, // can be // updated. av.setShowConsensusHistogram(chist.getState()); - ap.alignFrame.setMenusForViewport(); ap.repaint(); // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); } @@ -575,7 +574,6 @@ public class AnnotationLabels extends JPanel implements MouseListener, // can be // updated. av.setShowSequenceLogo(cprof.getState()); - ap.alignFrame.setMenusForViewport(); ap.repaint(); // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); } @@ -597,7 +595,6 @@ public class AnnotationLabels extends JPanel implements MouseListener, // updated. av.setShowSequenceLogo(true); av.setNormaliseSequenceLogo(cprofnorm.getState()); - ap.alignFrame.setMenusForViewport(); ap.repaint(); // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); } @@ -727,7 +724,6 @@ public class AnnotationLabels extends JPanel implements MouseListener, // can be // updated. av.setShowInformationHistogram(chist.getState()); - ap.alignFrame.setMenusForViewport(); ap.repaint(); // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); } @@ -747,8 +743,8 @@ public class AnnotationLabels extends JPanel implements MouseListener, // view // can be // updated. + av.updateInformation(ap); av.setShowHMMSequenceLogo(cprof.getState()); - ap.alignFrame.setMenusForViewport(); ap.repaint(); // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); } @@ -770,16 +766,12 @@ public class AnnotationLabels extends JPanel implements MouseListener, // updated. av.setShowHMMSequenceLogo(true); av.setNormaliseHMMSequenceLogo(cprofnorm.getState()); - ap.alignFrame.setMenusForViewport(); ap.repaint(); // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); } }); pop.add(cprofnorm); } - final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ); - consclipbrd.addActionListener(this); - pop.add(consclipbrd); } } pop.show(this, evt.getX(), evt.getY()); diff --git a/src/jalview/renderer/AnnotationRenderer.java b/src/jalview/renderer/AnnotationRenderer.java index 78b3a88..9aec02c 100644 --- a/src/jalview/renderer/AnnotationRenderer.java +++ b/src/jalview/renderer/AnnotationRenderer.java @@ -74,6 +74,9 @@ public class AnnotationRenderer boolean av_renderHistogram = true, av_renderProfile = true, av_normaliseProfile = false; + boolean av_renderInformationHistogram = true, av_renderHMMProfile = true, + av_normaliseHMMProfile = false; + ResidueShaderI profcolour = null; private ColumnSelection columnSelection; @@ -320,6 +323,9 @@ public class AnnotationRenderer av_renderHistogram = av.isShowConsensusHistogram(); av_renderProfile = av.isShowSequenceLogo(); av_normaliseProfile = av.isNormaliseSequenceLogo(); + av_renderInformationHistogram = av.isShowInformationHistogram(); + av_renderHMMProfile = av.isShowHMMSequenceLogo(); + av_normaliseHMMProfile = av.isNormaliseHMMSequenceLogo(); profcolour = av.getResidueShading(); if (profcolour == null || profcolour.getColourScheme() == null) { @@ -360,8 +366,8 @@ public class AnnotationRenderer // if (aa.label.startsWith("Information")) { - HiddenMarkovModel hmm = aa.getHMM(); - return AAFrequency.getHMMProfileFor(hmm, column, + HiddenMarkovModel hmm = aa.sequenceRef.getHMM(); + return AAFrequency.extractHMMProfile(hmm, column, av_ignoreBelowBackground); // TODO check if this follows standard // pipeline } @@ -472,6 +478,8 @@ hconsensus.get(column), boolean scaleColLabel = false; final AlignmentAnnotation consensusAnnot = av .getAlignmentConsensusAnnotation(); + final AlignmentAnnotation informationAnnot = av + .getAlignmentInformationAnnotation(); final AlignmentAnnotation structConsensusAnnot = av .getAlignmentStrucConsensusAnnotation(); final AlignmentAnnotation complementConsensusAnnot = av @@ -509,6 +517,12 @@ hconsensus.get(column), renderProfile = av_renderProfile; normaliseProfile = av_normaliseProfile; } + else if (row == informationAnnot) + { + renderHistogram = av_renderInformationHistogram; + renderProfile = av_renderHMMProfile; + normaliseProfile = av_normaliseHMMProfile; + } else { renderHistogram = true; diff --git a/src/jalview/renderer/ResidueShader.java b/src/jalview/renderer/ResidueShader.java index b6f7fe6..3a94b4f 100644 --- a/src/jalview/renderer/ResidueShader.java +++ b/src/jalview/renderer/ResidueShader.java @@ -372,4 +372,11 @@ public class ResidueShader implements ResidueShaderI { colourScheme = cs; } + + @Override + public void setInformation(ProfilesI info) + { + // TODO Auto-generated method stub + + } } diff --git a/src/jalview/renderer/ResidueShaderI.java b/src/jalview/renderer/ResidueShaderI.java index a914a1a..d85c70c 100644 --- a/src/jalview/renderer/ResidueShaderI.java +++ b/src/jalview/renderer/ResidueShaderI.java @@ -15,6 +15,8 @@ public interface ResidueShaderI public abstract void setConsensus(ProfilesI cons); + public abstract void setInformation(ProfilesI info); + public abstract boolean conservationApplied(); public abstract void setConservationApplied(boolean conservationApplied); diff --git a/src/jalview/viewmodel/AlignmentViewport.java b/src/jalview/viewmodel/AlignmentViewport.java index 61b0b00..91caebc 100644 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@ -57,6 +57,7 @@ import jalview.viewmodel.styles.ViewStyle; import jalview.workers.AlignCalcManager; import jalview.workers.ComplementConsensusThread; import jalview.workers.ConsensusThread; +import jalview.workers.InformationThread; import jalview.workers.StrucConsensusThread; import java.awt.Color; @@ -606,6 +607,8 @@ public abstract class AlignmentViewport implements AlignViewportI, public boolean autoCalculateConsensus = true; + public boolean autoCalculateInformation = true; + protected boolean autoCalculateStrucConsensus = true; protected boolean ignoreGapsInConsensusCalculation = false; @@ -699,7 +702,14 @@ public abstract class AlignmentViewport implements AlignViewportI, protected AlignmentAnnotation[] groupConservation; - protected AlignmentAnnotation informationContent; + protected AlignmentAnnotation[] groupInformation; + + protected AlignmentAnnotation information; + + /** + * results of alignment information analysis for visible portion of view + */ + protected ProfilesI hinformation = null; /** * results of alignment consensus analysis for visible portion of view @@ -756,6 +766,18 @@ public abstract class AlignmentViewport implements AlignViewportI, } @Override + public ProfilesI setSequenceInformationHash() + { + return hinformation; + } + + @Override + public ProfilesI getSequenceInformationHash() + { + return hinformation; + } + + @Override public Hashtable[] getComplementConsensusHash() { return hcomplementConsensus; @@ -795,7 +817,7 @@ public abstract class AlignmentViewport implements AlignViewportI, @Override public AlignmentAnnotation getAlignmentInformationAnnotation() { - return informationContent; + return information; } @Override @@ -889,6 +911,23 @@ public abstract class AlignmentViewport implements AlignViewportI, } } + /** + * trigger update of information annotation + */ + public void updateInformation(final AlignmentViewPanel ap) + { + if (information == null) + { + return; + } + if (calculator + .getRegisteredWorkersOfClass(InformationThread.class) == null) + { + calculator.registerWorker(new InformationThread(this, ap)); + } + + } + // --------START Structure Conservation public void updateStrucConsensus(final AlignmentViewPanel ap) { @@ -946,6 +985,7 @@ public abstract class AlignmentViewport implements AlignViewportI, * defensively null out references to large objects in case * this object is not garbage collected (as if!) */ + information = null; consensus = null; complementConsensus = null; strucConsensus = null; @@ -1057,6 +1097,7 @@ public abstract class AlignmentViewport implements AlignViewportI, if (showHMMSequenceLogo != this.showHMMSequenceLogo) { this.showHMMSequenceLogo = showHMMSequenceLogo; + calculator.updateAnnotationFor(InformationThread.class); } this.showHMMSequenceLogo = showHMMSequenceLogo; } @@ -1299,12 +1340,7 @@ public abstract class AlignmentViewport implements AlignViewportI, ignoreBelowBackGroundFrequencyCalculation = b; if (ap != null) { - // updateConsensus(ap); - if (residueShading != null) - { - residueShading.setThreshold(residueShading.getThreshold(), - ignoreBelowBackGroundFrequencyCalculation); - } + updateInformation(ap); } } @@ -1923,6 +1959,10 @@ public abstract class AlignmentViewport implements AlignViewportI, { updateStrucConsensus(ap); } + if (information != null) + { + updateInformation(ap); + } // Reset endRes of groups if beyond alignment width int alWidth = alignment.getWidth(); @@ -1959,6 +1999,7 @@ public abstract class AlignmentViewport implements AlignViewportI, rs.alignmentChanged(alignment, hiddenRepSequences); rs.setConsensus(hconsensus); + rs.setInformation(hinformation); if (rs.conservationApplied()) { rs.setConservation(Conservation.calculateConservation("All", @@ -2005,6 +2046,7 @@ public abstract class AlignmentViewport implements AlignViewportI, } } + /** * If this is a protein alignment and there are mappings to cDNA, adds the * cDNA consensus annotation and returns true, else returns false. @@ -2056,6 +2098,19 @@ public abstract class AlignmentViewport implements AlignViewportI, } } + public void initInformation(SequenceI hmmSequence) + { + information = new AlignmentAnnotation("Information", + MessageManager.getString("label.information_description"), + new Annotation[1], 0f, 6.52f, AlignmentAnnotation.BAR_GRAPH); + information.hasText = true; + information.autoCalculated = true; + information.hasText = true; + information.autoCalculated = false; + information.sequenceRef = hmmSequence; + alignment.addAnnotation(information); + } + // these should be extracted from the view model - style and settings for // derived annotation private void initGapCounts() @@ -2205,6 +2260,9 @@ public abstract class AlignmentViewport implements AlignViewportI, boolean showprf = isShowSequenceLogo(); boolean showConsHist = isShowConsensusHistogram(); boolean normLogo = isNormaliseSequenceLogo(); + boolean showHMMPrf = isShowHMMSequenceLogo(); + boolean showInfoHist = isShowInformationHistogram(); + boolean normHMMLogo = isNormaliseHMMSequenceLogo(); /** * TODO reorder the annotation rows according to group/sequence ordering on @@ -2242,6 +2300,9 @@ public abstract class AlignmentViewport implements AlignViewportI, sg.setshowSequenceLogo(showprf); sg.setShowConsensusHistogram(showConsHist); sg.setNormaliseSequenceLogo(normLogo); + sg.setshowHMMSequenceLogo(showHMMPrf); + sg.setShowInformationHistogram(showInfoHist); + sg.setNormaliseHMMSequenceLogo(normHMMLogo); } if (conv) { diff --git a/src/jalview/workers/AlignCalcManager.java b/src/jalview/workers/AlignCalcManager.java index addb372..d52ffe5 100644 --- a/src/jalview/workers/AlignCalcManager.java +++ b/src/jalview/workers/AlignCalcManager.java @@ -74,7 +74,7 @@ public class AlignCalcManager implements AlignCalcManagerI .synchronizedList(new ArrayList()); updating = Collections .synchronizedMap(new Hashtable, List>()); - canUpdate = new HashSet(); + canUpdate = new HashSet<>(); } @Override @@ -286,7 +286,7 @@ public class AlignCalcManager implements AlignCalcManagerI public List getRegisteredWorkersOfClass( Class workerClass) { - List workingClass = new ArrayList(); + List workingClass = new ArrayList<>(); synchronized (canUpdate) { for (AlignCalcWorkerI worker : canUpdate) @@ -313,8 +313,8 @@ public class AlignCalcManager implements AlignCalcManagerI public void removeRegisteredWorkersOfClass( Class typeToRemove) { - List removable = new ArrayList(); - Set toremovannot = new HashSet(); + List removable = new ArrayList<>(); + Set toremovannot = new HashSet<>(); synchronized (restartable) { for (AlignCalcWorkerI worker : restartable) @@ -364,7 +364,7 @@ public class AlignCalcManager implements AlignCalcManagerI * first just find those to remove (to avoid * ConcurrentModificationException) */ - List toRemove = new ArrayList(); + List toRemove = new ArrayList<>(); for (AlignCalcWorkerI worker : restartable) { if (worker.involves(ann))