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