2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.ws.jws2;
23 import jalview.analysis.AlignSeq;
24 import jalview.bin.Console;
25 import jalview.datamodel.Alignment;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.AlignmentOrder;
28 import jalview.datamodel.AlignmentView;
29 import jalview.datamodel.HiddenColumns;
30 import jalview.datamodel.Sequence;
31 import jalview.datamodel.SequenceI;
32 import jalview.gui.AlignFrame;
33 import jalview.gui.Desktop;
34 import jalview.gui.SplitFrame;
35 import jalview.gui.WebserviceInfo;
36 import jalview.util.MessageManager;
37 import jalview.ws.AWsJob;
38 import jalview.ws.JobStateSummary;
39 import jalview.ws.WSClientI;
40 import jalview.ws.jws2.dm.JabaWsParamSet;
41 import jalview.ws.params.WsParamSetI;
43 import java.util.ArrayList;
44 import java.util.Hashtable;
45 import java.util.List;
47 import java.util.Vector;
49 import javax.swing.JInternalFrame;
51 import compbio.data.msa.MsaWS;
52 import compbio.metadata.Argument;
53 import compbio.metadata.ChunkHolder;
54 import compbio.metadata.JobStatus;
55 import compbio.metadata.Preset;
57 class MsaWSThread extends AWS2Thread implements WSClientI
59 boolean submitGaps = false; // pass sequences including gaps to alignment
63 boolean preserveOrder = true; // and always store and recover sequence
67 class MsaWSJob extends JWs2Job
71 WsParamSetI preset = null;
73 List<Argument> arguments = null;
78 ArrayList<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
83 compbio.data.sequence.Alignment alignment;
85 // set if the job didn't get run - then the input is simply returned to the
87 private boolean returnInput = false;
97 public MsaWSJob(int jobNum, SequenceI[] inSeqs)
100 if (!prepareInput(inSeqs, 2))
103 subjobComplete = true;
109 Hashtable<String, Map> SeqNames = new Hashtable();
111 Vector<String[]> emptySeqs = new Vector();
114 * prepare input sequences for MsaWS service
117 * jalview sequences to be prepared
119 * minimum number of residues required for this MsaWS service
120 * @return true if seqs contains sequences to be submitted to service.
122 // TODO: return compbio.seqs list or nothing to indicate validity.
123 private boolean prepareInput(SequenceI[] seqs, int minlen)
128 throw new Error(MessageManager.getString(
129 "error.implementation_error_minlen_must_be_greater_zero"));
131 for (int i = 0; i < seqs.length; i++)
133 if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
138 boolean valid = nseqs > 1; // need at least two seqs
139 compbio.data.sequence.FastaSequence seq;
140 for (int i = 0, n = 0; i < seqs.length; i++)
143 String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
147 SeqNames.put(newname,
148 jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i]));
149 if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
151 // make new input sequence with or without gaps
152 seq = new compbio.data.sequence.FastaSequence(newname,
153 (submitGaps) ? seqs[i].getSequenceAsString()
154 : AlignSeq.extractGaps(
155 jalview.util.Comparison.GapChars,
156 seqs[i].getSequenceAsString()));
162 if (seqs[i].getEnd() >= seqs[i].getStart())
164 empty = (submitGaps) ? seqs[i].getSequenceAsString()
165 : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
166 seqs[i].getSequenceAsString());
168 emptySeqs.add(new String[] { newname, empty });
176 * @return true if getAlignment will return a valid alignment result.
179 public boolean hasResults()
181 if (subjobComplete && isFinished() && (alignment != null
182 || (emptySeqs != null && emptySeqs.size() > 0)))
191 * get the alignment including any empty sequences in the original order
192 * with original ids. Caller must access the alignment.getMetadata() object
193 * to annotate the final result passsed to the user.
195 * @return { SequenceI[], AlignmentOrder }
197 public Object[] getAlignment()
199 // is this a generic subjob or a Jws2 specific Object[] return signature
202 SequenceI[] alseqs = null;
203 char alseq_gapchar = '-';
205 if (alignment.getSequences().size() > 0)
207 alseqs = new SequenceI[alignment.getSequences().size()];
208 for (compbio.data.sequence.FastaSequence seq : alignment
211 alseqs[alseq_l++] = new Sequence(seq.getId(),
214 alseq_gapchar = alignment.getMetadata().getGapchar();
217 // add in the empty seqs.
218 if (emptySeqs.size() > 0)
220 SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
225 for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
227 if (w < alseqs[i].getLength())
229 w = alseqs[i].getLength();
231 t_alseqs[i] = alseqs[i];
235 // check that aligned width is at least as wide as emptySeqs width.
237 for (i = 0, w = emptySeqs.size(); i < w; i++)
239 String[] es = emptySeqs.get(i);
240 if (es != null && es[1] != null)
242 int sw = es[1].length();
249 // make a gapped string.
250 StringBuffer insbuff = new StringBuffer(w);
251 for (i = 0; i < nw; i++)
253 insbuff.append(alseq_gapchar);
257 for (i = 0; i < alseq_l; i++)
259 int sw = t_alseqs[i].getLength();
263 alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
264 + insbuff.substring(0, sw - nw));
268 for (i = 0, w = emptySeqs.size(); i < w; i++)
270 String[] es = emptySeqs.get(i);
273 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
274 insbuff.toString(), 1, 0);
278 if (es[1].length() < nw)
280 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
282 es[1] + insbuff.substring(0, nw - es[1].length()),
283 1, 1 + es[1].length());
287 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
294 AlignmentOrder msaorder = new AlignmentOrder(alseqs);
295 // always recover the order - makes parseResult()'s life easier.
296 jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
297 // account for any missing sequences
298 jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
299 return new Object[] { alseqs, msaorder };
305 * mark subjob as cancelled and set result object appropriatly
310 subjobComplete = true;
316 * @return boolean true if job can be submitted.
319 public boolean hasValidInput()
321 // TODO: get attributes for this MsaWS instance to check if it can do two
322 // sequence alignment.
323 if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ?
330 StringBuffer jobProgress = new StringBuffer();
332 public void setStatus(String string)
334 jobProgress.setLength(0);
335 jobProgress.append(string);
339 public String getStatus()
341 return jobProgress.toString();
345 public boolean hasStatus()
347 return jobProgress != null;
351 * @return the lastChunk
353 public long getLastChunk()
360 * the lastChunk to set
362 public void setLastChunk(long lastChunk)
364 this.lastChunk = lastChunk;
367 String alignmentProgram = null;
369 public String getAlignmentProgram()
371 return alignmentProgram;
374 public boolean hasArguments()
376 return (arguments != null && arguments.size() > 0)
377 || (preset != null && preset instanceof JabaWsParamSet);
380 public List<Argument> getJabaArguments()
382 List<Argument> newargs = new ArrayList<Argument>();
383 if (preset != null && preset instanceof JabaWsParamSet)
385 newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
387 if (arguments != null && arguments.size() > 0)
389 newargs.addAll(arguments);
395 * add a progess header to status string containing presets/args used
397 public void addInitialStatus()
401 jobProgress.append("Using "
402 + (preset instanceof JabaPreset ? "Server" : "User")
403 + "Preset: " + preset.getName());
404 if (preset instanceof JabaWsParamSet)
406 for (Argument opt : ((JabaWsParamSet) preset).getjabaArguments())
409 opt.getName() + " " + opt.getDefaultValue() + "\n");
413 if (arguments != null && arguments.size() > 0)
415 jobProgress.append("With custom parameters : \n");
416 // merge arguments with preset's own arguments.
417 for (Argument opt : arguments)
420 opt.getName() + " " + opt.getDefaultValue() + "\n");
423 jobProgress.append("\nJob Output:\n");
426 public boolean isPresetJob()
428 return preset != null && preset instanceof JabaPreset;
431 public Preset getServerPreset()
433 return (isPresetJob()) ? ((JabaPreset) preset).p : null;
437 String alTitle; // name which will be used to form new alignment window.
439 AlignmentI dataset; // dataset to which the new alignment will be
443 @SuppressWarnings("unchecked")
447 * set basic options for this (group) of Msa jobs
454 private MsaWSThread(MsaWS server, String wsUrl, WebserviceInfo wsinfo,
455 jalview.gui.AlignFrame alFrame, AlignmentView alview,
456 String wsname, boolean subgaps, boolean presorder)
458 super(alFrame, wsinfo, alview, wsname, wsUrl);
459 this.server = server;
460 this.submitGaps = subgaps;
461 this.preserveOrder = presorder;
465 * create one or more Msa jobs to align visible seuqences in _msa
478 MsaWSThread(MsaWS server2, WsParamSetI preset, List<Argument> paramset,
479 String wsUrl, WebserviceInfo wsinfo,
480 jalview.gui.AlignFrame alFrame, String wsname, String title,
481 AlignmentView _msa, boolean subgaps, boolean presorder,
484 this(server2, wsUrl, wsinfo, alFrame, _msa, wsname, subgaps, presorder);
485 OutputHeader = wsInfo.getProgressText();
489 SequenceI[][] conmsa = _msa.getVisibleContigs('-');
492 int nvalid = 0, njobs = conmsa.length;
493 jobs = new MsaWSJob[njobs];
494 for (int j = 0; j < njobs; j++)
498 jobs[j] = new MsaWSJob(wsinfo.addJobPane(), conmsa[j]);
502 jobs[j] = new MsaWSJob(0, conmsa[j]);
504 if (((MsaWSJob) jobs[j]).hasValidInput())
508 ((MsaWSJob) jobs[j]).preset = preset;
509 ((MsaWSJob) jobs[j]).arguments = paramset;
510 ((MsaWSJob) jobs[j]).alignmentProgram = wsname;
513 wsinfo.setProgressName("region " + jobs[j].getJobnum(),
514 jobs[j].getJobnum());
516 wsinfo.setProgressText(jobs[j].getJobnum(), OutputHeader);
518 validInput = nvalid > 0;
522 boolean validInput = false;
526 * @return true if the thread will perform a calculation
528 public boolean hasValidInput()
534 public boolean isCancellable()
540 public void cancelJob()
542 if (!jobComplete && jobs != null)
544 boolean cancelled = true;
545 for (int job = 0; job < jobs.length; job++)
547 if (jobs[job].isSubmitted() && !jobs[job].isSubjobComplete())
549 String cancelledMessage = "";
552 boolean cancelledJob = server.cancelJob(jobs[job].getJobId());
553 if (true) // cancelledJob || true)
556 // if the Jaba server indicates the job can't be cancelled, its
557 // because its running on the server's local execution engine
558 // so we just close the window anyway.
559 cancelledMessage = "Job cancelled.";
560 ((MsaWSJob) jobs[job]).cancel(); // TODO: refactor to avoid this
562 wsInfo.setStatus(jobs[job].getJobnum(),
563 WebserviceInfo.STATE_CANCELLED_OK);
567 // VALID UNSTOPPABLE JOB
568 cancelledMessage += "Server cannot cancel this job. just close the window.\n";
570 // wsInfo.setStatus(jobs[job].jobnum,
571 // WebserviceInfo.STATE_RUNNING);
573 } catch (Exception exc)
575 cancelledMessage += ("\nProblems cancelling the job : Exception received...\n"
578 "Exception whilst cancelling " + jobs[job].getJobId(),
581 wsInfo.setProgressText(jobs[job].getJobnum(),
582 OutputHeader + cancelledMessage + "\n");
586 // if we hadn't submitted then just mark the job as cancelled.
587 jobs[job].setSubjobComplete(true);
588 wsInfo.setStatus(jobs[job].getJobnum(),
589 WebserviceInfo.STATE_CANCELLED_OK);
595 wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
598 this.interrupt(); // kick thread to update job states.
604 wsInfo.setProgressText(OutputHeader
605 + "Server cannot cancel this job because it has not been submitted properly. just close the window.\n");
611 public void pollJob(AWsJob job) throws Exception
613 // TODO: investigate if we still need to cast here in J1.6
614 MsaWSJob j = ((MsaWSJob) job);
615 // this is standard code, but since the interface doesn't comprise of a
616 // basic one that implements (getJobStatus, pullExecStatistics) we have to
617 // repeat the code for all jw2s services.
618 j.setjobStatus(server.getJobStatus(job.getJobId()));
619 updateJobProgress(j);
625 * @return true if more job progress data was available
628 protected boolean updateJobProgress(MsaWSJob j) throws Exception
630 StringBuffer response = j.jobProgress;
631 long lastchunk = j.getLastChunk();
632 boolean changed = false;
635 j.setLastChunk(lastchunk);
636 ChunkHolder chunk = server.pullExecStatistics(j.getJobId(),
640 changed |= chunk.getChunk().length() > 0;
641 response.append(chunk.getChunk());
642 lastchunk = chunk.getNextPosition();
646 } catch (InterruptedException x)
652 } while (lastchunk >= 0 && j.getLastChunk() != lastchunk);
657 public void StartJob(AWsJob job)
659 Exception lex = null;
660 // boiler plate template
661 if (!(job instanceof MsaWSJob))
663 throw new Error(MessageManager.formatMessage(
664 "error.implementation_error_msawbjob_called", new String[]
665 { job.getClass().toString() }));
667 MsaWSJob j = (MsaWSJob) job;
670 if (Console.isDebugEnabled())
673 "Tried to submit an already submitted job " + j.getJobId());
679 if (j.seqs == null || j.seqs.size() == 0)
681 // special case - selection consisted entirely of empty sequences...
682 j.setjobStatus(JobStatus.FINISHED);
683 j.setStatus(MessageManager.getString("label.empty_alignment_job"));
687 j.addInitialStatus(); // list the presets/parameters used for the job in
691 j.setJobId(server.presetAlign(j.seqs, j.getServerPreset()));
693 else if (j.hasArguments())
695 j.setJobId(server.customAlign(j.seqs, j.getJabaArguments()));
699 j.setJobId(server.align(j.seqs));
702 if (j.getJobId() != null)
704 j.setSubmitted(true);
705 j.setSubjobComplete(false);
706 // jalview.bin.Console.outPrintln(WsURL + " Job Id '" + jobId + "'");
711 throw new Exception(MessageManager.formatMessage(
712 "exception.web_service_returned_null_try_later",
716 } catch (compbio.metadata.UnsupportedRuntimeException _lex)
719 wsInfo.appendProgressText(MessageManager.formatMessage(
720 "info.job_couldnt_be_run_server_doesnt_support_program",
722 { _lex.getMessage() }));
723 wsInfo.warnUser(_lex.getMessage(),
724 MessageManager.getString("warn.service_not_supported"));
725 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
726 wsInfo.setStatus(j.getJobnum(),
727 WebserviceInfo.STATE_STOPPED_SERVERERROR);
728 } catch (compbio.metadata.LimitExceededException _lex)
731 wsInfo.appendProgressText(MessageManager.formatMessage(
732 "info.job_couldnt_be_run_exceeded_hard_limit", new String[]
733 { _lex.getMessage() }));
734 wsInfo.warnUser(_lex.getMessage(),
735 MessageManager.getString("warn.input_is_too_big"));
736 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
737 wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
738 } catch (compbio.metadata.WrongParameterException _lex)
741 wsInfo.warnUser(_lex.getMessage(),
742 MessageManager.getString("warn.invalid_job_param_set"));
743 wsInfo.appendProgressText(MessageManager.formatMessage(
744 "info.job_couldnt_be_run_incorrect_param_setting",
746 { _lex.getMessage() }));
747 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
748 wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
751 // For unexpected errors
752 jalview.bin.Console.errPrintln(WebServiceName
753 + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
754 + "When contacting Server:" + WsUrl + "\n");
755 e.printStackTrace(System.err);
756 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
757 wsInfo.setStatus(j.getJobnum(),
758 WebserviceInfo.STATE_STOPPED_SERVERERROR);
759 } catch (Exception e)
761 // For unexpected errors
762 jalview.bin.Console.errPrintln(WebServiceName
763 + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
764 + "When contacting Server:" + WsUrl + "\n");
765 e.printStackTrace(System.err);
766 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
767 wsInfo.setStatus(j.getJobnum(),
768 WebserviceInfo.STATE_STOPPED_SERVERERROR);
771 if (!j.isSubmitted())
773 // Boilerplate code here
774 // TODO: JBPNote catch timeout or other fault types explicitly
776 j.setAllowedServerExceptions(0);
777 wsInfo.appendProgressText(j.getJobnum(), MessageManager.getString(
778 "info.failed_to_submit_sequences_for_alignment"));
784 public void parseResult()
786 long progbar = System.currentTimeMillis();
787 wsInfo.setProgressBar(
788 MessageManager.getString("status.collecting_job_results"),
790 int results = 0; // number of result sets received
791 JobStateSummary finalState = new JobStateSummary();
794 for (int j = 0; j < jobs.length; j++)
796 MsaWSJob msjob = ((MsaWSJob) jobs[j]);
797 if (jobs[j].isFinished() && msjob.alignment == null)
799 int nunchanged = 3, nexcept = 3;
800 boolean jpchanged = false, jpex = false;
805 jpchanged = updateJobProgress(msjob);
811 } catch (Exception e)
815 "Exception when retrieving remaining Job progress data for job "
816 + msjob.getJobId() + " on server " + WsUrl);
820 // set flag remember that we've had an exception.
828 Thread.sleep(jpex ? 2400 : 1200); // wait a bit longer if we
829 // experienced an exception.
830 } catch (Exception ex)
836 } while (nunchanged > 0 && nexcept > 0);
838 if (Console.isDebugEnabled())
840 jalview.bin.Console.outPrintln("Job Execution file for job: "
841 + msjob.getJobId() + " on server " + WsUrl);
842 jalview.bin.Console.outPrintln(msjob.getStatus());
843 jalview.bin.Console.outPrintln("*** End of status");
848 msjob.alignment = server.getResult(msjob.getJobId());
849 } catch (compbio.metadata.ResultNotAvailableException e)
851 // job has failed for some reason - probably due to invalid
854 "Results not available for finished job - marking as broken job.",
856 msjob.jobProgress.append(
857 "\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
858 + e.getLocalizedMessage());
859 msjob.setjobStatus(JobStatus.FAILED);
860 } catch (Exception e)
862 Console.error("Couldn't get Alignment for job.", e);
863 // TODO: Increment count and retry ?
864 msjob.setjobStatus(JobStatus.UNDEFINED);
867 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
868 if (jobs[j].isSubmitted() && jobs[j].isSubjobComplete()
869 && jobs[j].hasResults())
872 compbio.data.sequence.Alignment alignment = ((MsaWSJob) jobs[j]).alignment;
873 if (alignment != null)
875 // server.close(jobs[j].getJobnum());
876 // wsInfo.appendProgressText(jobs[j].getJobnum(),
877 // "\nAlignment Object Method Notes\n");
878 // wsInfo.appendProgressText(jobs[j].getJobnum(),
880 // "+alignment.getMetadata().getProgram().toString());
881 // JBPNote The returned files from a webservice could be
882 // hidden behind icons in the monitor window that,
883 // when clicked, pop up their corresponding data
887 } catch (Exception ex)
891 "Unexpected exception when processing results for " + alTitle,
893 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
897 wsInfo.showResultsNewFrame
898 .addActionListener(new java.awt.event.ActionListener()
901 public void actionPerformed(java.awt.event.ActionEvent evt)
903 displayResults(true);
907 .addActionListener(new java.awt.event.ActionListener()
910 public void actionPerformed(java.awt.event.ActionEvent evt)
912 displayResults(false);
915 wsInfo.setResultsReady();
919 wsInfo.setFinishedNoResults();
921 updateGlobalStatus(finalState);
922 wsInfo.setProgressBar(null, progbar);
926 * Display alignment results in a new frame (or - not currently supported -
927 * added to an existing alignment).
931 void displayResults(boolean newFrame)
933 // view input or result data for each block
934 List<AlignmentOrder> alorders = new ArrayList<AlignmentOrder>();
935 SequenceI[][] results = new SequenceI[jobs.length][];
936 AlignmentOrder[] orders = new AlignmentOrder[jobs.length];
937 String lastProgram = null;
939 for (int j = 0; j < jobs.length; j++)
941 if (jobs[j].hasResults())
943 msjob = (MsaWSJob) jobs[j];
944 Object[] res = msjob.getAlignment();
945 lastProgram = msjob.getAlignmentProgram();
946 alorders.add((AlignmentOrder) res[1]);
947 results[j] = (SequenceI[]) res[0];
948 orders[j] = (AlignmentOrder) res[1];
950 // SequenceI[] alignment = input.getUpdated
957 Object[] newview = input.getUpdatedView(results, orders, getGapChar());
958 // trash references to original result data
959 for (int j = 0; j < jobs.length; j++)
964 SequenceI[] alignment = (SequenceI[]) newview[0];
965 HiddenColumns hidden = (HiddenColumns) newview[1];
966 Alignment al = new Alignment(alignment);
967 // TODO: add 'provenance' property to alignment from the method notes
968 if (lastProgram != null)
970 al.setProperty("Alignment Program", lastProgram);
972 // accompanying each subjob
975 al.setDataset(dataset);
978 propagateDatasetMappings(al);
979 // JBNote- TODO: warn user if a block is input rather than aligned data ?
983 displayInNewFrame(al, alorders, hidden);
988 // TODO 2.9.x feature
989 jalview.bin.Console.outPrintln("MERGE WITH OLD FRAME");
990 // TODO: modify alignment in original frame, replacing old for new
991 // alignment using the commands.EditCommand model to ensure the update can
997 * Display the alignment result in a new frame.
1001 * @param columnselection
1003 protected void displayInNewFrame(AlignmentI al,
1004 List<AlignmentOrder> alorders, HiddenColumns hidden)
1006 AlignFrame af = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH,
1007 AlignFrame.DEFAULT_HEIGHT);
1009 // initialise with same renderer settings as in parent alignframe.
1010 af.getFeatureRenderer().transferSettings(this.featureSettings);
1012 if (alorders.size() > 0)
1014 addSortByMenuItems(af, alorders);
1017 // TODO: refactor retrieve and show as new splitFrame as Desktop method
1020 * If alignment was requested from one half of a SplitFrame, show in a
1021 * SplitFrame with the other pane similarly aligned.
1023 AlignFrame requestedBy = getRequestingAlignFrame();
1024 if (requestedBy != null && requestedBy.getSplitViewContainer() != null
1025 && requestedBy.getSplitViewContainer()
1026 .getComplement(requestedBy) != null)
1028 AlignmentI complement = requestedBy.getSplitViewContainer()
1029 .getComplement(requestedBy);
1030 String complementTitle = requestedBy.getSplitViewContainer()
1031 .getComplementTitle(requestedBy);
1032 // becomes null if the alignment window was closed before the alignment
1034 AlignmentI copyComplement = new Alignment(complement);
1035 // todo should this be done by copy constructor?
1036 copyComplement.setGapCharacter(complement.getGapCharacter());
1037 // share the same dataset (and the mappings it holds)
1038 copyComplement.setDataset(complement.getDataset());
1039 copyComplement.alignAs(al);
1040 if (copyComplement.getHeight() > 0)
1042 af.setTitle(alTitle);
1043 AlignFrame af2 = new AlignFrame(copyComplement,
1044 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
1045 af2.setTitle(complementTitle);
1046 String linkedTitle = MessageManager
1047 .getString("label.linked_view_title");
1048 JInternalFrame splitFrame = new SplitFrame(
1049 al.isNucleotide() ? af : af2, al.isNucleotide() ? af2 : af);
1050 Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
1056 * Not from SplitFrame, or failed to created a complementary alignment
1058 Desktop.addInternalFrame(af, alTitle, AlignFrame.DEFAULT_WIDTH,
1059 AlignFrame.DEFAULT_HEIGHT);
1063 * Add sort order options to the AlignFrame menus.
1068 protected void addSortByMenuItems(AlignFrame af,
1069 List<AlignmentOrder> alorders)
1072 if (alorders.size() == 1)
1074 af.addSortByOrderMenuItem(WebServiceName + " Ordering",
1079 // construct a non-redundant ordering set
1080 List<String> names = new ArrayList<String>();
1081 for (int i = 0, l = alorders.size(); i < l; i++)
1083 String orderName = " Region " + i;
1088 if (alorders.get(i).equals(alorders.get(j)))
1092 orderName += "," + j;
1100 if (i == 0 && j == 1)
1106 names.add(orderName);
1109 for (int i = 0, l = alorders.size(); i < l; i++)
1111 af.addSortByOrderMenuItem(
1112 WebServiceName + (names.get(i)) + " Ordering",
1119 public boolean canMergeResults()