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
136 sqs[msaIndex].removeGaps();
\r
137 SequenceI profileseq=al.getSequenceAt(FirstSeq);
\r
138 profileseq.setSequence(sqs[msaIndex].getSequence());
\r
141 if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash(
\r
142 al.getSequenceAt(FirstSeq), SequenceInfo))
\r
144 throw (new Exception(
\r
145 "Couldn't recover sequence properties for JNet Query sequence!"));
\r
147 al.setDataset(null);
\r
148 jalview.io.JnetAnnotationMaker.add_annotation(prediction, al, FirstSeq,
\r
150 SequenceI profileseq=al.getSequenceAt(0); // this includes any gaps.
\r
151 alignToProfileSeq(al, profileseq);
\r
152 if (predMap!=null) {
\r
153 // Adjust input view for gaps
\r
154 // propagate insertions into profile
\r
155 alcsel=propagateInsertions(profileseq, al, input);
\r
159 return new Object[] { al, alcsel}; // , FirstSeq, noMsa};
\r
162 * 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
164 * @param profileseq
\r
166 private void alignToProfileSeq(Alignment al, SequenceI profileseq) {
\r
167 char gc = al.getGapCharacter();
\r
168 int[] gapMap = profileseq.gapMap();
\r
169 // insert gaps into profile
\r
170 for (int lp=0,r=0; r<gapMap.length; r++) {
\r
171 if (gapMap[r]-lp>1) {
\r
172 StringBuffer sb=new StringBuffer();
\r
173 for (int s=0, ns=gapMap[r]-lp; s<ns; s++) {
\r
176 for (int s=1,ns=al.getHeight(); s<ns; s++) {
\r
177 String sq = al.getSequenceAt(s).getSequence();
\r
178 int diff=gapMap[r]-sq.length();
\r
182 while ((diff=gapMap[r]-sq.length())>0) {
\r
183 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
185 al.getSequenceAt(s).setSequence(sq);
\r
187 al.getSequenceAt(s).setSequence(sq.substring(0,gapMap[r])+sb.toString()+sq.substring(gapMap[r]));
\r
196 * Add gaps into the sequences aligned to profileseq under the given AlignmentView
\r
197 * @param profileseq
\r
201 private ColumnSelection propagateInsertions(SequenceI profileseq, Alignment al, AlignmentView input) {
\r
202 char gc = al.getGapCharacter();
\r
203 Object[] alandcolsel = input.getAlignmentAndColumnSelection(gc);
\r
204 ColumnSelection nview = (ColumnSelection) alandcolsel[1];
\r
206 nview.pruneDeletions(ShiftList.parseMap((origseq=((SequenceI[]) alandcolsel[0])[0]).gapMap())); // recover original prediction sequence's mapping to view.
\r
207 int[] viscontigs=nview.getVisibleContigs(0, profileseq.getLength());
\r
210 // input.pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()))
\r
211 // add profile to visible contigs
\r
212 for (int v=0; v<viscontigs.length; v+=2) {
\r
213 if (viscontigs[v]>spos) {
\r
214 StringBuffer sb=new StringBuffer();
\r
215 for (int s=0, ns=viscontigs[v]-spos; s<ns; s++) {
\r
218 for (int s=0,ns=al.getHeight(); s<ns; s++) {
\r
219 SequenceI sqobj = al.getSequenceAt(s);
\r
220 if (sqobj!=profileseq) {
\r
221 String sq = al.getSequenceAt(s).getSequence();
\r
222 if (sq.length()<=spos+offset) {
\r
224 int diff=spos+offset-sq.length()-1;
\r
228 while ((diff=spos+offset-sq.length()-1)>0) {
\r
229 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
234 al.getSequenceAt(s).setSequence(sq.substring(0,spos+offset)+sb.toString()+sq.substring(spos+offset));
\r
238 //offset+=sb.length();
\r
240 spos = viscontigs[v+1]+1;
\r
242 if ((offset+spos)<profileseq.getLength()) {
\r
243 StringBuffer sb=new StringBuffer();
\r
244 for (int s=0, ns=profileseq.getLength()-spos-offset; s<ns; s++) {
\r
247 for (int s=1,ns=al.getHeight(); s<ns; s++) {
\r
248 String sq = al.getSequenceAt(s).getSequence();
\r
250 int diff=origseq.getLength()-sq.length();
\r
252 sq=sq+((diff>=sb.length()) ? sb.toString() : sb.substring(0, diff));
\r
253 diff=origseq.getLength()-sq.length();
\r
260 public JPredJob(Hashtable SequenceInfo, SequenceI seq, int[] delMap)
\r
263 this.predMap = delMap;
\r
264 String sq = AlignSeq.extractGaps(Comparison.GapChars, seq.getSequence());
\r
265 if (sq.length() >= 20)
\r
267 this.SequenceInfo = SequenceInfo;
\r
268 sequence = new vamsas.objects.simple.Sequence();
\r
269 sequence.setId(seq.getName());
\r
270 sequence.setSeq(sq);
\r
274 public JPredJob(Hashtable SequenceInfo, SequenceI[] msf, int[] delMap)
\r
276 this(SequenceInfo, msf[0], delMap);
\r
277 if (sequence != null)
\r
279 if (msf.length > 1)
\r
281 msa = new vamsas.objects.simple.Msfalignment();
\r
282 jalview.io.PileUpfile pileup = new jalview.io.PileUpfile();
\r
283 msa.setMsf(pileup.print(msf));
\r
288 ext.vamsas.Jpred server;
\r
289 String altitle = "";
\r
290 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, String wsurl, AlignmentView alview, AlignFrame alframe) {
\r
292 this.altitle = altitle;
\r
293 this.server = server;
\r
294 this.wsInfo = wsinfo;
\r
295 this.input = alview;
\r
296 this.alignFrame = alframe;
\r
301 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, String wsurl, Hashtable SequenceInfo,SequenceI seq, int[] delMap, AlignmentView alview, AlignFrame alframe)
\r
303 this(wsinfo, altitle, server,wsurl, alview, alframe);
\r
304 JPredJob job = new JPredJob(SequenceInfo, seq, delMap);
\r
305 if (job.hasValidInput())
\r
307 OutputHeader = wsInfo.getProgressText();
\r
315 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, Hashtable SequenceInfo, SequenceI[] msf, int[] delMap, AlignmentView alview, AlignFrame alframe, String wsurl)
\r
317 this(wsinfo, altitle, server,wsurl, alview, alframe);
\r
318 JPredJob job = new JPredJob(SequenceInfo, msf, delMap);
\r
319 if (job.hasValidInput())
\r
324 OutputHeader = wsInfo.getProgressText();
\r
328 void StartJob(WSJob j)
\r
330 if (! (j instanceof JPredJob))
\r
332 throw new Error("Implementation error - StartJob(JpredJob) called on " +
\r
337 JPredJob job = (JPredJob) j;
\r
338 if (job.msa != null)
\r
340 job.jobId = server.predictOnMsa(job.msa);
\r
343 if (job.sequence!=null)
\r
345 job.jobId = server.predict(job.sequence); // debug like : job.jobId = "/jobs/www-jpred/jp_Yatat29";//
\r
348 if (job.jobId != null)
\r
350 if (job.jobId.startsWith("Broken"))
\r
352 job.result = (vamsas.objects.simple.Result)new JpredResult();
\r
353 job.result.setInvalid(true);
\r
354 job.result.setStatus("Submission " + job.jobId);
\r
358 job.submitted = true;
\r
359 job.subjobComplete = false;
\r
360 Cache.log.info(WsUrl + " Job Id '" + job.jobId + "'");
\r
365 throw new Exception("Server timed out - try again later\n");
\r
368 catch (Exception e)
\r
370 if (e.getMessage().indexOf("Exception") > -1)
\r
372 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
373 wsInfo.setProgressText(j.jobnum,
\r
374 "Failed to submit the prediction. (Just close the window)\n"
\r
376 "It is most likely that there is a problem with the server.\n");
\r
377 System.err.println(
\r
378 "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +
\r
379 e.getMessage() + "\n");
\r
381 jalview.bin.Cache.log.warn("Server Exception", e);
\r
385 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
386 // JBPNote - this could be a popup informing the user of the problem.
\r
387 wsInfo.appendProgressText(j.jobnum,
\r
388 "Failed to submit the prediction:\n"
\r
390 wsInfo.getProgressText());
\r
392 jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);
\r
395 j.allowedServerExceptions = -1;
\r
396 j.subjobComplete = true;
\r
402 int results = 0; // number of result sets received
\r
403 JobStateSummary finalState = new JobStateSummary();
\r
406 for (int j = 0; j < jobs.length; j++)
\r
408 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
\r
409 if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
\r
415 catch (Exception ex)
\r
418 Cache.log.error("Unexpected exception when processing results for " +
\r
420 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
\r
424 wsInfo.showResultsNewFrame
\r
425 .addActionListener(new java.awt.event.ActionListener()
\r
427 public void actionPerformed(
\r
428 java.awt.event.ActionEvent evt)
\r
430 displayResults(true);
\r
433 wsInfo.mergeResults
\r
434 .addActionListener(new java.awt.event.ActionListener()
\r
436 public void actionPerformed(
\r
437 java.awt.event.ActionEvent evt)
\r
439 displayResults(false);
\r
442 wsInfo.setResultsReady();
\r
446 wsInfo.setFinishedNoResults();
\r
450 void displayResults(boolean newWindow)
\r
452 // TODO: cope with multiple subjobs.
\r
455 Object[] res = null;
\r
457 for (int jn = 0; jn < jobs.length; jn++)
\r
459 Object[] jobres = null;
\r
460 JPredJob j = (JPredJob) jobs[jn];
\r
462 if (j.hasResults())
\r
464 // hack - we only deal with all single seuqence predictions or all profile predictions
\r
465 msa = (j.msa!=null) ? true : msa;
\r
468 jalview.bin.Cache.log.debug("Parsing output of job " + jn);
\r
469 jobres = j.getResultSet();
\r
470 jalview.bin.Cache.log.debug("Finished parsing output.");
\r
471 if (jobs.length==1)
\r
474 // do merge with other job results
\r
475 throw new Error("Multiple JNet subjob merging not yet implemented.");
\r
478 catch (Exception e)
\r
480 jalview.bin.Cache.log.error(
\r
481 "JNet Client: JPred Annotation Parse Error",
\r
483 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
484 wsInfo.appendProgressText(j.jobnum,
\r
485 OutputHeader + "\n" +
\r
486 j.result.getStatus() +
\r
487 "\nInvalid JNet job result data!\n" +
\r
489 j.result.setBroken(true);
\r
500 if (res[1]!=null) {
\r
501 af = new AlignFrame((Alignment)res[0], (ColumnSelection) res[1], AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
503 af = new AlignFrame((Alignment)res[0], AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
506 /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
508 if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {
\r
510 throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");
\r
514 // update hidden regions to account for loss of gaps in profile. - if any
\r
515 // gapMap returns insert list, interpreted as delete list by pruneDeletions
\r
516 //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));
\r
519 af = new AlignFrame((Alignment) res[0], (ColumnSelection) res[1],AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
521 Desktop.addInternalFrame(af, altitle,
\r
522 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
526 Cache.log.info("Append results onto existing alignment.");
\r
531 void pollJob(WSJob job)
\r
534 job.result = server.getresult(job.jobId);
\r
536 public boolean isCancellable()
\r
541 public void cancelJob()
\r
543 throw new Error("Implementation error!");
\r
546 public boolean canMergeResults()
\r