Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.hmmer

File HMMBuild.java

 

Coverage histogram

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

Code metrics

50
117
6
1
373
263
36
0.31
19.5
6
6

Classes

Class Line # Actions
HMMBuild 35 117 36
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    package jalview.hmmer;
2   
3    import jalview.analysis.SeqsetUtils.SequenceInfo;
4    import jalview.api.AlignViewportI;
5    import jalview.bin.Cache;
6    import jalview.bin.Console;
7    import jalview.datamodel.Alignment;
8    import jalview.datamodel.AlignmentI;
9    import jalview.datamodel.AnnotatedCollectionI;
10    import jalview.datamodel.ResidueCount;
11    import jalview.datamodel.SequenceGroup;
12    import jalview.datamodel.SequenceI;
13    import jalview.gui.AlignFrame;
14    import jalview.gui.JvOptionPane;
15    import jalview.io.DataSourceType;
16    import jalview.io.FileParse;
17    import jalview.io.HMMFile;
18    import jalview.util.FileUtils;
19    import jalview.util.MessageManager;
20    import jalview.ws.params.ArgumentI;
21   
22    import java.io.File;
23    import java.io.IOException;
24    import java.util.ArrayList;
25    import java.util.Hashtable;
26    import java.util.List;
27    import java.util.Map;
28   
29    /**
30    * A class that runs the hmmbuild command as a separate process.
31    *
32    * @author gmcarstairs
33    *
34    */
 
