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
353 super(alframe, wsinfo, alview, wsurl);
\r
354 this.altitle = altitle;
\r
355 this.server = server;
\r
358 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,
\r
359 String wsurl, Hashtable SequenceInfo, SequenceI seq, int[] delMap,
\r
360 AlignmentView alview, AlignFrame alframe)
\r
362 this(wsinfo, altitle, server, wsurl, alview, alframe);
\r
363 JPredJob job = new JPredJob(SequenceInfo, seq, delMap);
\r
364 if (job.hasValidInput())
\r
366 OutputHeader = wsInfo.getProgressText();
\r
374 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,
\r
375 Hashtable SequenceInfo, SequenceI[] msf, int[] delMap,
\r
376 AlignmentView alview, AlignFrame alframe, String wsurl)
\r
378 this(wsinfo, altitle, server, wsurl, alview, alframe);
\r
379 JPredJob job = new JPredJob(SequenceInfo, msf, delMap);
\r
380 if (job.hasValidInput())
\r
385 OutputHeader = wsInfo.getProgressText();
\r
390 void StartJob(WSJob j)
\r
392 if (! (j instanceof JPredJob))
\r
394 throw new Error("Implementation error - StartJob(JpredJob) called on " +
\r
399 JPredJob job = (JPredJob) j;
\r
400 if (job.msa != null)
\r
402 job.jobId = server.predictOnMsa(job.msa);
\r
405 if (job.sequence != null)
\r
407 job.jobId = server.predict(job.sequence); // debug like : job.jobId = "/jobs/www-jpred/jp_Yatat29";//
\r
410 if (job.jobId != null)
\r
412 if (job.jobId.startsWith("Broken"))
\r
414 job.result = (vamsas.objects.simple.Result)new JpredResult();
\r
415 job.result.setInvalid(true);
\r
416 job.result.setStatus("Submission " + 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 if (e.getMessage().indexOf("Exception") > -1)
\r
434 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
435 wsInfo.setProgressText(j.jobnum,
\r
436 "Failed to submit the prediction. (Just close the window)\n"
\r
438 "It is most likely that there is a problem with the server.\n");
\r
439 System.err.println(
\r
440 "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +
\r
441 e.getMessage() + "\n");
\r
443 jalview.bin.Cache.log.warn("Server Exception", e);
\r
447 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
448 // JBPNote - this could be a popup informing the user of the problem.
\r
449 wsInfo.appendProgressText(j.jobnum,
\r
450 "Failed to submit the prediction:\n"
\r
452 wsInfo.getProgressText());
\r
454 jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);
\r
457 j.allowedServerExceptions = -1;
\r
458 j.subjobComplete = true;
\r
464 int results = 0; // number of result sets received
\r
465 JobStateSummary finalState = new JobStateSummary();
\r
468 for (int j = 0; j < jobs.length; j++)
\r
470 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
\r
471 if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
\r
477 catch (Exception ex)
\r
480 Cache.log.error("Unexpected exception when processing results for " +
\r
482 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
\r
486 wsInfo.showResultsNewFrame
\r
487 .addActionListener(new java.awt.event.ActionListener()
\r
489 public void actionPerformed(
\r
490 java.awt.event.ActionEvent evt)
\r
492 displayResults(true);
\r
495 wsInfo.mergeResults
\r
496 .addActionListener(new java.awt.event.ActionListener()
\r
498 public void actionPerformed(
\r
499 java.awt.event.ActionEvent evt)
\r
501 displayResults(false);
\r
504 wsInfo.setResultsReady();
\r
508 wsInfo.setFinishedNoResults();
\r
512 void displayResults(boolean newWindow)
\r
514 // TODO: cope with multiple subjobs.
\r
517 Object[] res = null;
\r
518 boolean msa = false;
\r
519 for (int jn = 0; jn < jobs.length; jn++)
\r
521 Object[] jobres = null;
\r
522 JPredJob j = (JPredJob) jobs[jn];
\r
524 if (j.hasResults())
\r
526 // hack - we only deal with all single seuqence predictions or all profile predictions
\r
527 msa = (j.msa != null) ? true : msa;
\r
530 jalview.bin.Cache.log.debug("Parsing output of job " + jn);
\r
531 jobres = j.getResultSet();
\r
532 jalview.bin.Cache.log.debug("Finished parsing output.");
\r
533 if (jobs.length == 1)
\r
539 // do merge with other job results
\r
541 "Multiple JNet subjob merging not yet implemented.");
\r
544 catch (Exception e)
\r
546 jalview.bin.Cache.log.error(
\r
547 "JNet Client: JPred Annotation Parse Error",
\r
549 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
550 wsInfo.appendProgressText(j.jobnum,
\r
551 OutputHeader + "\n" +
\r
552 j.result.getStatus() +
\r
553 "\nInvalid JNet job result data!\n" +
\r
555 j.result.setBroken(true);
\r
567 if (res[1] != null)
\r
569 af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],
\r
570 AlignFrame.DEFAULT_WIDTH,
\r
571 AlignFrame.DEFAULT_HEIGHT);
\r
575 af = new AlignFrame( (Alignment) res[0], AlignFrame.DEFAULT_WIDTH,
\r
576 AlignFrame.DEFAULT_HEIGHT);
\r
581 /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
582 if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {
\r
584 throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");
\r
588 // update hidden regions to account for loss of gaps in profile. - if any
\r
589 // gapMap returns insert list, interpreted as delete list by pruneDeletions
\r
590 //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));
\r
593 af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],
\r
594 AlignFrame.DEFAULT_WIDTH,
\r
595 AlignFrame.DEFAULT_HEIGHT);
\r
597 Desktop.addInternalFrame(af, altitle,
\r
598 AlignFrame.DEFAULT_WIDTH,
\r
599 AlignFrame.DEFAULT_HEIGHT);
\r
603 Cache.log.info("Append results onto existing alignment.");
\r
609 void pollJob(WSJob job)
\r
612 job.result = server.getresult(job.jobId);
\r
615 public boolean isCancellable()
\r
620 public void cancelJob()
\r
622 throw new Error("Implementation error!");
\r
625 public boolean canMergeResults()
\r