5 import jalview.analysis.*;
\r
6 import jalview.bin.*;
\r
7 import jalview.datamodel.*;
\r
8 import jalview.datamodel.Alignment;
\r
9 import jalview.gui.*;
\r
10 import jalview.io.*;
\r
11 import jalview.util.*;
\r
12 import vamsas.objects.simple.JpredResult;
\r
15 extends WSThread implements WSClientI
\r
17 // TODO: put mapping between JPredJob input and input data here - JNetAnnotation adding is done after result parsing.
\r
19 extends WSThread.WSJob
\r
21 // TODO: make JPredJob deal only with what was sent to and received from a JNet service
\r
22 int[] predMap = null; // mapping from sequence(i) to the original sequence(predMap[i]) being predicted on
\r
23 vamsas.objects.simple.Sequence sequence;
\r
24 vamsas.objects.simple.Msfalignment msa;
\r
25 java.util.Hashtable SequenceInfo = null;
\r
26 int msaIndex = 0; // the position of the original sequence in the array of Sequences in the input object that this job holds a prediction for
\r
29 * @return true if getResultSet will return a valid alignment and prediction result.
\r
31 public boolean hasResults()
\r
33 if (subjobComplete && result != null && result.isFinished()
\r
34 && ( (JpredResult) result).getPredfile() != null &&
\r
35 ( (JpredResult) result).getAligfile() != null)
\r
42 boolean hasValidInput()
\r
44 if (sequence != null)
\r
53 * @return null or Object[] { annotated alignment for this prediction, ColumnSelection for this prediction} or null if no results available.
\r
56 public Object[] getResultSet()
\r
59 if (result == null || !result.isFinished())
\r
63 Alignment al = null;
\r
64 ColumnSelection alcsel = null;
\r
65 int FirstSeq = -1; // the position of the query sequence in Alignment al
\r
67 JpredResult result = (JpredResult)this.result;
\r
69 jalview.bin.Cache.log.debug("Parsing output from JNet job.");
\r
70 // JPredFile prediction = new JPredFile("C:/JalviewX/files/jpred.txt", "File");
\r
71 jalview.io.JPredFile prediction = new jalview.io.JPredFile(result.
\r
74 SequenceI[] preds = prediction.getSeqsAsArray();
\r
75 jalview.bin.Cache.log.debug("Got prediction profile.");
\r
77 if ( (this.msa != null) && (result.getAligfile() != null))
\r
79 jalview.bin.Cache.log.debug("Getting associated alignment.");
\r
80 // we ignore the returned alignment if we only predicted on a single sequence
\r
81 String format = new jalview.io.IdentifyFile().Identify(result.
\r
85 if (jalview.io.FormatAdapter.isValidFormat(format))
\r
88 if (predMap != null)
\r
90 Object[] alandcolsel = input.getAlignmentAndColumnSelection(
\r
92 sqs = (SequenceI[]) alandcolsel[0];
\r
93 al = new Alignment(sqs);
\r
94 alcsel = (ColumnSelection) alandcolsel[1];
\r
98 al = new FormatAdapter().readFile(result.getAligfile(),
\r
100 sqs = new SequenceI[al.getHeight()];
\r
102 for (int i = 0, j = al.getHeight(); i < j; i++)
\r
104 sqs[i] = al.getSequenceAt(i);
\r
106 if (!jalview.analysis.SeqsetUtils.deuniquify( (Hashtable)
\r
107 SequenceInfo, sqs))
\r
109 throw (new Exception(
\r
110 "Couldn't recover sequence properties for alignment."));
\r
114 al.setDataset(null);
\r
116 jalview.io.JnetAnnotationMaker.add_annotation(prediction, al,
\r
123 throw (new Exception(
\r
124 "Unknown format " + format + " for file : \n" +
\r
125 result.getAligfile()));
\r
130 al = new Alignment(preds);
\r
131 FirstSeq = prediction.getQuerySeqPosition();
\r
132 if (predMap != null)
\r
134 char gc = getGapChar();
\r
135 SequenceI[] sqs = (SequenceI[]) ( (java.lang.Object[]) input.
\r
136 getAlignmentAndColumnSelection(gc))[
\r
138 if (this.msaIndex >= sqs.length)
\r
140 throw new Error("Implementation Error! Invalid msaIndex for JPredJob on parent MSA input object!");
\r
144 //Uses RemoveGapsCommand
\r
146 new jalview.commands.RemoveGapsCommand("Remove Gaps",
\r
151 SequenceI profileseq = al.getSequenceAt(FirstSeq);
\r
152 profileseq.setSequence(sqs[msaIndex].getSequenceAsString());
\r
155 if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash(
\r
156 al.getSequenceAt(FirstSeq), SequenceInfo))
\r
158 throw (new Exception(
\r
159 "Couldn't recover sequence properties for JNet Query sequence!"));
\r
163 al.setDataset(null);
\r
164 jalview.io.JnetAnnotationMaker.add_annotation(prediction, al,
\r
167 SequenceI profileseq = al.getSequenceAt(0); // this includes any gaps.
\r
168 alignToProfileSeq(al, profileseq);
\r
169 if (predMap != null)
\r
171 // Adjust input view for gaps
\r
172 // propagate insertions into profile
\r
173 alcsel = propagateInsertions(profileseq, al, input);
\r
177 return new Object[]
\r
179 al, alcsel}; // , FirstSeq, noMsa};
\r
183 * Given an alignment where all other sequences except profileseq are aligned to the ungapped profileseq, insert gaps in the other sequences to realign them with the residues in profileseq
\r
185 * @param profileseq
\r
187 private void alignToProfileSeq(Alignment al, SequenceI profileseq)
\r
189 char gc = al.getGapCharacter();
\r
190 int[] gapMap = profileseq.gapMap();
\r
191 // insert gaps into profile
\r
192 for (int lp = 0, r = 0; r < gapMap.length; r++)
\r
194 if (gapMap[r] - lp > 1)
\r
196 StringBuffer sb = new StringBuffer();
\r
197 for (int s = 0, ns = gapMap[r] - lp; s < ns; s++)
\r
201 for (int s = 1, ns = al.getHeight(); s < ns; s++)
\r
203 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
204 int diff = gapMap[r] - sq.length();
\r
209 while ( (diff = gapMap[r] - sq.length()) > 0)
\r
212 ( (diff >= sb.length()) ? sb.toString() :
\r
213 sb.substring(0, diff));
\r
215 al.getSequenceAt(s).setSequence(sq);
\r
219 al.getSequenceAt(s).setSequence(sq.substring(0, gapMap[r]) +
\r
221 sq.substring(gapMap[r]));
\r
230 * Add gaps into the sequences aligned to profileseq under the given AlignmentView
\r
231 * @param profileseq
\r
235 private ColumnSelection propagateInsertions(SequenceI profileseq,
\r
237 AlignmentView input)
\r
239 char gc = al.getGapCharacter();
\r
240 Object[] alandcolsel = input.getAlignmentAndColumnSelection(gc);
\r
241 ColumnSelection nview = (ColumnSelection) alandcolsel[1];
\r
243 nview.pruneDeletions(ShiftList.parseMap( (origseq = ( (SequenceI[])
\r
244 alandcolsel[0])[0]).gapMap())); // recover original prediction sequence's mapping to view.
\r
245 int[] viscontigs = nview.getVisibleContigs(0, profileseq.getLength());
\r
248 // input.pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()))
\r
249 // add profile to visible contigs
\r
250 for (int v = 0; v < viscontigs.length; v += 2)
\r
252 if (viscontigs[v] > spos)
\r
254 StringBuffer sb = new StringBuffer();
\r
255 for (int s = 0, ns = viscontigs[v] - spos; s < ns; s++)
\r
259 for (int s = 0, ns = al.getHeight(); s < ns; s++)
\r
261 SequenceI sqobj = al.getSequenceAt(s);
\r
262 if (sqobj != profileseq)
\r
264 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
265 if (sq.length() <= spos + offset)
\r
268 int diff = spos + offset - sq.length() - 1;
\r
273 while ( (diff = spos + offset - sq.length() - 1) > 0)
\r
276 ( (diff >= sb.length()) ? sb.toString() :
\r
277 sb.substring(0, diff));
\r
280 sq += sb.toString();
\r
284 al.getSequenceAt(s).setSequence(sq.substring(0, spos + offset) +
\r
286 sq.substring(spos + offset));
\r
290 //offset+=sb.length();
\r
292 spos = viscontigs[v + 1] + 1;
\r
294 if ( (offset + spos) < profileseq.getLength())
\r
296 StringBuffer sb = new StringBuffer();
\r
297 for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)
\r
301 for (int s = 1, ns = al.getHeight(); s < ns; s++)
\r
303 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
305 int diff = origseq.getLength() - sq.length();
\r
309 ( (diff >= sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
310 diff = origseq.getLength() - sq.length();
\r
317 public JPredJob(Hashtable SequenceInfo, SequenceI seq, int[] delMap)
\r
320 this.predMap = delMap;
\r
321 String sq = AlignSeq.extractGaps(Comparison.GapChars,
\r
322 seq.getSequenceAsString());
\r
323 if (sq.length() >= 20)
\r
325 this.SequenceInfo = SequenceInfo;
\r
326 sequence = new vamsas.objects.simple.Sequence();
\r
327 sequence.setId(seq.getName());
\r
328 sequence.setSeq(sq);
\r
332 public JPredJob(Hashtable SequenceInfo, SequenceI[] msf, int[] delMap)
\r
334 this(SequenceInfo, msf[0], delMap);
\r
335 if (sequence != null)
\r
337 if (msf.length > 1)
\r
339 msa = new vamsas.objects.simple.Msfalignment();
\r
340 jalview.io.PileUpfile pileup = new jalview.io.PileUpfile();
\r
341 msa.setMsf(pileup.print(msf));
\r
347 ext.vamsas.Jpred server;
\r
348 String altitle = "";
\r
349 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,
\r
350 String wsurl, AlignmentView alview, AlignFrame alframe)
\r
352 super(alframe, wsinfo, alview, wsurl);
\r
353 this.altitle = altitle;
\r
354 this.server = server;
\r
357 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,
\r
358 String wsurl, Hashtable SequenceInfo, SequenceI seq, int[] delMap,
\r
359 AlignmentView alview, AlignFrame alframe)
\r
361 this(wsinfo, altitle, server, wsurl, alview, alframe);
\r
362 JPredJob job = new JPredJob(SequenceInfo, seq, delMap);
\r
363 if (job.hasValidInput())
\r
365 OutputHeader = wsInfo.getProgressText();
\r
373 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,
\r
374 Hashtable SequenceInfo, SequenceI[] msf, int[] delMap,
\r
375 AlignmentView alview, AlignFrame alframe, String wsurl)
\r
377 this(wsinfo, altitle, server, wsurl, alview, alframe);
\r
378 JPredJob job = new JPredJob(SequenceInfo, msf, delMap);
\r
379 if (job.hasValidInput())
\r
384 OutputHeader = wsInfo.getProgressText();
\r
389 void StartJob(WSJob j)
\r
391 if (! (j instanceof JPredJob))
\r
393 throw new Error("Implementation error - StartJob(JpredJob) called on " +
\r
398 JPredJob job = (JPredJob) j;
\r
399 if (job.msa != null)
\r
401 job.jobId = server.predictOnMsa(job.msa);
\r
404 if (job.sequence != null)
\r
406 job.jobId = server.predict(job.sequence); // debug like : job.jobId = "/jobs/www-jpred/jp_Yatat29";//
\r
409 if (job.jobId != null)
\r
411 if (job.jobId.startsWith("Broken"))
\r
413 job.result = (vamsas.objects.simple.Result)new JpredResult();
\r
414 job.result.setInvalid(true);
\r
415 job.result.setStatus("Submission " + job.jobId);
\r
416 throw new Exception(job.jobId);
\r
420 job.submitted = true;
\r
421 job.subjobComplete = false;
\r
422 Cache.log.info(WsUrl + " Job Id '" + job.jobId + "'");
\r
427 throw new Exception("Server timed out - try again later\n");
\r
430 catch (Exception e)
\r
432 // kill the whole job.
\r
433 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
434 if (e.getMessage().indexOf("Exception") > -1)
\r
436 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
437 wsInfo.setProgressText(j.jobnum,
\r
438 "Failed to submit the prediction. (Just close the window)\n"
\r
440 "It is most likely that there is a problem with the server.\n");
\r
441 System.err.println(
\r
442 "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +
\r
443 e.getMessage() + "\n");
\r
445 jalview.bin.Cache.log.warn("Server Exception", e);
\r
449 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
450 // JBPNote - this could be a popup informing the user of the problem.
\r
451 wsInfo.appendProgressText(j.jobnum,
\r
452 "Failed to submit the prediction:\n"
\r
454 wsInfo.getProgressText());
\r
456 jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);
\r
459 j.allowedServerExceptions = -1;
\r
460 j.subjobComplete = true;
\r
466 int results = 0; // number of result sets received
\r
467 JobStateSummary finalState = new JobStateSummary();
\r
470 for (int j = 0; j < jobs.length; j++)
\r
472 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
\r
473 if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
\r
479 catch (Exception ex)
\r
482 Cache.log.error("Unexpected exception when processing results for " +
\r
484 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
\r
488 wsInfo.showResultsNewFrame
\r
489 .addActionListener(new java.awt.event.ActionListener()
\r
491 public void actionPerformed(
\r
492 java.awt.event.ActionEvent evt)
\r
494 displayResults(true);
\r
497 wsInfo.mergeResults
\r
498 .addActionListener(new java.awt.event.ActionListener()
\r
500 public void actionPerformed(
\r
501 java.awt.event.ActionEvent evt)
\r
503 displayResults(false);
\r
506 wsInfo.setResultsReady();
\r
510 wsInfo.setFinishedNoResults();
\r
514 void displayResults(boolean newWindow)
\r
516 // TODO: cope with multiple subjobs.
\r
519 Object[] res = null;
\r
520 boolean msa = false;
\r
521 for (int jn = 0; jn < jobs.length; jn++)
\r
523 Object[] jobres = null;
\r
524 JPredJob j = (JPredJob) jobs[jn];
\r
526 if (j.hasResults())
\r
528 // hack - we only deal with all single seuqence predictions or all profile predictions
\r
529 msa = (j.msa != null) ? true : msa;
\r
532 jalview.bin.Cache.log.debug("Parsing output of job " + jn);
\r
533 jobres = j.getResultSet();
\r
534 jalview.bin.Cache.log.debug("Finished parsing output.");
\r
535 if (jobs.length == 1)
\r
541 // do merge with other job results
\r
543 "Multiple JNet subjob merging not yet implemented.");
\r
546 catch (Exception e)
\r
548 jalview.bin.Cache.log.error(
\r
549 "JNet Client: JPred Annotation Parse Error",
\r
551 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
552 wsInfo.appendProgressText(j.jobnum,
\r
553 OutputHeader + "\n" +
\r
554 j.result.getStatus() +
\r
555 "\nInvalid JNet job result data!\n" +
\r
557 j.result.setBroken(true);
\r
569 if (res[1] != null)
\r
571 af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],
\r
572 AlignFrame.DEFAULT_WIDTH,
\r
573 AlignFrame.DEFAULT_HEIGHT);
\r
577 af = new AlignFrame( (Alignment) res[0], AlignFrame.DEFAULT_WIDTH,
\r
578 AlignFrame.DEFAULT_HEIGHT);
\r
583 /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
584 if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {
\r
586 throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");
\r
590 // update hidden regions to account for loss of gaps in profile. - if any
\r
591 // gapMap returns insert list, interpreted as delete list by pruneDeletions
\r
592 //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));
\r
595 af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],
\r
596 AlignFrame.DEFAULT_WIDTH,
\r
597 AlignFrame.DEFAULT_HEIGHT);
\r
599 Desktop.addInternalFrame(af, altitle,
\r
600 AlignFrame.DEFAULT_WIDTH,
\r
601 AlignFrame.DEFAULT_HEIGHT);
\r
605 Cache.log.info("Append results onto existing alignment.");
\r
611 void pollJob(WSJob job)
\r
614 job.result = server.getresult(job.jobId);
\r
617 public boolean isCancellable()
\r
622 public void cancelJob()
\r
624 throw new Error("Implementation error!");
\r
627 public boolean canMergeResults()
\r