JAL-3954 Do not retrieve alignment for failed jobs
[jalview.git] / src / jalview / ws2 / actions / hmmer / PhmmerTask.java
1 package jalview.ws2.actions.hmmer;
2
3 import static jalview.util.Comparison.GapChars;
4
5 import java.io.IOException;
6 import java.util.Arrays;
7 import java.util.List;
8
9 import jalview.analysis.AlignSeq;
10 import jalview.bin.Console;
11 import jalview.datamodel.AlignmentAnnotation;
12 import jalview.datamodel.AlignmentI;
13 import jalview.datamodel.AlignmentView;
14 import jalview.datamodel.Annotation;
15 import jalview.datamodel.Sequence;
16 import jalview.datamodel.SequenceI;
17 import jalview.util.Comparison;
18 import jalview.ws.params.ArgumentI;
19 import jalview.ws2.actions.AbstractPollableTask;
20 import jalview.ws2.actions.BaseJob;
21 import jalview.ws2.actions.ServiceInputInvalidException;
22 import jalview.ws2.actions.api.TaskEventListener;
23 import jalview.ws2.api.Credentials;
24 import jalview.ws2.api.JobStatus;
25 import jalview.ws2.client.api.AlignmentWebServiceClientI;
26
27 class PhmmerTask extends AbstractPollableTask<BaseJob, AlignmentI>
28 {
29   private final AlignmentWebServiceClientI client;
30   private final AlignmentView view;
31
32   PhmmerTask(AlignmentWebServiceClientI client, List<ArgumentI> args,
33           Credentials credentials, AlignmentView view,
34           TaskEventListener<AlignmentI> eventListener)
35   {
36     super(client, args, credentials, eventListener);
37     this.client = client;
38     this.view = view;
39   }
40
41   @Override
42   protected List<BaseJob> prepare() throws ServiceInputInvalidException
43   {
44     Console.info("Preparing sequence for phmmer job");
45     var sequence = view.getVisibleAlignment('-').getSequenceAt(0);
46     var seq = new Sequence(sequence.getName(),
47             AlignSeq.extractGaps(GapChars, sequence.getSequenceAsString()));
48     var job = new BaseJob(List.of(seq))
49     {
50       @Override
51       public boolean isInputValid()
52       {
53         return true;
54       }
55     };
56     job.setStatus(JobStatus.READY);
57     return List.of(job);
58   }
59
60   @Override
61   protected AlignmentI done() throws IOException
62   {
63     var job = getSubJobs().get(0);
64     var status = job.getStatus();
65     Console.info(String.format("phmmer finished job \"%s\" with status %s",
66             job.getServerJob().getJobId(), status));
67     if (status != JobStatus.COMPLETED)
68       return null;
69     var outputAlignment = client.getAlignment(job.getServerJob());
70     var querySeq = job.getInputSequences().get(0).deriveSequence();
71     {
72       AlignmentAnnotation refpos = null;
73       for (var annot : outputAlignment.getAlignmentAnnotation())
74       {
75         if (annot.sequenceRef == null && annot.label.equals("Reference Positions"))
76         {
77           refpos = annot;
78           break;
79         }
80       }
81       if (refpos != null)
82       {
83         querySeq = alignQeuryToReferencePositions(querySeq, refpos);
84       }
85     }
86     outputAlignment.insertSequenceAt(0, querySeq);
87     return outputAlignment;
88   }
89
90   private SequenceI alignQeuryToReferencePositions(SequenceI query, AlignmentAnnotation refpos)
91   {
92     var sequenceBuilder = new StringBuilder();
93     var index = 0;
94     for (Annotation a : refpos.annotations)
95     {
96       // TODO: we assume that the number of "x" annotations is equal to the number
97       // of residues. may need a safeguard against invalid input
98       if (a != null && a.displayCharacter.equals("x"))
99       {
100         char c;
101         do
102           c = query.getCharAt(index++);
103         while (Comparison.isGap(c));
104         sequenceBuilder.append(c);
105       }
106       else
107       {
108         sequenceBuilder.append(Comparison.GAP_DASH);
109       }
110     }
111     query.setSequence(sequenceBuilder.toString());
112     return query;
113   }
114 }