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.SeqAnnotationServiceCalcWorker; 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 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 seqs, WsParamSetI preset, List arguments) throws Throwable { String rslt = null; scoremanager = null; List 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 getAlignmentAnnotation( AnnotationWsJob running, SeqAnnotationServiceCalcWorker 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()); } /** * service specific annotation creation method * * @param running * @param alignViewport * @param gapMap * @return */ abstract List annotationFromScoreManager( AnnotationWsJob running, AlignViewportI alignViewport, boolean[] gapMap); /** * create and complete an annotation row from a JABAWS score object * * @param alignViewport * @param gapMap * @param ourAnnot * @param calcId * @param alWidth * @param scr */ protected void createAnnotationRowsForScores(AlignViewportI alignViewport, boolean[] gapMap, List 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); } } /** * create a sequence associated annotation row for JABAWS score object scr * * @param alignViewport * @param gapMap * @param ourAnnot * @param typeName * @param calcId * @param dseq * @param base * @param scr * @return */ protected AlignmentAnnotation createAnnotationRowsForScores( AlignViewportI alignViewport, boolean[] gapMap, List 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; } /** * replace an existing sequence associated annotation with another, creating * association as necessary * * @param newAnnot * - annotation row used to create an instance on the dataset * sequence. * @param typeName * - label used to match existing row * @param calcId * - calcId for existing row * @param aSeq * - alignment sequence with reference to destination dataet sequence */ 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 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(); } /** * create column annotation elements from Jabaws score object * * @param gapMap * @param annotation * @param base * @param alWidth * @param scr * JABAWS score object */ protected void constructAnnotationFromScore(boolean[] gapMap, AlignmentAnnotation annotation, int base, int alWidth, Score scr) { Annotation[] elm = new Annotation[alWidth]; Iterator 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(); } }