9c796448a060021f51dea9faab33bab1f5180ae4
[jalview.git] / src / jalview / ws2 / client / ebi / PhmmerWSClient.java
1 package jalview.ws2.client.ebi;
2
3 import java.io.IOException;
4 import java.io.StringReader;
5 import java.net.URI;
6 import java.util.List;
7
8 import jalview.datamodel.AlignmentI;
9 import jalview.datamodel.SequenceI;
10 import jalview.io.DataSourceType;
11 import jalview.io.FileFormat;
12 import jalview.io.FormatAdapter;
13 import jalview.ws.params.ArgumentI;
14 import jalview.ws.params.simple.BooleanOption;
15 import jalview.ws.params.simple.DoubleParameter;
16 import jalview.ws.params.simple.IntegerParameter;
17 import jalview.ws2.api.Credentials;
18 import jalview.ws2.api.JobStatus;
19 import jalview.ws2.api.WebServiceJobHandle;
20 import jalview.ws2.client.api.AlignmentWebServiceClientI;
21 import jalview.ws2.client.api.WebServiceClientI;
22 import uk.ac.dundee.compbio.hmmerclient.PhmmerClient;
23 import uk.ac.dundee.compbio.hmmerclient.PhmmerRequest;
24 import uk.ac.dundee.compbio.hmmerclient.PhmmerRequest.SequenceDatabase;
25 import uk.ac.dundee.compbio.hmmerclient.PhmmerRequest.SubstitutionMatrix;
26
27 public class PhmmerWSClient implements AlignmentWebServiceClientI
28 {
29
30   final PhmmerClient client;
31
32   PhmmerWSClient(PhmmerClient client)
33   {
34     this.client = client;
35   }
36
37   @Override
38   public String getUrl()
39   {
40     return client.getURL().toString();
41   }
42
43   @Override
44   public String getClientName()
45   {
46     return "ebi-job-dispatcher";
47   }
48
49   @Override
50   public WebServiceJobHandle submit(List<SequenceI> sequences,
51           List<ArgumentI> args, Credentials credentials) throws IOException
52   {
53     var request = PhmmerRequest.newBuilder();
54     String sequence = FileFormat.Fasta.getWriter(null)
55             .print(new SequenceI[]{ sequences.get(0) }, false);
56     request.sequence(new StringReader(sequence));
57     populateRequestArguments(request, args);
58     var email = credentials.getEmail() != null ? credentials.getEmail() :
59       "nouser@jalview.org";
60     var jobId = client.submit(request.build(), email);
61     return new WebServiceJobHandle(
62             getClientName(), "phmmer", getUrl(), jobId);
63   }
64   
65   private static void populateRequestArguments(PhmmerRequest.Builder request, List<ArgumentI> args)
66   {
67     boolean useBitScore = false;
68     boolean useEValue = false;
69     for (var arg : args)
70     {
71       if (arg.getName().equals("cut-offs"))
72         if (arg.getValue().equals("E"))
73           useEValue = true;
74         else if (arg.getValue().equals("T"))
75           useBitScore = true;
76         else
77           throw new IllegalArgumentException(
78                   "cut-offs argument contains value other than \"E\" or \"T\": "
79                           + arg.getValue());
80     }
81     assert (useBitScore || useEValue) && !(useBitScore && useEValue);
82     for (var arg : args)
83     {
84       switch (arg.getName())
85       {
86       case "incE":
87         request.incE(useEValue ? DoubleParameter.parseFloat(arg) : null);
88         break;
89       case "incdomE":
90         request.incdomE(useEValue ? DoubleParameter.parseFloat(arg) : null);
91         break;
92       case "E":
93         request.E(useEValue ? DoubleParameter.parseFloat(arg) : null);
94         break;
95       case "domE":
96         request.domE(useEValue ? DoubleParameter.parseFloat(arg) : null);
97         break;
98       case "incT":
99         request.incT(useBitScore ? DoubleParameter.parseFloat(arg) : null);
100         break;
101       case "incdomT":
102         request.incdomT(useBitScore ? DoubleParameter.parseFloat(arg) : null);
103         break;
104       case "T":
105         request.T(useBitScore ? DoubleParameter.parseFloat(arg) : null);
106         break;
107       case "domT":
108         request.domT(useBitScore ? DoubleParameter.parseFloat(arg) : null);
109         break;
110       case "popen":
111         request.popen(DoubleParameter.parseFloat(arg));
112         break;
113       case "pextend":
114         request.pextend(DoubleParameter.parseFloat(arg));
115         break;
116       case "mx":
117         request.mx(parseSubstitutionMatrix(arg));
118         break;
119       case "nobias":
120         request.noBias(BooleanOption.parseBoolean(arg));
121         break;
122       case "compressedout":
123         request.compressedOut(BooleanOption.parseBoolean(arg));
124         break;
125       case "alignView":
126         request.compressedOut(BooleanOption.parseBoolean(arg));
127         break;
128       case "database":
129         request.database(parseSequenceDatabase(arg));
130         break;
131       case "evalue":
132         request.evalue(DoubleParameter.parseFloat(arg));
133         break;
134       case "nhits":
135         request.nhits(IntegerParameter.parseInt(arg));
136         break;
137       }
138     }
139   }
140
141   private static SubstitutionMatrix parseSubstitutionMatrix(ArgumentI arg)
142   {
143     if (arg.getValue() == null)
144       return null;
145     switch (arg.getValue())
146     {
147     case "BLOSUM45":
148       return SubstitutionMatrix.BLOSUM45;
149     case "BLOSUM62":
150       return SubstitutionMatrix.BLOSUM62;
151     case "BLOSUM90":
152       return SubstitutionMatrix.BLOSUM90;
153     case "PAM30":
154       return SubstitutionMatrix.PAM30;
155     case "PAM70":
156       return SubstitutionMatrix.PAM70;
157     default:
158       throw new IllegalArgumentException(
159               "invalid matrix " + arg.getValue());
160     }
161   }
162
163   private static SequenceDatabase parseSequenceDatabase(ArgumentI arg)
164   {
165     if (arg.getValue() == null)
166       return null;
167     switch (arg.getValue())
168     {
169     case "swissprot":
170       return SequenceDatabase.SWISS_PROT;
171     case "uniprotrefprot":
172       return SequenceDatabase.REFERENCE_PROTEOMES;
173     case "uniprotkb":
174       return SequenceDatabase.UNIPROTKB;
175     case "pdb":
176       return SequenceDatabase.PDB;
177     case "rp75":
178       return SequenceDatabase.RP75;
179     case "rp55":
180       return SequenceDatabase.RP55;
181     case "rp35":
182       return SequenceDatabase.RP35;
183     case "rp15":
184       return SequenceDatabase.RP15;
185     case "ensembl":
186       return SequenceDatabase.ENSEMBL;
187     case "merops":
188       return SequenceDatabase.MEROPS;
189     case "qfo":
190       return SequenceDatabase.QUEST_FOR_ORTHOLOGS;
191     case "chembl":
192       return SequenceDatabase.CHEMBL;
193     default:
194       throw new IllegalArgumentException(
195               "invalid database " + arg.getValue());
196     }
197   }
198
199   @Override
200   public JobStatus getStatus(WebServiceJobHandle job) throws IOException
201   {
202     var status = client.getStatus(job.getJobId());
203     switch (status)
204     {
205     case PENDING: return JobStatus.SUBMITTED;
206     case QUEUED: return JobStatus.QUEUED;
207     case RUNNING: return JobStatus.RUNNING;
208     case FINISHED: return JobStatus.COMPLETED;
209     case FAILURE: return JobStatus.FAILED;
210     case ERROR: return JobStatus.SERVER_ERROR;
211     case NOT_FOUND: return JobStatus.SERVER_ERROR;
212     case UNDEFINED: return JobStatus.UNKNOWN;
213     }
214     return JobStatus.UNKNOWN;
215   }
216
217   @Override
218   public String getLog(WebServiceJobHandle job) throws IOException
219   {
220     return "";
221   }
222
223   @Override
224   public String getErrorLog(WebServiceJobHandle job) throws IOException
225   {
226     return "";
227   }
228
229   @Override
230   public void cancel(WebServiceJobHandle job)
231           throws IOException, UnsupportedOperationException
232   {
233     throw new UnsupportedOperationException(
234             "ebi job dispatcher does not support job cancellation");
235   }
236
237   /**
238    * FIXME: Temporary hack
239    */
240   @Override
241   public AlignmentI getAlignment(WebServiceJobHandle job) throws IOException
242   {
243     URI url = client.getResultURL(job.getJobId(), "sto");
244     return new FormatAdapter().readFile(url.toString(), DataSourceType.URL, FileFormat.Stockholm);
245   }
246 }