--- /dev/null
+package jalview.ws.jws2.jabaws2;
+
+import jalview.api.AlignViewportI;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceI;
+import jalview.util.MessageManager;
+import jalview.ws.api.JobId;
+import jalview.ws.api.SequenceAnnotationServiceI;
+import jalview.ws.gui.AnnotationWsJob;
+import jalview.ws.jws2.AbstractJabaCalcWorker;
+import jalview.ws.jws2.JabaParamStore;
+import jalview.ws.jws2.JabaPreset;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.WsParamSetI;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import compbio.data.msa.SequenceAnnotation;
+import compbio.data.sequence.FastaSequence;
+import compbio.data.sequence.Score;
+import compbio.data.sequence.ScoreManager;
+import compbio.metadata.JobSubmissionException;
+import compbio.metadata.WrongParameterException;
+
+public abstract class JabawsAnnotationInstance
+ extends JabawsServiceInstance<SequenceAnnotation>
+ implements SequenceAnnotationServiceI
+{
+
+ /**
+ * holds last results obtained when non-null. TODO: remove this as a field ?
+ */
+ protected ScoreManager scoremanager = null;
+
+ public JabawsAnnotationInstance(Jws2Instance handle)
+ {
+ super(handle);
+ }
+
+
+ /**
+ *
+ * @return the calcId for this Jabaws Service (convenience method).
+ *
+ * TODO: decide if this is really convenient since manager and
+ * instance have same method !
+ */
+ public String getCalcId()
+ {
+ return our.aaui == null ? null : our.aaui.getCalcId();
+ }
+
+ @Override
+ public JobId submitToService(List<SequenceI> seqs, WsParamSetI preset,
+ List<ArgumentI> arguments) throws Throwable
+ {
+ String rslt = null;
+ scoremanager = null;
+ List<FastaSequence> jabaseqs = new ArrayList(seqs.size());
+ for (SequenceI seq : seqs)
+ {
+ jabaseqs.add(
+ new FastaSequence(seq.getName(), seq.getSequenceAsString()));
+ }
+ if (preset == null && arguments == null)
+ {
+ rslt = service.analize(jabaseqs);
+ }
+ if (preset != null)
+ {
+ if (preset instanceof JabaPreset)
+ {
+ // TODO: verify behaviour is really the same, since preset analyze was
+ // never called in Jalview 2.11.x
+ rslt = service.presetAnalize(jabaseqs,
+ ((JabaPreset) preset).getJabaPreset());
+ }
+ else
+ {
+ rslt = service.customAnalize(jabaseqs,
+ JabaParamStore.getJabafromJwsArgs(preset.getArguments()));
+ }
+ }
+ else if (arguments != null && arguments.size() > 0)
+ {
+ try
+ {
+ rslt = service.customAnalize(jabaseqs,
+ JabaParamStore.getJabafromJwsArgs(arguments));
+ } catch (WrongParameterException x)
+ {
+ throw new JobSubmissionException(MessageManager.getString(
+ "exception.jobsubmission_invalid_params_set"), x);
+
+ }
+ }
+
+ if (rslt == null)
+ {
+ return null;
+ }
+ return new JobId(our.getServiceType(), our.getName(), rslt);
+ }
+
+ @Override
+ public List<AlignmentAnnotation> getAlignmentAnnotation(
+ AnnotationWsJob running,
+ AbstractJabaCalcWorker abstractJabaCalcWorker) throws Throwable
+ {
+ if (scoremanager == null)
+ {
+ // TODO: raise annotation unavailable exception ?
+ scoremanager = service.getAnnotation(running.getJobId());
+ }
+ if (scoremanager == null)
+ {
+ return List.of();
+ }
+
+ return annotationFromScoreManager(running,
+ abstractJabaCalcWorker.getAlignViewport(),
+ abstractJabaCalcWorker.getGapMap());
+ }
+
+ abstract List<AlignmentAnnotation> annotationFromScoreManager(
+ AnnotationWsJob running,
+ AlignViewportI alignViewport, boolean[] gapMap);
+
+ // From JabawsCalcWorker
+
+ protected void createAnnotationRowsForScores(AlignViewportI alignViewport,
+ boolean[] gapMap, List<AlignmentAnnotation> ourAnnot,
+ String calcId,
+ int alWidth, Score scr)
+ {
+ // simple annotation row
+ AlignmentAnnotation annotation = alignViewport.getAlignment()
+ .findOrCreateAnnotation(scr.getMethod(), calcId, true, null,
+ null);
+ if (alWidth == gapMap.length) // scr.getScores().size())
+ {
+ constructAnnotationFromScore(gapMap, annotation, 0,
+ alWidth, scr);
+ ourAnnot.add(annotation);
+ }
+ }
+
+ protected AlignmentAnnotation createAnnotationRowsForScores(
+ AlignViewportI alignViewport, boolean[] gapMap,
+ List<AlignmentAnnotation> ourAnnot, String typeName,
+ String calcId, SequenceI dseq, int base, Score scr)
+ {
+ System.out.println("Creating annotation on dseq:" + dseq.getStart()
+ + " base is " + base + " and length=" + dseq.getLength()
+ + " == " + scr.getScores().size());
+ // AlignmentAnnotation annotation = new AlignmentAnnotation(
+ // scr.getMethod(), typeName, new Annotation[]
+ // {}, 0, -1, AlignmentAnnotation.LINE_GRAPH);
+ // annotation.setCalcId(calcId);
+ AlignmentAnnotation annotation = alignViewport.getAlignment()
+ .findOrCreateAnnotation(typeName, calcId, false, dseq, null);
+ constructAnnotationFromScore(gapMap, annotation, 0, dseq.getLength(),
+ scr);
+ annotation.createSequenceMapping(dseq, base, false);
+ annotation.adjustForAlignment();
+ dseq.addAlignmentAnnotation(annotation);
+ ourAnnot.add(annotation);
+ return annotation;
+ }
+
+ protected void replaceAnnotationOnAlignmentWith(
+ AlignmentAnnotation newAnnot, String typeName, String calcId,
+ SequenceI aSeq)
+ {
+ SequenceI dsseq = aSeq.getDatasetSequence();
+ while (dsseq.getDatasetSequence() != null)
+ {
+ dsseq = dsseq.getDatasetSequence();
+ }
+ // look for same annotation on dataset and lift this one over
+ List<AlignmentAnnotation> dsan = dsseq.getAlignmentAnnotations(calcId,
+ typeName);
+ if (dsan != null && dsan.size() > 0)
+ {
+ for (AlignmentAnnotation dssan : dsan)
+ {
+ dsseq.removeAlignmentAnnotation(dssan);
+ }
+ }
+ AlignmentAnnotation dssan = new AlignmentAnnotation(newAnnot);
+ dsseq.addAlignmentAnnotation(dssan);
+ dssan.adjustForAlignment();
+ }
+
+ protected void constructAnnotationFromScore(boolean[] gapMap,
+ AlignmentAnnotation annotation,
+ int base, int alWidth, Score scr)
+ {
+ Annotation[] elm = new Annotation[alWidth];
+ Iterator<Float> vals = scr.getScores().iterator();
+ float m = 0f, x = 0f;
+ for (int i = 0; vals.hasNext(); i++)
+ {
+ float val = vals.next().floatValue();
+ if (i == 0)
+ {
+ m = val;
+ x = val;
+ }
+ else
+ {
+ if (m > val)
+ {
+ m = val;
+ }
+ ;
+ if (x < val)
+ {
+ x = val;
+ }
+ }
+ // if we're at a gapped column then skip to next ungapped position
+ if (gapMap != null && gapMap.length > 0)
+ {
+ // if gapMap is a different length to the result then it may be out of
+ // sync with the job.
+ while (i < gapMap.length && !gapMap[i])
+ {
+ elm[i++] = new Annotation("", "", ' ', Float.NaN);
+ }
+ }
+ elm[i] = new Annotation("", "" + val, ' ', val);
+ }
+
+ annotation.annotations = elm;
+ annotation.belowAlignment = true;
+ if (x < 0)
+ {
+ x = 0;
+ }
+ x += (x - m) * 0.1;
+ annotation.graphMax = x;
+ annotation.graphMin = m;
+ annotation.validateRangeAndDisplay();
+ }
+
+}