5 import javax.swing.*;
\r
7 import vamsas.objects.simple.JpredResult;
\r
10 import jalview.analysis.*;
\r
11 import jalview.bin.*;
\r
12 import jalview.datamodel.*;
\r
13 import jalview.gui.*;
\r
14 import jalview.io.*;
\r
15 import jalview.util.*;
\r
16 import jalview.ws.WSThread.*;
\r
20 implements WSClientI
\r
22 // TODO: put mapping between JPredJob input and input data here - JNetAnnotation adding is done after result parsing.
\r
24 extends WSThread.WSJob
\r
26 // TODO: make JPredJob deal only with what was sent to and received from a JNet service
\r
27 int[] predMap=null; // mapping from sequence(i) to the original sequence(predMap[i]) being predicted on
\r
28 vamsas.objects.simple.Sequence sequence;
\r
29 vamsas.objects.simple.Msfalignment msa;
\r
30 java.util.Hashtable SequenceInfo = null;
\r
31 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
34 * @return true if getResultSet will return a valid alignment and prediction result.
\r
36 public boolean hasResults()
\r
38 if (subjobComplete && result != null && result.isFinished()
\r
39 && ( (JpredResult) result).getPredfile() != null &&
\r
40 ( (JpredResult) result).getAligfile() != null)
\r
47 boolean hasValidInput()
\r
49 if (sequence != null)
\r
57 * @return null or Object[] { annotated alignment for this prediction, ColumnSelection for this prediction} or null if no results available.
\r
60 public Object[] getResultSet()
\r
63 if (result == null || !result.isFinished())
\r
67 Alignment al = null;
\r
68 ColumnSelection alcsel=null;
\r
69 int FirstSeq = -1; // the position of the query sequence in Alignment al
\r
71 JpredResult result = (JpredResult)this.result;
\r
73 jalview.bin.Cache.log.debug("Parsing output from JNet job.");
\r
74 // JPredFile prediction = new JPredFile("C:/JalviewX/files/jpred.txt", "File");
\r
75 jalview.io.JPredFile prediction = new jalview.io.JPredFile(result.
\r
78 SequenceI[] preds = prediction.getSeqsAsArray();
\r
79 jalview.bin.Cache.log.debug("Got prediction profile.");
\r
81 if ( (this.msa != null) && (result.getAligfile() != null))
\r
83 jalview.bin.Cache.log.debug("Getting associated alignment.");
\r
84 // we ignore the returned alignment if we only predicted on a single sequence
\r
85 String format = new jalview.io.IdentifyFile().Identify(result.
\r
89 if (jalview.io.FormatAdapter.isValidFormat(format))
\r
92 if (predMap!=null) {
\r
93 Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
94 sqs = (SequenceI[]) alandcolsel[0];
\r
95 al = new Alignment(sqs);
\r
96 alcsel=(ColumnSelection) alandcolsel[1];
\r
98 al = new Alignment(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, FirstSeq,
\r
122 throw (new Exception(
\r
123 "Unknown format "+format+" for file : \n" +
\r
124 result.getAligfile()));
\r
129 al = new Alignment(preds);
\r
130 FirstSeq = prediction.getQuerySeqPosition();
\r
131 if (predMap!=null) {
\r
132 char gc = alignFrame.getViewport().getGapCharacter();
\r
133 SequenceI[] sqs = (SequenceI[]) ((java.lang.Object[]) input.getAlignmentAndColumnSelection(gc))[0];
\r
134 if (this.msaIndex>=sqs.length)
\r
135 throw new Error("Implementation Error! Invalid msaIndex for JPredJob on parent MSA input object!");
\r
138 //Uses RemoveGapsCommand
\r
140 new jalview.commands.RemoveGapsCommand("Remove Gaps",
\r
141 new SequenceI[] {sqs[msaIndex]},
\r
144 SequenceI profileseq=al.getSequenceAt(FirstSeq);
\r
145 profileseq.setSequence(sqs[msaIndex].getSequenceAsString());
\r
148 if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash(
\r
149 al.getSequenceAt(FirstSeq), SequenceInfo))
\r
151 throw (new Exception(
\r
152 "Couldn't recover sequence properties for JNet Query sequence!"));
\r
154 al.setDataset(null);
\r
155 jalview.io.JnetAnnotationMaker.add_annotation(prediction, al, FirstSeq,
\r
157 SequenceI profileseq=al.getSequenceAt(0); // this includes any gaps.
\r
158 alignToProfileSeq(al, profileseq);
\r
159 if (predMap!=null) {
\r
160 // Adjust input view for gaps
\r
161 // propagate insertions into profile
\r
162 alcsel=propagateInsertions(profileseq, al, input);
\r
166 return new Object[] { al, alcsel}; // , FirstSeq, noMsa};
\r
169 * 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
171 * @param profileseq
\r
173 private void alignToProfileSeq(Alignment al, SequenceI profileseq) {
\r
174 char gc = al.getGapCharacter();
\r
175 int[] gapMap = profileseq.gapMap();
\r
176 // insert gaps into profile
\r
177 for (int lp=0,r=0; r<gapMap.length; r++) {
\r
178 if (gapMap[r]-lp>1) {
\r
179 StringBuffer sb=new StringBuffer();
\r
180 for (int s=0, ns=gapMap[r]-lp; s<ns; s++) {
\r
183 for (int s=1,ns=al.getHeight(); s<ns; s++) {
\r
184 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
185 int diff=gapMap[r]-sq.length();
\r
189 while ((diff=gapMap[r]-sq.length())>0) {
\r
190 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
192 al.getSequenceAt(s).setSequence(sq);
\r
194 al.getSequenceAt(s).setSequence(sq.substring(0,gapMap[r])+sb.toString()+sq.substring(gapMap[r]));
\r
203 * Add gaps into the sequences aligned to profileseq under the given AlignmentView
\r
204 * @param profileseq
\r
208 private ColumnSelection propagateInsertions(SequenceI profileseq, Alignment al, AlignmentView input) {
\r
209 char gc = al.getGapCharacter();
\r
210 Object[] alandcolsel = input.getAlignmentAndColumnSelection(gc);
\r
211 ColumnSelection nview = (ColumnSelection) alandcolsel[1];
\r
213 nview.pruneDeletions(ShiftList.parseMap((origseq=((SequenceI[]) alandcolsel[0])[0]).gapMap())); // recover original prediction sequence's mapping to view.
\r
214 int[] viscontigs=nview.getVisibleContigs(0, profileseq.getLength());
\r
217 // input.pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()))
\r
218 // add profile to visible contigs
\r
219 for (int v=0; v<viscontigs.length; v+=2) {
\r
220 if (viscontigs[v]>spos) {
\r
221 StringBuffer sb=new StringBuffer();
\r
222 for (int s=0, ns=viscontigs[v]-spos; s<ns; s++) {
\r
225 for (int s=0,ns=al.getHeight(); s<ns; s++) {
\r
226 SequenceI sqobj = al.getSequenceAt(s);
\r
227 if (sqobj!=profileseq) {
\r
228 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
229 if (sq.length()<=spos+offset) {
\r
231 int diff=spos+offset-sq.length()-1;
\r
235 while ((diff=spos+offset-sq.length()-1)>0) {
\r
236 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
241 al.getSequenceAt(s).setSequence(sq.substring(0,spos+offset)+sb.toString()+sq.substring(spos+offset));
\r
245 //offset+=sb.length();
\r
247 spos = viscontigs[v+1]+1;
\r
249 if ((offset+spos)<profileseq.getLength()) {
\r
250 StringBuffer sb=new StringBuffer();
\r
251 for (int s=0, ns=profileseq.getLength()-spos-offset; s<ns; s++) {
\r
254 for (int s=1,ns=al.getHeight(); s<ns; s++) {
\r
255 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
257 int diff=origseq.getLength()-sq.length();
\r
259 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
260 diff=origseq.getLength()-sq.length();
\r
267 public JPredJob(Hashtable SequenceInfo, SequenceI seq, int[] delMap)
\r
270 this.predMap = delMap;
\r
271 String sq = AlignSeq.extractGaps(Comparison.GapChars,
\r
272 seq.getSequenceAsString());
\r
273 if (sq.length() >= 20)
\r
275 this.SequenceInfo = SequenceInfo;
\r
276 sequence = new vamsas.objects.simple.Sequence();
\r
277 sequence.setId(seq.getName());
\r
278 sequence.setSeq(sq);
\r
282 public JPredJob(Hashtable SequenceInfo, SequenceI[] msf, int[] delMap)
\r
284 this(SequenceInfo, msf[0], delMap);
\r
285 if (sequence != null)
\r
287 if (msf.length > 1)
\r
289 msa = new vamsas.objects.simple.Msfalignment();
\r
290 jalview.io.PileUpfile pileup = new jalview.io.PileUpfile();
\r
291 msa.setMsf(pileup.print(msf));
\r
296 ext.vamsas.Jpred server;
\r
297 String altitle = "";
\r
298 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, String wsurl, AlignmentView alview, AlignFrame alframe) {
\r
300 this.altitle = altitle;
\r
301 this.server = server;
\r
302 this.wsInfo = wsinfo;
\r
303 this.input = alview;
\r
304 this.alignFrame = alframe;
\r
309 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, String wsurl, Hashtable SequenceInfo,SequenceI seq, int[] delMap, AlignmentView alview, AlignFrame alframe)
\r
311 this(wsinfo, altitle, server,wsurl, alview, alframe);
\r
312 JPredJob job = new JPredJob(SequenceInfo, seq, delMap);
\r
313 if (job.hasValidInput())
\r
315 OutputHeader = wsInfo.getProgressText();
\r
323 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, Hashtable SequenceInfo, SequenceI[] msf, int[] delMap, AlignmentView alview, AlignFrame alframe, String wsurl)
\r
325 this(wsinfo, altitle, server,wsurl, alview, alframe);
\r
326 JPredJob job = new JPredJob(SequenceInfo, msf, delMap);
\r
327 if (job.hasValidInput())
\r
332 OutputHeader = wsInfo.getProgressText();
\r
336 void StartJob(WSJob j)
\r
338 if (! (j instanceof JPredJob))
\r
340 throw new Error("Implementation error - StartJob(JpredJob) called on " +
\r
345 JPredJob job = (JPredJob) j;
\r
346 if (job.msa != null)
\r
348 job.jobId = server.predictOnMsa(job.msa);
\r
351 if (job.sequence!=null)
\r
353 job.jobId = server.predict(job.sequence); // debug like : job.jobId = "/jobs/www-jpred/jp_Yatat29";//
\r
356 if (job.jobId != null)
\r
358 if (job.jobId.startsWith("Broken"))
\r
360 job.result = (vamsas.objects.simple.Result)new JpredResult();
\r
361 job.result.setInvalid(true);
\r
362 job.result.setStatus("Submission " + job.jobId);
\r
366 job.submitted = true;
\r
367 job.subjobComplete = false;
\r
368 Cache.log.info(WsUrl + " Job Id '" + job.jobId + "'");
\r
373 throw new Exception("Server timed out - try again later\n");
\r
376 catch (Exception e)
\r
378 if (e.getMessage().indexOf("Exception") > -1)
\r
380 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
381 wsInfo.setProgressText(j.jobnum,
\r
382 "Failed to submit the prediction. (Just close the window)\n"
\r
384 "It is most likely that there is a problem with the server.\n");
\r
385 System.err.println(
\r
386 "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +
\r
387 e.getMessage() + "\n");
\r
389 jalview.bin.Cache.log.warn("Server Exception", e);
\r
393 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
394 // JBPNote - this could be a popup informing the user of the problem.
\r
395 wsInfo.appendProgressText(j.jobnum,
\r
396 "Failed to submit the prediction:\n"
\r
398 wsInfo.getProgressText());
\r
400 jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);
\r
403 j.allowedServerExceptions = -1;
\r
404 j.subjobComplete = true;
\r
410 int results = 0; // number of result sets received
\r
411 JobStateSummary finalState = new JobStateSummary();
\r
414 for (int j = 0; j < jobs.length; j++)
\r
416 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
\r
417 if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
\r
423 catch (Exception ex)
\r
426 Cache.log.error("Unexpected exception when processing results for " +
\r
428 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
\r
432 wsInfo.showResultsNewFrame
\r
433 .addActionListener(new java.awt.event.ActionListener()
\r
435 public void actionPerformed(
\r
436 java.awt.event.ActionEvent evt)
\r
438 displayResults(true);
\r
441 wsInfo.mergeResults
\r
442 .addActionListener(new java.awt.event.ActionListener()
\r
444 public void actionPerformed(
\r
445 java.awt.event.ActionEvent evt)
\r
447 displayResults(false);
\r
450 wsInfo.setResultsReady();
\r
454 wsInfo.setFinishedNoResults();
\r
458 void displayResults(boolean newWindow)
\r
460 // TODO: cope with multiple subjobs.
\r
463 Object[] res = null;
\r
465 for (int jn = 0; jn < jobs.length; jn++)
\r
467 Object[] jobres = null;
\r
468 JPredJob j = (JPredJob) jobs[jn];
\r
470 if (j.hasResults())
\r
472 // hack - we only deal with all single seuqence predictions or all profile predictions
\r
473 msa = (j.msa!=null) ? true : msa;
\r
476 jalview.bin.Cache.log.debug("Parsing output of job " + jn);
\r
477 jobres = j.getResultSet();
\r
478 jalview.bin.Cache.log.debug("Finished parsing output.");
\r
479 if (jobs.length==1)
\r
482 // do merge with other job results
\r
483 throw new Error("Multiple JNet subjob merging not yet implemented.");
\r
486 catch (Exception e)
\r
488 jalview.bin.Cache.log.error(
\r
489 "JNet Client: JPred Annotation Parse Error",
\r
491 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
492 wsInfo.appendProgressText(j.jobnum,
\r
493 OutputHeader + "\n" +
\r
494 j.result.getStatus() +
\r
495 "\nInvalid JNet job result data!\n" +
\r
497 j.result.setBroken(true);
\r
508 if (res[1]!=null) {
\r
509 af = new AlignFrame((Alignment)res[0], (ColumnSelection) res[1], AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
511 af = new AlignFrame((Alignment)res[0], AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
514 /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
516 if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {
\r
518 throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");
\r
522 // update hidden regions to account for loss of gaps in profile. - if any
\r
523 // gapMap returns insert list, interpreted as delete list by pruneDeletions
\r
524 //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));
\r
527 af = new AlignFrame((Alignment) res[0], (ColumnSelection) res[1],AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
529 Desktop.addInternalFrame(af, altitle,
\r
530 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
534 Cache.log.info("Append results onto existing alignment.");
\r
539 void pollJob(WSJob job)
\r
542 job.result = server.getresult(job.jobId);
\r
544 public boolean isCancellable()
\r
549 public void cancelJob()
\r
551 throw new Error("Implementation error!");
\r
554 public boolean canMergeResults()
\r