From 4eefb40838faa0a3c03be3480ff74ba2ac67a5c1 Mon Sep 17 00:00:00 2001 From: jprocter Date: Fri, 11 Aug 2006 17:30:22 +0000 Subject: [PATCH] multiple web service jobs from visible blocks of an alignment. --- src/jalview/datamodel/AlignmentOrder.java | 14 +- src/jalview/datamodel/AlignmentView.java | 14 + src/jalview/gui/WebserviceInfo.java | 145 +++++- src/jalview/jbgui/GWebserviceInfo.java | 11 - src/jalview/ws/Discoverer.java | 7 + src/jalview/ws/MsaWSClient.java | 401 +---------------- src/jalview/ws/MsaWSThread.java | 686 +++++++++++++++++++++++++++++ 7 files changed, 860 insertions(+), 418 deletions(-) create mode 100644 src/jalview/ws/MsaWSThread.java diff --git a/src/jalview/datamodel/AlignmentOrder.java b/src/jalview/datamodel/AlignmentOrder.java index 1fa3b96..231009a 100755 --- a/src/jalview/datamodel/AlignmentOrder.java +++ b/src/jalview/datamodel/AlignmentOrder.java @@ -167,7 +167,19 @@ public class AlignmentOrder { return Order; } - + /** + * replaces oldref with newref in the alignment order. + * @param oldref + * @param newref + * @return + */ + public boolean updateSequence(SequenceI oldref, SequenceI newref) { + int found=Order.indexOf(oldref); + if (found>-1) { + Order.setElementAt(newref, found); + } + return found>-1; + } /** * AlignmentOrder * diff --git a/src/jalview/datamodel/AlignmentView.java b/src/jalview/datamodel/AlignmentView.java index 727bc76..3524942 100644 --- a/src/jalview/datamodel/AlignmentView.java +++ b/src/jalview/datamodel/AlignmentView.java @@ -19,6 +19,7 @@ public class AlignmentView */ private SeqCigar[] sequences = null; private int[] contigs = null; + private int width=0; public AlignmentView(CigarArray seqcigararray) { if (!seqcigararray.isSeqCigarArray()) @@ -26,6 +27,7 @@ public class AlignmentView //contigs = seqcigararray.applyDeletions(); contigs = seqcigararray.getDeletedRegions(); sequences = seqcigararray.getSeqCigarArray(); + width = seqcigararray.getWidth(); // visible width } public void setSequences(SeqCigar[] sequences) @@ -66,4 +68,16 @@ public class AlignmentView } return seqs; } + /** + * + * @return visible number of columns in alignment view + */ + public int getWidth() { + return width; + } + + protected void setWidth(int width) { + this.width = width; + } + } diff --git a/src/jalview/gui/WebserviceInfo.java b/src/jalview/gui/WebserviceInfo.java index 9dadee7..63ef9f0 100755 --- a/src/jalview/gui/WebserviceInfo.java +++ b/src/jalview/gui/WebserviceInfo.java @@ -18,14 +18,15 @@ */ package jalview.gui; -import jalview.jbgui.*; +import java.util.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; - import javax.swing.*; +import jalview.jbgui.*; + /** * Base class for web service client thread and gui @@ -35,6 +36,7 @@ import javax.swing.*; */ public class WebserviceInfo extends GWebserviceInfo { + /** Job is Queued */ public static final int STATE_QUEUING = 0; @@ -59,7 +61,43 @@ public class WebserviceInfo extends GWebserviceInfo jalview.ws.WSClientI thisService; boolean serviceIsCancellable; JInternalFrame frame; - + JTabbedPane subjobs=null; + java.util.Vector jobPanes = null; + // tabbed or not + public synchronized int addJobPane() { + JScrollPane jobpane = new JScrollPane(); + JTextArea progressText = new JTextArea(); + progressText.setFont(new java.awt.Font("Verdana", 0, 10)); + progressText.setBorder(null); + progressText.setEditable(false); + progressText.setText("WS Job"); + progressText.setLineWrap(true); + progressText.setWrapStyleWord(true); + jobpane.setName("JobPane"); + jobpane.getViewport().add(progressText, null); + jobpane.setBorder(null); + if (jobPanes==null) { + jobPanes = new Vector(); + } + int newpane = jobPanes.size(); + jobPanes.add(jobpane); + + if (newpane==0) { + this.add(jobpane, BorderLayout.CENTER); + } else { + if (newpane==1) { + // revert to a tabbed pane. + JScrollPane firstpane; + this.remove(firstpane=(JScrollPane) jobPanes.get(0)); + subjobs=new JTabbedPane(); + this.add(subjobs, BorderLayout.CENTER); + subjobs.add(firstpane); + subjobs.setTitleAt(0, firstpane.getName()); + } + subjobs.add(jobpane); + } + return newpane; // index for accessor methods below + } /** * Creates a new WebserviceInfo object. * @@ -153,7 +191,38 @@ public class WebserviceInfo extends GWebserviceInfo { currentStatus = status; } - + /** + * subjob status indicator + * @param jobpane + * @param status + */ + public void setStatus(int jobpane, int status) { + if (jobpane<0 || jobpane>=jobPanes.size()) { + throw new Error("setStatus called for non-existent job pane."+jobpane); + } + switch (status) { + case STATE_QUEUING: + setProgressText(jobpane, "QUEUED"); + break; + case STATE_RUNNING: + setProgressText(jobpane, "RUNNING"); + break; + case STATE_STOPPED_OK: + setProgressText(jobpane, "FINISHED"); + break; + case STATE_CANCELLED_OK: + setProgressText(jobpane, "CANCELLED"); + break; + case STATE_STOPPED_ERROR: + setProgressText(jobpane, "BROKEN"); + break; + case STATE_STOPPED_SERVERERROR: + setProgressText(jobpane, "ALERT"); + break; + default: + setProgressText(jobpane, "UNKNOWN STATE"); + } + } /** * DOCUMENT ME! * @@ -183,25 +252,29 @@ public class WebserviceInfo extends GWebserviceInfo { infoText.append(text); } - /** * DOCUMENT ME! * * @return DOCUMENT ME! */ - public String getProgressText() + public String getProgressText(int which) { - return progressText.getText(); + if (jobPanes == null) + addJobPane(); + return ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport(). + getComponent(0)).getText(); } - /** * DOCUMENT ME! * * @param text DOCUMENT ME! */ - public void setProgressText(String text) + public void setProgressText(int which, String text) { - progressText.setText(text); + if (jobPanes == null) + addJobPane(); + ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport(). + getComponent(0)).setText(text); } /** @@ -209,9 +282,57 @@ public class WebserviceInfo extends GWebserviceInfo * * @param text DOCUMENT ME! */ + public void appendProgressText(int which, String text) + { + if (jobPanes == null) + addJobPane(); + ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport(). + getComponent(0)).append(text); + } + /** + * setProgressText(0, text) + */ + public void setProgressText(String text) + { + setProgressText(0, text); + } + /** + * appendProgressText(0, text) + */ public void appendProgressText(String text) { - progressText.append(text); + appendProgressText(0, text); + } + /** + * getProgressText(0) + */ + public String getProgressText() + { + return getProgressText(0); + } + /** + * get the tab title for a subjob + * @param which int + * @return String + */ + public String getProgressName(int which) { + if (jobPanes==null) + addJobPane(); + if (subjobs!=null) + return subjobs.getTitleAt(which); + else + return ((JScrollPane) jobPanes.get(which)).getViewport().getComponent(0).getName(); + } + /** + * set the tab title for a subjob + * @param name String + * @param which int + */ + public void setProgressName(String name, int which) { + if (subjobs!=null) + subjobs.setTitleAt(which, name); + else + ((JScrollPane) jobPanes.get(which)).getViewport().getComponent(0).setName(name); } /** @@ -246,7 +367,7 @@ public class WebserviceInfo extends GWebserviceInfo } - class AnimatedPanel extends JPanel implements Runnable + class AnimatedPanel extends JPanel implements Runnable { long startTime = 0; BufferedImage offscreen; diff --git a/src/jalview/jbgui/GWebserviceInfo.java b/src/jalview/jbgui/GWebserviceInfo.java index e5a163c..3dfb905 100755 --- a/src/jalview/jbgui/GWebserviceInfo.java +++ b/src/jalview/jbgui/GWebserviceInfo.java @@ -33,8 +33,6 @@ public class GWebserviceInfo extends JPanel { protected JTextArea infoText = new JTextArea(); JScrollPane jScrollPane1 = new JScrollPane(); - JScrollPane jScrollPane2 = new JScrollPane(); - protected JTextArea progressText = new JTextArea(); JPanel jPanel1 = new JPanel(); BorderLayout borderLayout1 = new BorderLayout(); BorderLayout borderLayout2 = new BorderLayout(); @@ -74,17 +72,10 @@ public class GWebserviceInfo extends JPanel infoText.setLineWrap(true); infoText.setWrapStyleWord(true); this.setLayout(borderLayout1); - progressText.setFont(new java.awt.Font("Verdana", 0, 10)); - progressText.setBorder(null); - progressText.setEditable(false); - progressText.setText(""); - progressText.setLineWrap(true); - progressText.setWrapStyleWord(true); jPanel1.setLayout(borderLayout2); titlePanel.setBackground(Color.white); titlePanel.setPreferredSize(new Dimension(0, 60)); titlePanel.setLayout(borderLayout3); - jScrollPane2.setBorder(null); jScrollPane1.setBorder(null); jScrollPane1.setPreferredSize(new Dimension(400, 70)); cancel.setFont(new java.awt.Font("Verdana", 0, 11)); @@ -100,11 +91,9 @@ public class GWebserviceInfo extends JPanel buttonPanel.setOpaque(false); showResultsNewFrame.setText("New Frame"); mergeResults.setText("Merge Results"); - this.add(jScrollPane2, BorderLayout.CENTER); this.add(jPanel1, BorderLayout.NORTH); jPanel1.add(jScrollPane1, BorderLayout.CENTER); jScrollPane1.getViewport().add(infoText, null); - jScrollPane2.getViewport().add(progressText, null); jPanel1.add(titlePanel, BorderLayout.NORTH); titlePanel.add(buttonPanel, BorderLayout.EAST); buttonPanel.add(cancel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0 diff --git a/src/jalview/ws/Discoverer.java b/src/jalview/ws/Discoverer.java index f30cced..bf08dcd 100755 --- a/src/jalview/ws/Discoverer.java +++ b/src/jalview/ws/Discoverer.java @@ -174,6 +174,13 @@ public class Discoverer ), new ServiceHandle( "MsaWS", + "Katoh, K., K. Kuma, K., Toh, H., and Miyata, T. (2005) "+ + "\"MAFFT version 5: improvement in accuracy of multiple sequence alignment.\""+ + " Nucleic Acids Research, 33 511-518", + "http://www.compbio.dundee.ac.uk/JalviewWS/services/MafftWS", + "MAFFT Multiple Sequence Alignment"), + new ServiceHandle( + "MsaWS", "Thompson, J.D., Higgins, D.G. and Gibson, T.J. (1994) CLUSTAL W: improving the sensitivity of progressive multiple" + " sequence alignment through sequence weighting, position specific gap penalties and weight matrix choice." + " Nucleic Acids Research, 22 4673-4680", diff --git a/src/jalview/ws/MsaWSClient.java b/src/jalview/ws/MsaWSClient.java index 49c879b..eda71f5 100755 --- a/src/jalview/ws/MsaWSClient.java +++ b/src/jalview/ws/MsaWSClient.java @@ -37,7 +37,7 @@ import javax.swing.*; * @version $Revision$ */ public class MsaWSClient - extends WSClient + extends WSClient { /** * server is a WSDL2Java generated stub for an archetypal MsaWSI service. @@ -63,7 +63,7 @@ public class MsaWSClient Alignment seqdataset, AlignFrame _alignFrame) { - + super(); alignFrame = _alignFrame; if (!sh.getAbstractName().equals("MsaWS")) { @@ -76,7 +76,7 @@ public class MsaWSClient return; } - if ((wsInfo = this.setWebService(sh))==null) + if ((wsInfo = setWebService(sh))==null) { JOptionPane.showMessageDialog(Desktop.desktop, "The Multiple Sequence Alignment Service named " + @@ -102,8 +102,10 @@ public class MsaWSClient wsInfo.setProgressText( ( (submitGaps) ? "Re-alignment" : "Alignment") + " of " + altitle + "\nJob details\n"); - MsaWSThread musclethread = new MsaWSThread(WebServiceName + - " alignment of " + altitle, msa, + MsaWSThread musclethread = new MsaWSThread(server, WsURL, wsInfo, alignFrame, + WebServiceName, + WebServiceName+" alignment of " + altitle, + msa, submitGaps, preserveOrder, seqdataset); wsInfo.setthisService(musclethread); musclethread.start(); @@ -150,393 +152,4 @@ public class MsaWSClient { return "Multiple Sequence Alignment"; } - - protected class MsaWSThread - extends Thread implements WSClientI - { - String ServiceName = WebServiceName; - String OutputHeader; - vamsas.objects.simple.MsaResult result = null; - vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple. - SequenceSet(); - Hashtable SeqNames = null; - boolean submitGaps = false; // pass sequences including gaps to alignment service - boolean preserveOrder = true; // and always store and recover sequence order - String jobId; - String alTitle; // name which will be used to form new alignment window. - int allowedServerExceptions = 3; // thread dies if too many exceptions. - boolean jobComplete = false; - - Alignment dataset; // dataset to which the new alignment will be associated. - - MsaWSThread(String title, AlignmentView _msa, boolean subgaps, - boolean presorder, Alignment seqset) - { - // jbpnote - transformation should be above here - this is per sequence set contig, not for many contigs. - alTitle = title; - submitGaps = subgaps; - preserveOrder = presorder; - dataset = seqset; - OutputHeader = wsInfo.getProgressText(); - SeqNames = new Hashtable(); - SeqCigar[] msa = _msa.getSequences(); - vamsas.objects.simple.Sequence[] seqarray = new vamsas.objects.simple. - Sequence[msa.length]; - - for (int i = 0,n=0; i < msa.length; i++) - { - String newname = jalview.analysis.SeqsetUtils.unique_name(i); - SequenceI mseq = msa[i].getSeq('-'); - // uniquify as we go - // TODO: JBPNote: this is a ubiquitous transformation - set of jalview seq objects to vamsas sequences with name preservation - SeqNames.put(newname, - jalview.analysis.SeqsetUtils.SeqCharacterHash(mseq)); - seqarray[i] = new vamsas.objects.simple.Sequence(); - seqarray[i].setId(newname); - seqarray[i].setSeq( (submitGaps) ? mseq.getSequence() - : AlignSeq.extractGaps( - jalview.util.Comparison.GapChars, - mseq.getSequence())); - } - - this.seqs = new vamsas.objects.simple.SequenceSet(); - this.seqs.setSeqs(seqarray); - } - - public boolean isCancellable() - { - return true; - } - - public void cancelJob() - { - if ( (jobId != null) && !jobId.equals("") && !jobComplete) - { - String cancelledMessage = ""; - - try - { - vamsas.objects.simple.WsJobId cancelledJob = server.cancel(jobId); - - if (cancelledJob.getStatus() == 2) - { - // CANCELLED_JOB - cancelledMessage = "Job cancelled."; - wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK); - jobComplete = true; - jobsRunning--; - result = null; - } - else if (cancelledJob.getStatus() == 3) - { - // VALID UNSTOPPABLE JOB - cancelledMessage += - "Server cannot cancel this job. just close the window.\n"; - } - - if (cancelledJob.getJobId() != null) - { - cancelledMessage += ("[" + cancelledJob.getJobId() + - "]"); - } - - cancelledMessage += "\n"; - } - catch (Exception exc) - { - cancelledMessage += - ("\nProblems cancelling the job : Exception received...\n" + - exc + "\n"); - exc.printStackTrace(); - } - - wsInfo.setProgressText(OutputHeader + cancelledMessage + "\n"); - } - else - { - if (!jobComplete) - { - wsInfo.setProgressText(OutputHeader + - "Server cannot cancel this job because it has not been submitted properly. just close the window.\n"); - } - } - } - - public void run() - { - StartJob(); - - while (!jobComplete && (allowedServerExceptions > 0)) - { - try - { - if ( (result = server.getResult(jobId)) == null) - { - throw (new Exception( - "Timed out when communicating with server\nTry again later.\n")); - } - jalview.bin.Cache.log.debug("Result state " + result.getState() + - "(ServerError=" + result.isServerError() + - ")"); - if (result.isRunning()) - { - wsInfo.setStatus(WebserviceInfo.STATE_RUNNING); - } - else if (result.isQueued()) - { - wsInfo.setStatus(WebserviceInfo.STATE_QUEUING); - } - - if (result.isFinished()) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); - wsInfo.showResultsNewFrame.addActionListener(new java.awt.event.ActionListener() - { - public void actionPerformed(java.awt.event.ActionEvent evt) - { - displayResults(true); - } - }); - wsInfo.mergeResults.addActionListener(new java.awt.event.ActionListener() - { - public void actionPerformed(java.awt.event.ActionEvent evt) - { - displayResults(false); - } - }); - wsInfo.setResultsReady(); - parseResult(); - jobComplete = true; - jobsRunning--; - } - else - { - if (result.getStatus() != null) - { - wsInfo.setProgressText(OutputHeader + "\n"+ result.getStatus()); - } - if (result.isServerError()) - { - jobComplete = true; - jobsRunning--; - - break; - } - if (! (result.isJobFailed() || result.isServerError() || - result.isBroken() || result.isFailed())) - { - Thread.sleep(5000); - - // System.out.println("I'm alive "+seqid+" "+jobid); - } - else - { - jobComplete = true; - jobsRunning--; - break; - } - } - } - catch (Exception ex) - { - allowedServerExceptions--; - wsInfo.appendProgressText("\n" + ServiceName + - " Server exception!\n" + ex.getMessage()); - System.err.println(ServiceName + " Server exception: " + - ex.getMessage()); - - // ex.printStackTrace(); JBPNote Debug - try - { - if (allowedServerExceptions > 0) - { - Thread.sleep(5000); - } - } - catch (InterruptedException ex1) - { - } - } - catch(OutOfMemoryError er) - { - jobComplete = true; - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); - JOptionPane.showInternalMessageDialog(Desktop.desktop, - "Out of memory handling result!!" - +"\nSee help files for increasing Java Virtual Machine memory." - ,"Out of memory", JOptionPane.WARNING_MESSAGE ); - System.out.println("MsaWSClient: "+er); - System.gc(); - } - } - - if (allowedServerExceptions == 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); - } - else - { - if (result != null) - { - if ( !(result.isJobFailed() || result.isServerError())) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); - } - - if (result.isBroken() || result.isFailed()) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); - } - - if (result.isServerError()) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); - } - } - } - } - - void StartJob() - { - try - { - vamsas.objects.simple.WsJobId jobsubmit = server.align(seqs); - - if ( (jobsubmit != null) && (jobsubmit.getStatus() == 1)) - { - jobId = jobsubmit.getJobId(); - System.out.println(WsURL + " Job Id '" + jobId + "'"); - } - else - { - if (jobsubmit == null) - { - throw new Exception("Server at " + WsURL + - " returned null object, it probably cannot be contacted. Try again later ?"); - } - - throw new Exception(jobsubmit.getJobId()); - } - } - catch (Exception e) - { - // TODO: JBPNote catch timeout or other fault types explicitly - // For unexpected errors - System.err.println(WebServiceName + - "Client: Failed to submit the sequences for alignment (probably a server side problem)\n" + - "When contacting Server:" + WsURL + "\n" + - e.toString() + - "\n"); - this.allowedServerExceptions = 0; - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); - wsInfo.appendProgressText( - "Failed to submit sequences for alignment.\n" + - "It is most likely that there is a problem with the server.\n" + - "Just close the window\n"); - - // e.printStackTrace(); // TODO: JBPNote DEBUG - } - } - - private jalview.datamodel.Sequence[] getVamsasAlignment( - vamsas.objects.simple.Alignment valign) - { - vamsas.objects.simple.Sequence[] seqs = valign.getSeqs().getSeqs(); - jalview.datamodel.Sequence[] msa = new jalview.datamodel.Sequence[seqs. - length]; - - for (int i = 0, j = seqs.length; i < j; i++) - { - msa[i] = new jalview.datamodel.Sequence(seqs[i].getId(), - seqs[i].getSeq()); - } - - return msa; - } - - void parseResult() - { - - try - { - // OutputHeader = output.getText(); - if (result.isFailed()) - { - OutputHeader += "Job failed.\n"; - } - - if (result.getStatus() != null) - { - OutputHeader += ("\n" + result.getStatus()); - } - - if (result.getMsa() != null) - { - OutputHeader += "\nAlignment Object Method Notes\n"; - - String[] lines = result.getMsa().getMethod(); - - for (int line = 0; line < lines.length; line++) - { - OutputHeader += (lines[line] + "\n"); - } - - // JBPNote The returned files from a webservice could be - // hidden behind icons in the monitor window that, - // when clicked, pop up their corresponding data - } - - wsInfo.setProgressText(OutputHeader); - } - catch (Exception ex) - { - ex.printStackTrace(); - } - } - - void displayResults(boolean newFrame) - { - SequenceI [] seqs = getVamsasAlignment(result.getMsa()); - - if (seqs != null) - { - AlignmentOrder msaorder = new AlignmentOrder(seqs); - - if (preserveOrder) - { - jalview.analysis.AlignmentSorter.recoverOrder(seqs); - } - - jalview.analysis.SeqsetUtils.deuniquify(SeqNames, seqs); - - Alignment al = new Alignment(seqs); - if (dataset!=null) - { - al.setDataset(dataset); - } - - if(newFrame) - { - // TODO: JBPNote Should also rename the query sequence sometime... - AlignFrame af = new AlignFrame(al); - - //>>>This is a fix for the moment, until a better solution is found!!<<< - af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer()); - - af.addSortByOrderMenuItem(ServiceName + " Ordering", - msaorder); - - Desktop.addInternalFrame(af, alTitle, - AlignFrame.NEW_WINDOW_WIDTH, - AlignFrame.NEW_WINDOW_HEIGHT); - - } - else - { - System.out.println("MERGE WITH OLD FRAME"); - - } - } - } - } } diff --git a/src/jalview/ws/MsaWSThread.java b/src/jalview/ws/MsaWSThread.java new file mode 100644 index 0000000..b8912e2 --- /dev/null +++ b/src/jalview/ws/MsaWSThread.java @@ -0,0 +1,686 @@ +package jalview.ws; + +import jalview.datamodel.AlignmentView; +import jalview.datamodel.AlignmentOrder; +import jalview.datamodel.ColumnSelection; +import jalview.gui.WebserviceInfo; +import jalview.analysis.AlignSeq; +import jalview.bin.Cache; +import jalview.gui.AlignFrame; +import javax.swing.JOptionPane; + +import vamsas.objects.simple.MsaResult; +import vamsas.objects.simple.Result; +import jalview.datamodel.Alignment; +import jalview.datamodel.SeqCigar; +import jalview.gui.Desktop; +import jalview.datamodel.SequenceI; +import java.util.Hashtable; +import java.util.Vector; + +/** + *

+ * Title: + *

+ * + *

+ * Description: + *

+ * + *

+ * Copyright: Copyright (c) 2004 + *

+ * + *

+ * Company: Dundee University + *

+ * + * @author not attributable + * @version 1.0 + */ +class MsaWSThread extends Thread implements WSClientI { + jalview.gui.AlignFrame alignFrame; + + WebserviceInfo wsInfo = null; + + String WebServiceName = null; + + String OutputHeader; + AlignmentView input; + boolean submitGaps = false; // pass sequences including gaps to alignment + + // service + + boolean preserveOrder = true; // and always store and recover sequence + + // order + + class MsaWSJob { + int jobnum = 0; // WebServiceInfo pane for this job + + String jobId; // ws job ticket + + vamsas.objects.simple.MsaResult result = null; + + vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple.SequenceSet(); + + /** + * MsaWSJob + * + * @param jobNum + * int + * @param jobId + * String + */ + public MsaWSJob(int jobNum, SequenceI[] inSeqs) { + this.jobnum = jobNum; + prepareInput(inSeqs); + } + + int allowedServerExceptions = 3; // thread dies if too many + + // exceptions. + boolean submitted=false; + boolean subjobComplete = false; + + Hashtable SeqNames = new Hashtable(); + Vector emptySeqs = new Vector(); + private void prepareInput(SequenceI[] seqs) { + int nseqs = 0; + for (int i = 0; i < seqs.length; i++) { + if (seqs[i].getStart() < seqs[i].getEnd()) { + nseqs++; + } + } + vamsas.objects.simple.Sequence[] seqarray = + (nseqs>0) + ? new vamsas.objects.simple.Sequence[nseqs] + :null; + for (int i = 0, n = 0; i < seqs.length; i++) { + + String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same + // for + // any + // subjob + SeqNames.put(newname, jalview.analysis.SeqsetUtils + .SeqCharacterHash(seqs[i])); + if (seqs[i].getStart() < seqs[i].getEnd()) { + seqarray[n] = new vamsas.objects.simple.Sequence(); + seqarray[n].setId(newname); + seqarray[n++].setSeq((submitGaps) ? seqs[i].getSequence() + : AlignSeq.extractGaps( + jalview.util.Comparison.GapChars, seqs[i] + .getSequence())); + } else { + emptySeqs.add(newname); + } + } + this.seqs = new vamsas.objects.simple.SequenceSet(); + this.seqs.setSeqs(seqarray); + } + public Object[] getAlignment() { + + if (result!=null) { + SequenceI[] alseqs=null; + char alseq_gapchar='-'; + int alseq_l=0; + if (result.getMsa() != null) { + alseqs = getVamsasAlignment(result.getMsa()); + alseq_gapchar=result.getMsa().getGapchar().charAt(0); + alseq_l = alseqs.length; + } + if (emptySeqs.size()>0) { + SequenceI[] t_alseqs = new SequenceI[alseq_l+emptySeqs.size()]; + // get width + int i,w=0; + if (alseq_l>0) { + for (i=0,w=alseqs[0].getLength(); i 0) { + int start = 0; + njobs=0; + int width = _msa.getWidth(); + for (int contig = 0; contig < contigs.length; contig += 3) { + if ((contigs[contig+1] - start) > 0) { + njobs++; + } + width+=contigs[contig+2];// end up with full region width (including hidden regions) + start = contigs[contig+1] + contigs[contig + 2]; + } + if (start 0) { + SequenceI mseq[] = new SequenceI[msa.length]; + for (int s = 0; s < mseq.length; s++) { + mseq[s] = msa[s].getSeq('-').getSubSequence(start, + contigs[contig+1]); + } + if (j!=0) { + jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq); + } else { + jobs[j] = new MsaWSJob(0, mseq); + } + wsinfo.setProgressName("region "+jobs[j].jobnum,jobs[j].jobnum); + wsinfo.setProgressText(jobs[j].jobnum, OutputHeader); + j++; + } + start = contigs[contig+1] + contigs[contig + 2]; + } + if (start 0) { + jobs[j].allowedServerExceptions--; + Cache.log.debug("Sleeping after a server exception."); + try { + Thread.sleep(5000); + } + catch (InterruptedException ex1) { + } + } else { + Cache.log.warn("Dropping job "+j+" "+jobs[j].jobId); + jobs[j].subjobComplete=true; + wsInfo.setStatus(jobs[j].jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR); + } + } + catch (OutOfMemoryError er) { + jobComplete = true; + jobs[j].subjobComplete=true; + jobs[j].result=null; // may contain out of date result object + wsInfo.setStatus(jobs[j].jobnum, + WebserviceInfo.STATE_STOPPED_ERROR); + JOptionPane + .showInternalMessageDialog( + Desktop.desktop, + "Out of memory handling result for job !!" + + "\nSee help files for increasing Java Virtual Machine memory.", + "Out of memory", JOptionPane.WARNING_MESSAGE); + Cache.log.error("Out of memory when retrieving Job "+j+" id:" + WsUrl+"/"+jobs[j].jobId, er); + System.gc(); + } + } + if (jobs[j].result!=null) { + String progheader=""; + // Parse state of job[j] + if (jobs[j].result.isRunning()) { + running++; + wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_RUNNING); + } else if (jobs[j].result.isQueued()) { + queuing++; + wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_QUEUING); + } else if (jobs[j].result.isFinished()) { + finished++; + jobs[j].subjobComplete = true; + wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_OK); + } else if (jobs[j].result.isFailed()) { + progheader += "Job failed.\n"; + jobs[j].subjobComplete=true; + wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_ERROR); + error++; + } else if (jobs[j].result.isServerError()) { + serror++; + jobs[j].subjobComplete = true; + wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_SERVERERROR); + } else if (jobs[j].result.isBroken() || jobs[j].result.isFailed()) { + error++; + jobs[j].subjobComplete=true; + wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_ERROR); + } + // and pass on any sub-job messages to the user + wsInfo.setProgressText(jobs[j].jobnum, OutputHeader); + wsInfo.appendProgressText(jobs[j].jobnum, progheader); + if (jobs[j].result.getStatus() != null) { + wsInfo.appendProgressText(jobs[j].jobnum, jobs[j].result.getStatus()); + } + } else { + if (jobs[j].submitted && jobs[j].subjobComplete) { + if (jobs[j].allowedServerExceptions==0) { + serror++; + } else if (jobs[j].result==null) { + error++; + } + } + } + } + // Decide on overall state based on collected jobs[] states + if (running>0) { + wsInfo.setStatus(WebserviceInfo.STATE_RUNNING); + } else if (queuing>0) { + wsInfo.setStatus(WebserviceInfo.STATE_QUEUING); + } else { + jobComplete=true; + if (finished>0) { + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); + } else if (error>0) { + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); + } else if (serror>0) { + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); + } + } + if (!jobComplete) { + try { + Thread.sleep(5000); + } + catch (InterruptedException e) { + Cache.log.debug("Interrupted sleep waiting for next job poll.",e); + } + // System.out.println("I'm alive "+alTitle); + } + } + if (jobComplete) { + parseResult(); // tidy up and make results available to user + } + } + + void StartJob(MsaWSJob j) { + if (j.submitted) { + if (Cache.log.isDebugEnabled()) { + Cache.log.debug("Tried to submit an already submitted job "+j.jobId); + } + return; + } + if (j.seqs.getSeqs()==null) { + // special case - selection consisted entirely of empty sequences... + j.submitted=true; + j.result=new MsaResult(); + j.result.setFinished(true); + j.result.setStatus("Empty Alignment Job"); + j.result.setMsa(null); + } + try { + vamsas.objects.simple.WsJobId jobsubmit = server.align(j.seqs); + + if ((jobsubmit != null) && (jobsubmit.getStatus() == 1)) { + j.jobId = jobsubmit.getJobId(); + j.submitted=true; + j.subjobComplete = false; + // System.out.println(WsURL + " Job Id '" + jobId + "'"); + } else { + if (jobsubmit == null) { + throw new Exception( + "Server at " + + WsUrl + + " returned null object, it probably cannot be contacted. Try again later ?"); + } + + throw new Exception(jobsubmit.getJobId()); + } + } catch (Exception e) { + // TODO: JBPNote catch timeout or other fault types explicitly + // For unexpected errors + System.err + .println(WebServiceName + + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n" + + "When contacting Server:" + WsUrl + "\n" + + e.toString() + "\n"); + j.allowedServerExceptions = 0; + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); + wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR); + wsInfo + .appendProgressText( + j.jobnum, + "Failed to submit sequences for alignment.\n" + + "It is most likely that there is a problem with the server.\n" + + "Just close the window\n"); + + // e.printStackTrace(); // TODO: JBPNote DEBUG + } + } + + private jalview.datamodel.Sequence[] getVamsasAlignment( + vamsas.objects.simple.Alignment valign) { + vamsas.objects.simple.Sequence[] seqs = valign.getSeqs().getSeqs(); + jalview.datamodel.Sequence[] msa = new jalview.datamodel.Sequence[seqs.length]; + + for (int i = 0, j = seqs.length; i < j; i++) { + msa[i] = new jalview.datamodel.Sequence(seqs[i].getId(), seqs[i] + .getSeq()); + } + + return msa; + } + + void parseResult() { + try { + for (int j=0; j