35    public class HMMBuild extends HmmerCommand
36    {
37    static final String ARG_AMINO = "--amino";
38   
39    static final String ARG_DNA = "--dna";
40   
41    static final String ARG_RNA = "--rna";
42   
43    /**
44    * Constructor
45    *
46    * @param alignFrame
47    * @param args
48    */
 
49  0 toggle public HMMBuild(AlignFrame alignFrame, List<ArgumentI> args)
50    {
51  0 super(alignFrame, args);
52    }
53   
54    /**
55    * Builds a HMM from an alignment (and/or groups), then imports and adds it to
56    * the alignment (and/or groups). Call this method directly to execute
57    * synchronously, or via start() in a new Thread for asynchronously.
58    */
 
59  0 toggle @Override
60    public void run()
61    {
62  0 if (params == null || params.isEmpty())
63    {
64  0 Console.error("No parameters to HMMBuild!|");
65  0 return;
66    }
67   
68  0 long msgID = System.currentTimeMillis();
69  0 af.setProgressBar(MessageManager.getString("status.running_hmmbuild"),
70    msgID);
71   
72  0 AlignViewportI viewport = af.getViewport();
73  0 try
74    {
75    /*
76    * run hmmbuild for alignment and/or groups as selected
77    */
78  0 List<AnnotatedCollectionI> runBuildFor = parseParameters(viewport);
79   
80  0 for (AnnotatedCollectionI grp : runBuildFor)
81    {
82  0 runHMMBuild(grp);
83    }
84    } finally
85    {
86  0 af.setProgressBar("", msgID);
87  0 viewport.alignmentChanged(af.alignPanel);
88  0 af.buildColourMenu(); // to enable HMMER colour schemes
89    }
90    }
91   
92    /**
93    * Scans the parameters to determine whether to run hmmmbuild for the whole
94    * alignment or specified subgroup(s) or both
95    *
96    * @param viewport
97    * @return
98    */
 
99  0 toggle protected List<AnnotatedCollectionI> parseParameters(
100    AlignViewportI viewport)
101    {
102  0 List<AnnotatedCollectionI> runBuildFor = new ArrayList<>();
103  0 boolean foundArg = false;
104   
105  0 for (ArgumentI arg : params)
106    {
107  0 String name = arg.getName();
108  0 if (MessageManager.getString("label.hmmbuild_for").equals(name))
109    {
110  0 foundArg = true;
111  0 String value = arg.getValue();
112   
113  0 if (MessageManager.getString("label.alignment").equals(value))
114    {
115  0 runBuildFor.add(viewport.getAlignmentView(false)
116    .getVisibleAlignment('-'));
117    }
118  0 else if (MessageManager.getString("label.groups_and_alignment")
119    .equals(value))
120    {
121  0 runBuildFor.add(viewport.getAlignmentView(false)
122    .getVisibleAlignment('-'));
123  0 runBuildFor.addAll(viewport.getAlignment().getGroups());
124    }
125  0 else if (MessageManager.getString("label.groups").equals(value))
126    {
127  0 runBuildFor.addAll(viewport.getAlignment().getGroups());
128    }
129  0 else if (MessageManager.getString("label.selected_group")
130    .equals(value))
131    {
132  0 runBuildFor.add(viewport.getSelectionGroup());
133    }
134    }
135  0 else if (MessageManager.getString("label.use_reference")
136    .equals(name))
137    {
138    // todo disable this option if no RF annotation on alignment
139  0 if (!af.getViewport().hasReferenceAnnotation())
140    {
141  0 JvOptionPane.showInternalMessageDialog(af, MessageManager
142    .getString("warn.no_reference_annotation"));
143    // return;
144    }
145    }
146    }
147   
148    /*
149    * default is to build for the whole alignment
150    */
151  0 if (!foundArg)
152    {
153  0 runBuildFor.add(alignment);
154    }
155   
156  0 return runBuildFor;
157    }
158   
159    /**
160    * Runs hmmbuild on the given sequences (alignment or group)
161    *
162    * @param grp
163    */
 
164  0 toggle private void runHMMBuild(AnnotatedCollectionI ac)
165    {
166  0 File hmmFile = null;
167  0 File alignmentFile = null;
168  0 try
169    {
170  0 hmmFile = FileUtils.createTempFile("hmm", ".hmm");
171  0 alignmentFile = FileUtils.createTempFile("output", ".sto");
172   
173  0 if (ac instanceof Alignment)
174    {
175  0 AlignmentI al = (Alignment) ac;
176    // todo pad gaps in an unaligned SequenceGroup as well?
177  0 if (!al.isAligned())
178    {
179  0 al.padGaps();
180    }
181    }
182   
183  0 deleteHmmSequences(ac);
184   
185  0 List<SequenceI> copy = new ArrayList<>();
186  0 if (ac instanceof Alignment)
187    {
188  0 copy.addAll(ac.getSequences());
189    }
190    else
191    {
192  0 SequenceI[] sel = ((SequenceGroup) ac)
193    .getSelectionAsNewSequences((AlignmentI) ac.getContext());
194  0 for (SequenceI seq : sel)
195    {
196  0 if (seq != null)
197    {
198  0 copy.add(seq);
199    }
200    }
201    }
202    // TODO rather than copy alignment data we should anonymize in situ -
203    // export/File import could use anonymization hash to reinstate references
204    // at import level ?
205   
206  0 SequenceI[] copyArray = copy.toArray(new SequenceI[copy.size()]);
207  0 Map<String, SequenceInfo> sequencesHash = stashSequences(copyArray);
208   
209  0 exportStockholm(copyArray, alignmentFile, ac);
210   
211  0 recoverSequences(sequencesHash, copy.toArray(new SequenceI[] {}));
212   
213  0 boolean ran = runCommand(alignmentFile, hmmFile, ac);
214  0 if (!ran)
215    {
216  0 JvOptionPane.showInternalMessageDialog(af, MessageManager
217    .formatMessage("warn.command_failed", "hmmbuild"));
218  0 return;
219    }
220  0 importData(hmmFile, ac);
221    } catch (Exception e)
222    {
223  0 e.printStackTrace();
224    } finally
225    {
226  0 if (hmmFile != null)
227    {
228  0 hmmFile.delete();
229    }
230  0 if (alignmentFile != null)
231    {
232  0 alignmentFile.delete();
233    }
234    }
235    }
236   
237    /**
238    * Constructs and executes the hmmbuild command as a separate process
239    *
240    * @param sequencesFile
241    * the alignment from which the HMM is built
242    * @param hmmFile
243    * the output file to which the HMM is written
244    * @param group
245    * alignment or group for which the hmm is generated
246    *
247    * @return
248    * @throws IOException
249    */
 
250  0 toggle private boolean runCommand(File sequencesFile, File hmmFile,
251    AnnotatedCollectionI group) throws IOException
252    {
253  0 String cmd = getCommandPath(HMMBUILD);
254  0 if (cmd == null)
255    {
256  0 return false; // executable not found
257    }
258  0 List<String> args = new ArrayList<>();
259  0 args.add(cmd);
260   
261    /*
262    * HMM name (will be given to consensus sequence) is
263    * - as specified by an input parameter if set
264    * - else group name with _HMM appended (if for a group)
265    * - else align frame title with _HMM appended (if title is not too long)
266    * - else "Alignment_HMM"
267    */
268  0 String name = "";
269   
270  0 if (params != null)
271    {
272  0 for (ArgumentI arg : params)
273    {
274  0 String argName = arg.getName();
275  0 switch (argName)
276    {
277  0 case "HMM Name":
278  0 name = arg.getValue().trim();
279  0 break;
280  0 case "Use Reference Annotation":
281  0 args.add("--hand");
282  0 break;
283    }
284    }
285    }
286   
287  0 if (group instanceof SequenceGroup)
288    {
289  0 name = ((SequenceGroup) group).getName() + "_HMM";
290    }
291   
292  0 if ("".equals(name))
293    {
294  0 if (af != null && af.getTitle().length() < 15)
295    {
296  0 name = af.getTitle();
297    }
298    else
299    {
300  0 name = "Alignment_HMM";
301    }
302    }
303   
304  0 args.add("-n");
305  0 args.add(name.replace(' ', '_'));
306  0 if (!alignment.isNucleotide())
307    {
308  0 args.add(ARG_AMINO); // TODO check for rna
309    }
310    else
311    {
312  0 args.add(ARG_DNA);
313    }
314   
315  0 args.add(getFilePath(hmmFile, true));
316  0 args.add(getFilePath(sequencesFile, true));
317   
318  0 return runCommand(args);
319    }
320   
321    /**
322    * Imports the .hmm file produced by hmmbuild, and inserts the HMM consensus
323    * sequence (with attached HMM profile) as the first sequence in the alignment
324    * or group for which it was generated
325    *
326    * @param hmmFile
327    * @param ac
328    * (optional) the group for which the hmm was generated
329    * @throws IOException
330    */
 
331  0 toggle private void importData(File hmmFile, AnnotatedCollectionI ac)
332    throws IOException
333    {
334  0 if (hmmFile.length() == 0L)
335    {
336  0 Console.error("Error: hmmbuild produced empty hmm file");
337  0 return;
338    }
339   
340  0 HMMFile file = new HMMFile(
341    new FileParse(hmmFile.getAbsolutePath(), DataSourceType.FILE));
342  0 SequenceI hmmSeq = file.getHMM().getConsensusSequence();
343   
344   
345   
346  0 ResidueCount counts = new ResidueCount(alignment.getSequences());
347  0 hmmSeq.getHMM().setBackgroundFrequencies(counts);
348   
349  0 if (hmmSeq == null)
350    {
351    // hmmbuild failure not detected earlier
352  0 return;
353    }
354   
355  0 if (ac instanceof SequenceGroup)
356    {
357  0 SequenceGroup grp = (SequenceGroup) ac;
358  0 char gapChar = alignment.getGapCharacter();
359  0 hmmSeq.insertCharAt(0, ac.getStartRes(), gapChar);
360  0 hmmSeq.insertCharAt(ac.getEndRes() + 1,
361    alignment.getWidth() - ac.getEndRes() - 1, gapChar);
362  0 SequenceI topSeq = grp.getSequencesInOrder(alignment)[0];
363  0 int topIndex = alignment.findIndex(topSeq);
364  0 alignment.insertSequenceAt(topIndex, hmmSeq);
365  0 ac.setSeqrep(hmmSeq);
366  0 grp.addSequence(hmmSeq, false);
367    }
368    else
369    {
370  0 alignment.insertSequenceAt(0, hmmSeq);
371    }
372    }
373    }