JAL-3070 javadoc for (mostly) jabaws specific methods
[jalview.git] / src / jalview / ws / jws2 / jabaws2 / JabawsAnnotationInstance.java
1 package jalview.ws.jws2.jabaws2;
2
3 import jalview.api.AlignViewportI;
4 import jalview.datamodel.AlignmentAnnotation;
5 import jalview.datamodel.Annotation;
6 import jalview.datamodel.SequenceI;
7 import jalview.util.MessageManager;
8 import jalview.ws.api.JobId;
9 import jalview.ws.api.SequenceAnnotationServiceI;
10 import jalview.ws.gui.AnnotationWsJob;
11 import jalview.ws.jws2.AbstractJabaCalcWorker;
12 import jalview.ws.jws2.JabaParamStore;
13 import jalview.ws.jws2.JabaPreset;
14 import jalview.ws.params.ArgumentI;
15 import jalview.ws.params.WsParamSetI;
16
17 import java.util.ArrayList;
18 import java.util.Iterator;
19 import java.util.List;
20
21 import compbio.data.msa.SequenceAnnotation;
22 import compbio.data.sequence.FastaSequence;
23 import compbio.data.sequence.Score;
24 import compbio.data.sequence.ScoreManager;
25 import compbio.metadata.JobSubmissionException;
26 import compbio.metadata.WrongParameterException;
27
28 public abstract class JabawsAnnotationInstance
29         extends JabawsServiceInstance<SequenceAnnotation>
30         implements SequenceAnnotationServiceI
31 {
32
33   /**
34    * holds last results obtained when non-null. TODO: remove this as a field ?
35    */
36   protected ScoreManager scoremanager = null;
37
38   public JabawsAnnotationInstance(Jws2Instance handle)
39   {
40     super(handle);
41   }
42
43
44   /**
45    * 
46    * @return the calcId for this Jabaws Service (convenience method).
47    * 
48    *         TODO: decide if this is really convenient since manager and
49    *         instance have same method !
50    */
51   public String getCalcId()
52   {
53     return our.aaui == null ? null : our.aaui.getCalcId();
54   }
55
56   @Override
57   public JobId submitToService(List<SequenceI> seqs, WsParamSetI preset,
58           List<ArgumentI> arguments) throws Throwable
59   {
60     String rslt = null;
61     scoremanager = null;
62     List<FastaSequence> jabaseqs = new ArrayList(seqs.size());
63     for (SequenceI seq : seqs)
64     {
65       jabaseqs.add(
66               new FastaSequence(seq.getName(), seq.getSequenceAsString()));
67     }
68     if (preset == null && arguments == null)
69     {
70       rslt = service.analize(jabaseqs);
71     }
72     if (preset != null)
73     {
74       if (preset instanceof JabaPreset)
75       {
76         // TODO: verify behaviour is really the same, since preset analyze was
77         // never called in Jalview 2.11.x
78         rslt = service.presetAnalize(jabaseqs,
79                 ((JabaPreset) preset).getJabaPreset());
80       }
81       else
82       {
83         rslt = service.customAnalize(jabaseqs,
84                 JabaParamStore.getJabafromJwsArgs(preset.getArguments()));
85       }
86     }
87     else if (arguments != null && arguments.size() > 0)
88     {
89       try
90       {
91         rslt = service.customAnalize(jabaseqs,
92                 JabaParamStore.getJabafromJwsArgs(arguments));
93       } catch (WrongParameterException x)
94       {
95         throw new JobSubmissionException(MessageManager.getString(
96                 "exception.jobsubmission_invalid_params_set"), x);
97
98       }
99     }
100
101     if (rslt == null)
102     {
103       return null;
104     }
105     return new JobId(our.getServiceType(), our.getName(), rslt);
106   }
107
108   @Override
109   public List<AlignmentAnnotation> getAlignmentAnnotation(
110           AnnotationWsJob running,
111           AbstractJabaCalcWorker abstractJabaCalcWorker) throws Throwable
112   {
113     if (scoremanager == null)
114     {
115       // TODO: raise annotation unavailable exception ?
116       scoremanager = service.getAnnotation(running.getJobId());
117     }
118     if (scoremanager == null)
119     {
120       return List.of();
121     }
122
123     return annotationFromScoreManager(running,
124             abstractJabaCalcWorker.getAlignViewport(),
125             abstractJabaCalcWorker.getGapMap());
126   }
127
128   /**
129    * service specific annotation creation method
130    * 
131    * @param running
132    * @param alignViewport
133    * @param gapMap
134    * @return
135    */
136   abstract List<AlignmentAnnotation> annotationFromScoreManager(
137           AnnotationWsJob running,
138           AlignViewportI alignViewport, boolean[] gapMap);
139
140   /**
141    * create and complete an annotation row from a JABAWS score object
142    * 
143    * @param alignViewport
144    * @param gapMap
145    * @param ourAnnot
146    * @param calcId
147    * @param alWidth
148    * @param scr
149    */
150
151   protected void createAnnotationRowsForScores(AlignViewportI alignViewport,
152           boolean[] gapMap, List<AlignmentAnnotation> ourAnnot,
153           String calcId,
154           int alWidth, Score scr)
155   {
156     // simple annotation row
157     AlignmentAnnotation annotation = alignViewport.getAlignment()
158             .findOrCreateAnnotation(scr.getMethod(), calcId, true, null,
159                     null);
160     if (alWidth == gapMap.length) // scr.getScores().size())
161     {
162       constructAnnotationFromScore(gapMap, annotation, 0,
163               alWidth, scr);
164       ourAnnot.add(annotation);
165     }
166   }
167
168   /**
169    * create a sequence associated annotation row for JABAWS score object scr
170    * 
171    * @param alignViewport
172    * @param gapMap
173    * @param ourAnnot
174    * @param typeName
175    * @param calcId
176    * @param dseq
177    * @param base
178    * @param scr
179    * @return
180    */
181   protected AlignmentAnnotation createAnnotationRowsForScores(
182           AlignViewportI alignViewport, boolean[] gapMap,
183           List<AlignmentAnnotation> ourAnnot, String typeName,
184           String calcId, SequenceI dseq, int base, Score scr)
185   {
186     System.out.println("Creating annotation on dseq:" + dseq.getStart()
187             + " base is " + base + " and length=" + dseq.getLength()
188             + " == " + scr.getScores().size());
189     // AlignmentAnnotation annotation = new AlignmentAnnotation(
190     // scr.getMethod(), typeName, new Annotation[]
191     // {}, 0, -1, AlignmentAnnotation.LINE_GRAPH);
192     // annotation.setCalcId(calcId);
193     AlignmentAnnotation annotation = alignViewport.getAlignment()
194             .findOrCreateAnnotation(typeName, calcId, false, dseq, null);
195     constructAnnotationFromScore(gapMap, annotation, 0, dseq.getLength(),
196             scr);
197     annotation.createSequenceMapping(dseq, base, false);
198     annotation.adjustForAlignment();
199     dseq.addAlignmentAnnotation(annotation);
200     ourAnnot.add(annotation);
201     return annotation;
202   }
203
204   /**
205    * replace an existing sequence associated annotation with another, creating
206    * association as necessary
207    * 
208    * @param newAnnot
209    *          - annotation row used to create an instance on the dataset
210    *          sequence.
211    * @param typeName
212    *          - label used to match existing row
213    * @param calcId
214    *          - calcId for existing row
215    * @param aSeq
216    *          - alignment sequence with reference to destination dataet sequence
217    */
218   protected void replaceAnnotationOnAlignmentWith(
219           AlignmentAnnotation newAnnot, String typeName, String calcId,
220           SequenceI aSeq)
221   {
222     SequenceI dsseq = aSeq.getDatasetSequence();
223     while (dsseq.getDatasetSequence() != null)
224     {
225       dsseq = dsseq.getDatasetSequence();
226     }
227     // look for same annotation on dataset and lift this one over
228     List<AlignmentAnnotation> dsan = dsseq.getAlignmentAnnotations(calcId,
229             typeName);
230     if (dsan != null && dsan.size() > 0)
231     {
232       for (AlignmentAnnotation dssan : dsan)
233       {
234         dsseq.removeAlignmentAnnotation(dssan);
235       }
236     }
237     AlignmentAnnotation dssan = new AlignmentAnnotation(newAnnot);
238     dsseq.addAlignmentAnnotation(dssan);
239     dssan.adjustForAlignment();
240   }
241
242   /**
243    * create column annotation elements from Jabaws score object
244    * 
245    * @param gapMap
246    * @param annotation
247    * @param base
248    * @param alWidth
249    * @param scr
250    *          JABAWS score object
251    */
252   protected void constructAnnotationFromScore(boolean[] gapMap,
253           AlignmentAnnotation annotation,
254           int base, int alWidth, Score scr)
255   {
256     Annotation[] elm = new Annotation[alWidth];
257     Iterator<Float> vals = scr.getScores().iterator();
258     float m = 0f, x = 0f;
259     for (int i = 0; vals.hasNext(); i++)
260     {
261       float val = vals.next().floatValue();
262       if (i == 0)
263       {
264         m = val;
265         x = val;
266       }
267       else
268       {
269         if (m > val)
270         {
271           m = val;
272         }
273         ;
274         if (x < val)
275         {
276           x = val;
277         }
278       }
279       // if we're at a gapped column then skip to next ungapped position
280       if (gapMap != null && gapMap.length > 0)
281       {
282         // if gapMap is a different length to the result then it may be out of
283         // sync with the job.
284         while (i < gapMap.length && !gapMap[i])
285         {
286           elm[i++] = new Annotation("", "", ' ', Float.NaN);
287         }
288       }
289       elm[i] = new Annotation("", "" + val, ' ', val);
290     }
291
292     annotation.annotations = elm;
293     annotation.belowAlignment = true;
294     if (x < 0)
295     {
296       x = 0;
297     }
298     x += (x - m) * 0.1;
299     annotation.graphMax = x;
300     annotation.graphMin = m;
301     annotation.validateRangeAndDisplay();
302   }
303
304 }