3 import jalview.api.AlignViewportI;
4 import jalview.bin.Cache;
5 import jalview.datamodel.Alignment;
6 import jalview.datamodel.AlignmentI;
7 import jalview.datamodel.AlignmentView;
8 import jalview.datamodel.AnnotatedCollectionI;
9 import jalview.datamodel.ResidueCount;
10 import jalview.datamodel.SequenceGroup;
11 import jalview.datamodel.SequenceI;
12 import jalview.gui.AlignFrame;
13 import jalview.gui.JvOptionPane;
14 import jalview.io.DataSourceType;
15 import jalview.io.FileParse;
16 import jalview.io.HMMFile;
17 import jalview.util.FileUtils;
18 import jalview.util.MessageManager;
19 import jalview.ws.params.ArgumentI;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Hashtable;
25 import java.util.List;
28 * A class that runs the hmmbuild command as a separate process.
33 public class HMMBuild extends HmmerCommand
35 static final String ARG_AMINO = "--amino";
37 static final String ARG_DNA = "--dna";
39 static final String ARG_RNA = "--rna";
47 public HMMBuild(AlignFrame alignFrame, List<ArgumentI> args)
49 super(alignFrame, args);
53 * Builds a HMM from an alignment (and/or groups), then imports and adds it to
54 * the alignment (and/or groups). Call this method directly to execute
55 * synchronously, or via start() in a new Thread for asynchronously.
60 if (params == null || params.isEmpty())
62 Cache.log.error("No parameters to HMMBuild!|");
66 long msgID = System.currentTimeMillis();
67 af.setProgressBar(MessageManager.getString("status.running_hmmbuild"),
70 AlignViewportI viewport = af.getViewport();
74 * run hmmbuild for alignment and/or groups as selected
76 List<AnnotatedCollectionI> runBuildFor = parseParameters(viewport);
78 for (AnnotatedCollectionI grp : runBuildFor)
84 af.setProgressBar("", msgID);
85 viewport.alignmentChanged(af.alignPanel);
86 af.buildColourMenu(); // to enable HMMER colour schemes
91 * Scans the parameters to determine whether to run hmmmbuild for the whole
92 * alignment or specified subgroup(s) or both
97 protected List<AnnotatedCollectionI> parseParameters(
98 AlignViewportI viewport)
100 List<AnnotatedCollectionI> runBuildFor = new ArrayList<>();
101 boolean foundArg = false;
103 for (ArgumentI arg : params)
105 String name = arg.getName();
106 if (MessageManager.getString("label.hmmbuild_for").equals(name))
109 String value = arg.getValue();
111 if (MessageManager.getString("label.alignment").equals(value))
113 runBuildFor.add(viewport.getAlignmentView(false)
114 .getVisibleAlignment('-'));
116 else if (MessageManager.getString("label.groups_and_alignment")
119 AlignmentView av = viewport.getAlignmentView(true);
120 runBuildFor.add(av.getVisibleAlignment('-'));
121 runBuildFor.addAll(av.getVisibleGroups('-'));
123 else if (MessageManager.getString("label.groups").equals(value))
125 AlignmentView av = viewport.getAlignmentView(false);
126 runBuildFor.addAll(av.getVisibleGroups('-'));
128 else if (MessageManager.getString("label.selected_group")
131 AlignmentView av = viewport.getAlignmentView(true);
132 runBuildFor.add(av.getVisibleAlignment('-'));
135 else if (MessageManager.getString("label.use_reference")
138 // todo disable this option if no RF annotation on alignment
139 if (!af.getViewport().hasReferenceAnnotation())
141 JvOptionPane.showInternalMessageDialog(af, MessageManager
142 .getString("warn.no_reference_annotation"));
149 * default is to build for the whole alignment
153 runBuildFor.add(alignment);
160 * Runs hmmbuild on the given sequences (alignment or group)
164 private void runHMMBuild(AnnotatedCollectionI ac)
167 File alignmentFile = null;
170 hmmFile = FileUtils.createTempFile("hmm", ".hmm");
171 alignmentFile = FileUtils.createTempFile("output", ".sto");
173 if (ac instanceof Alignment)
175 AlignmentI al = (Alignment) ac;
176 // todo pad gaps in an unaligned SequenceGroup as well?
183 deleteHmmSequences(ac);
185 List<SequenceI> copy = new ArrayList<>();
186 if (ac instanceof Alignment)
188 copy.addAll(ac.getSequences());
192 SequenceI[] sel = ((SequenceGroup) ac)
193 .getSelectionAsNewSequences((AlignmentI) ac.getContext());
194 for (SequenceI seq : sel)
199 // TODO rather than copy alignment data we should anonymize in situ -
200 // export/File import could use anonymization hash to reinstate references
203 SequenceI[] copyArray = copy.toArray(new SequenceI[copy.size()]);
204 Hashtable sequencesHash = stashSequences(copyArray);
206 exportStockholm(copyArray, alignmentFile, ac);
208 recoverSequences(sequencesHash, copy.toArray(new SequenceI[] {}));
210 boolean ran = runCommand(alignmentFile, hmmFile, ac);
213 JvOptionPane.showInternalMessageDialog(af, MessageManager
214 .formatMessage("warn.command_failed", "hmmbuild"));
217 importData(hmmFile, ac);
218 } catch (Exception e)
227 if (alignmentFile != null)
229 alignmentFile.delete();
235 * Constructs and executes the hmmbuild command as a separate process
237 * @param sequencesFile
238 * the alignment from which the HMM is built
240 * the output file to which the HMM is written
242 * alignment or group for which the hmm is generated
245 * @throws IOException
247 private boolean runCommand(File sequencesFile, File hmmFile,
248 AnnotatedCollectionI group) throws IOException
250 String cmd = getCommandPath(HMMBUILD);
253 return false; // executable not found
255 List<String> args = new ArrayList<>();
259 * HMM name (will be given to consensus sequence) is
260 * - as specified by an input parameter if set
261 * - else group name with _HMM appended (if for a group)
262 * - else align frame title with _HMM appended (if title is not too long)
263 * - else "Alignment_HMM"
269 for (ArgumentI arg : params)
271 String argName = arg.getName();
275 name = arg.getValue().trim();
277 case "Use Reference Annotation":
284 if (group instanceof SequenceGroup)
286 name = ((SequenceGroup) group).getName() + "_HMM";
291 if (af != null && af.getTitle().length() < 15)
293 name = af.getTitle();
297 name = "Alignment_HMM";
302 args.add(name.replace(' ', '_'));
303 if (!alignment.isNucleotide())
305 args.add(ARG_AMINO); // TODO check for rna
312 args.add(getFilePath(hmmFile, true));
313 args.add(getFilePath(sequencesFile, true));
315 return runCommand(args);
319 * Imports the .hmm file produced by hmmbuild, and inserts the HMM consensus
320 * sequence (with attached HMM profile) as the first sequence in the alignment
321 * or group for which it was generated
325 * (optional) the group for which the hmm was generated
326 * @throws IOException
328 private void importData(File hmmFile, AnnotatedCollectionI ac)
331 if (hmmFile.length() == 0L)
333 Cache.log.error("Error: hmmbuild produced empty hmm file");
337 HMMFile file = new HMMFile(
338 new FileParse(hmmFile.getAbsolutePath(), DataSourceType.FILE));
339 SequenceI hmmSeq = file.getHMM().getConsensusSequence();
340 ResidueCount counts = new ResidueCount(alignment.getSequences());
341 hmmSeq.getHMM().setBackgroundFrequencies(counts);
345 // hmmbuild failure not detected earlier
349 if (ac instanceof SequenceGroup)
351 SequenceGroup grp = (SequenceGroup) ac;
352 char gapChar = alignment.getGapCharacter();
353 hmmSeq.insertCharAt(0, ac.getStartRes(), gapChar);
354 hmmSeq.insertCharAt(ac.getEndRes() + 1,
355 alignment.getWidth() - ac.getEndRes() - 1, gapChar);
356 SequenceI topSeq = grp.getSequencesInOrder(alignment)[0];
357 int topIndex = alignment.findIndex(topSeq);
358 alignment.insertSequenceAt(topIndex, hmmSeq);
359 ac.setSeqrep(hmmSeq);
360 grp.addSequence(hmmSeq, false);
364 alignment.insertSequenceAt(0, hmmSeq);