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].getSequence());
\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).getSequence();
\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).getSequence();
\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).getSequence();
\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, seq.getSequence());
\r
272 if (sq.length() >= 20)
\r
274 this.SequenceInfo = SequenceInfo;
\r
275 sequence = new vamsas.objects.simple.Sequence();
\r
276 sequence.setId(seq.getName());
\r
277 sequence.setSeq(sq);
\r
281 public JPredJob(Hashtable SequenceInfo, SequenceI[] msf, int[] delMap)
\r
283 this(SequenceInfo, msf[0], delMap);
\r
284 if (sequence != null)
\r
286 if (msf.length > 1)
\r
288 msa = new vamsas.objects.simple.Msfalignment();
\r
289 jalview.io.PileUpfile pileup = new jalview.io.PileUpfile();
\r
290 msa.setMsf(pileup.print(msf));
\r
295 ext.vamsas.Jpred server;
\r
296 String altitle = "";
\r
297 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, String wsurl, AlignmentView alview, AlignFrame alframe) {
\r
299 this.altitle = altitle;
\r
300 this.server = server;
\r
301 this.wsInfo = wsinfo;
\r
302 this.input = alview;
\r
303 this.alignFrame = alframe;
\r
308 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, String wsurl, Hashtable SequenceInfo,SequenceI seq, int[] delMap, AlignmentView alview, AlignFrame alframe)
\r
310 this(wsinfo, altitle, server,wsurl, alview, alframe);
\r
311 JPredJob job = new JPredJob(SequenceInfo, seq, delMap);
\r
312 if (job.hasValidInput())
\r
314 OutputHeader = wsInfo.getProgressText();
\r
322 JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server, Hashtable SequenceInfo, SequenceI[] msf, int[] delMap, AlignmentView alview, AlignFrame alframe, String wsurl)
\r
324 this(wsinfo, altitle, server,wsurl, alview, alframe);
\r
325 JPredJob job = new JPredJob(SequenceInfo, msf, delMap);
\r
326 if (job.hasValidInput())
\r
331 OutputHeader = wsInfo.getProgressText();
\r
335 void StartJob(WSJob j)
\r
337 if (! (j instanceof JPredJob))
\r
339 throw new Error("Implementation error - StartJob(JpredJob) called on " +
\r
344 JPredJob job = (JPredJob) j;
\r
345 if (job.msa != null)
\r
347 job.jobId = server.predictOnMsa(job.msa);
\r
350 if (job.sequence!=null)
\r
352 job.jobId = server.predict(job.sequence); // debug like : job.jobId = "/jobs/www-jpred/jp_Yatat29";//
\r
355 if (job.jobId != null)
\r
357 if (job.jobId.startsWith("Broken"))
\r
359 job.result = (vamsas.objects.simple.Result)new JpredResult();
\r
360 job.result.setInvalid(true);
\r
361 job.result.setStatus("Submission " + job.jobId);
\r
365 job.submitted = true;
\r
366 job.subjobComplete = false;
\r
367 Cache.log.info(WsUrl + " Job Id '" + job.jobId + "'");
\r
372 throw new Exception("Server timed out - try again later\n");
\r
375 catch (Exception e)
\r
377 if (e.getMessage().indexOf("Exception") > -1)
\r
379 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
\r
380 wsInfo.setProgressText(j.jobnum,
\r
381 "Failed to submit the prediction. (Just close the window)\n"
\r
383 "It is most likely that there is a problem with the server.\n");
\r
384 System.err.println(
\r
385 "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +
\r
386 e.getMessage() + "\n");
\r
388 jalview.bin.Cache.log.warn("Server Exception", e);
\r
392 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
393 // JBPNote - this could be a popup informing the user of the problem.
\r
394 wsInfo.appendProgressText(j.jobnum,
\r
395 "Failed to submit the prediction:\n"
\r
397 wsInfo.getProgressText());
\r
399 jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);
\r
402 j.allowedServerExceptions = -1;
\r
403 j.subjobComplete = true;
\r
409 int results = 0; // number of result sets received
\r
410 JobStateSummary finalState = new JobStateSummary();
\r
413 for (int j = 0; j < jobs.length; j++)
\r
415 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
\r
416 if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
\r
422 catch (Exception ex)
\r
425 Cache.log.error("Unexpected exception when processing results for " +
\r
427 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
\r
431 wsInfo.showResultsNewFrame
\r
432 .addActionListener(new java.awt.event.ActionListener()
\r
434 public void actionPerformed(
\r
435 java.awt.event.ActionEvent evt)
\r
437 displayResults(true);
\r
440 wsInfo.mergeResults
\r
441 .addActionListener(new java.awt.event.ActionListener()
\r
443 public void actionPerformed(
\r
444 java.awt.event.ActionEvent evt)
\r
446 displayResults(false);
\r
449 wsInfo.setResultsReady();
\r
453 wsInfo.setFinishedNoResults();
\r
457 void displayResults(boolean newWindow)
\r
459 // TODO: cope with multiple subjobs.
\r
462 Object[] res = null;
\r
464 for (int jn = 0; jn < jobs.length; jn++)
\r
466 Object[] jobres = null;
\r
467 JPredJob j = (JPredJob) jobs[jn];
\r
469 if (j.hasResults())
\r
471 // hack - we only deal with all single seuqence predictions or all profile predictions
\r
472 msa = (j.msa!=null) ? true : msa;
\r
475 jalview.bin.Cache.log.debug("Parsing output of job " + jn);
\r
476 jobres = j.getResultSet();
\r
477 jalview.bin.Cache.log.debug("Finished parsing output.");
\r
478 if (jobs.length==1)
\r
481 // do merge with other job results
\r
482 throw new Error("Multiple JNet subjob merging not yet implemented.");
\r
485 catch (Exception e)
\r
487 jalview.bin.Cache.log.error(
\r
488 "JNet Client: JPred Annotation Parse Error",
\r
490 wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
\r
491 wsInfo.appendProgressText(j.jobnum,
\r
492 OutputHeader + "\n" +
\r
493 j.result.getStatus() +
\r
494 "\nInvalid JNet job result data!\n" +
\r
496 j.result.setBroken(true);
\r
507 if (res[1]!=null) {
\r
508 af = new AlignFrame((Alignment)res[0], (ColumnSelection) res[1], AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
510 af = new AlignFrame((Alignment)res[0], AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
513 /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());
\r
515 if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {
\r
517 throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");
\r
521 // update hidden regions to account for loss of gaps in profile. - if any
\r
522 // gapMap returns insert list, interpreted as delete list by pruneDeletions
\r
523 //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));
\r
526 af = new AlignFrame((Alignment) res[0], (ColumnSelection) res[1],AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
528 Desktop.addInternalFrame(af, altitle,
\r
529 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
\r
533 Cache.log.info("Append results onto existing alignment.");
\r
538 void pollJob(WSJob job)
\r
541 job.result = server.getresult(job.jobId);
\r
543 public boolean isCancellable()
\r
548 public void cancelJob()
\r
550 throw new Error("Implementation error!");
\r
553 public boolean canMergeResults()
\r