3 import jalview.analysis.AlignmentSorter;
4 import jalview.analysis.SeqsetUtils.SequenceInfo;
5 import jalview.datamodel.Alignment;
6 import jalview.datamodel.AlignmentI;
7 import jalview.datamodel.AlignmentOrder;
8 import jalview.datamodel.AlignmentView;
9 import jalview.datamodel.HiddenColumns;
10 import jalview.datamodel.HiddenMarkovModel;
11 import jalview.datamodel.SequenceI;
12 import jalview.gui.AlignFrame;
13 import jalview.gui.Desktop;
14 import jalview.gui.JvOptionPane;
15 import jalview.gui.SplitFrame;
16 import jalview.io.DataSourceType;
17 import jalview.io.StockholmFile;
18 import jalview.util.FileUtils;
19 import jalview.util.MessageManager;
20 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
21 import jalview.ws.params.ArgumentI;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Hashtable;
27 import java.util.List;
30 import javax.swing.JInternalFrame;
32 public class HMMAlign extends HmmerCommand
34 static final String HMMALIGN = "hmmalign";
36 private final AlignmentI dataset;
39 * Constructor for the HMMAlignThread
44 public HMMAlign(AlignFrame af, List<ArgumentI> args)
47 if (alignment.getDataset() != null)
49 dataset = alignment.getDataset();
58 * Runs the HMMAlignThread: the data on the alignment or group is exported,
59 * then the command is executed in the command line and then the data is
60 * imported and displayed in a new frame (if true). The command is executed
61 * for each segment of the alignment. Call this method directly to execute
62 * synchronously, or via start() in a new Thread for asynchronously.
67 HiddenMarkovModel hmm = getHmmProfile();
69 long msgId = System.currentTimeMillis();
70 af.setProgressBar(MessageManager.getString("status.running_hmmalign"),
73 // ensure alignments are the same length
76 AlignmentView msa = af.gatherSequencesForAlignment();
77 SequenceI[][] subAlignments = msa.getVisibleContigs(alignment.getGapCharacter());
79 List<AlignmentOrder> allOrders = new ArrayList<>();
81 SequenceI[][] allResults = new SequenceI[subAlignments.length][];
83 for (SequenceI[] seqs : subAlignments)
85 Map<String, SequenceInfo> sequencesHash = stashSequences(seqs);
88 File modelFile = FileUtils.createTempFile("hmm", ".hmm");
89 File alignmentFile = FileUtils.createTempFile("output", ".sto");
90 File resultFile = FileUtils.createTempFile("input", ".sto");
92 exportStockholm(seqs, alignmentFile.getAbsoluteFile(), null);
93 exportHmm(hmm, modelFile.getAbsoluteFile());
95 boolean ran = runCommand(modelFile, alignmentFile, resultFile);
98 JvOptionPane.showInternalMessageDialog(af, MessageManager
99 .formatMessage("warn.command_failed", "hmmalign"));
103 SequenceI[] result = importData(resultFile, allOrders);
104 recoverSequences(sequencesHash, result);
105 allResults[job] = result;
107 alignmentFile.delete();
109 } catch (IOException e)
116 String title = "hmmalign to " + hmm.getConsensusSequence().getName();
117 displayResults(allResults, allOrders, msa, title);
119 af.setProgressBar("", msgId);
123 * Executes the hmmalign command and returns true if successful, false if an
127 * the HMM to align to
128 * @param alignmentFile
129 * the sequences to align
131 * the file to hold the results of alignment
133 * @throws IOException
135 private boolean runCommand(File modelFile, File alignmentFile,
136 File resultFile) throws IOException
138 String command = getCommandPath(HMMALIGN);
143 List<String> args = new ArrayList<>();
148 for (ArgumentI arg : params)
150 String name = arg.getName();
151 if (MessageManager.getString("label.trim_termini").equals(name))
158 args.add(getFilePath(resultFile, true));
159 args.add(getFilePath(modelFile, true));
160 args.add(getFilePath(alignmentFile, true));
162 return runCommand(args);
166 * Imports the data from the file holding the output of hmmalign
170 * a list of alignment orders to add to
173 * @throws IOException
175 private SequenceI[] importData(File resultFile,
176 List<AlignmentOrder> allOrders) throws IOException
178 StockholmFile file = new StockholmFile(getFilePath(resultFile, false),
179 DataSourceType.FILE);
180 SequenceI[] result = file.getSeqsAsArray();
181 AlignmentOrder msaorder = new AlignmentOrder(result);
182 AlignmentSorter.recoverOrder(result);
183 allOrders.add(msaorder);
189 * Displays the results of all 'jobs' in a new frame
197 private void displayResults(SequenceI[][] allResults,
198 List<AlignmentOrder> allOrders, AlignmentView msa, String title)
200 AlignmentOrder[] arrOrders = allOrders
201 .toArray(new AlignmentOrder[allOrders.size()]);
202 Object[] newview = msa.getUpdatedView(allResults, arrOrders,
203 alignment.getGapCharacter());
204 SequenceI[] seqs = (SequenceI[]) newview[0];
205 HiddenColumns hidden = (HiddenColumns) newview[1];
206 Alignment al = new Alignment(seqs);
207 al.setProperty("Alignment Program", "hmmalign");
210 al.setDataset(dataset);
213 displayInNewFrame(al, allOrders, hidden, title);
217 * Displays the results in a new frame
220 * The alignment containing the results
222 * The order of the sequences in the alignment on which the jobs were
225 * Hidden columns in the previous alignment
228 private void displayInNewFrame(AlignmentI al,
229 List<AlignmentOrder> alorders, HiddenColumns hidden, String title)
231 AlignFrame alignFrame = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH,
232 AlignFrame.DEFAULT_HEIGHT);
233 alignFrame.setTitle(title);
235 FeatureRendererSettings featureSettings = af.getFeatureRenderer()
237 // initialise with same renderer settings as in parent alignframe.
238 alignFrame.getFeatureRenderer().transferSettings(featureSettings);
240 addSortByMenuItems(alignFrame, alorders);
242 // TODO: refactor retrieve and show as new splitFrame as Desktop method
245 * If alignment was requested from one half of a SplitFrame, show in a
246 * SplitFrame with the other pane similarly aligned.
248 AlignFrame requestedBy = this.af;
249 if (requestedBy != null && requestedBy.getSplitViewContainer() != null
250 && requestedBy.getSplitViewContainer()
251 .getComplement(requestedBy) != null)
253 AlignmentI complement = requestedBy.getSplitViewContainer()
254 .getComplement(requestedBy);
255 String complementTitle = requestedBy.getSplitViewContainer()
256 .getComplementTitle(requestedBy);
257 // becomes null if the alignment window was closed before the alignment
259 AlignmentI copyComplement = new Alignment(complement);
260 // todo should this be done by copy constructor?
261 copyComplement.setGapCharacter(complement.getGapCharacter());
262 // share the same dataset (and the mappings it holds)
263 copyComplement.setDataset(complement.getDataset());
264 copyComplement.alignAs(al);
265 if (copyComplement.getHeight() > 0)
267 alignFrame.setTitle(this.af.getTitle());
268 AlignFrame af2 = new AlignFrame(copyComplement,
269 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
270 af2.setTitle(complementTitle);
271 String linkedTitle = MessageManager
272 .getString("label.linked_view_title");
273 JInternalFrame splitFrame = new SplitFrame(
274 al.isNucleotide() ? alignFrame : af2, al.isNucleotide() ? af2 : alignFrame);
275 Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
281 * Not from SplitFrame, or failed to created a complementary alignment
283 Desktop.addInternalFrame(alignFrame, alignFrame.getTitle(), AlignFrame.DEFAULT_WIDTH,
284 AlignFrame.DEFAULT_HEIGHT);
288 * Adds sort order options to the AlignFrame menus
293 protected void addSortByMenuItems(AlignFrame alignFrame,
294 List<AlignmentOrder> alorders)
297 if (alorders.size() == 1)
299 alignFrame.addSortByOrderMenuItem("hmmalign" + " Ordering", alorders.get(0));
303 // construct a non-redundant ordering set
304 List<String> names = new ArrayList<>();
305 for (int i = 0, l = alorders.size(); i < l; i++)
307 String orderName = " Region " + i;
312 if (alorders.get(i).equals(alorders.get(j)))
316 orderName += "," + j;
324 if (i == 0 && j == 1)
330 names.add(orderName);
333 for (int i = 0, l = alorders.size(); i < l; i++)
335 alignFrame.addSortByOrderMenuItem("hmmalign" + (names.get(i)) + " Ordering",