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