Clover icon

Coverage Report

  1. Project Clover database Wed Dec 3 2025 17:03:17 GMT
  2. Package jalview.ws.gui

File MsaWSJob.java

 

Coverage histogram

../../../img/srcFileCovDistChart0.png
60% of files have more coverage

Code metrics

60
98
14
1
370
259
52
0.53
7
14
3.71

Classes

Class Line # Actions
MsaWSJob 15 98 52
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    package jalview.ws.gui;
2   
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;
11   
12    import java.util.ArrayList;
13    import java.util.Vector;
14   
 
15    class MsaWSJob extends WsJob
16    {
17    /**
18    * holds basic MSA analysis configuration - todo - encapsulate
19    */
20    private final MsaWSThread msaWSThread;
21   
22    long lastChunk = 0;
23   
24    /**
25    * input
26    */
27    ArrayList<SequenceI> seqs = new ArrayList<>();
28   
29    /**
30    * output
31    */
32    AlignmentI alignment;
33   
34    // set if the job didn't get run - then the input is simply returned to the
35    // user
36    private boolean returnInput = false;
37   
38    /**
39    * MsaWSJob
40    *
41    * @param jobNum
42    * int
43    * @param msaWSThread
44    * TODO - abstract the properties provided by the thread
45    * @param jobId
46    * String
47    */
 
48  0 toggle public MsaWSJob(MsaWSThread msaWSThread, int jobNum, SequenceI[] inSeqs)
49    {
50  0 this.msaWSThread = msaWSThread;
51  0 this.jobnum = jobNum;
52  0 if (!prepareInput(inSeqs, 2))
53    {
54  0 submitted = true;
55  0 subjobComplete = true;
56  0 returnInput = true;
57    } else
58    {
59  0 validInput = true;
60    }
61   
62    }
63   
64    Vector<String[]> emptySeqs = new Vector();
65   
66    /**
67    * prepare input sequences for MsaWS service
68    *
69    * @param seqs
70    * jalview sequences to be prepared
71    * @param minlen
72    * minimum number of residues required for this MsaWS service
73    * @return true if seqs contains sequences to be submitted to service.
74    */
75    // TODO: return compbio.seqs list or nothing to indicate validity.
 
76  0 toggle private boolean prepareInput(SequenceI[] seqs, int minlen)
77    {
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.
81   
82  0 int nseqs = 0;
83  0 if (minlen < 0)
84    {
85  0 throw new Error(MessageManager.getString(
86    "error.implementation_error_minlen_must_be_greater_zero"));
87    }
88  0 for (int i = 0; i < seqs.length; i++)
89    {
90  0 if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
91    {
92  0 nseqs++;
93    }
94    }
95  0 boolean valid = nseqs > 1; // need at least two seqs
96  0 Sequence seq;
97  0 for (int i = 0, n = 0; i < seqs.length; i++)
98    {
99  0 String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
100    // for
101    // any
102    // subjob
103  0 SeqNames.put(newname,
104    jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i]));
105  0 if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
106    {
107    // make new input sequence with or without gaps
108  0 seq = new Sequence(newname,
109  0 (this.msaWSThread.submitGaps) ? seqs[i].getSequenceAsString()
110    : AlignSeq.extractGaps(
111    jalview.util.Comparison.GapChars,
112    seqs[i].getSequenceAsString()));
113  0 this.seqs.add(seq);
114    }
115    else
116    {
117  0 String empty = null;
118  0 if (seqs[i].getEnd() >= seqs[i].getStart())
119    {
120  0 empty = (this.msaWSThread.submitGaps) ? seqs[i].getSequenceAsString()
121    : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
122    seqs[i].getSequenceAsString());
123    }
124  0 emptySeqs.add(new String[] { newname, empty });
125    }
126    }
127  0 return valid;
128    }
129   
130    /**
131    *
132    * @return true if getAlignment will return a valid alignment result.
133    */
 
134  0 toggle @Override
135    public boolean hasResults()
136    {
137  0 if (subjobComplete && isFinished() && (alignment != null
138    || (emptySeqs != null && emptySeqs.size() > 0)))
139    {
140  0 return true;
141    }
142  0 return false;
143    }
144   
145    /**
146    *
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.
150    *
151    * @return { SequenceI[], AlignmentOrder }
152    */
 
