fixed end-residue bug and subjob panel names bug
[jalview.git] / src / jalview / ws / MsaWSThread.java
1 package jalview.ws;
2
3 import jalview.datamodel.AlignmentView;
4 import jalview.datamodel.AlignmentOrder;
5 import jalview.datamodel.ColumnSelection;
6 import jalview.gui.WebserviceInfo;
7 import jalview.analysis.AlignSeq;
8 import jalview.bin.Cache;
9 import jalview.gui.AlignFrame;
10 import javax.swing.JOptionPane;
11
12 import vamsas.objects.simple.MsaResult;
13 import vamsas.objects.simple.Result;
14 import jalview.datamodel.Alignment;
15 import jalview.datamodel.SeqCigar;
16 import jalview.gui.Desktop;
17 import jalview.datamodel.SequenceI;
18 import java.util.Hashtable;
19 import java.util.Vector;
20
21 /**
22  * <p>
23  * Title:
24  * </p>
25  * 
26  * <p>
27  * Description:
28  * </p>
29  * 
30  * <p>
31  * Copyright: Copyright (c) 2004
32  * </p>
33  * 
34  * <p>
35  * Company: Dundee University
36  * </p>
37  * 
38  * @author not attributable
39  * @version 1.0
40  */
41 class MsaWSThread extends Thread implements WSClientI {
42   jalview.gui.AlignFrame alignFrame;
43   
44   WebserviceInfo wsInfo = null;
45   
46   String WebServiceName = null;
47   
48   String OutputHeader;
49   AlignmentView input;
50   boolean submitGaps = false; // pass sequences including gaps to alignment
51   
52   // service
53   
54   boolean preserveOrder = true; // and always store and recover sequence
55   
56   // order
57   
58   class MsaWSJob {
59     int jobnum = 0; // WebServiceInfo pane for this job
60     
61     String jobId; // ws job ticket
62     
63     vamsas.objects.simple.MsaResult result = null;
64     
65     vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple.SequenceSet();
66     
67     /**
68      * MsaWSJob
69      * 
70      * @param jobNum
71      *            int
72      * @param jobId
73      *            String
74      */
75     public MsaWSJob(int jobNum, SequenceI[] inSeqs) {
76       this.jobnum = jobNum;
77       prepareInput(inSeqs);
78     }
79     
80     int allowedServerExceptions = 3; // thread dies if too many
81     
82     // exceptions.
83     boolean submitted=false;
84     boolean subjobComplete = false;
85     
86     Hashtable SeqNames = new Hashtable();
87     Vector emptySeqs = new Vector();
88     private void prepareInput(SequenceI[] seqs) {
89       int nseqs = 0;
90       for (int i = 0; i < seqs.length; i++) {
91         if (seqs[i].getStart() < seqs[i].getEnd()) {
92           nseqs++;
93         }
94       }
95       vamsas.objects.simple.Sequence[] seqarray = 
96         (nseqs>0) 
97         ? new vamsas.objects.simple.Sequence[nseqs]
98                                              :null;
99         for (int i = 0, n = 0; i < seqs.length; i++) {
100           
101           String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
102           // for
103           // any
104           // subjob
105           SeqNames.put(newname, jalview.analysis.SeqsetUtils
106               .SeqCharacterHash(seqs[i]));
107           if (seqs[i].getStart() < seqs[i].getEnd()) {
108             seqarray[n] = new vamsas.objects.simple.Sequence();
109             seqarray[n].setId(newname);
110             seqarray[n++].setSeq((submitGaps) ? seqs[i].getSequence()
111                 : AlignSeq.extractGaps(
112                     jalview.util.Comparison.GapChars, seqs[i]
113                                                            .getSequence()));
114           } else {
115             emptySeqs.add(newname);
116           }
117         }
118         this.seqs = new vamsas.objects.simple.SequenceSet();
119         this.seqs.setSeqs(seqarray);
120     }
121     /**
122      * 
123      * @return true if getAlignment will return a valid alignment result.
124      */
125     public boolean hasResults() {
126       if (subjobComplete && result!=null && jobs[0].result.isFinished())
127         return true;
128       return false;
129     }
130     public Object[] getAlignment() {
131       
132       if (result!=null && result.isFinished()) {
133         SequenceI[] alseqs=null;
134         char alseq_gapchar='-';
135         int alseq_l=0;
136         if (result.getMsa() != null) {
137           alseqs = getVamsasAlignment(result.getMsa());
138           alseq_gapchar=result.getMsa().getGapchar().charAt(0);
139           alseq_l = alseqs.length;
140         }
141         if (emptySeqs.size()>0) {
142           SequenceI[] t_alseqs = new SequenceI[alseq_l+emptySeqs.size()];
143           // get width
144           int i,w=0;
145           if (alseq_l>0) {
146             for (i=0,w=alseqs[0].getLength(); i<alseq_l; i++) {
147               if (w<alseqs[i].getLength())
148                 w=alseqs[i].getLength();
149               t_alseqs[i] = alseqs[i];
150               alseqs[i] = null;
151             }
152           }
153           // make a gapped string.
154           StringBuffer insbuff=new StringBuffer(w);
155           for (i=0; i<w; i++)
156             insbuff.append(alseq_gapchar);
157           for (i=0, w=emptySeqs.size(); i<w; i++) {
158             t_alseqs[i+alseqs.length] = new jalview.datamodel.Sequence((String)emptySeqs.get(i), insbuff.toString());
159           }
160           alseqs = t_alseqs;
161         } 
162         AlignmentOrder msaorder = new AlignmentOrder(alseqs);
163         // always recover the order - makes parseResult()'s life easier.
164         jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
165         // account for any missing sequences
166         jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
167         return new Object[] { alseqs, msaorder};
168       }
169       return null;
170     }
171   }
172   MsaWSJob jobs[] = null;
173   
174   String alTitle; // name which will be used to form new alignment window.
175   
176   boolean jobComplete = false;
177   
178   Alignment dataset; // dataset to which the new alignment will be
179   
180   // associated.
181   
182   ext.vamsas.MuscleWS server = null;
183   
184   String WsUrl = null;
185   
186   /**
187    * set basic options for this (group) of Msa jobs
188    * 
189    * @param subgaps
190    *            boolean
191    * @param presorder
192    *            boolean
193    */
194   MsaWSThread(ext.vamsas.MuscleWS server, String wsUrl,
195       WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame, AlignmentView alview,
196       String wsname, boolean subgaps, boolean presorder) {
197     this.server = server;
198     this.WsUrl = wsUrl;
199     this.wsInfo = wsinfo;
200     this.WebServiceName = wsname;
201     this.input = alview;
202     this.submitGaps = subgaps;
203     this.preserveOrder = presorder;
204     this.alignFrame = alFrame;
205   }
206   
207   /**
208    * create one or more Msa jobs to align visible seuqences in _msa
209    * 
210    * @param title
211    *            String
212    * @param _msa
213    *            AlignmentView
214    * @param subgaps
215    *            boolean
216    * @param presorder
217    *            boolean
218    * @param seqset
219    *            Alignment
220    */
221   MsaWSThread(ext.vamsas.MuscleWS server, String wsUrl,
222       WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame,
223       String wsname, String title, AlignmentView _msa, boolean subgaps,
224       boolean presorder, Alignment seqset) {
225     this(server, wsUrl, wsinfo, alFrame, _msa, wsname, subgaps, presorder);
226     OutputHeader = wsInfo.getProgressText();
227     alTitle = title;
228     dataset = seqset;
229     SeqCigar[] msa = _msa.getSequences();
230     int[] contigs = _msa.getContigs();
231     int njobs=1;
232     if (contigs != null && contigs.length > 0) {
233       int start = 0;
234       njobs=0;
235       int width = _msa.getWidth();
236       for (int contig = 0; contig < contigs.length; contig += 3) {
237         if ((contigs[contig+1] - start) > 0) {
238           njobs++;
239         }
240         width+=contigs[contig+2];// end up with full region width (including hidden regions)
241         start = contigs[contig+1] + contigs[contig + 2];
242       }
243       if (start<width) {
244         njobs++;
245       }
246       jobs = new MsaWSJob[njobs];
247       start=0;
248       int j=0;
249       for (int contig = 0; contig < contigs.length; contig += 3) {
250         if (contigs[contig+1] - start > 0) {
251           SequenceI mseq[] = new SequenceI[msa.length];
252           for (int s = 0; s < mseq.length; s++) {
253             mseq[s] = msa[s].getSeq('-').getSubSequence(start,
254                 contigs[contig+1]);
255           }
256           if (j!=0) {
257             jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq);
258           } else {
259             jobs[j] = new MsaWSJob(0, mseq);
260           }
261           wsinfo.setProgressName("region "+jobs[j].jobnum,jobs[j].jobnum);
262           wsinfo.setProgressText(jobs[j].jobnum, OutputHeader);
263           j++;
264         }
265         start = contigs[contig+1] + contigs[contig + 2];
266       }
267       if (start<width) {
268         SequenceI mseq[] = new SequenceI[msa.length];
269         for (int s = 0; s < mseq.length; s++) {
270           mseq[s] = msa[s].getSeq('-').getSubSequence(start,
271               width+1);
272         }
273         if (j!=0) {
274           jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq);
275         } else {
276           jobs[j] = new MsaWSJob(0, mseq);
277         }
278         wsinfo.setProgressName("region "+jobs[j].jobnum,jobs[j].jobnum);
279         wsinfo.setProgressText(jobs[j].jobnum, OutputHeader);
280         j++;        
281       }
282     } else {
283       SequenceI mseq[] = new SequenceI[msa.length];
284       for (int s = 0; s < mseq.length; s++) {
285         mseq[s] = msa[s].getSeq('-');
286       }
287       jobs = new MsaWSJob[1];
288       wsinfo.setProgressText(OutputHeader); // ensures default text
289       jobs[0] = new MsaWSJob(0, mseq);
290     }
291   }
292   
293   public boolean isCancellable() {
294     return true;
295   }
296   
297   public void cancelJob() {
298     if (!jobComplete && jobs != null) {
299       boolean cancelled = true;
300       for (int job = 0; job < jobs.length; job++) {
301         if (jobs[job].submitted && !jobs[job].subjobComplete)
302         { 
303           String cancelledMessage = "";
304           try {
305             vamsas.objects.simple.WsJobId cancelledJob = server
306             .cancel(jobs[job].jobId);
307             if (cancelledJob.getStatus() == 2) {
308               // CANCELLED_JOB
309               cancelledMessage = "Job cancelled.";
310               jobs[job].subjobComplete = true;
311               jobs[job].result = null;
312               wsInfo.setStatus(jobs[job].jobnum, WebserviceInfo.STATE_CANCELLED_OK);
313             } else if (cancelledJob.getStatus() == 3) {
314               // VALID UNSTOPPABLE JOB
315               cancelledMessage += "Server cannot cancel this job. just close the window.\n";
316               cancelled = false;
317               wsInfo.setStatus(jobs[job].jobnum, WebserviceInfo.STATE_CANCELLED_OK);
318             }
319             
320             if (cancelledJob.getJobId() != null) {
321               cancelledMessage += ("[" + cancelledJob.getJobId() + "]");
322             }
323             
324             cancelledMessage += "\n";
325           } catch (Exception exc) {
326             cancelledMessage += ("\nProblems cancelling the job : Exception received...\n"
327                 + exc + "\n");
328             exc.printStackTrace();
329           }
330           wsInfo.setProgressText(jobs[job].jobnum, OutputHeader
331               + cancelledMessage + "\n");
332         }
333       }
334       if (cancelled) {
335         wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
336         jobComplete = true;
337       }
338     } else {
339       if (!jobComplete) {
340         wsInfo
341         .setProgressText(OutputHeader
342             + "Server cannot cancel this job because it has not been submitted properly. just close the window.\n");
343       }
344     }
345   }
346   
347   public void run() {
348     
349     while (!jobComplete) {
350       int running=0;
351       int queuing=0;
352       int finished=0;
353       int error=0;
354       int serror=0;
355       for (int j=0; j<jobs.length; j++) {
356         
357         if (!jobs[j].submitted && jobs[j].seqs.getSeqs()!=null)
358           StartJob(jobs[j]);          
359         
360         if (jobs[j].submitted && !jobs[j].subjobComplete) {
361           try {
362             if ((jobs[j].result = server.getResult(jobs[j].jobId)) == null) {
363               throw (new Exception(
364               "Timed out when communicating with server\nTry again later.\n"));
365             }
366             jalview.bin.Cache.log.debug("Job "+j+" Result state " + jobs[j].result.getState()
367                 + "(ServerError=" + jobs[j].result.isServerError() + ")");
368           } catch (Exception ex) {
369             // Deal with Transaction exceptions
370             wsInfo.appendProgressText(jobs[j].jobnum, "\n" + WebServiceName
371                 + " Server exception!\n" + ex.getMessage());
372             Cache.log.warn(WebServiceName + " job(" + jobs[j].jobnum
373                 + ") Server exception: " + ex.getMessage());
374             
375             if (jobs[j].allowedServerExceptions > 0) {
376               jobs[j].allowedServerExceptions--;
377               Cache.log.debug("Sleeping after a server exception.");
378               try {
379                 Thread.sleep(5000);
380               }
381               catch (InterruptedException ex1) {
382               }
383             } else {
384               Cache.log.warn("Dropping job "+j+" "+jobs[j].jobId);
385               jobs[j].subjobComplete=true;
386               wsInfo.setStatus(jobs[j].jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
387             }
388           }
389           catch (OutOfMemoryError er) {   
390             jobComplete = true;
391             jobs[j].subjobComplete=true;
392             jobs[j].result=null; // may contain out of date result object
393             wsInfo.setStatus(jobs[j].jobnum,
394                 WebserviceInfo.STATE_STOPPED_ERROR);
395             JOptionPane
396             .showInternalMessageDialog(
397                 Desktop.desktop,
398                 "Out of memory handling result for job !!"
399                 + "\nSee help files for increasing Java Virtual Machine memory.",
400                 "Out of memory", JOptionPane.WARNING_MESSAGE);
401             Cache.log.error("Out of memory when retrieving Job "+j+" id:" + WsUrl+"/"+jobs[j].jobId, er);
402             System.gc();
403           }
404         }
405         if (jobs[j].result!=null) {
406           String progheader="";
407           // Parse state of job[j]
408           if (jobs[j].result.isRunning()) {
409             running++;
410             wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_RUNNING);
411           } else if (jobs[j].result.isQueued()) {
412             queuing++;
413             wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_QUEUING);
414           } else if (jobs[j].result.isFinished()) {
415             finished++;
416             jobs[j].subjobComplete = true;
417             wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_OK);
418           } else if (jobs[j].result.isFailed()) {
419             progheader += "Job failed.\n";
420             jobs[j].subjobComplete=true;
421             wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_ERROR);
422             error++;
423           } else if (jobs[j].result.isServerError()) {
424             serror++;
425             jobs[j].subjobComplete = true;
426             wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_SERVERERROR);
427           } else if (jobs[j].result.isBroken() || jobs[j].result.isFailed()) {
428             error++;
429             jobs[j].subjobComplete=true;
430             wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_ERROR);
431           }
432           // and pass on any sub-job messages to the user
433           wsInfo.setProgressText(jobs[j].jobnum, OutputHeader);
434           wsInfo.appendProgressText(jobs[j].jobnum, progheader);
435           if (jobs[j].result.getStatus() != null) {
436             wsInfo.appendProgressText(jobs[j].jobnum, jobs[j].result.getStatus());
437           }
438         } else {
439           if (jobs[j].submitted && jobs[j].subjobComplete) {
440             if (jobs[j].allowedServerExceptions==0) {
441               serror++;
442             } else if (jobs[j].result==null) {
443               error++;
444             } 
445           }
446         }
447       }
448       // Decide on overall state based on collected jobs[] states
449       if (running>0) {
450         wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
451       } else if (queuing>0) {
452         wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
453       } else {
454         jobComplete=true;
455         if (finished>0) {
456           wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
457         } else if (error>0) {
458           wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);          
459         } else if (serror>0) {
460           wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
461         }
462       }
463       if (!jobComplete) {
464         try {
465           Thread.sleep(5000);
466         }
467         catch (InterruptedException e) {
468           Cache.log.debug("Interrupted sleep waiting for next job poll.",e);
469         }
470         // System.out.println("I'm alive "+alTitle);
471       }
472     }
473     if (jobComplete) {
474       parseResult(); // tidy up and make results available to user
475     }
476   }
477   
478   void StartJob(MsaWSJob j) {
479     if (j.submitted) {
480       if (Cache.log.isDebugEnabled()) {
481         Cache.log.debug("Tried to submit an already submitted job "+j.jobId);
482       }
483       return;
484     }
485     if (j.seqs.getSeqs()==null) {
486       // special case - selection consisted entirely of empty sequences...
487       j.submitted=true;
488       j.result=new MsaResult();
489       j.result.setFinished(true);
490       j.result.setStatus("Empty Alignment Job");
491       j.result.setMsa(null);
492     }
493     try {
494       vamsas.objects.simple.WsJobId jobsubmit = server.align(j.seqs);
495       
496       if ((jobsubmit != null) && (jobsubmit.getStatus() == 1)) {
497         j.jobId = jobsubmit.getJobId();
498         j.submitted=true;
499         j.subjobComplete = false;
500         // System.out.println(WsURL + " Job Id '" + jobId + "'");
501       } else {
502         if (jobsubmit == null) {
503           throw new Exception(
504               "Server at "
505               + WsUrl
506               + " returned null object, it probably cannot be contacted. Try again later ?");
507         }
508         
509         throw new Exception(jobsubmit.getJobId());
510       }
511     } catch (Exception e) {
512       // TODO: JBPNote catch timeout or other fault types explicitly
513       // For unexpected errors
514       System.err
515       .println(WebServiceName
516           + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
517           + "When contacting Server:" + WsUrl + "\n"
518           + e.toString() + "\n");
519       j.allowedServerExceptions = 0;
520       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
521       wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
522       wsInfo
523       .appendProgressText(
524           j.jobnum,
525           "Failed to submit sequences for alignment.\n"
526           + "It is most likely that there is a problem with the server.\n"
527           + "Just close the window\n");
528       
529       // e.printStackTrace(); // TODO: JBPNote DEBUG
530     }
531   }
532   
533   private jalview.datamodel.Sequence[] getVamsasAlignment(
534       vamsas.objects.simple.Alignment valign) {
535     vamsas.objects.simple.Sequence[] seqs = valign.getSeqs().getSeqs();
536     jalview.datamodel.Sequence[] msa = new jalview.datamodel.Sequence[seqs.length];
537     
538     for (int i = 0, j = seqs.length; i < j; i++) {
539       msa[i] = new jalview.datamodel.Sequence(seqs[i].getId(), seqs[i]
540                                                                     .getSeq());
541     }
542     
543     return msa;
544   }
545   
546   void parseResult() {
547     try {
548       for (int j=0; j<jobs.length; j++) {
549         if (jobs[j].submitted && jobs[j].subjobComplete) {
550           if (jobs[j].result!=null) {
551             vamsas.objects.simple.Alignment valign = jobs[j].result.getMsa();
552             if (valign!= null) {
553               wsInfo.appendProgressText(jobs[j].jobnum,"\nAlignment Object Method Notes\n");
554               String[] lines = valign.getMethod();
555               for (int line = 0; line < lines.length; line++) {
556                 wsInfo.appendProgressText(jobs[j].jobnum, lines[line] + "\n");
557               }
558               // JBPNote The returned files from a webservice could be
559               //  hidden behind icons in the monitor window that,
560               // when clicked, pop up their corresponding data
561             }
562           }
563         }
564       }
565     }
566     catch (Exception ex) {
567       
568       Cache.log.error("Unexpected exception when processing results for "+alTitle,ex);
569       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
570     }
571     
572     wsInfo.showResultsNewFrame
573     .addActionListener(new java.awt.event.ActionListener() {
574       public void actionPerformed(
575           java.awt.event.ActionEvent evt) {
576         displayResults(true);
577       }
578     });
579     wsInfo.mergeResults
580     .addActionListener(new java.awt.event.ActionListener() {
581       public void actionPerformed(
582           java.awt.event.ActionEvent evt) {
583         displayResults(false);
584       }
585     });
586     wsInfo.setResultsReady();
587   }
588   void displayResults(boolean newFrame) {
589     int contigs[] = input.getContigs();
590     SeqCigar[] seqs = input.getSequences();
591     SequenceI[] alignment = new SequenceI[seqs.length];
592     ColumnSelection columnselection = new ColumnSelection();
593     Vector alorders=new Vector();
594     if (contigs != null && contigs.length > 0) {
595       int cshift=0;
596       int start = 0;
597       int nwidth = 0;
598       int j=0;
599       for (int contig = 0; contig < contigs.length; contig += 3) {
600         if (cshift+contigs[contig] - start > 0) {
601           Object[] subalg =  jobs[j++].getAlignment();
602           alorders.add(subalg[1]);
603           SequenceI mseq[] = (SequenceI[]) subalg[0];
604           int width = mseq[0].getLength();
605           for (int s = 0; s < mseq.length; s++) {
606             if (alignment[s]==null) {
607               alignment[s] = mseq[s];
608             } else {
609               alignment[s].setSequence(alignment[s].getSequence()+mseq[s].getSequence());
610               if (alignment[s].getEnd()<mseq[s].getEnd())
611                 alignment[s].setEnd(mseq[s].getEnd());
612               ((AlignmentOrder) subalg[1]).updateSequence(mseq[s], alignment[s]);
613             }
614           }
615           nwidth+=width;
616         }
617         // advance to begining of visible region
618         start = cshift+contigs[contig] + contigs[contig + 2];
619         // add hidden segment to right of next region
620         for (int s=0; s<seqs.length; s++) {
621           SequenceI hseq = seqs[s].getSeq('-').getSubSequence(cshift+contigs[contig], start);
622           if (alignment[s]==null) {
623             alignment[s] = hseq;
624           } else {
625             alignment[s].setSequence(alignment[s].getSequence()+hseq.getSequence());
626             alignment[s].setEnd(hseq.getEnd());
627           }
628         }
629         // mark hidden segment as hidden in the new alignment
630         columnselection.hideColumns(nwidth, nwidth+contigs[contig+2]-1);
631         nwidth+=contigs[contig+2];
632         cshift+=contigs[contig+2];
633       }
634       // Do final job - if it exists
635       if (j<jobs.length) {
636         Object[] subalg =  jobs[j].getAlignment();
637         alorders.add(subalg[1]);
638         SequenceI mseq[] = (SequenceI[]) subalg[0];
639         int width = mseq[0].getLength();
640         for (int s = 0; s < mseq.length; s++) {
641           if (alignment[s]==null) {
642             alignment[s] = mseq[s];
643           } else {
644             alignment[s].setSequence(alignment[s].getSequence()+mseq[s].getSequence());
645             alignment[s].setEnd(mseq[s].getEnd());
646             ((AlignmentOrder) subalg[1]).updateSequence(mseq[s], alignment[s]);
647           }
648         }
649         nwidth+=width;  
650       }
651     } else {
652       if (jobs[0].hasResults()) {
653         Object[] alg = jobs[0].getAlignment();
654         alignment = (SequenceI[]) alg[0];
655         alorders.add(alg[1]);
656       } else {
657         alignment = SeqCigar.createAlignmentSequences(seqs, '-', columnselection,null);
658       }
659     }
660     Alignment al = new Alignment(alignment);
661     if (dataset != null) {
662       al.setDataset(dataset);
663     }
664     
665     if (newFrame) {
666       // TODO: JBPNote Should also rename the query sequence
667       // sometime...
668       AlignFrame af = new AlignFrame(al,columnselection);
669       
670       // >>>This is a fix for the moment, until a better solution is
671       // found!!<<<
672       af.getFeatureRenderer().transferSettings(
673           alignFrame.getFeatureRenderer());
674       if (alorders.size()>0) {
675         if (alorders.size()==1) {
676           af.addSortByOrderMenuItem(WebServiceName + " Ordering",
677               (AlignmentOrder) alorders.get(0));
678         } else {
679           // construct a non-redundant ordering set
680           Vector names=new Vector();
681           for (int i=0,l=alorders.size(); i<l; i++) {
682             String orderName = new String("Region "+i);
683             int j=i+1;
684             int r=l;
685             while (j<l) {
686               if (((AlignmentOrder) alorders.get(i)).equals(((AlignmentOrder) alorders.get(j)))) {
687                 alorders.remove(j); l--;
688                 orderName+=","+j;
689               } else
690                 j++;
691             }
692             
693             if (i==0 && j==1)
694               names.add(new String(""));
695             else
696               names.add(orderName);
697           }
698           for (int i=0,l=alorders.size(); i<l; i++) {
699             af.addSortByOrderMenuItem(WebServiceName + ((String) names.get(i))+" Ordering",
700                 (AlignmentOrder) alorders.get(i));              
701           }
702         }
703       }
704       
705       Desktop.addInternalFrame(af, alTitle,
706           AlignFrame.NEW_WINDOW_WIDTH,
707           AlignFrame.NEW_WINDOW_HEIGHT);
708       
709     } else {
710       System.out.println("MERGE WITH OLD FRAME");
711       
712     }
713   }
714 }