1 package jalview.ws.gui;
3 import jalview.analysis.AlignSeq;
4 import jalview.datamodel.AlignmentI;
5 import jalview.datamodel.AlignmentOrder;
6 import jalview.datamodel.Sequence;
7 import jalview.datamodel.SequenceI;
8 import jalview.util.MessageManager;
9 import jalview.ws.jws2.dm.JabaWsParamSet;
10 import jalview.ws.params.ArgumentI;
12 import java.util.ArrayList;
13 import java.util.Vector;
15 class MsaWSJob extends WsJob
18 * holds basic MSA analysis configuration - todo - encapsulate
20 private final MsaWSThread msaWSThread;
27 ArrayList<SequenceI> seqs = new ArrayList<>();
34 // set if the job didn't get run - then the input is simply returned to the
36 private boolean returnInput = false;
44 * TODO - abstract the properties provided by the thread
48 public MsaWSJob(MsaWSThread msaWSThread, int jobNum, SequenceI[] inSeqs)
50 this.msaWSThread = msaWSThread;
52 if (!prepareInput(inSeqs, 2))
55 subjobComplete = true;
64 Vector<String[]> emptySeqs = new Vector();
67 * prepare input sequences for MsaWS service
70 * jalview sequences to be prepared
72 * minimum number of residues required for this MsaWS service
73 * @return true if seqs contains sequences to be submitted to service.
75 // TODO: return compbio.seqs list or nothing to indicate validity.
76 private boolean prepareInput(SequenceI[] seqs, int minlen)
78 // TODO: service specific input data is generated in this method - for
79 // JABAWS it is client-side
80 // prepared, but for Slivka it could be uploaded at this stage.
85 throw new Error(MessageManager.getString(
86 "error.implementation_error_minlen_must_be_greater_zero"));
88 for (int i = 0; i < seqs.length; i++)
90 if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
95 boolean valid = nseqs > 1; // need at least two seqs
97 for (int i = 0, n = 0; i < seqs.length; i++)
99 String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
103 SeqNames.put(newname,
104 jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i]));
105 if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
107 // make new input sequence with or without gaps
108 seq = new Sequence(newname,
109 (this.msaWSThread.submitGaps) ? seqs[i].getSequenceAsString()
110 : AlignSeq.extractGaps(
111 jalview.util.Comparison.GapChars,
112 seqs[i].getSequenceAsString()));
118 if (seqs[i].getEnd() >= seqs[i].getStart())
120 empty = (this.msaWSThread.submitGaps) ? seqs[i].getSequenceAsString()
121 : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
122 seqs[i].getSequenceAsString());
124 emptySeqs.add(new String[] { newname, empty });
132 * @return true if getAlignment will return a valid alignment result.
135 public boolean hasResults()
137 if (subjobComplete && isFinished() && (alignment != null
138 || (emptySeqs != null && emptySeqs.size() > 0)))
147 * get the alignment including any empty sequences in the original order
148 * with original ids. Caller must access the alignment.getMetadata() object
149 * to annotate the final result passsed to the user.
151 * @return { SequenceI[], AlignmentOrder }
153 public Object[] getAlignment()
155 // TODO: make this generic based on MsaResultI
156 // TODO: decide if the data loss for this return signature is avoidable
157 // (ie should we just return AlignmentI instead ?)
160 SequenceI[] alseqs = null;
161 char alseq_gapchar = '-';
163 alseqs = new SequenceI[alignment.getSequences().size()];
164 if (alignment.getSequences().size() > 0)
166 for (SequenceI seq : alignment
169 alseqs[alseq_l++] = new Sequence(seq);
171 alseq_gapchar = alignment.getGapCharacter();
174 // add in the empty seqs.
175 if (emptySeqs.size() > 0)
177 SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
182 for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
184 if (w < alseqs[i].getLength())
186 w = alseqs[i].getLength();
188 t_alseqs[i] = alseqs[i];
192 // check that aligned width is at least as wide as emptySeqs width.
194 for (i = 0, w = emptySeqs.size(); i < w; i++)
196 String[] es = emptySeqs.get(i);
197 if (es != null && es[1] != null)
199 int sw = es[1].length();
206 // make a gapped string.
207 StringBuffer insbuff = new StringBuffer(w);
208 for (i = 0; i < nw; i++)
210 insbuff.append(alseq_gapchar);
214 for (i = 0; i < alseq_l; i++)
216 int sw = t_alseqs[i].getLength();
220 alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
221 + insbuff.substring(0, sw - nw));
225 for (i = 0, w = emptySeqs.size(); i < w; i++)
227 String[] es = emptySeqs.get(i);
230 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
231 insbuff.toString(), 1, 0);
235 if (es[1].length() < nw)
237 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
239 es[1] + insbuff.substring(0, nw - es[1].length()),
240 1, 1 + es[1].length());
244 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
251 AlignmentOrder msaorder = new AlignmentOrder(alseqs);
252 // always recover the order - makes parseResult()'s life easier.
253 jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
254 // account for any missing sequences
255 jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
256 return new Object[] { alseqs, msaorder };
262 * mark subjob as cancelled and set result object appropriatly
267 subjobComplete = true;
273 * @return boolean true if job can be submitted.
276 public boolean hasValidInput()
278 // TODO: get attributes for this MsaWS instance to check if it can do two
279 // sequence alignment.
280 // TODO: check type of sequences are valid for this service
281 if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ?
288 StringBuffer jobProgress = new StringBuffer();
291 public void setStatus(String string)
293 jobProgress.setLength(0);
294 jobProgress.append(string);
298 public String getStatus()
300 return jobProgress.toString();
304 public boolean hasStatus()
306 return jobProgress != null;
310 * @return the lastChunk
312 public long getLastChunk()
319 * the lastChunk to set
321 public void setLastChunk(long lastChunk)
323 this.lastChunk = lastChunk;
326 String alignmentProgram = null;
328 public String getAlignmentProgram()
330 return alignmentProgram;
333 public boolean hasArguments()
335 return (arguments != null && arguments.size() > 0)
336 || (preset != null && preset instanceof JabaWsParamSet);
340 * add a progess header to status string containing presets/args used
342 public void addInitialStatus()
344 // TODO: decide if it is useful to report 'JABAWS format' argument lists
345 // rather than generic Jalview service arguments
349 "Using " + (preset.isModifiable() ? "Server" : "User")
350 + "Preset: " + preset.getName());
351 for (ArgumentI opt : preset.getArguments())
353 jobProgress.append(opt.getName() + " " + opt.getValue() + "\n");
358 if (arguments != null && arguments.size() > 0)
360 jobProgress.append("With custom parameters : \n");
361 // merge arguments with preset's own arguments.
362 for (ArgumentI opt : arguments)
364 jobProgress.append(opt.getName() + " " + opt.getValue() + "\n");
367 jobProgress.append("\nJob Output:\n");