153  0 toggle public Object[] getAlignment()
154    {
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 ?)
158  0 if (hasResults())
159    {
160  0 SequenceI[] alseqs = null;
161  0 char alseq_gapchar = '-';
162  0 int alseq_l = 0;
163  0 alseqs = new SequenceI[alignment.getSequences().size()];
164  0 if (alignment.getSequences().size() > 0)
165    {
166  0 for (SequenceI seq : alignment
167    .getSequences())
168    {
169  0 alseqs[alseq_l++] = new Sequence(seq);
170    }
171  0 alseq_gapchar = alignment.getGapCharacter();
172   
173    }
174    // add in the empty seqs.
175  0 if (emptySeqs.size() > 0)
176    {
177  0 SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
178    // get width
179  0 int i, w = 0;
180  0 if (alseq_l > 0)
181    {
182  0 for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
183    {
184  0 if (w < alseqs[i].getLength())
185    {
186  0 w = alseqs[i].getLength();
187    }
188  0 t_alseqs[i] = alseqs[i];
189  0 alseqs[i] = null;
190    }
191    }
192    // check that aligned width is at least as wide as emptySeqs width.
193  0 int ow = w, nw = w;
194  0 for (i = 0, w = emptySeqs.size(); i < w; i++)
195    {
196  0 String[] es = emptySeqs.get(i);
197  0 if (es != null && es[1] != null)
198    {
199  0 int sw = es[1].length();
200  0 if (nw < sw)
201    {
202  0 nw = sw;
203    }
204    }
205    }
206    // make a gapped string.
207  0 StringBuffer insbuff = new StringBuffer(w);
208  0 for (i = 0; i < nw; i++)
209    {
210  0 insbuff.append(alseq_gapchar);
211    }
212  0 if (ow < nw)
213    {
214  0 for (i = 0; i < alseq_l; i++)
215    {
216  0 int sw = t_alseqs[i].getLength();
217  0 if (nw > sw)
218    {
219    // pad at end
220  0 alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
221    + insbuff.substring(0, sw - nw));
222    }
223    }
224    }
225  0 for (i = 0, w = emptySeqs.size(); i < w; i++)
226    {
227  0 String[] es = emptySeqs.get(i);
228  0 if (es[1] == null)
229    {
230  0 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
231    insbuff.toString(), 1, 0);
232    }
233    else
234    {
235  0 if (es[1].length() < nw)
236    {
237  0 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
238    es[0],
239    es[1] + insbuff.substring(0, nw - es[1].length()),
240    1, 1 + es[1].length());
241    }
242    else
243    {
244  0 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
245    es[0], es[1]);
246    }
247    }
248    }
249  0 alseqs = t_alseqs;
250    }
251  0 AlignmentOrder msaorder = new AlignmentOrder(alseqs);
252    // always recover the order - makes parseResult()'s life easier.
253  0 jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
254    // account for any missing sequences
255  0 jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
256  0 return new Object[] { alseqs, msaorder };
257    }
258  0 return null;
259    }
260   
261    /**
262    * mark subjob as cancelled and set result object appropriatly
263    */
 
264  0 toggle void cancel()
265    {
266  0 cancelled = true;
267  0 subjobComplete = true;
268  0 alignment = null;
269    }
270   
271    /**
272    *
273    * @return boolean true if job can be submitted.
274    */
 
275  0 toggle @Override
276    public boolean hasValidInput()
277    {
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  0 if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ?
282    {
283  0 return true;
284    }
285  0 return false;
286    }
287   
288    StringBuffer jobProgress = new StringBuffer();
289   
 
290  0 toggle @Override
291    public void setStatus(String string)
292    {
293  0 jobProgress.setLength(0);
294  0 jobProgress.append(string);
295    }
296   
 
297  0 toggle @Override
298    public String getStatus()
299    {
300  0 return jobProgress.toString();
301    }
302   
 
303  0 toggle @Override
304    public boolean hasStatus()
305    {
306  0 return jobProgress != null;
307    }
308   
309    /**
310    * @return the lastChunk
311    */
 
312  0 toggle public long getLastChunk()
313    {
314  0 return lastChunk;
315    }
316   
317    /**
318    * @param lastChunk
319    * the lastChunk to set
320    */
 
321  0 toggle public void setLastChunk(long lastChunk)
322    {
323  0 this.lastChunk = lastChunk;
324    }
325   
326    String alignmentProgram = null;
327   
 
328  0 toggle public String getAlignmentProgram()
329    {
330  0 return alignmentProgram;
331    }
332   
 
333  0 toggle public boolean hasArguments()
334    {
335  0 return (arguments != null && arguments.size() > 0)
336    || (preset != null && preset instanceof JabaWsParamSet);
337    }
338   
339    /**
340    * add a progess header to status string containing presets/args used
341    */
 
342  0 toggle public void addInitialStatus()
343    {
344    // TODO: decide if it is useful to report 'JABAWS format' argument lists
345    // rather than generic Jalview service arguments
346  0 if (preset != null)
347    {
348  0 jobProgress.append(
349  0 "Using " + (preset.isModifiable() ? "Server" : "User")
350    + "Preset: " + preset.getName());
351  0 for (ArgumentI opt : preset.getArguments())
352    {
353  0 jobProgress.append(opt.getName() + " " + opt.getValue() + "\n");
354    }
355    }
356    else
357    {
358  0 if (arguments != null && arguments.size() > 0)
359    {
360  0 jobProgress.append("With custom parameters : \n");
361    // merge arguments with preset's own arguments.
362  0 for (ArgumentI opt : arguments)
363    {
364  0 jobProgress.append(opt.getName() + " " + opt.getValue() + "\n");
365    }
366    }
367  0 jobProgress.append("\nJob Output:\n");
368    }
369    }
370    }