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