1 package jalview.ws.rest;
3 import jalview.bin.Cache;
4 import jalview.datamodel.Alignment;
5 import jalview.datamodel.AlignmentAnnotation;
6 import jalview.datamodel.AlignmentI;
7 import jalview.datamodel.AlignmentOrder;
8 import jalview.datamodel.Annotation;
9 import jalview.datamodel.ColumnSelection;
10 import jalview.datamodel.SequenceGroup;
11 import jalview.datamodel.SequenceI;
12 import jalview.gui.AlignFrame;
13 import jalview.gui.Desktop;
14 import jalview.gui.WebserviceInfo;
15 import jalview.io.NewickFile;
16 import jalview.io.packed.JalviewDataset;
17 import jalview.io.packed.JalviewDataset.AlignmentSet;
18 import jalview.ws.AWSThread;
19 import jalview.ws.AWsJob;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Enumeration;
26 import java.util.Hashtable;
27 import java.util.List;
28 import java.util.Map.Entry;
29 import java.util.Vector;
31 import org.apache.axis.transport.http.HTTPConstants;
32 import org.apache.http.Header;
33 import org.apache.http.HttpEntity;
34 import org.apache.http.HttpResponse;
35 import org.apache.http.client.ClientProtocolException;
36 import org.apache.http.client.methods.HttpGet;
37 import org.apache.http.client.methods.HttpPost;
38 import org.apache.http.client.methods.HttpRequestBase;
39 import org.apache.http.entity.mime.HttpMultipartMode;
40 import org.apache.http.entity.mime.MultipartEntity;
41 import org.apache.http.impl.client.DefaultHttpClient;
42 import org.apache.http.protocol.BasicHttpContext;
43 import org.apache.http.protocol.HttpContext;
44 import org.apache.http.util.EntityUtils;
46 public class RestJobThread extends AWSThread
53 protected RestClient restClient;;
55 public RestJobThread(RestClient restClient)
57 super(restClient.af, null, restClient._input,
58 restClient.service.postUrl);
59 this.restClient = restClient; // may not be needed
61 // minimal job - submit given input and parse result onto alignment as
62 // annotation/whatever
64 // look for tree data, etc.
66 // for moment do following job type only
67 // input=visiblealignment,groupsindex
68 // ie one subjob using groups defined on alignment.
69 if (!restClient.service.isHseparable())
71 jobs = new RestJob[1];
72 jobs[0] = new RestJob(0, this,
73 restClient._input.getVisibleAlignment(restClient.service
75 restClient._input.getVisibleContigs());
76 // need a function to get a range on a view/alignment and return both
77 // annotation, groups and selection subsetted to just that region.
82 int[] viscontig = restClient._input.getVisibleContigs();
83 AlignmentI[] viscontigals = restClient._input
84 .getVisibleContigAlignments(restClient.service
86 if (viscontigals != null && viscontigals.length > 0)
88 jobs = new RestJob[viscontigals.length];
89 for (int j = 0; j < jobs.length; j++)
91 int[] visc = new int[]
92 { viscontig[j * 2], viscontig[j * 2 + 1] };
95 jobs[j] = new RestJob(j, this, viscontigals[j], visc);
99 jobs[j] = new RestJob(0, this, viscontigals[j], visc);
106 * subjob types row based: per sequence in alignment/selected region { input
107 * is one sequence or sequence ID } per alignment/selected region { input is
108 * set of sequences, alignment, one or more sets of sequence IDs,
111 if (!restClient.service.isHseparable())
114 // create a bunch of subjobs per visible contig to ensure result honours
116 // TODO: determine if a 'soft' hSeperable property is needed - e.g. if
117 // user does SS-pred on sequence with big hidden regions, its going to be
122 // create a single subjob for the visible/selected input
125 // TODO: decide if vSeperable exists: eg. column wide analysis where hidden
126 // rows do not affect output - generally no analysis that generates
127 // alignment annotation is vSeparable -
131 * create gui components for monitoring jobs
133 * @param webserviceInfo
135 public void setWebServiceInfo(WebserviceInfo webserviceInfo)
137 wsInfo = webserviceInfo;
138 for (int j = 0; j < jobs.length; j++)
141 // Copy over any per job params
144 wsInfo.setProgressName("region " + jobs[j].getJobnum(),
145 jobs[j].getJobnum());
149 wsInfo.setProgressText(jobs[j].getJobnum(), OutputHeader);
154 private String getStage(Stage stg)
156 if (stg == Stage.SUBMIT)
157 return "submitting ";
158 if (stg == Stage.POLL)
159 return "checking status of ";
161 return (" being confused about ");
164 private void doPoll(RestJob rj) throws Exception
166 String postUrl = rj.getPollUrl();
167 doHttpReq(Stage.POLL, rj, postUrl);
171 * construct the post and handle the response.
175 public void doPost(RestJob rj) throws Exception
177 String postUrl = rj.getPostUrl();
178 doHttpReq(Stage.SUBMIT, rj, postUrl);
182 * do the HTTP request - and respond/set statuses appropriate to the current
187 * - provides any data needed for posting and used to record state
189 * - actual URL to post/get from
192 protected void doHttpReq(Stage stg, RestJob rj, String postUrl)
195 StringBuffer respText = new StringBuffer();
196 // con.setContentHandlerFactory(new
197 // jalview.ws.io.mime.HttpContentHandler());
198 HttpRequestBase request = null;
199 String messages = "";
200 if (stg == Stage.SUBMIT)
203 // http://evgenyg.wordpress.com/2010/05/01/uploading-files-multipart-post-apache/
205 HttpPost htpost = new HttpPost(postUrl);
206 MultipartEntity postentity = new MultipartEntity(
207 HttpMultipartMode.STRICT);
208 for (Entry<String, InputType> input : rj.getInputParams())
210 if (input.getValue().validFor(rj))
212 postentity.addPart(input.getKey(), input.getValue()
213 .formatForInput(rj));
217 messages += "Skipped an input (" + input.getKey()
218 + ") - Couldn't generate it from available data.";
221 htpost.setEntity(postentity);
226 request = new HttpGet(postUrl);
230 DefaultHttpClient httpclient = new DefaultHttpClient();
232 HttpContext localContext = new BasicHttpContext();
233 HttpResponse response = null;
236 response = httpclient.execute(request);
237 } catch (ClientProtocolException he)
239 rj.statMessage = "Web Protocol Exception when attempting to "
240 + getStage(stg) + "Job. See Console output for details.";
241 rj.setAllowedServerExceptions(0);// unrecoverable;
243 Cache.log.fatal("Unexpected REST Job " + getStage(stg)
244 + "exception for URL " + rj.rsd.postUrl);
246 } catch (IOException e)
248 rj.statMessage = "IO Exception when attempting to "
249 + getStage(stg) + "Job. See Console output for details.";
250 Cache.log.warn("IO Exception for REST Job " + getStage(stg)
251 + "exception for URL " + rj.rsd.postUrl);
255 switch (response.getStatusLine().getStatusCode())
259 Cache.log.debug("Processing result set.");
260 processResultSet(rj, response, request);
263 rj.statMessage = "<br>Job submitted successfully. Results available at this URL:\n"
273 if (!rj.isSubmitted()
275 .getHeaders(HTTPConstants.HEADER_LOCATION)) != null
281 .warn("Ignoring additional "
283 + " location(s) provided in response header ( next one is '"
284 + loc[1].getValue() + "' )");
286 rj.setJobId(loc[0].getValue());
287 rj.setSubmitted(true);
289 completeStatus(rj, response);
293 rj.setSubmitted(true);
294 rj.setAllowedServerExceptions(0);
295 rj.setSubjobComplete(true);
298 completeStatus(rj, response, "" + getStage(stg)
299 + "failed. Reason below:\n");
302 // Some other response. Probably need to pop up the content in a window.
303 // TODO: deal with all other HTTP response codes from server.
304 Cache.log.warn("Unhandled response status when " + getStage(stg)
305 + "for " + postUrl + ": " + response.getStatusLine());
308 response.getEntity().consumeContent();
309 } catch (IOException e)
311 Cache.log.debug("IOException when consuming unhandled response",
320 * job has completed. Something valid should be available from con
325 * is a stateless request - expected to return the same data
326 * regardless of how many times its called.
328 private void processResultSet(RestJob rj, HttpResponse con,
331 if (rj.statMessage == null)
335 rj.statMessage += "Job Complete.\n";
338 rj.resSet = new HttpResultSet(rj, con, req);
340 } catch (IOException e)
342 rj.statMessage += "Couldn't parse results. Failed.";
344 rj.gotresult = false;
348 private void completeStatus(RestJob rj, HttpResponse con)
351 completeStatus(rj, con, null);
355 private void completeStatus(RestJob rj, HttpResponse con, String prefix)
358 StringBuffer sb = new StringBuffer();
364 if (rj.statMessage != null && rj.statMessage.length() > 0)
366 sb.append(rj.statMessage);
368 HttpEntity en = con.getEntity();
370 * Just append the content as a string.
373 StringBuffer content = new StringBuffer(f = EntityUtils.toString(en));
375 int body = f.indexOf("<body");
378 content.delete(0, f.indexOf(">", body));
380 if (body > -1 && sb.length() > 0)
383 content.insert(0, sb);
387 rj.statMessage = content.toString();
391 public void pollJob(AWsJob job) throws Exception
393 assert (job instanceof RestJob);
394 System.err.println("Debug RestJob: Polling Job");
395 doPoll((RestJob) job);
399 public void StartJob(AWsJob job)
401 assert (job instanceof RestJob);
404 System.err.println("Debug RestJob: Posting Job");
405 doPost((RestJob) job);
406 } catch (Exception ex)
408 job.setSubjobComplete(true);
409 job.setAllowedServerExceptions(-1);
410 Cache.log.error("Exception when trying to start Rest Job.", ex);
415 public void parseResult()
417 // crazy users will see this message
418 // TODO: finish this! and remove the message below!
419 Cache.log.warn("Rest job result parser is currently INCOMPLETE!");
421 for (RestJob rj : (RestJob[]) jobs)
423 if (rj.hasResponse() && rj.resSet != null && rj.resSet.isValid())
428 Cache.log.debug("Parsing data for job " + rj.getJobId());
434 Cache.log.debug("Finished parsing data for job " + rj.getJobId());
438 Cache.log.warn("Failed to finish parsing data for job "
440 ex.printStackTrace();
441 } catch (Exception ex)
443 Cache.log.warn("Failed to finish parsing data for job "
445 ex.printStackTrace();
451 // add listeners and activate result display gui elements
453 * decisions based on job result content + state of alignFrame that
454 * originated the job:
457 * 1. Can/Should this job automatically open a new window for results
461 wsInfo.setViewResultsImmediatly(false);
465 // realiseResults(true, true);
467 // otherwise, should automatically view results
469 // TODO: check if at least one or more contexts are valid - if so, enable
471 wsInfo.showResultsNewFrame.addActionListener(new ActionListener()
475 public void actionPerformed(ActionEvent e)
477 realiseResults(false);
481 wsInfo.mergeResults.addActionListener(new ActionListener()
485 public void actionPerformed(ActionEvent e)
487 realiseResults(true);
492 wsInfo.setResultsReady();
496 // tell the user nothing was returned.
501 * instructions for whether to create new alignment view on current alignment
502 * set, add to current set, or create new alignFrame
504 private enum AddDataTo
507 * add annotation, trees etc to current view
511 * create a new view derived from current view and add data to that
515 * create a new alignment frame for the result set and add annotation to
521 public void realiseResults(boolean merge)
524 * 2. Should the job modify the parent alignment frame/view(s) (if they
525 * still exist and the alignment hasn't been edited) in order to display new
526 * annotation/features.
529 * alignment panels derived from each alignment set returned by service.
531 ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<jalview.gui.AlignmentPanel>();
533 * list of instructions for how to process each distinct alignment set
534 * returned by the job set
536 ArrayList<AddDataTo> resultDest = new ArrayList<AddDataTo>();
538 * when false, zeroth pane is panel derived from input deta.
540 boolean newAlignment = false;
542 * gap character to be used for alignment reconstruction
544 char gapCharacter = restClient.av.getGapCharacter();
545 // Now, iterate over all alignment sets returned from all jobs:
546 // first inspect jobs and collate results data in order to count alignments
548 // then assemble results from decomposed (v followed by h-separated) jobs
549 // finally, new views and alignments will be created and displayed as
551 boolean hsepjobs = restClient.service.isHseparable();
552 boolean vsepjobs = restClient.service.isVseparable();
553 // total number of distinct alignment sets generated by job set.
554 int numAlSets = 0, als = 0;
555 List<AlignmentI> destAls = new ArrayList<AlignmentI>();
556 List<jalview.datamodel.ColumnSelection> destColsel = new ArrayList<jalview.datamodel.ColumnSelection>();
557 List<List<NewickFile>> trees = new ArrayList<List<NewickFile>>();
562 // iterate over each alignment set returned from each subjob. Treating
563 // each one returned in parallel with others.
564 // Result collation arrays
567 * mapping between index of sequence in alignment that was submitted to
568 * server and index of sequence in the input alignment
570 int[][] ordermap = new int[jobs.length][];
571 SequenceI[][] rseqs = new SequenceI[jobs.length][];
572 AlignmentOrder[] orders = new AlignmentOrder[jobs.length];
573 AlignmentAnnotation[][] alan = new AlignmentAnnotation[jobs.length][];
574 SequenceGroup[][] sgrp = new SequenceGroup[jobs.length][];
575 // Now collect all data for alignment Set als from job array
576 for (int j = 0; j < jobs.length; j++)
578 RestJob rj = (RestJob) jobs[j];
581 JalviewDataset rset = rj.context;
582 if (rset.hasAlignments())
584 if (numAlSets < rset.getAl().size())
586 numAlSets = rset.getAl().size();
588 if (als < rset.getAl().size()
589 && rset.getAl().get(als).isModified())
591 // Collate result data
592 // TODO: decide if all alignmentI should be collected rather than
593 // specific alignment data containers
594 // for moment, we just extract content, but this means any
595 // alignment properties may be lost.
596 AlignmentSet alset = rset.getAl().get(als);
597 alan[j] = alset.al.getAlignmentAnnotation();
598 if (alset.al.getGroups() != null)
600 sgrp[j] = new SequenceGroup[alset.al.getGroups().size()];
601 alset.al.getGroups().toArray(sgrp[j]);
607 orders[j] = new AlignmentOrder(alset.al);
608 rseqs[j] = alset.al.getSequencesArray();
609 ordermap[j] = rj.getOrderMap();
610 // if (rj.isInputUniquified()) {
611 // jalview.analysis.AlignmentSorter.recoverOrder(rseqs[als]);
614 if (alset.trees != null)
616 trees.add(new ArrayList<NewickFile>(alset.trees));
620 trees.add(new ArrayList<NewickFile>());
626 // Now aggregate and present results from this frame of alignment data.
627 int nvertsep = 0, nvertseps = 1;
630 // Jobs relate to different rows of input alignment.
631 // Jobs are subdivided by rows before columns,
632 // so there will now be a number of subjobs according tohsep for each
634 // TODO: get vertical separation intervals for each job and set
636 // TODO: merge data from each group/sequence onto whole
640 * index into rest jobs subdivided vertically
643 // Destination alignments for all result data.
644 ArrayList<SequenceGroup> visgrps = new ArrayList<SequenceGroup>();
645 Hashtable<String, SequenceGroup> groupNames = new Hashtable<String, SequenceGroup>();
646 ArrayList<AlignmentAnnotation> visAlAn = null;
647 for (nvertsep = 0; nvertsep < nvertseps; nvertsep++)
649 // TODO: set scope w.r.t. original alignment view for vertical
652 // results for a job exclude hidden columns of input data, so map
653 // back on to all visible regions
655 * rest job result we are working with
659 RestJob rj = (RestJob) jobs[nrj];
660 int contigs[] = input.getVisibleContigs();
661 AlignmentI destAl = null;
662 jalview.datamodel.ColumnSelection destCs = null;
663 // Resolve destAl for this data.
664 if (als == 0 && rj.isInputContextModified())
666 // special case: transfer features, annotation, groups, etc,
668 // context to align panel derived from input data
669 if (destAls.size() > als)
671 destAl = destAls.get(als);
675 if (!restClient.isAlignmentModified() && merge)
677 destAl = restClient.av.getAlignment();
678 destCs = restClient.av.getColumnSelection();
680 .add(restClient.isShowResultsInNewView() ? AddDataTo.newView
681 : AddDataTo.currentView);
682 destPanels.add(restClient.recoverAlignPanelForView());
687 // recreate the input alignment data
688 Object[] idat = input
689 .getAlignmentAndColumnSelection(gapCharacter);
690 destAl = new Alignment((SequenceI[]) idat[0]);
691 destCs = (ColumnSelection) idat[1];
692 resultDest.add(AddDataTo.newAlignment);
693 // but do not add to the alignment panel list - since we need to
694 // create a whole new alignFrame set.
697 destColsel.add(destCs);
702 // alignment(s) returned by service is to be re-integrated and
704 if (destAls.size() > als)
708 // TODO: decide if multiple multiple alignments returned by
709 // non-vseparable services are allowed.
711 .warn("dealing with multiple alignment products returned by non-vertically separable service.");
713 // recover reference to last alignment created for this rest frame
714 // ready for extension
715 destAl = destAls.get(als);
716 destCs = destColsel.get(als);
724 // single alignment for any job that gets mapped back on to
725 // input data. Reconstruct by interleaving parts of returned
726 // alignment with hidden parts of input data.
727 SequenceI[][] nsq = splitSeqsOnVisibleContigs(rseqs[nrj],
728 contigs, gapCharacter);
729 AlignmentOrder alo[] = new AlignmentOrder[nsq.length];
730 for (int no = 0; no < alo.length; no++)
732 alo[no] = new AlignmentOrder(orders[nrj].getOrder());
734 newview = input.getUpdatedView(nsq, orders, gapCharacter);
738 // each job maps to a single visible contig, and all need to be
739 // stitched back together.
740 // reconstruct using sub-region based MSA alignment construction
742 newview = input.getUpdatedView(rseqs, orders, gapCharacter);
744 destAl = new Alignment((SequenceI[]) newview[0]);
745 destCs = (ColumnSelection) newview[1];
747 // TODO create alignment from result data with propagated
750 destColsel.add(destCs);
751 resultDest.add(AddDataTo.newAlignment);
752 throw new Error("Impl. Error! TODO: ");
756 * save initial job in this set in case alignment is h-separable
760 for (int ncnt = 0; ncnt < contigs.length; ncnt += 2)
764 // single alignment for any job that gets mapped back on to input
769 // each job maps to a single visible contig, and all need to be
770 // stitched back together.
775 // TODO: apply options for group merging and annotation merging.
776 // If merging not supported, then either clear hashtables now or
777 // use them to rename the new annotation/groups for each contig if
778 // a conflict occurs.
780 if (sgrp[nrj] != null)
782 for (SequenceGroup sg : sgrp[nrj])
784 boolean recovered = false;
785 SequenceGroup exsg = null;
786 if (sg.getName() != null)
788 exsg = groupNames.get(sg.getName());
793 exsg = new SequenceGroup(sg);
794 groupNames.put(exsg.getName(), exsg);
796 exsg.setStartRes(sg.getStartRes() + contigs[ncnt]);
797 exsg.setEndRes(sg.getEndRes() + contigs[ncnt]);
799 // now replace any references from the result set with
800 // corresponding refs from alignment input set.
802 // TODO: cope with recovering hidden sequences from
805 Vector sqs = sg.getSequences(null);
806 for (int sqsi = 0, iSize = sqs.size(); sqsi < iSize; sqsi++)
808 SequenceI oseq = (SequenceI) sqs.get(sqsi);
809 SequenceI nseq = getNewSeq(oseq, rseqs[nrj],
810 ordermap[nrj], destAl);
815 exsg.deleteSequence(oseq, false);
817 exsg.addSequence(nseq, false);
822 .warn("Couldn't resolve original sequence for new sequence.");
827 if (exsg.getSeqrep() == sg.getSeqrep())
829 // lift over sequence rep reference too
830 SequenceI oseq = sg.getSeqrep();
831 SequenceI nseq = getNewSeq(oseq, rseqs[nrj],
832 ordermap[nrj], destAl);
835 exsg.setSeqrep(nseq);
842 // adjust boundaries of recovered group w.r.t. new group being
843 // merged on to original alignment.
844 int start = sg.getStartRes() + contigs[ncnt], end = sg
845 .getEndRes() + contigs[ncnt];
846 if (start < exsg.getStartRes())
848 exsg.setStartRes(start);
850 if (end > exsg.getEndRes())
860 // and finally add in annotation and any trees for each job
861 for (int ncnt = 0; ncnt < contigs.length; ncnt += 2)
865 // single alignment for any job that gets mapped back on to input
870 // each job maps to a single visible contig, and all need to be
871 // stitched back together.
878 // merge alignmentAnnotation into one row
879 if (alan[nrj] != null)
881 for (int an = 0; an < alan[nrj].length; an++)
883 SequenceI sqass = null;
884 SequenceGroup grass = null;
885 if (alan[nrj][an].sequenceRef != null)
887 // TODO: ensure this relocates sequence reference to local
889 sqass = getNewSeq(alan[nrj][an].sequenceRef, rseqs[nrj],
890 ordermap[nrj], destAl);
892 if (alan[nrj][an].groupRef != null)
894 // TODO: verify relocate group reference to local context
896 grass = groupNames.get(alan[nrj][an].groupRef.getName());
900 .error("Couldn't relocate group referemce for group "
901 + alan[nrj][an].groupRef.getName());
906 visAlAn = new ArrayList<AlignmentAnnotation>();
908 AlignmentAnnotation visan = null;
909 for (AlignmentAnnotation v : visAlAn)
912 && v.label.equals(alan[nrj][an].label))
919 visan = new AlignmentAnnotation(alan[nrj][an]);
920 // copy annotations, and wipe out/update refs.
921 visan.annotations = new Annotation[input.getWidth()];
922 visan.groupRef = grass;
923 visan.sequenceRef = sqass;
926 // now copy local annotation data into correct position
927 System.arraycopy(alan[nrj][an].annotations, 0,
928 visan.annotations, contigs[ncnt],
929 alan[nrj][an].annotations.length);
934 if (trees.get(nrj).size() > 0)
936 for (NewickFile nf : trees.get(nrj))
938 // TODO: process each newick file, lifting over sequence refs to
939 // current alignment, if necessary.
941 .error("Tree recovery from restjob not yet implemented.");
946 } // end of vseps loops.
949 for (AlignmentAnnotation v : visAlAn)
951 destAls.get(als).addAnnotation(v);
956 for (SequenceGroup sg : visgrps)
958 destAls.get(als).addGroup(sg);
961 } while (++als < numAlSets);
962 // Finally, assemble each new alignment, and create new gui components to
965 * current AlignFrame where results will go.
967 AlignFrame destaf = restClient.recoverAlignFrameForView();
969 * current pane being worked with
971 jalview.gui.AlignmentPanel destPanel = restClient
972 .recoverAlignPanelForView();
974 for (AddDataTo action : resultDest)
977 ColumnSelection destcs;
978 String alTitle = restClient.service.details.Action + " using "
979 + restClient.service.details.Name + " on "
980 + " whatever you clicked on." + "(set " + als + ")";
984 destal = destAls.get(als);
985 destcs = destColsel.get(als);
986 destaf = new AlignFrame(destal, destcs, AlignFrame.DEFAULT_WIDTH,
987 AlignFrame.DEFAULT_HEIGHT);
988 // todo transfer any feature settings and colouring
990 * destaf.getFeatureRenderer().transferSettings(this.featureSettings);
991 * // update orders if (alorders.size() > 0) { if (alorders.size() == 1)
992 * { af.addSortByOrderMenuItem(WebServiceName + " Ordering",
993 * (AlignmentOrder) alorders.get(0)); } else { // construct a
994 * non-redundant ordering set Vector names = new Vector(); for (int i =
995 * 0, l = alorders.size(); i < l; i++) { String orderName = new
996 * String(" Region " + i); int j = i + 1;
998 * while (j < l) { if (((AlignmentOrder) alorders.get(i))
999 * .equals(((AlignmentOrder) alorders.get(j)))) { alorders.remove(j);
1000 * l--; orderName += "," + j; } else { j++; } }
1002 * if (i == 0 && j == 1) { names.add(new String("")); } else {
1003 * names.add(orderName); } } for (int i = 0, l = alorders.size(); i < l;
1004 * i++) { af.addSortByOrderMenuItem( WebServiceName + ((String)
1005 * names.get(i)) + " Ordering", (AlignmentOrder) alorders.get(i)); } } }
1007 Desktop.addInternalFrame(destaf, alTitle, AlignFrame.DEFAULT_WIDTH,
1008 AlignFrame.DEFAULT_HEIGHT);
1020 if (restClient.isShowResultsInNewView())
1022 // destPanel = destPanel.alignFrame.newView(false);
1030 * if (als) // add the destination panel to frame zero of result panel set }
1031 * } if (destPanels.size()==0) { AlignFrame af = new AlignFrame((AlignmentI)
1032 * idat[0], (ColumnSelection) idat[1], AlignFrame.DEFAULT_WIDTH,
1033 * AlignFrame.DEFAULT_HEIGHT);
1035 * jalview.gui.Desktop.addInternalFrame(af, "Results for " +
1036 * restClient.service.details.Name + " " + restClient.service.details.Action
1037 * + " on " + restClient.af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1038 * AlignFrame.DEFAULT_HEIGHT); destPanel = af.alignPanel; // create totally
1039 * new alignment from stashed data/results
1046 * alignments. New alignments are added to dataset, and subsequently
1047 * annotated/visualised accordingly. 1. New alignment frame created for new
1048 * alignment. Decide if any vis settings should be inherited from old
1049 * alignment frame (e.g. sequence ordering ?). 2. Subsequent data added to
1050 * alignment as below:
1053 * annotation update to original/newly created context alignment: 1.
1054 * identify alignment where annotation is to be loaded onto. 2. Add
1055 * annotation, excluding any duplicates. 3. Ensure annotation is visible on
1056 * alignment - honouring ordering given by file.
1059 * features updated to original or newly created context alignment: 1.
1060 * Features are(or were already) added to dataset. 2. Feature settings
1061 * modified to ensure all features are displayed - honouring any ordering
1062 * given by result file. Consider merging action with the code used by the
1063 * DAS fetcher to update alignment views with new info.
1066 * Seq associated data files (PDB files). 1. locate seq association in
1067 * current dataset/alignment context and add file as normal - keep handle of
1068 * any created ref objects. 2. decide if new data should be displayed : PDB
1069 * display: if alignment has PDB display already, should new pdb files be
1073 // destPanel.adjustAnnotationHeight();
1078 * split the given array of sequences into blocks of subsequences
1079 * corresponding to each visible contig
1084 * padding character for ragged ends of visible contig region.
1087 private SequenceI[][] splitSeqsOnVisibleContigs(SequenceI[] sequenceIs,
1088 int[] contigs, char gapChar)
1090 int nvc = contigs == null ? 1 : contigs.length / 2;
1091 SequenceI[][] blocks = new SequenceI[nvc][];
1092 if (contigs == null)
1094 blocks[0] = new SequenceI[sequenceIs.length];
1095 System.arraycopy(sequenceIs, 0, blocks[0], 0, sequenceIs.length);
1099 // deja vu - have I written this before ?? propagateGaps does this in a
1101 char[] gapset = null;
1102 int start = 0, width = 0;
1103 for (int c = 0; c < nvc; c++)
1105 width = contigs[c * 2 + 1] - contigs[c * 2] + 1;
1106 for (int s = 0; s < sequenceIs.length; s++)
1108 int end = sequenceIs[s].getLength();
1111 if (start + width < end)
1113 blocks[c][s] = sequenceIs[s].getSubSequence(start, start
1118 blocks[c][s] = sequenceIs[s].getSubSequence(start, end);
1119 String sq = blocks[c][s].getSequenceAsString();
1120 for (int n = start + width; n > end; n--)
1128 if (gapset == null || gapset.length < width)
1130 char ng[] = new char[width];
1134 System.arraycopy(gapset, 0, ng, 0, gs = gapset.length);
1136 while (gs < ng.length)
1141 blocks[c][s] = sequenceIs[s].getSubSequence(end, end);
1142 blocks[c][s].setSequence(gapset.toString().substring(0, width));
1147 // adjust window for next visible segnment
1148 start += contigs[c * 2 + 1] - contigs[c * 2];
1156 * recover corresponding sequence from original input data corresponding to
1157 * sequence in a specific job's input data.
1165 private SequenceI getNewSeq(SequenceI oseq, SequenceI[] sequenceIs,
1166 int[] is, AlignmentI destAl)
1169 while (p < sequenceIs.length && sequenceIs[p] != oseq)
1173 if (p < sequenceIs.length && p < destAl.getHeight())
1175 return destAl.getSequenceAt(is[p]);
1182 * @return true if the run method is safe to call
1184 public boolean isValid()
1188 for (RestJob rj : (RestJob[]) jobs)
1190 if (!rj.hasValidInput())
1192 // invalid input for this job
1193 System.err.println("Job " + rj.getJobnum()
1194 + " has invalid input.");
1200 // TODO Auto-generated method stub