JAL-2629 add ability to build a HMM from a group
[jalview.git] / src / jalview / workers / InformationThread.java
1 package jalview.workers;
2
3 import jalview.analysis.AAFrequency;
4 import jalview.api.AlignViewportI;
5 import jalview.api.AlignmentViewPanel;
6 import jalview.datamodel.AlignmentAnnotation;
7 import jalview.datamodel.AlignmentI;
8 import jalview.datamodel.Annotation;
9 import jalview.datamodel.HiddenMarkovModel;
10 import jalview.datamodel.ProfilesI;
11 import jalview.datamodel.SequenceI;
12 import jalview.renderer.ResidueShaderI;
13
14 import java.util.List;
15
16 public class InformationThread extends AlignCalcWorker
17 {
18
19   public InformationThread(AlignViewportI alignViewport,
20             AlignmentViewPanel alignPanel)
21     {
22       super(alignViewport, alignPanel);
23     }
24
25     @Override
26     public void run()
27     {
28       if (calcMan.isPending(this))
29       {
30         return;
31       }
32       calcMan.notifyStart(this);
33       long started = System.currentTimeMillis();
34
35     List<AlignmentAnnotation> information = getInformationAnnotations();
36       try
37       {
38       if ((information == null) || calcMan.isPending(this))
39         {
40           calcMan.workerComplete(this);
41           return;
42         }
43         while (!calcMan.notifyWorking(this))
44         {
45           // System.err.println("Thread
46         // (Information"+Thread.currentThread().getName()+") Waiting around.");
47           try
48           {
49             if (ap != null)
50             {
51               ap.paintAlignment(false);
52             }
53             Thread.sleep(200);
54           } catch (Exception ex)
55           {
56             ex.printStackTrace();
57           }
58         }
59         if (alignViewport.isClosed())
60         {
61           abortAndDestroy();
62           return;
63         }
64         AlignmentI alignment = alignViewport.getAlignment();
65
66         int aWidth = -1;
67
68         if (alignment == null || (aWidth = alignment.getWidth()) < 0)
69         {
70           calcMan.workerComplete(this);
71           return;
72         }
73
74       eraseInformation(aWidth);
75       computeInformation(alignment);
76         updateResultAnnotation(true);
77
78         if (ap != null)
79         {
80           ap.paintAlignment(true);
81         }
82       } catch (OutOfMemoryError error)
83       {
84         calcMan.disableWorker(this);
85       ap.raiseOOMWarning("calculating information", error);
86     } finally
87     {
88       calcMan.workerComplete(this);
89       }
90
91
92
93     }
94
95     /**
96    * Clear out any existing information annotations
97    * 
98    * @param aWidth
99    *          the width (number of columns) of the annotated alignment
100    */
101   protected void eraseInformation(int aWidth)
102     {
103
104     List<AlignmentAnnotation> information = getInformationAnnotations();
105     for (AlignmentAnnotation info : information)
106     {
107       info.annotations = new Annotation[aWidth];
108     }
109     }
110
111
112     /**
113      * @param alignment
114      */
115   protected void computeInformation(AlignmentI alignment)
116     {
117
118       int width = alignment.getWidth();
119     List<SequenceI> hmmSeqs = alignment.getHMMConsensusSequences(false);
120     int index = 0;
121     for (SequenceI seq : hmmSeqs)
122     {
123       HiddenMarkovModel hmm = seq.getHMM();
124       ProfilesI hinformation = AAFrequency.calculateInformation(hmm, width,
125               0, width, true, alignViewport.isIgnoreBelowBackground());
126       alignViewport.setSequenceInformationHash(hinformation, index);
127       // setColourSchemeInformation(hinformation);
128       index++;
129     }
130     }
131
132     /**
133      * @return
134      */
135     protected SequenceI[] getSequences()
136     {
137       return alignViewport.getAlignment().getSequencesArray();
138     }
139
140     /**
141    * @param hinformation
142    */
143   protected void setColourSchemeInformation(ProfilesI information)
144     {
145       ResidueShaderI cs = alignViewport.getResidueShading();
146       if (cs != null)
147       {
148       cs.setInformation(information);
149       }
150     }
151
152     /**
153    * Get the Information annotation for the alignment
154    * 
155    * @return
156    */
157   protected List<AlignmentAnnotation> getInformationAnnotations()
158     {
159     return alignViewport.getInformationAnnotations();
160     }
161
162     /**
163      * Get the Gap annotation for the alignment
164      * 
165      * @return
166      */
167     protected AlignmentAnnotation getGapAnnotation()
168     {
169       return alignViewport.getAlignmentGapAnnotation();
170     }
171
172     /**
173    * update the information annotation from the sequence profile data using
174    * current visualization settings.
175    */
176     @Override
177     public void updateAnnotation()
178     {
179
180       updateResultAnnotation(false);
181     }
182
183
184     public void updateResultAnnotation(boolean immediate)
185     {
186     List<AlignmentAnnotation> annots = getInformationAnnotations();
187     int index = 0;
188     for (AlignmentAnnotation information : annots)
189     {
190       ProfilesI hinformation = (ProfilesI) getSequenceInformation(index);
191       if (immediate || !calcMan.isWorking(this) && information != null
192             && hinformation != null)
193       {
194         deriveInformation(information, hinformation);
195       }
196       index++;
197       }
198     }
199
200     /**
201    * Convert the computed information data into the desired annotation for
202    * display.
203    * 
204    * @param informationAnnotation
205    *          the annotation to be populated
206    * @param hinformation
207    *          the computed information data
208    */
209   protected void deriveInformation(
210           AlignmentAnnotation informationAnnotation, ProfilesI hinformation)
211     {
212
213       long nseq = getSequences().length;
214     AAFrequency.completeInformation(informationAnnotation, hinformation,
215             hinformation.getStartColumn(), hinformation.getEndColumn() + 1,
216             alignViewport.isIgnoreBelowBackground(),
217               alignViewport.isShowHMMSequenceLogo(), nseq);
218     }
219
220
221
222     /**
223    * Get the information data stored on the viewport.
224    * 
225    * @return
226    */
227   protected Object getSequenceInformation(int index)
228     {
229     // TODO convert ComplementInformationThread to use Profile
230     return alignViewport.getSequenceInformationHash(index);
231     }
232   }
233
234
235
236
237