5 import javax.swing.*;
\r
7 import vamsas.objects.simple.JpredResult;
\r
9 import jalview.analysis.*;
\r
10 import jalview.bin.*;
\r
11 import jalview.datamodel.*;
\r
12 import jalview.gui.*;
\r
13 import jalview.io.*;
\r
14 import jalview.util.*;
\r
18 implements WSClientI
\r
20 // TODO: put mapping between JPredJob input and input data here - JNetAnnotation adding is done after result parsing.
\r
22 extends WSThread.WSJob
\r
24 // TODO: make JPredJob deal only with what was sent to and received from a JNet service
\r
25 int[] predMap=null; // mapping from sequence(i) to the original sequence(predMap[i]) being predicted on
\r
26 vamsas.objects.simple.Sequence sequence;
\r
27 vamsas.objects.simple.Msfalignment msa;
\r
28 java.util.Hashtable SequenceInfo = null;
\r
29 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
32 * @return true if getResultSet will return a valid alignment and prediction result.
\r
34 public boolean hasResults()
\r
36 if (subjobComplete && result != null && result.isFinished()
\r
37 && ( (JpredResult) result).getPredfile() != null &&
\r
38 ( (JpredResult) result).getAligfile() != null)
\r
45 boolean hasValidInput()
\r
47 if (sequence != null)
\r
55 * @return null or Object[] { annotated alignment for this prediction, ColumnSelection for this prediction} or null if no results available.
\r
58 public Object[] getResultSet()
\r
61 if (result == null || !result.isFinished())
\r
65 Alignment al = null;
\r
66 ColumnSelection alcsel=null;
\r
67 int FirstSeq = -1; // the position of the query sequence in Alignment al
\r
69 JpredResult result = (JpredResult)this.result;
\r
71 jalview.bin.Cache.log.debug("Parsing output from JNet job.");
\r
72 // JPredFile prediction = new JPredFile("C:/JalviewX/files/jpred.txt", "File");
\r
73 jalview.io.JPredFile prediction = new jalview.io.JPredFile(result.
\r
76 SequenceI[] preds = prediction.getSeqsAsArray();
\r
77 jalview.bin.Cache.log.debug("Got prediction profile.");
\r
79 if ( (this.msa != null) && (result.getAligfile() != null))
\r
81 jalview.bin.Cache.log.debug("Getting associated alignment.");
\r
82 // we ignore the returned alignment if we only predicted on a single sequence
\r
83 String format = new jalview.io.IdentifyFile().Identify(result.
\r
87 if (jalview.io.FormatAdapter.isValidFormat(format))
\r
90 if (predMap!=null) {
\r
91 Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
92 sqs = (SequenceI[]) alandcolsel[0];
\r
93 al = new Alignment(sqs);
\r
94 alcsel=(ColumnSelection) alandcolsel[1];
\r
96 al = new FormatAdapter().readFile(result.getAligfile(),
\r
98 sqs = new SequenceI[al.getHeight()];
\r
100 for (int i = 0, j = al.getHeight(); i < j; i++)
\r
102 sqs[i] = al.getSequenceAt(i);
\r
104 if (!jalview.analysis.SeqsetUtils.deuniquify( (Hashtable)
\r
105 SequenceInfo, sqs))
\r
107 throw (new Exception(
\r
108 "Couldn't recover sequence properties for alignment."));
\r
112 al.setDataset(null);
\r
114 jalview.io.JnetAnnotationMaker.add_annotation(prediction, al, FirstSeq,
\r
120 throw (new Exception(
\r
121 "Unknown format "+format+" for file : \n" +
\r
122 result.getAligfile()));
\r
127 al = new Alignment(preds);
\r
128 FirstSeq = prediction.getQuerySeqPosition();
\r
129 if (predMap!=null) {
\r
130 char gc = alignFrame.getViewport().getGapCharacter();
\r
131 SequenceI[] sqs = (SequenceI[]) ((java.lang.Object[]) input.getAlignmentAndColumnSelection(gc))[0];
\r
132 if (this.msaIndex>=sqs.length)
\r
133 throw new Error("Implementation Error! Invalid msaIndex for JPredJob on parent MSA input object!");
\r
136 //Uses RemoveGapsCommand
\r
138 new jalview.commands.RemoveGapsCommand("Remove Gaps",
\r
139 new SequenceI[] {sqs[msaIndex]},
\r
142 SequenceI profileseq=al.getSequenceAt(FirstSeq);
\r
143 profileseq.setSequence(sqs[msaIndex].getSequenceAsString());
\r
146 if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash(
\r
147 al.getSequenceAt(FirstSeq), SequenceInfo))
\r
149 throw (new Exception(
\r
150 "Couldn't recover sequence properties for JNet Query sequence!"));
\r
152 al.setDataset(null);
\r
153 jalview.io.JnetAnnotationMaker.add_annotation(prediction, al, FirstSeq,
\r
155 SequenceI profileseq=al.getSequenceAt(0); // this includes any gaps.
\r
156 alignToProfileSeq(al, profileseq);
\r
157 if (predMap!=null) {
\r
158 // Adjust input view for gaps
\r
159 // propagate insertions into profile
\r
160 alcsel=propagateInsertions(profileseq, al, input);
\r
164 return new Object[] { al, alcsel}; // , FirstSeq, noMsa};
\r
167 * 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
169 * @param profileseq
\r
171 private void alignToProfileSeq(Alignment al, SequenceI profileseq) {
\r
172 char gc = al.getGapCharacter();
\r
173 int[] gapMap = profileseq.gapMap();
\r
174 // insert gaps into profile
\r
175 for (int lp=0,r=0; r<gapMap.length; r++) {
\r
176 if (gapMap[r]-lp>1) {
\r
177 StringBuffer sb=new StringBuffer();
\r
178 for (int s=0, ns=gapMap[r]-lp; s<ns; s++) {
\r
181 for (int s=1,ns=al.getHeight(); s<ns; s++) {
\r
182 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
183 int diff=gapMap[r]-sq.length();
\r
187 while ((diff=gapMap[r]-sq.length())>0) {
\r
188 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
190 al.getSequenceAt(s).setSequence(sq);
\r
192 al.getSequenceAt(s).setSequence(sq.substring(0,gapMap[r])+sb.toString()+sq.substring(gapMap[r]));
\r
201 * Add gaps into the sequences aligned to profileseq under the given AlignmentView
\r
202 * @param profileseq
\r
206 private ColumnSelection propagateInsertions(SequenceI profileseq, Alignment al, AlignmentView input) {
\r
207 char gc = al.getGapCharacter();
\r
208 Object[] alandcolsel = input.getAlignmentAndColumnSelection(gc);
\r
209 ColumnSelection nview = (ColumnSelection) alandcolsel[1];
\r
211 nview.pruneDeletions(ShiftList.parseMap((origseq=((SequenceI[]) alandcolsel[0])[0]).gapMap())); // recover original prediction sequence's mapping to view.
\r
212 int[] viscontigs=nview.getVisibleContigs(0, profileseq.getLength());
\r
215 // input.pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()))
\r
216 // add profile to visible contigs
\r
217 for (int v=0; v<viscontigs.length; v+=2) {
\r
218 if (viscontigs[v]>spos) {
\r
219 StringBuffer sb=new StringBuffer();
\r
220 for (int s=0, ns=viscontigs[v]-spos; s<ns; s++) {
\r
223 for (int s=0,ns=al.getHeight(); s<ns; s++) {
\r
224 SequenceI sqobj = al.getSequenceAt(s);
\r
225 if (sqobj!=profileseq) {
\r
226 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
227 if (sq.length()<=spos+offset) {
\r
229 int diff=spos+offset-sq.length()-1;
\r
233 while ((diff=spos+offset-sq.length()-1)>0) {
\r
234 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
239 al.getSequenceAt(s).setSequence(sq.substring(0,spos+offset)+sb.toString()+sq.substring(spos+offset));
\r
243 //offset+=sb.length();
\r
245 spos = viscontigs[v+1]+1;
\r
247 if ((offset+spos)<profileseq.getLength()) {
\r
248 StringBuffer sb=new StringBuffer();
\r
249 for (int s=0, ns=profileseq.getLength()-spos-offset; s<ns; s++) {
\r
252 for (int s=1,ns=al.getHeight(); s<ns; s++) {
\r
253 String sq = al.getSequenceAt(s).getSequenceAsString();
\r
255 int diff=origseq.getLength()-sq.length();
\r
257 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
258 diff=origseq.getLength()-sq.length();
\r
265 public JPredJob(Hashtable SequenceInfo, SequenceI seq, int[] delMap)
\r
268 this.predMap = delMap;
\r
269 String sq = AlignSeq.extractGaps(Comparison.GapChars,
\r
270 seq.getSequenceAsString());
\r
271 if (sq.length() >= 20)
\r
273 this.SequenceInfo = SequenceInfo;
\r
274 sequence = new vamsas.objects.simple.Sequence();
\r
275 sequence.setId(seq.getName());
\r
276 sequence.setSeq(sq);
\r
280 public JPredJob(Hashtable SequenceInfo, SequenceI[] msf, int[] delMap)
\r
282 this(SequenceInfo, msf[0], delMap);
\r
283 if (sequence != null)
\r
285 if (msf.length > 1)
\r
287 msa = new vamsas.objects.simple.Msfalignment();
\r
288 jalview.io.PileUpfile pileup = new jalview.io.PileUpfile();
\r
289 msa.setMsf(pileup.print(msf));
\r
294 ext.vamsas.Jpred server;
\r
295 String altitle = "";
\r
296 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, String wsurl, AlignmentView alview, AlignFrame alframe) {
\r
298 this.altitle = altitle;
\r
299 this.server = server;
\r
300 this.wsInfo = wsinfo;
\r
301 this.input = alview;
\r
302 this.alignFrame = alframe;
\r
307 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, String wsurl, Hashtable SequenceInfo,SequenceI seq, int[] delMap, AlignmentView alview, AlignFrame alframe)
\r
309 this(wsinfo, altitle, server,wsurl, alview, alframe);
\r
310 JPredJob job = new JPredJob(SequenceInfo, seq, delMap);
\r
311 if (job.hasValidInput())
\r
313 OutputHeader = wsInfo.getProgressText();
\r
321 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, Hashtable SequenceInfo, SequenceI[] msf, int[] delMap, AlignmentView alview, AlignFrame alframe, String wsurl)
\r
323 this(wsinfo, altitle, server,wsurl, alview, alframe);
\r
324 JPredJob job = new JPredJob(SequenceInfo, msf, delMap);
\r
325 if (job.hasValidInput())
\r
330 OutputHeader = wsInfo.getProgressText();
\r
334 void StartJob(WSJob j)
\r
336 if (! (j instanceof JPredJob))
\r
338 throw new Error("Implementation error - StartJob(JpredJob) called on " +
\r
343 JPredJob job = (JPredJob) j;
\r
344 if (job.msa != null)
\r
346 job.jobId = server.predictOnMsa(job.msa);
\r
349 if (job.sequence!=null)
\r
351 job.jobId = server.predict(job.sequence); // debug like : job.jobId = "/jobs/www-jpred/jp_Yatat29";//
\r
354 if (job.jobId != null)
\r
356 if (job.jobId.startsWith("Broken"))
\r
358 job.result = (vamsas.objects.simple.Result)new JpredResult();
\r
359 job.result.setInvalid(true);
\r
360 job.result.setStatus("Submission " + job.jobId);
\r
364 job.submitted = true;
\r
365 job.subjobComplete = false;
\r
366 Cache.log.info(WsUrl + " Job Id '" + job.jobId + "'");
\r
371 throw new Exception("Server timed out - try again later\n");
\r
374 catch (Exception e)
\r
376 if (e.getMessage().indexOf("Exception") > -1)
\r
378 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
379 wsInfo.setProgressText(j.jobnum,
\r
380 "Failed to submit the prediction. (Just close the window)\n"
\r
382 "It is most likely that there is a problem with the server.\n");
\r
383 System.err.println(
\r
384 "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +
\r
385 e.getMessage() + "\n");
\r
387 jalview.bin.Cache.log.warn("Server Exception", e);
\r
391 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
392 // JBPNote - this could be a popup informing the user of the problem.
\r
393 wsInfo.appendProgressText(j.jobnum,
\r
394 "Failed to submit the prediction:\n"
\r
396 wsInfo.getProgressText());
\r
398 jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);
\r
401 j.allowedServerExceptions = -1;
\r
402 j.subjobComplete = true;
\r
408 int results = 0; // number of result sets received
\r
409 JobStateSummary finalState = new JobStateSummary();
\r
412 for (int j = 0; j < jobs.length; j++)
\r
414 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
\r
415 if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
\r
421 catch (Exception ex)
\r
424 Cache.log.error("Unexpected exception when processing results for " +
\r
426 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
\r
430 wsInfo.showResultsNewFrame
\r
431 .addActionListener(new java.awt.event.ActionListener()
\r
433 public void actionPerformed(
\r
434 java.awt.event.ActionEvent evt)
\r
436 displayResults(true);
\r
439 wsInfo.mergeResults
\r
440 .addActionListener(new java.awt.event.ActionListener()
\r
442 public void actionPerformed(
\r
443 java.awt.event.ActionEvent evt)
\r
445 displayResults(false);
\r
448 wsInfo.setResultsReady();
\r
452 wsInfo.setFinishedNoResults();
\r
456 void displayResults(boolean newWindow)
\r
458 // TODO: cope with multiple subjobs.
\r
461 Object[] res = null;
\r
463 for (int jn = 0; jn < jobs.length; jn++)
\r
465 Object[] jobres = null;
\r
466 JPredJob j = (JPredJob) jobs[jn];
\r
468 if (j.hasResults())
\r
470 // hack - we only deal with all single seuqence predictions or all profile predictions
\r
471 msa = (j.msa!=null) ? true : msa;
\r
474 jalview.bin.Cache.log.debug("Parsing output of job " + jn);
\r
475 jobres = j.getResultSet();
\r
476 jalview.bin.Cache.log.debug("Finished parsing output.");
\r
477 if (jobs.length==1)
\r
480 // do merge with other job results
\r
481 throw new Error("Multiple JNet subjob merging not yet implemented.");
\r
484 catch (Exception e)
\r
486 jalview.bin.Cache.log.error(
\r
487 "JNet Client: JPred Annotation Parse Error",
\r
489 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
490 wsInfo.appendProgressText(j.jobnum,
\r
491 OutputHeader + "\n" +
\r
492 j.result.getStatus() +
\r
493 "\nInvalid JNet job result data!\n" +
\r
495 j.result.setBroken(true);
\r
506 if (res[1]!=null) {
\r
507 af = new AlignFrame((Alignment)res[0], (ColumnSelection) res[1], AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
509 af = new AlignFrame((Alignment)res[0], AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
512 /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
514 if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {
\r
516 throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");
\r
520 // update hidden regions to account for loss of gaps in profile. - if any
\r
521 // gapMap returns insert list, interpreted as delete list by pruneDeletions
\r
522 //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));
\r
525 af = new AlignFrame((Alignment) res[0], (ColumnSelection) res[1],AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
527 Desktop.addInternalFrame(af, altitle,
\r
528 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
532 Cache.log.info("Append results onto existing alignment.");
\r
537 void pollJob(WSJob job)
\r
540 job.result = server.getresult(job.jobId);
\r
542 public boolean isCancellable()
\r
547 public void cancelJob()
\r
549 throw new Error("Implementation error!");
\r
552 public boolean canMergeResults()
\r