1 package jalview.ws.jws2;
3 import static java.lang.String.format;
5 import java.util.Hashtable;
8 import jalview.analysis.SeqsetUtils;
9 import jalview.bin.Cache;
10 import jalview.datamodel.Alignment;
11 import jalview.datamodel.AlignmentAnnotation;
12 import jalview.datamodel.AlignmentI;
13 import jalview.datamodel.AlignmentView;
14 import jalview.datamodel.HiddenColumns;
15 import jalview.datamodel.SequenceI;
16 import jalview.gui.AlignFrame;
17 import jalview.gui.Desktop;
18 import jalview.gui.WebserviceInfo;
19 import jalview.io.JPredFile;
20 import jalview.io.JnetAnnotationMaker;
21 import jalview.util.MessageManager;
22 import jalview.ws.AWSThread;
23 import jalview.ws.AWsJob;
24 import jalview.ws.JobStateSummary;
25 import jalview.ws.WSClientI;
26 import jalview.ws.api.CancellableI;
27 import jalview.ws.api.JPredMutlipleAlignmentServiceI;
28 import jalview.ws.gui.WsJob;
29 import jalview.ws.gui.WsJob.JobState;
32 class JPredJob extends WsJob
34 Hashtable<?, ?> sequenceInfo;
37 AlignmentI alignment = null;
38 HiddenColumns hiddenCols = null;
40 public JPredJob(Hashtable<?, ?> sequenceInfo, SequenceI[] msf, int[] delMap)
42 this.sequenceInfo = sequenceInfo;
43 this.msf = List.of(msf);
48 public boolean hasValidInput()
54 public boolean hasResults()
56 return (isSubjobComplete() && alignment != null);
61 public class JPredThread extends AWSThread implements WSClientI
64 private JPredMutlipleAlignmentServiceI server;
66 private Hashtable<?, ?> sequenceInfo;
67 private SequenceI[] msf;
70 public JPredThread(WebserviceInfo wsInfo, String title,
71 JPredMutlipleAlignmentServiceI server, Hashtable<?, ?> sequenceInfo,
72 SequenceI[] msf, int[] delMap, AlignmentView view, AlignFrame frame,
75 super(frame, wsInfo, view, wsURL);
78 this.sequenceInfo = sequenceInfo;
81 JPredJob job = new JPredJob(sequenceInfo, msf, delMap);
82 this.jobs = new JPredJob[] { job };
86 public boolean isCancellable()
88 return server instanceof CancellableI;
92 public boolean canMergeResults()
98 public void cancelJob()
100 // TODO Auto-generated method stub
105 public void pollJob(AWsJob job_) throws Exception
107 var job = (JPredJob) job_;
108 server.updateStatus(job);
109 server.updateJobProgress(job);
113 public void StartJob(AWsJob job_)
115 if (!(job_ instanceof JPredJob))
116 throw new RuntimeException("Invalid job type");
117 var job = (JPredJob) job_;
118 if (job.isSubmitted())
125 var jobHandle = server.align(job.msf);
126 if (jobHandle != null)
127 job.setJobHandle(jobHandle);
129 catch (Throwable th) {
130 if (!server.handleSubmitError(th, job, wsInfo)) {
134 if (job.getJobId() != null) {
135 job.setSubmitted(true);
136 job.setSubjobComplete(false);
140 throw new Exception(MessageManager.formatMessage(
141 "exception.web_service_returned_null_try_later",
148 // For unexpected errors
149 System.err.println(WebServiceName
150 + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
151 + "When contacting Server:" + WsUrl + "\n");
152 th.printStackTrace(System.err);
153 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
154 wsInfo.setStatus(job.getJobnum(),
155 WebserviceInfo.STATE_STOPPED_SERVERERROR);
160 if (!job.isSubmitted())
162 job.setAllowedServerExceptions(0);
163 wsInfo.appendProgressText(job.getJobnum(), MessageManager.getString(
164 "info.failed_to_submit_sequences_for_alignment"));
170 public void parseResult()
172 long progbar = (long) (Math.random() * ~(1L << 63));
173 wsInfo.setProgressBar(
174 MessageManager.getString("status.collecting_job_results"), progbar);
176 var finalState = new JobStateSummary();
179 for (int i = 0; i < jobs.length; i++) {
180 final var job = (JPredJob) jobs[i];
181 finalState.updateJobPanelState(wsInfo, OutputHeader, job);
182 if (job.isFinished()) {
184 server.updateJobProgress(job);
186 catch (Exception e) {
187 Cache.log.warn(format(
188 "Exception when retrieving remaining Job progress data " +
189 "for job %s on server %s", job.getJobId(), WsUrl));
192 // removed the waiting loop
193 Cache.log.debug(format("Job Execution file for job: %s " +
194 "on server %s%n%s", job.getJobId(), WsUrl, job.getStatus()));
196 prepareJobResult(job);
198 catch (Exception e) {
199 if (!server.handleCollectionException(e, job, wsInfo)) {
200 Cache.log.error("Could not get alignment for job.", e);
201 job.setState(JobState.SERVERERROR);
205 finalState.updateJobPanelState(wsInfo, OutputHeader, job);
206 if (job.isSubmitted() && job.isSubjobComplete() && job.hasResults()) {
211 catch (Exception e) {
213 "Unexpected exception when processing results for " + title, e);
214 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
217 wsInfo.showResultsNewFrame.addActionListener(
218 (evt) -> displayResults(true));
219 wsInfo.mergeResults.addActionListener(
220 (evt) -> displayResults(false));
221 wsInfo.setResultsReady();
224 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
225 wsInfo.appendInfoText("No jobs ran.");
226 wsInfo.setFinishedNoResults();
228 updateGlobalStatus(finalState);
229 wsInfo.removeProgressBar(progbar);
232 private void prepareJobResult(JPredJob job) throws Exception
234 HiddenColumns hiddenCols = null;
236 AlignmentI alignment;
237 var prediction = server.getPrediction(job.getJobHandle());
238 var preds = prediction.getSeqsAsArray();
240 if (job.delMap != null)
242 Object[] alandcolsel = input
243 .getAlignmentAndHiddenColumns(getGapChar());
244 alignment = new Alignment((SequenceI[]) alandcolsel[0]);
245 hiddenCols = (HiddenColumns) alandcolsel[1];
249 alignment = server.getAlignment(job.getJobHandle());
250 var seqs = new SequenceI[alignment.getHeight()];
251 for (int i = 0; i < alignment.getHeight(); i++)
253 seqs[i] = alignment.getSequenceAt(i);
255 if (!SeqsetUtils.deuniquify(sequenceInfo, seqs))
257 throw (new Exception(MessageManager.getString(
258 "exception.couldnt_recover_sequence_properties_for_alignment")));
262 if (currentView.getDataset() != null)
264 alignment.setDataset(currentView.getDataset());
268 alignment.setDataset(null);
270 JnetAnnotationMaker.add_annotation(prediction, alignment, firstSeq, false,
273 for (var annot : alignment.getAlignmentAnnotation())
275 if (annot.sequenceRef != null)
277 replaceAnnotationOnAlignmentWith(annot, annot.label,
278 "jalview.ws.JPred", annot.sequenceRef);
281 job.alignment = alignment;
282 job.hiddenCols = hiddenCols;
285 private static void replaceAnnotationOnAlignmentWith(
286 AlignmentAnnotation newAnnot, String typeName, String calcId,
289 SequenceI dsseq = aSeq.getDatasetSequence();
290 while (dsseq.getDatasetSequence() != null)
292 dsseq = dsseq.getDatasetSequence();
294 // look for same annotation on dataset and lift this one over
295 List<AlignmentAnnotation> dsan = dsseq.getAlignmentAnnotations(calcId,
297 if (dsan != null && dsan.size() > 0)
299 for (AlignmentAnnotation dssan : dsan)
301 dsseq.removeAlignmentAnnotation(dssan);
304 AlignmentAnnotation dssan = new AlignmentAnnotation(newAnnot);
305 dsseq.addAlignmentAnnotation(dssan);
306 dssan.adjustForAlignment();
309 private void displayResults(boolean newWindow)
311 if (jobs == null || jobs.length == 0)
315 var job = (JPredJob) jobs[0];
316 if (job.hasResults() && newWindow)
319 job.alignment.setSeqrep(job.alignment.getSequenceAt(0));
320 frame = new AlignFrame(job.alignment, job.hiddenCols,
321 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
322 Desktop.addInternalFrame(frame, title, AlignFrame.DEFAULT_WIDTH,
323 AlignFrame.DEFAULT_HEIGHT);