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