3 import jalview.analysis.AlignmentSorter;
4 import jalview.analysis.SeqsetUtils;
5 import jalview.bin.Cache;
6 import jalview.datamodel.Alignment;
7 import jalview.datamodel.AlignmentI;
8 import jalview.datamodel.AlignmentOrder;
9 import jalview.datamodel.AlignmentView;
10 import jalview.datamodel.HiddenColumns;
11 import jalview.datamodel.HiddenMarkovModel;
12 import jalview.datamodel.SequenceI;
13 import jalview.gui.AlignFrame;
14 import jalview.gui.Desktop;
15 import jalview.gui.JvOptionPane;
16 import jalview.gui.SplitFrame;
17 import jalview.io.DataSourceType;
18 import jalview.io.StockholmFile;
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.List;
28 import javax.swing.JInternalFrame;
30 public class HMMAlignThread extends HmmerCommand implements Runnable
32 static final String HMMALIGN = "hmmalign";
35 * feature settings from view that job was associated with
37 protected FeatureRendererSettings featureSettings = null;
43 List<AlignmentOrder> orders;
47 HiddenMarkovModel hmm;
59 File inputTemp = null;
61 List<AlignmentOrder> allOrders;
63 SequenceI[][] allResults;
66 * Constructor for the HMMAlignThread. If create new frame is set to true, a
67 * new frame will be created.
70 * @param createNewFrame
72 public HMMAlignThread(AlignFrame af, boolean createNewFrame,
76 alignment = af.getViewport().getAlignment();
77 if (alignment.getDataset() != null)
79 dataset = alignment.getDataset();
81 newFrame = createNewFrame;
82 featureSettings = af.getFeatureRenderer().getSettings();
87 * Runs the HMMAlignThread: the data on the alignment or group is exported,
88 * then the command is executed in the command line and then the data is
89 * imported and displayed in a new frame (if true). The command is executed
90 * for each segemtn of the alignment.
96 hmm = af.getSelectedHMM();
98 barID = System.currentTimeMillis();
99 af.setProgressBar(MessageManager.getString("status.running_hmmalign"),
102 SequenceI[][] subAlignments = msa.getVisibleContigs('-');
103 allOrders = new ArrayList<>();
104 allResults = new SequenceI[subAlignments.length][];
106 for (SequenceI[] seqs : subAlignments)
108 uniquifySequences(seqs);
111 createTemporaryFiles();
112 } catch (IOException e2)
114 e2.printStackTrace();
118 exportData(seqs, outTemp.getAbsoluteFile(), hmm,
119 hmmTemp.getAbsoluteFile(), null);
120 } catch (IOException e1)
122 e1.printStackTrace();
126 boolean ran = runCommand();
129 JvOptionPane.showInternalMessageDialog(af,
130 MessageManager.getString("warn.hmmalign_failed"));
133 } catch (IOException | InterruptedException e)
140 } catch (IOException | InterruptedException e)
142 // TODO Auto-generated catch block
148 displayResults(newFrame);
150 af.setProgressBar("", barID);
155 * Creates temporary files for exporting and importing the data.
157 * @throws IOException
159 private void createTemporaryFiles() throws IOException
163 hmmTemp = File.createTempFile("hmm", ".hmm");
164 hmmTemp.deleteOnExit();
168 outTemp = File.createTempFile("output", ".sto");
169 outTemp.deleteOnExit();
171 inputTemp = File.createTempFile("input", ".sto");
172 inputTemp.deleteOnExit();
176 * Executes the hmmalign command in the command line
179 * @throws IOException
180 * @throws InterruptedException
182 private boolean runCommand() throws IOException, InterruptedException
184 String binaryPath = getCommandRoot(HMMALIGN);
185 if (binaryPath == null) {
188 String command = binaryPath + SPACE;
189 // todo parse version from ./hmmerbuild -h
190 String version = Cache.getProperty("HMMER_VERSION");
191 if (!"3.1b2".equals(version))
193 // command += ALLCOL; // todo obsolete option?
197 for (ArgumentI arg : args)
199 String name = arg.getName();
202 case "Trim Non-Matching Termini":
207 command += " -o " + inputTemp.getAbsolutePath() + SPACE
208 + hmmTemp.getAbsolutePath() + SPACE
209 + outTemp.getAbsolutePath();
210 return runCommand(command);
214 * Imports the data from the temporary file to which the output of hmmalign is
215 * directed. this is used for an internal job.
218 * The index of the 'job' (or region of an alignment).
219 * @throws IOException
220 * @throws InterruptedException
222 private void importData(int index)
223 throws IOException, InterruptedException
225 StockholmFile file = new StockholmFile(inputTemp.getAbsolutePath(),
226 DataSourceType.FILE);
227 SequenceI[] result = file.getSeqsAsArray();
228 AlignmentOrder msaorder = new AlignmentOrder(result);
229 AlignmentSorter.recoverOrder(result);
230 SeqsetUtils.deuniquify(hash, result);
231 allOrders.add(msaorder);
232 allResults[index] = result;
239 * Gathers the sequences in preparation for the alignment.
241 private void prepareAlignment()
243 // hmmSeqs = alignment.getHMMConsensusSequences(true);
244 msa = af.gatherSequencesForAlignment();
248 * Displays the results of all 'jobs'.
252 private void displayResults(boolean newFrame)
254 AlignmentOrder[] arrOrders = allOrders
255 .toArray(new AlignmentOrder[allOrders.size()]);
256 Object[] newview = msa.getUpdatedView(allResults, arrOrders, '-');
257 SequenceI[] alignment = (SequenceI[]) newview[0];
258 HiddenColumns hidden = (HiddenColumns) newview[1];
259 Alignment al = new Alignment(alignment);
260 al.setProperty("Alignment Program", "hmmalign");
263 al.setDataset(dataset);
268 displayInNewFrame(al, allOrders, hidden);
273 * Displays the results in a new frame.
276 * The alignment containing the results.
278 * The order of the sequences in the alignment on which the jobs were
281 * Hidden columns in the previous alignment.
283 private void displayInNewFrame(AlignmentI al,
284 List<AlignmentOrder> alorders, HiddenColumns hidden)
286 AlignFrame af = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH,
287 AlignFrame.DEFAULT_HEIGHT);
289 // initialise with same renderer settings as in parent alignframe.
290 af.getFeatureRenderer().transferSettings(this.featureSettings);
292 if (allOrders.size() > 0)
294 addSortByMenuItems(af, allOrders);
297 // TODO: refactor retrieve and show as new splitFrame as Desktop method
300 * If alignment was requested from one half of a SplitFrame, show in a
301 * SplitFrame with the other pane similarly aligned.
303 AlignFrame requestedBy = this.af;
304 if (requestedBy != null && requestedBy.getSplitViewContainer() != null
305 && requestedBy.getSplitViewContainer()
306 .getComplement(requestedBy) != null)
308 AlignmentI complement = requestedBy.getSplitViewContainer()
309 .getComplement(requestedBy);
310 String complementTitle = requestedBy.getSplitViewContainer()
311 .getComplementTitle(requestedBy);
312 // becomes null if the alignment window was closed before the alignment
314 AlignmentI copyComplement = new Alignment(complement);
315 // todo should this be done by copy constructor?
316 copyComplement.setGapCharacter(complement.getGapCharacter());
317 // share the same dataset (and the mappings it holds)
318 copyComplement.setDataset(complement.getDataset());
319 copyComplement.alignAs(al);
320 if (copyComplement.getHeight() > 0)
322 af.setTitle(this.af.getTitle());
323 AlignFrame af2 = new AlignFrame(copyComplement,
324 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
325 af2.setTitle(complementTitle);
326 String linkedTitle = MessageManager
327 .getString("label.linked_view_title");
328 JInternalFrame splitFrame = new SplitFrame(
329 al.isNucleotide() ? af : af2, al.isNucleotide() ? af2 : af);
330 Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
336 * Not from SplitFrame, or failed to created a complementary alignment
338 Desktop.addInternalFrame(af, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
339 AlignFrame.DEFAULT_HEIGHT);
343 * Add sort order options to the AlignFrame menus.
348 protected void addSortByMenuItems(AlignFrame af,
349 List<AlignmentOrder> alorders)
352 if (alorders.size() == 1)
354 af.addSortByOrderMenuItem("hmmalign" + " Ordering", alorders.get(0));
358 // construct a non-redundant ordering set
359 List<String> names = new ArrayList<>();
360 for (int i = 0, l = alorders.size(); i < l; i++)
362 String orderName = " Region " + i;
367 if (alorders.get(i).equals(alorders.get(j)))
371 orderName += "," + j;
379 if (i == 0 && j == 1)
385 names.add(orderName);
388 for (int i = 0, l = alorders.size(); i < l; i++)
390 af.addSortByOrderMenuItem("hmmalign" + (names.get(i)) + " Ordering",
397 * Runs hmmalign, and waits for the results to be imported before continuing
399 public void hmmalignWaitTillComplete()
401 Thread loader = new Thread(this);
404 while (loader.isAlive())
409 } catch (Exception ex)