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
419 job.submitted = true;
\r
420 job.subjobComplete = false;
\r
421 Cache.log.info(WsUrl + " Job Id '" + job.jobId + "'");
\r
426 throw new Exception("Server timed out - try again later\n");
\r
429 catch (Exception e)
\r
431 if (e.getMessage().indexOf("Exception") > -1)
\r
433 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
434 wsInfo.setProgressText(j.jobnum,
\r
435 "Failed to submit the prediction. (Just close the window)\n"
\r
437 "It is most likely that there is a problem with the server.\n");
\r
438 System.err.println(
\r
439 "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +
\r
440 e.getMessage() + "\n");
\r
442 jalview.bin.Cache.log.warn("Server Exception", e);
\r
446 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
447 // JBPNote - this could be a popup informing the user of the problem.
\r
448 wsInfo.appendProgressText(j.jobnum,
\r
449 "Failed to submit the prediction:\n"
\r
451 wsInfo.getProgressText());
\r
453 jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);
\r
456 j.allowedServerExceptions = -1;
\r
457 j.subjobComplete = true;
\r
463 int results = 0; // number of result sets received
\r
464 JobStateSummary finalState = new JobStateSummary();
\r
467 for (int j = 0; j < jobs.length; j++)
\r
469 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
\r
470 if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
\r
476 catch (Exception ex)
\r
479 Cache.log.error("Unexpected exception when processing results for " +
\r
481 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
\r
485 wsInfo.showResultsNewFrame
\r
486 .addActionListener(new java.awt.event.ActionListener()
\r
488 public void actionPerformed(
\r
489 java.awt.event.ActionEvent evt)
\r
491 displayResults(true);
\r
494 wsInfo.mergeResults
\r
495 .addActionListener(new java.awt.event.ActionListener()
\r
497 public void actionPerformed(
\r
498 java.awt.event.ActionEvent evt)
\r
500 displayResults(false);
\r
503 wsInfo.setResultsReady();
\r
507 wsInfo.setFinishedNoResults();
\r
511 void displayResults(boolean newWindow)
\r
513 // TODO: cope with multiple subjobs.
\r
516 Object[] res = null;
\r
517 boolean msa = false;
\r
518 for (int jn = 0; jn < jobs.length; jn++)
\r
520 Object[] jobres = null;
\r
521 JPredJob j = (JPredJob) jobs[jn];
\r
523 if (j.hasResults())
\r
525 // hack - we only deal with all single seuqence predictions or all profile predictions
\r
526 msa = (j.msa != null) ? true : msa;
\r
529 jalview.bin.Cache.log.debug("Parsing output of job " + jn);
\r
530 jobres = j.getResultSet();
\r
531 jalview.bin.Cache.log.debug("Finished parsing output.");
\r
532 if (jobs.length == 1)
\r
538 // do merge with other job results
\r
540 "Multiple JNet subjob merging not yet implemented.");
\r
543 catch (Exception e)
\r
545 jalview.bin.Cache.log.error(
\r
546 "JNet Client: JPred Annotation Parse Error",
\r
548 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
549 wsInfo.appendProgressText(j.jobnum,
\r
550 OutputHeader + "\n" +
\r
551 j.result.getStatus() +
\r
552 "\nInvalid JNet job result data!\n" +
\r
554 j.result.setBroken(true);
\r
566 if (res[1] != null)
\r
568 af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],
\r
569 AlignFrame.DEFAULT_WIDTH,
\r
570 AlignFrame.DEFAULT_HEIGHT);
\r
574 af = new AlignFrame( (Alignment) res[0], AlignFrame.DEFAULT_WIDTH,
\r
575 AlignFrame.DEFAULT_HEIGHT);
\r
580 /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
581 if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {
\r
583 throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");
\r
587 // update hidden regions to account for loss of gaps in profile. - if any
\r
588 // gapMap returns insert list, interpreted as delete list by pruneDeletions
\r
589 //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));
\r
592 af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],
\r
593 AlignFrame.DEFAULT_WIDTH,
\r
594 AlignFrame.DEFAULT_HEIGHT);
\r
596 Desktop.addInternalFrame(af, altitle,
\r
597 AlignFrame.DEFAULT_WIDTH,
\r
598 AlignFrame.DEFAULT_HEIGHT);
\r
602 Cache.log.info("Append results onto existing alignment.");
\r
608 void pollJob(WSJob job)
\r
611 job.result = server.getresult(job.jobId);
\r
614 public boolean isCancellable()
\r
619 public void cancelJob()
\r
621 throw new Error("Implementation error!");
\r
624 public boolean canMergeResults()
\r