X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws%2FMsaWSThread.java;h=3be0c5622281da2d6374d8d4270a2c8d89e15a41;hb=0bfa3d7bdca9a09b4ad6a2ec380042768db80395;hp=803bf443a9b781c61c6cb478ee5073aaf9a20eb8;hpb=129ad37552c4bd5b241e90e0caf8b7f32a32bfb7;p=jalview.git diff --git a/src/jalview/ws/MsaWSThread.java b/src/jalview/ws/MsaWSThread.java index 803bf44..3be0c56 100644 --- a/src/jalview/ws/MsaWSThread.java +++ b/src/jalview/ws/MsaWSThread.java @@ -1,9 +1,25 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer + * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ package jalview.ws; import java.util.*; -import javax.swing.*; - import jalview.analysis.*; import jalview.bin.*; import jalview.datamodel.*; @@ -32,16 +48,8 @@ import vamsas.objects.simple.MsaResult; * @version 1.0 */ class MsaWSThread - extends Thread implements WSClientI + extends WSThread 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 @@ -51,13 +59,9 @@ class MsaWSThread // order class MsaWSJob + extends WSThread.WSJob { - int jobnum = 0; // WebServiceInfo pane for this job - - String jobId; // ws job ticket - - vamsas.objects.simple.MsaResult result = null; - + // hold special input for this vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple. SequenceSet(); @@ -83,12 +87,6 @@ class MsaWSThread } - int allowedServerExceptions = 3; // thread dies if too many - - // exceptions. - boolean submitted = false; - boolean subjobComplete = false; - Hashtable SeqNames = new Hashtable(); Vector emptySeqs = new Vector(); /** @@ -129,20 +127,20 @@ class MsaWSThread { seqarray[n] = new vamsas.objects.simple.Sequence(); seqarray[n].setId(newname); - seqarray[n++].setSeq( (submitGaps) ? seqs[i].getSequence() + seqarray[n++].setSeq( (submitGaps) ? seqs[i].getSequenceAsString() : AlignSeq.extractGaps( jalview.util.Comparison.GapChars, seqs[i] - .getSequence())); + .getSequenceAsString())); } else { String empty = null; if (seqs[i].getEnd() >= seqs[i].getStart()) { - empty = (submitGaps) ? seqs[i].getSequence() + empty = (submitGaps) ? seqs[i].getSequenceAsString() : AlignSeq.extractGaps( jalview.util.Comparison.GapChars, seqs[i] - .getSequence()); + .getSequenceAsString()); } emptySeqs.add(new String[] {newname, empty}); @@ -160,7 +158,8 @@ class MsaWSThread public boolean hasResults() { if (subjobComplete && result != null && result.isFinished() - && result.getMsa() != null && result.getMsa().getSeqs() != null) + && ( (MsaResult) result).getMsa() != null && + ( (MsaResult) result).getMsa().getSeqs() != null) { return true; } @@ -175,10 +174,10 @@ class MsaWSThread SequenceI[] alseqs = null; char alseq_gapchar = '-'; int alseq_l = 0; - if (result.getMsa() != null) + if ( ( (MsaResult) result).getMsa() != null) { - alseqs = getVamsasAlignment(result.getMsa()); - alseq_gapchar = result.getMsa().getGapchar().charAt(0); + alseqs = getVamsasAlignment( ( (MsaResult) result).getMsa()); + alseq_gapchar = ( (MsaResult) result).getMsa().getGapchar().charAt(0); alseq_l = alseqs.length; } if (emptySeqs.size() > 0) @@ -226,7 +225,7 @@ class MsaWSThread if (nw > sw) { // pad at end - alseqs[i].setSequence(t_alseqs[i].getSequence() + + alseqs[i].setSequence(t_alseqs[i].getSequenceAsString() + insbuff.substring(0, sw - nw)); } } @@ -270,31 +269,36 @@ class MsaWSThread return null; } - boolean cancelled = false; /** * mark subjob as cancelled and set result object appropriatly */ - void cancel() { - cancelled=true; + void cancel() + { + cancelled = true; subjobComplete = true; result = null; } - } - MsaWSJob jobs[] = null; + /** + * + * @return boolean true if job can be submitted. + */ + boolean hasValidInput() + { + if (seqs.getSeqs() != null) + { + return true; + } + return false; + } + } String alTitle; // name which will be used to form new alignment window. - - boolean jobComplete = false; - Alignment dataset; // dataset to which the new alignment will be // associated. ext.vamsas.MuscleWS server = null; - - String WsUrl = null; - /** * set basic options for this (group) of Msa jobs * @@ -308,14 +312,10 @@ class MsaWSThread AlignmentView alview, String wsname, boolean subgaps, boolean presorder) { + super(alFrame, wsinfo, alview, wsname, wsUrl); this.server = server; - this.WsUrl = wsUrl; - this.wsInfo = wsinfo; - this.WebServiceName = wsname; - this.input = alview; this.submitGaps = subgaps; this.preserveOrder = presorder; - this.alignFrame = alFrame; } /** @@ -341,86 +341,29 @@ class MsaWSThread OutputHeader = wsInfo.getProgressText(); alTitle = title; dataset = seqset; - SeqCigar[] msa = _msa.getSequences(); - int[] contigs = _msa.getContigs(); - int njobs = 1; - if (contigs != null && contigs.length > 0) + + SequenceI[][] conmsa = _msa.getVisibleContigs('-'); + if (conmsa != null) { - 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 < width) - { - njobs++; - } + int njobs = conmsa.length; jobs = new MsaWSJob[njobs]; - start = 0; - int j = 0; - for (int contig = 0; contig < contigs.length; contig += 3) - { - if (contigs[contig + 1] - 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 < width) + for (int j = 0; j < njobs; j++) { - SequenceI mseq[] = new SequenceI[msa.length]; - for (int s = 0; s < mseq.length; s++) - { - mseq[s] = msa[s].getSeq('-').getSubSequence(start, - width + 1); - } if (j != 0) { - jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq); + jobs[j] = new MsaWSJob(wsinfo.addJobPane(), conmsa[j]); } else { - jobs[j] = new MsaWSJob(0, mseq); + jobs[j] = new MsaWSJob(0, conmsa[j]); + } + if (njobs > 0) + { + wsinfo.setProgressName("region " + jobs[j].jobnum, jobs[j].jobnum); } - wsinfo.setProgressName("region " + jobs[j].jobnum, jobs[j].jobnum); wsinfo.setProgressText(jobs[j].jobnum, OutputHeader); - j++; } } - else - { - SequenceI mseq[] = new SequenceI[msa.length]; - for (int s = 0; s < mseq.length; s++) - { - mseq[s] = msa[s].getSeq('-'); - } - jobs = new MsaWSJob[1]; - wsinfo.setProgressText(OutputHeader); // ensures default text - jobs[0] = new MsaWSJob(0, mseq); - } } public boolean isCancellable() @@ -446,7 +389,7 @@ class MsaWSThread { // CANCELLED_JOB cancelledMessage = "Job cancelled."; - jobs[job].cancel(); + ( (MsaWSJob) jobs[job]).cancel(); wsInfo.setStatus(jobs[job].jobnum, WebserviceInfo.STATE_CANCELLED_OK); } @@ -472,7 +415,8 @@ class MsaWSThread cancelledMessage += ("\nProblems cancelling the job : Exception received...\n" + exc + "\n"); - Cache.log.warn("Exception whilst cancelling "+jobs[job].jobId,exc); + Cache.log.warn("Exception whilst cancelling " + jobs[job].jobId, + exc); } wsInfo.setProgressText(jobs[job].jobnum, OutputHeader + cancelledMessage + "\n"); @@ -496,204 +440,20 @@ class MsaWSThread } } - class JobStateSummary { - int running = 0; - int queuing = 0; - int finished = 0; - int error = 0; - int serror = 0; - int cancelled=0; - int results=0; - void updateJobPanelState(WebserviceInfo wsInfo, MsaWSJob j) { - if (j.result != null) - { - String progheader = ""; - // Parse state of job[j] - if (j.result.isRunning()) - { - running++; - wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_RUNNING); - } - else if (j.result.isQueued()) - { - queuing++; - wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_QUEUING); - } - else if (j.result.isFinished()) - { - finished++; - j.subjobComplete = true; - if (j.hasResults()) - results++; - wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_OK); - } - else if (j.result.isFailed()) - { - progheader += "Job failed.\n"; - j.subjobComplete = true; - wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR); - error++; - } - else if (j.result.isServerError()) - { - serror++; - j.subjobComplete = true; - wsInfo.setStatus(j.jobnum, - WebserviceInfo.STATE_STOPPED_SERVERERROR); - } - else if (j.result.isBroken() || j.result.isFailed()) - { - error++; - j.subjobComplete = true; - wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR); - } - // and pass on any sub-job messages to the user - wsInfo.setProgressText(j.jobnum, OutputHeader); - wsInfo.appendProgressText(j.jobnum, progheader); - if (j.result.getStatus() != null) - { - wsInfo.appendProgressText(j.jobnum, j.result.getStatus()); - } - } - else - { - if (j.submitted && j.subjobComplete) - { - if (j.allowedServerExceptions == 0) - { - serror++; - } - else if (j.result == null) - { - error++; - } - } - } - } - } - public void run() + void pollJob(WSJob job) + throws Exception { - JobStateSummary jstate=null; - while (!jobComplete) - { - jstate = new JobStateSummary(); - for (int j = 0; j < jobs.length; j++) - { - - if (!jobs[j].submitted && jobs[j].seqs.getSeqs() != null) - { - StartJob(jobs[j]); - } - - if (jobs[j].submitted && !jobs[j].subjobComplete) - { - try - { - if ( (jobs[j].result = server.getResult(jobs[j].jobId)) == null) - { - throw (new Exception( - "Timed out when communicating with server\nTry again later.\n")); - } - jalview.bin.Cache.log.debug("Job " + j + " Result state " + - jobs[j].result.getState() - + "(ServerError=" + - jobs[j].result.isServerError() + ")"); - } - catch (Exception ex) - { - // Deal with Transaction exceptions - wsInfo.appendProgressText(jobs[j].jobnum, "\n" + WebServiceName - + " Server exception!\n" + ex.getMessage()); - Cache.log.warn(WebServiceName + " job(" + jobs[j].jobnum - + ") Server exception: " + ex.getMessage()); - - if (jobs[j].allowedServerExceptions > 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(); - } - } - jstate.updateJobPanelState(wsInfo, jobs[j]); - } - // Decide on overall state based on collected jobs[] states - if (jstate.running > 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_RUNNING); - } - else if (jstate.queuing > 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_QUEUING); - } - else - { - jobComplete = true; - if (jstate.finished > 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); - } - else if (jstate.error > 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); - } - else if (jstate.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 - } + ( (MsaWSJob) job).result = server.getResult( ( (MsaWSJob) job).jobId); } - void StartJob(MsaWSJob j) + void StartJob(WSJob job) { + if (! (job instanceof MsaWSJob)) + { + throw new Error("StartJob(MsaWSJob) called on a WSJobInstance " + + job.getClass()); + } + MsaWSJob j = (MsaWSJob) job; if (j.submitted) { if (Cache.log.isDebugEnabled()) @@ -709,7 +469,7 @@ class MsaWSThread j.result = new MsaResult(); j.result.setFinished(true); j.result.setStatus("Empty Alignment Job"); - j.result.setMsa(null); + ( (MsaResult) j.result).setMsa(null); } try { @@ -783,11 +543,12 @@ class MsaWSThread { for (int j = 0; j < jobs.length; j++) { - finalState.updateJobPanelState(wsInfo, jobs[j]); + finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]); if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults()) { results++; - vamsas.objects.simple.Alignment valign = jobs[j].result.getMsa(); + vamsas.objects.simple.Alignment valign = ( (MsaResult) jobs[j].result). + getMsa(); if (valign != null) { wsInfo.appendProgressText(jobs[j].jobnum, @@ -833,213 +594,63 @@ class MsaWSThread }); wsInfo.setResultsReady(); } + else + { + wsInfo.setFinishedNoResults(); + } } void displayResults(boolean newFrame) { // view input or result data for each block - // warn user if a block is input rather than aligned data ? - - int contigs[] = input.getContigs(); - SeqCigar[] seqs = input.getSequences(); - SequenceI[] alignment = new SequenceI[seqs.length]; - ColumnSelection columnselection = new ColumnSelection(); Vector alorders = new Vector(); - if (contigs != null && contigs.length > 0) - { - int start = 0; - int nwidth = 0; - int owidth = input.getWidth(); - int j = 0; - for (int contig = 0; contig < contigs.length; contig += 3) - { - owidth += contigs[contig + 2]; // recover final column width - if (contigs[contig + 1] - start > 0) - { - int width = 0; // subalignment width - if (jobs[j].hasResults()) - { - Object[] subalg = jobs[j++].getAlignment(); - alorders.add(subalg[1]); - SequenceI mseq[] = (SequenceI[]) subalg[0]; - width = mseq[0].getLength(); - for (int s = 0; s < mseq.length; s++) - { - if (alignment[s] == null) - { - alignment[s] = mseq[s]; - } - else - { - alignment[s].setSequence(alignment[s].getSequence() + - mseq[s].getSequence()); - if (mseq[s].getStart() <= mseq[s].getEnd()) - { - alignment[s].setEnd(mseq[s].getEnd()); - } - ( (AlignmentOrder) subalg[1]).updateSequence(mseq[s], - alignment[s]); - } - } - } - else - { - // recover input data or place gaps - if (true) - { - // recover input data - for (int s = 0; s < seqs.length; s++) - { - SequenceI oseq = seqs[s].getSeq('-').getSubSequence(start, - contigs[contig + 1]); - if (width < oseq.getLength()) - { - width = oseq.getLength(); - } - if (alignment[s] == null) - { - alignment[s] = oseq; - } - else - { - alignment[s].setSequence(alignment[s].getSequence() + - oseq.getSequence()); - if (oseq.getEnd() >= oseq.getStart()) - { - alignment[s].setEnd(oseq.getEnd()); - } - } - } + SequenceI[][] results = new SequenceI[jobs.length][]; + AlignmentOrder[] orders = new AlignmentOrder[jobs.length]; - } - j++; - } - nwidth += width; - } - // advance to begining of visible region - start = contigs[contig + 1] + contigs[contig + 2]; - // add hidden segment to right of next region - for (int s = 0; s < seqs.length; s++) - { - SequenceI hseq = seqs[s].getSeq('-').getSubSequence(contigs[contig + - 1], start); - if (alignment[s] == null) - { - alignment[s] = hseq; - } - else - { - alignment[s].setSequence(alignment[s].getSequence() + - hseq.getSequence()); - if (hseq.getEnd() >= hseq.getStart()) - { - alignment[s].setEnd(hseq.getEnd()); - } - } - } - // mark hidden segment as hidden in the new alignment - columnselection.hideColumns(nwidth, nwidth + contigs[contig + 2] - 1); - nwidth += contigs[contig + 2]; - } - // Do final job - if it exists - if (j < jobs.length) - { - int width = 0; - if (jobs[j].hasResults()) - { - Object[] subalg = jobs[j].getAlignment(); - alorders.add(subalg[1]); - SequenceI mseq[] = (SequenceI[]) subalg[0]; - width = mseq[0].getLength(); - for (int s = 0; s < mseq.length; s++) - { - if (alignment[s] == null) - { - alignment[s] = mseq[s]; - } - else - { - alignment[s].setSequence(alignment[s].getSequence() + - mseq[s].getSequence()); - if (mseq[s].getEnd() >= mseq[s].getStart()) - { - alignment[s].setEnd(mseq[s].getEnd()); - } - ( (AlignmentOrder) subalg[1]).updateSequence(mseq[s], alignment[s]); - } - } - } - else - { - if (start < owidth) - { - // recover input data or place gaps - if (true) - { - // recover input data - for (int s = 0; s < seqs.length; s++) - { - SequenceI oseq = seqs[s].getSeq('-').getSubSequence(start, - owidth + 1); - if (width < oseq.getLength()) - { - width = oseq.getLength(); - } - if (alignment[s] == null) - { - alignment[s] = oseq; - } - else - { - alignment[s].setSequence(alignment[s].getSequence() + - oseq.getSequence()); - if (oseq.getEnd() >= oseq.getStart()) - { - alignment[s].setEnd(oseq.getEnd()); - } - } - } - nwidth += width; - } - else - { - // place gaps. - throw new Error("Padding not yet implemented."); - } - } - } - } - } - else + for (int j = 0; j < jobs.length; j++) { - if (jobs[0].hasResults()) + if (jobs[j].hasResults()) { - Object[] alg = jobs[0].getAlignment(); - alignment = (SequenceI[]) alg[0]; - alorders.add(alg[1]); + Object[] res = ( (MsaWSJob) jobs[j]).getAlignment(); + alorders.add(res[1]); + results[j] = (SequenceI[]) res[0]; + orders[j] = (AlignmentOrder) res[1]; +// SequenceI[] alignment = input.getUpdated } else { - alignment = SeqCigar.createAlignmentSequences(seqs, '-', - columnselection, null); + results[j] = null; } } + Object[] newview = input.getUpdatedView(results, orders, getGapChar()); + // trash references to original result data + for (int j = 0; j < jobs.length; j++) + { + results[j] = null; + orders[j] = null; + } + SequenceI[] alignment = (SequenceI[]) newview[0]; + ColumnSelection columnselection = (ColumnSelection) newview[1]; Alignment al = new Alignment(alignment); + if (dataset != null) { al.setDataset(dataset); } + propagateDatasetMappings(al); + // JBNote- TODO: warn user if a block is input rather than aligned data ? + if (newFrame) { - // TODO: JBPNote Should also rename the query sequence - // sometime... - AlignFrame af = new AlignFrame(al, columnselection); + AlignFrame af = new AlignFrame(al, columnselection, + AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); - // >>>This is a fix for the moment, until a better solution is - // found!!<<< + // initialise with same renderer settings as in parent alignframe. af.getFeatureRenderer().transferSettings( - alignFrame.getFeatureRenderer()); + this.featureSettings); + // update orders if (alorders.size() > 0) { if (alorders.size() == 1) @@ -1053,9 +664,9 @@ class MsaWSThread Vector names = new Vector(); for (int i = 0, l = alorders.size(); i < l; i++) { - String orderName = new String("Region " + i); + String orderName = new String(" Region " + i); int j = i + 1; - int r = l; + while (j < l) { if ( ( (AlignmentOrder) alorders.get(i)).equals( ( ( @@ -1082,7 +693,8 @@ class MsaWSThread } for (int i = 0, l = alorders.size(); i < l; i++) { - af.addSortByOrderMenuItem(WebServiceName + ( (String) names.get(i)) + + af.addSortByOrderMenuItem(WebServiceName + + ( (String) names.get(i)) + " Ordering", (AlignmentOrder) alorders.get(i)); } @@ -1090,8 +702,8 @@ class MsaWSThread } Desktop.addInternalFrame(af, alTitle, - AlignFrame.NEW_WINDOW_WIDTH, - AlignFrame.NEW_WINDOW_HEIGHT); + AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); } else @@ -1100,4 +712,9 @@ class MsaWSThread } } + + public boolean canMergeResults() + { + return false; + } }