3 import jalview.api.AlignViewportI;
4 import jalview.bin.Cache;
5 import jalview.datamodel.Alignment;
6 import jalview.datamodel.AlignmentI;
7 import jalview.datamodel.AnnotatedCollectionI;
8 import jalview.datamodel.SequenceGroup;
9 import jalview.datamodel.SequenceI;
10 import jalview.gui.AlignFrame;
11 import jalview.gui.JvOptionPane;
12 import jalview.io.DataSourceType;
13 import jalview.io.FileParse;
14 import jalview.io.HMMFile;
15 import jalview.util.FileUtils;
16 import jalview.util.MessageManager;
17 import jalview.ws.params.ArgumentI;
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Hashtable;
23 import java.util.List;
26 * A class that runs the hmmbuild command as a separate process.
31 public class HMMBuild extends HmmerCommand
33 static final String ARG_AMINO = "--amino";
35 static final String ARG_DNA = "--dna";
37 static final String ARG_RNA = "--rna";
45 public HMMBuild(AlignFrame alignFrame, List<ArgumentI> args)
47 super(alignFrame, args);
51 * Builds a HMM from an alignment (and/or groups), then imports and adds it to
52 * the alignment (and/or groups). Call this method directly to execute
53 * synchronously, or via start() in a new Thread for asynchronously.
58 if (params == null || params.isEmpty())
60 Cache.log.error("No parameters to HMMBuild!|");
64 long msgID = System.currentTimeMillis();
65 af.setProgressBar(MessageManager.getString("status.running_hmmbuild"),
68 AlignViewportI viewport = af.getViewport();
72 * run hmmbuild for alignment and/or groups as selected
74 List<AnnotatedCollectionI> runBuildFor = parseParameters(viewport);
76 for (AnnotatedCollectionI grp : runBuildFor)
82 af.setProgressBar("", msgID);
83 viewport.alignmentChanged(af.alignPanel);
84 af.buildColourMenu(); // to enable HMMER colour schemes
89 * Scans the parameters to determine whether to run hmmmbuild for the whole
90 * alignment or specified subgroup(s) or both
95 protected List<AnnotatedCollectionI> parseParameters(
96 AlignViewportI viewport)
98 List<AnnotatedCollectionI> runBuildFor = new ArrayList<>();
99 for (ArgumentI arg : params)
101 String name = arg.getName();
102 if (MessageManager.getString("label.hmmbuild_for").equals(name))
104 String value = arg.getValue();
105 if (MessageManager.getString("label.alignment").equals(value))
107 runBuildFor.add(alignment);
109 else if (MessageManager.getString("label.groups_and_alignment")
112 runBuildFor.add(alignment);
113 runBuildFor.addAll(viewport.getAlignment().getGroups());
115 else if (MessageManager.getString("label.groups").equals(value))
117 runBuildFor.addAll(viewport.getAlignment().getGroups());
119 else if (MessageManager.getString("label.selected_group")
122 runBuildFor.add(viewport.getSelectionGroup());
125 else if (MessageManager.getString("label.use_reference")
128 // todo disable this option if no RF annotation on alignment
129 if (!af.getViewport().hasReferenceAnnotation())
131 JvOptionPane.showInternalMessageDialog(af, MessageManager
132 .getString("warn.no_reference_annotation"));
141 * Runs hmmbuild on the given sequences (alignment or group)
145 private void runHMMBuild(AnnotatedCollectionI ac)
148 File alignmentFile = null;
151 hmmFile = FileUtils.createTempFile("hmm", ".hmm");
152 alignmentFile = FileUtils.createTempFile("output", ".sto");
154 if (ac instanceof Alignment)
156 AlignmentI al = (Alignment) ac;
157 // todo pad gaps in an unaligned SequenceGroup as well?
164 deleteHmmSequences(ac);
166 List<SequenceI> copy = new ArrayList<>();
167 if (ac instanceof Alignment)
169 copy.addAll(ac.getSequences());
173 SequenceI[] sel = ((SequenceGroup) ac)
174 .getSelectionAsNewSequences((AlignmentI) ac.getContext());
175 for (SequenceI seq : sel)
181 SequenceI[] copyArray = copy.toArray(new SequenceI[copy.size()]);
182 Hashtable sequencesHash = stashSequences(copyArray);
184 exportStockholm(copyArray, alignmentFile, ac);
186 recoverSequences(sequencesHash, copy.toArray(new SequenceI[] {}));
188 boolean ran = runCommand(alignmentFile, hmmFile, ac);
193 importData(hmmFile, ac);
194 } catch (Exception e)
203 if (alignmentFile != null)
205 alignmentFile.delete();
211 * A helper method that deletes any HMM consensus sequence from the given
212 * collection, and from the parent alignment if <code>ac</code> is a subgroup
216 void deleteHmmSequences(AnnotatedCollectionI ac)
218 SequenceI hmmSeq = ac.getHmmConsensus();
221 if (ac instanceof SequenceGroup)
223 ((SequenceGroup) ac).deleteSequence(hmmSeq, false);
224 AnnotatedCollectionI context = ac.getContext();
225 if (context != null && context instanceof AlignmentI)
227 ((AlignmentI) context).deleteSequence(hmmSeq);
232 ((AlignmentI) ac).deleteSequence(hmmSeq);
238 * Constructs and executes the hmmbuild command as a separate process
240 * @param sequencesFile
241 * the alignment from which the HMM is built
243 * the output file to which the HMM is written
245 * alignment or group for which the hmm is generated
248 * @throws IOException
250 private boolean runCommand(File sequencesFile, File hmmFile,
251 AnnotatedCollectionI group) throws IOException
253 String cmd = getCommandPath(HMMBUILD);
256 return false; // executable not found
258 List<String> args = new ArrayList<>();
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"
272 for (ArgumentI arg : params)
274 String argName = arg.getName();
278 name = arg.getValue().trim();
280 case "Use Reference Annotation":
287 if (group instanceof SequenceGroup)
289 name = ((SequenceGroup) group).getName() + "_HMM";
294 if (af != null && af.getTitle().length() < 15)
296 name = af.getTitle();
300 name = "Alignment_HMM";
305 args.add(name.replace(' ', '_'));
306 if (!alignment.isNucleotide())
308 args.add(ARG_AMINO); // TODO check for rna
315 args.add(hmmFile.getAbsolutePath());
316 args.add(sequencesFile.getAbsolutePath());
318 return runCommand(args);
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
328 * (optional) the group for which the hmm was generated
329 * @throws IOException
331 private void importData(File hmmFile, AnnotatedCollectionI ac)
334 if (hmmFile.length() == 0L)
336 Cache.log.error("Error: hmmbuild produced empty hmm file");
340 HMMFile file = new HMMFile(
341 new FileParse(hmmFile.getAbsolutePath(), DataSourceType.FILE));
342 SequenceI hmmSeq = file.getHMM().getConsensusSequence();
346 // hmmbuild failure not detected earlier
350 if (ac instanceof SequenceGroup)
352 SequenceGroup grp = (SequenceGroup) ac;
353 char gapChar = alignment.getGapCharacter();
354 hmmSeq.insertCharAt(0, ac.getStartRes(), gapChar);
355 hmmSeq.insertCharAt(ac.getEndRes() + 1,
356 alignment.getWidth() - ac.getEndRes() - 1, gapChar);
357 SequenceI topSeq = grp.getSequencesInOrder(alignment)[0];
358 int topIndex = alignment.findIndex(topSeq);
359 alignment.insertSequenceAt(topIndex, hmmSeq);
360 ac.setSeqrep(hmmSeq);
361 grp.addSequence(hmmSeq, false);
362 grp.setHmmConsensus(hmmSeq);
366 alignment.insertSequenceAt(0, hmmSeq);
367 alignment.setHmmConsensus(hmmSeq);
370 if (af.getSelectedHMM() == null)
372 af.setSelectedHMMSequence(hmmSeq);