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
91 alignFrame.getViewport().getGapCharacter());
\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 = alignFrame.getViewport().getGapCharacter();
\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
149 alignFrame.getCurrentView().
\r
152 SequenceI profileseq = al.getSequenceAt(FirstSeq);
\r
153 profileseq.setSequence(sqs[msaIndex].getSequenceAsString());
\r
156 if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash(
\r
157 al.getSequenceAt(FirstSeq), SequenceInfo))
\r
159 throw (new Exception(
\r
160 "Couldn't recover sequence properties for JNet Query sequence!"));
\r
164 al.setDataset(null);
\r
165 jalview.io.JnetAnnotationMaker.add_annotation(prediction, al,
\r
168 SequenceI profileseq = al.getSequenceAt(0); // this includes any gaps.
\r
169 alignToProfileSeq(al, profileseq);
\r
170 if (predMap != null)
\r
172 // Adjust input view for gaps
\r
173 // propagate insertions into profile
\r
174 alcsel = propagateInsertions(profileseq, al, input);
\r
178 return new Object[]
\r
180 al, alcsel}; // , FirstSeq, noMsa};
\r
184 * 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
186 * @param profileseq
\r
188 private void alignToProfileSeq(Alignment al, SequenceI profileseq)
\r
190 char gc = al.getGapCharacter();
\r
191 int[] gapMap = profileseq.gapMap();
\r
192 // insert gaps into profile
\r
193 for (int lp = 0, r = 0; r < gapMap.length; r++)
\r
195 if (gapMap[r] - lp > 1)
\r
197 StringBuffer sb = new StringBuffer();
\r
198 for (int s = 0, ns = gapMap[r] - lp; s < ns; s++)
\r
202 for (int s = 1, ns = al.getHeight(); s < ns; s++)
\r
204 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
205 int diff = gapMap[r] - sq.length();
\r
210 while ( (diff = gapMap[r] - sq.length()) > 0)
\r
213 ( (diff >= sb.length()) ? sb.toString() :
\r
214 sb.substring(0, diff));
\r
216 al.getSequenceAt(s).setSequence(sq);
\r
220 al.getSequenceAt(s).setSequence(sq.substring(0, gapMap[r]) +
\r
222 sq.substring(gapMap[r]));
\r
231 * Add gaps into the sequences aligned to profileseq under the given AlignmentView
\r
232 * @param profileseq
\r
236 private ColumnSelection propagateInsertions(SequenceI profileseq,
\r
238 AlignmentView input)
\r
240 char gc = al.getGapCharacter();
\r
241 Object[] alandcolsel = input.getAlignmentAndColumnSelection(gc);
\r
242 ColumnSelection nview = (ColumnSelection) alandcolsel[1];
\r
244 nview.pruneDeletions(ShiftList.parseMap( (origseq = ( (SequenceI[])
\r
245 alandcolsel[0])[0]).gapMap())); // recover original prediction sequence's mapping to view.
\r
246 int[] viscontigs = nview.getVisibleContigs(0, profileseq.getLength());
\r
249 // input.pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()))
\r
250 // add profile to visible contigs
\r
251 for (int v = 0; v < viscontigs.length; v += 2)
\r
253 if (viscontigs[v] > spos)
\r
255 StringBuffer sb = new StringBuffer();
\r
256 for (int s = 0, ns = viscontigs[v] - spos; s < ns; s++)
\r
260 for (int s = 0, ns = al.getHeight(); s < ns; s++)
\r
262 SequenceI sqobj = al.getSequenceAt(s);
\r
263 if (sqobj != profileseq)
\r
265 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
266 if (sq.length() <= spos + offset)
\r
269 int diff = spos + offset - sq.length() - 1;
\r
274 while ( (diff = spos + offset - sq.length() - 1) > 0)
\r
277 ( (diff >= sb.length()) ? sb.toString() :
\r
278 sb.substring(0, diff));
\r
281 sq += sb.toString();
\r
285 al.getSequenceAt(s).setSequence(sq.substring(0, spos + offset) +
\r
287 sq.substring(spos + offset));
\r
291 //offset+=sb.length();
\r
293 spos = viscontigs[v + 1] + 1;
\r
295 if ( (offset + spos) < profileseq.getLength())
\r
297 StringBuffer sb = new StringBuffer();
\r
298 for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)
\r
302 for (int s = 1, ns = al.getHeight(); s < ns; s++)
\r
304 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
306 int diff = origseq.getLength() - sq.length();
\r
310 ( (diff >= sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
311 diff = origseq.getLength() - sq.length();
\r
318 public JPredJob(Hashtable SequenceInfo, SequenceI seq, int[] delMap)
\r
321 this.predMap = delMap;
\r
322 String sq = AlignSeq.extractGaps(Comparison.GapChars,
\r
323 seq.getSequenceAsString());
\r
324 if (sq.length() >= 20)
\r
326 this.SequenceInfo = SequenceInfo;
\r
327 sequence = new vamsas.objects.simple.Sequence();
\r
328 sequence.setId(seq.getName());
\r
329 sequence.setSeq(sq);
\r
333 public JPredJob(Hashtable SequenceInfo, SequenceI[] msf, int[] delMap)
\r
335 this(SequenceInfo, msf[0], delMap);
\r
336 if (sequence != null)
\r
338 if (msf.length > 1)
\r
340 msa = new vamsas.objects.simple.Msfalignment();
\r
341 jalview.io.PileUpfile pileup = new jalview.io.PileUpfile();
\r
342 msa.setMsf(pileup.print(msf));
\r
348 ext.vamsas.Jpred server;
\r
349 String altitle = "";
\r
350 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,
\r
351 String wsurl, AlignmentView alview, AlignFrame alframe)
\r
354 this.altitle = altitle;
\r
355 this.server = server;
\r
356 this.wsInfo = wsinfo;
\r
357 this.input = alview;
\r
358 this.alignFrame = alframe;
\r
362 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,
\r
363 String wsurl, Hashtable SequenceInfo, SequenceI seq, int[] delMap,
\r
364 AlignmentView alview, AlignFrame alframe)
\r
366 this(wsinfo, altitle, server, wsurl, alview, alframe);
\r
367 JPredJob job = new JPredJob(SequenceInfo, seq, delMap);
\r
368 if (job.hasValidInput())
\r
370 OutputHeader = wsInfo.getProgressText();
\r
378 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,
\r
379 Hashtable SequenceInfo, SequenceI[] msf, int[] delMap,
\r
380 AlignmentView alview, AlignFrame alframe, String wsurl)
\r
382 this(wsinfo, altitle, server, wsurl, alview, alframe);
\r
383 JPredJob job = new JPredJob(SequenceInfo, msf, delMap);
\r
384 if (job.hasValidInput())
\r
389 OutputHeader = wsInfo.getProgressText();
\r
394 void StartJob(WSJob j)
\r
396 if (! (j instanceof JPredJob))
\r
398 throw new Error("Implementation error - StartJob(JpredJob) called on " +
\r
403 JPredJob job = (JPredJob) j;
\r
404 if (job.msa != null)
\r
406 job.jobId = server.predictOnMsa(job.msa);
\r
409 if (job.sequence != null)
\r
411 job.jobId = server.predict(job.sequence); // debug like : job.jobId = "/jobs/www-jpred/jp_Yatat29";//
\r
414 if (job.jobId != null)
\r
416 if (job.jobId.startsWith("Broken"))
\r
418 job.result = (vamsas.objects.simple.Result)new JpredResult();
\r
419 job.result.setInvalid(true);
\r
420 job.result.setStatus("Submission " + job.jobId);
\r
424 job.submitted = true;
\r
425 job.subjobComplete = false;
\r
426 Cache.log.info(WsUrl + " Job Id '" + job.jobId + "'");
\r
431 throw new Exception("Server timed out - try again later\n");
\r
434 catch (Exception e)
\r
436 if (e.getMessage().indexOf("Exception") > -1)
\r
438 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
439 wsInfo.setProgressText(j.jobnum,
\r
440 "Failed to submit the prediction. (Just close the window)\n"
\r
442 "It is most likely that there is a problem with the server.\n");
\r
443 System.err.println(
\r
444 "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +
\r
445 e.getMessage() + "\n");
\r
447 jalview.bin.Cache.log.warn("Server Exception", e);
\r
451 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
452 // JBPNote - this could be a popup informing the user of the problem.
\r
453 wsInfo.appendProgressText(j.jobnum,
\r
454 "Failed to submit the prediction:\n"
\r
456 wsInfo.getProgressText());
\r
458 jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);
\r
461 j.allowedServerExceptions = -1;
\r
462 j.subjobComplete = true;
\r
468 int results = 0; // number of result sets received
\r
469 JobStateSummary finalState = new JobStateSummary();
\r
472 for (int j = 0; j < jobs.length; j++)
\r
474 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
\r
475 if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
\r
481 catch (Exception ex)
\r
484 Cache.log.error("Unexpected exception when processing results for " +
\r
486 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
\r
490 wsInfo.showResultsNewFrame
\r
491 .addActionListener(new java.awt.event.ActionListener()
\r
493 public void actionPerformed(
\r
494 java.awt.event.ActionEvent evt)
\r
496 displayResults(true);
\r
499 wsInfo.mergeResults
\r
500 .addActionListener(new java.awt.event.ActionListener()
\r
502 public void actionPerformed(
\r
503 java.awt.event.ActionEvent evt)
\r
505 displayResults(false);
\r
508 wsInfo.setResultsReady();
\r
512 wsInfo.setFinishedNoResults();
\r
516 void displayResults(boolean newWindow)
\r
518 // TODO: cope with multiple subjobs.
\r
521 Object[] res = null;
\r
522 boolean msa = false;
\r
523 for (int jn = 0; jn < jobs.length; jn++)
\r
525 Object[] jobres = null;
\r
526 JPredJob j = (JPredJob) jobs[jn];
\r
528 if (j.hasResults())
\r
530 // hack - we only deal with all single seuqence predictions or all profile predictions
\r
531 msa = (j.msa != null) ? true : msa;
\r
534 jalview.bin.Cache.log.debug("Parsing output of job " + jn);
\r
535 jobres = j.getResultSet();
\r
536 jalview.bin.Cache.log.debug("Finished parsing output.");
\r
537 if (jobs.length == 1)
\r
543 // do merge with other job results
\r
545 "Multiple JNet subjob merging not yet implemented.");
\r
548 catch (Exception e)
\r
550 jalview.bin.Cache.log.error(
\r
551 "JNet Client: JPred Annotation Parse Error",
\r
553 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
554 wsInfo.appendProgressText(j.jobnum,
\r
555 OutputHeader + "\n" +
\r
556 j.result.getStatus() +
\r
557 "\nInvalid JNet job result data!\n" +
\r
559 j.result.setBroken(true);
\r
571 if (res[1] != null)
\r
573 af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],
\r
574 AlignFrame.DEFAULT_WIDTH,
\r
575 AlignFrame.DEFAULT_HEIGHT);
\r
579 af = new AlignFrame( (Alignment) res[0], AlignFrame.DEFAULT_WIDTH,
\r
580 AlignFrame.DEFAULT_HEIGHT);
\r
585 /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
586 if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {
\r
588 throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");
\r
592 // update hidden regions to account for loss of gaps in profile. - if any
\r
593 // gapMap returns insert list, interpreted as delete list by pruneDeletions
\r
594 //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));
\r
597 af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],
\r
598 AlignFrame.DEFAULT_WIDTH,
\r
599 AlignFrame.DEFAULT_HEIGHT);
\r
601 Desktop.addInternalFrame(af, altitle,
\r
602 AlignFrame.DEFAULT_WIDTH,
\r
603 AlignFrame.DEFAULT_HEIGHT);
\r
607 Cache.log.info("Append results onto existing alignment.");
\r
613 void pollJob(WSJob job)
\r
616 job.result = server.getresult(job.jobId);
\r
619 public boolean isCancellable()
\r
624 public void cancelJob()
\r
626 throw new Error("Implementation error!");
\r
629 public boolean canMergeResults()
\r