3 import jalview.bin.Cache;
4 import jalview.datamodel.Alignment;
5 import jalview.datamodel.AlignmentI;
6 import jalview.datamodel.AlignmentOrder;
7 import jalview.datamodel.AlignmentView;
8 import jalview.datamodel.HiddenColumns;
9 import jalview.datamodel.HiddenMarkovModel;
10 import jalview.datamodel.SequenceI;
11 import jalview.gui.AlignFrame;
12 import jalview.gui.Desktop;
13 import jalview.gui.JvOptionPane;
14 import jalview.gui.Preferences;
15 import jalview.gui.SplitFrame;
16 import jalview.io.DataSourceType;
17 import jalview.io.StockholmFile;
18 import jalview.util.MessageManager;
19 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
20 import jalview.ws.params.ArgumentI;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
28 import javax.swing.JInternalFrame;
30 public class HMMAlignThread implements Runnable
34 * feature settings from view that job was associated with
36 protected FeatureRendererSettings featureSettings = null;
39 * Object containing frequently used commands.
41 HMMERCommands cmds = new HMMERCommands();
49 List<AlignmentOrder> orders;
53 HiddenMarkovModel hmm;
61 Map<Integer, SequenceI> hmmSeqs;
67 File inputTemp = null;
69 List<AlignmentOrder> allOrders;
71 SequenceI[][] allResults;
74 * Constructor for the HMMAlignThread. If create new frame is set to true, a
75 * new frame will be created.
78 * @param createNewFrame
80 public HMMAlignThread(AlignFrame af, boolean createNewFrame,
84 alignment = af.getViewport().getAlignment();
85 if (alignment.getDataset() != null)
87 dataset = alignment.getDataset();
89 newFrame = createNewFrame;
90 featureSettings = af.getFeatureRenderer().getSettings();
95 * Runs the HMMAlignThread: the data on the alignment or group is exported,
96 * then the command is executed in the command line and then the data is
97 * imported and displayed in a new frame (if true). The command is executed
98 * for each segemtn of the alignment.
104 hmm = af.getSelectedHMM();
106 barID = System.currentTimeMillis();
107 af.setProgressBar(MessageManager.getString("status.running_hmmalign"),
109 cmds.HMMERFOLDER = Cache.getProperty(Preferences.HMMER_PATH);
111 SequenceI[][] subAlignments = msa.getVisibleContigs('-');
112 allOrders = new ArrayList<>();
113 allResults = new SequenceI[subAlignments.length][];
115 for (SequenceI[] seqs : subAlignments)
117 cmds.uniquifySequences(seqs);
120 createTemporaryFiles();
121 } catch (IOException e2)
123 e2.printStackTrace();
127 cmds.exportData(seqs, outTemp.getAbsoluteFile(), hmm,
128 hmmTemp.getAbsoluteFile(), null);
129 } catch (IOException e1)
131 e1.printStackTrace();
135 boolean ran = runCommand();
138 JvOptionPane.showInternalMessageDialog(af,
139 MessageManager.getString("warn.hmmalign_failed"));
142 } catch (IOException | InterruptedException e)
149 } catch (IOException | InterruptedException e)
151 // TODO Auto-generated catch block
157 displayResults(newFrame);
159 af.setProgressBar(MessageManager.getString("status.running_hmmalign"),
165 * Creates temporary files for exporting and importing the data.
167 * @throws IOException
169 private void createTemporaryFiles() throws IOException
173 hmmTemp = File.createTempFile("hmm", ".hmm");
174 hmmTemp.deleteOnExit();
178 outTemp = File.createTempFile("output", ".sto");
179 outTemp.deleteOnExit();
181 inputTemp = File.createTempFile("input", ".sto");
182 inputTemp.deleteOnExit();
186 * Executes the hmmalign command in the command line.
189 * @throws IOException
190 * @throws InterruptedException
192 private boolean runCommand() throws IOException, InterruptedException
194 File file = new File(cmds.HMMERFOLDER + "/hmmalign");
195 if (!file.canExecute())
197 file = new File(cmds.HMMERFOLDER + "/hmmalign.exe");
199 if (!file.canExecute())
205 String command = cmds.HMMERFOLDER + cmds.HMMALIGN;
206 String version = Cache.getProperty("HMMER_VERSION");
207 if (!"3.1b2".equals(version))
209 command += cmds.ALLCOL;
213 for (ArgumentI arg : args)
215 String name = arg.getName();
218 case "Trim Non-Matching Termini":
223 command += " -o " + inputTemp.getAbsolutePath() + cmds.SPACE
224 + hmmTemp.getAbsolutePath() + cmds.SPACE
225 + outTemp.getAbsolutePath();
226 return cmds.runCommand(command);
230 * Imports the data from the temporary file to which the output of hmmalign is
231 * directed. this is used for an internal job.
234 * The index of the 'job' (or region of an alignment).
235 * @throws IOException
236 * @throws InterruptedException
238 private void importData(int index)
239 throws IOException, InterruptedException
241 StockholmFile file = new StockholmFile(inputTemp.getAbsolutePath(),
242 DataSourceType.FILE);
243 SequenceI[] result = file.getSeqsAsArray();
244 AlignmentOrder msaorder = new AlignmentOrder(result);
245 jalview.analysis.AlignmentSorter.recoverOrder(result);
246 jalview.analysis.SeqsetUtils.deuniquify(cmds.hash, result);
247 allOrders.add(msaorder);
248 allResults[index] = result;
255 * Gathers the sequences in preparation for the alignment.
257 private void prepareAlignment()
259 // hmmSeqs = alignment.getHMMConsensusSequences(true);
260 msa = af.gatherSequencesForAlignment();
264 * Displays the results of all 'jobs'.
268 private void displayResults(boolean newFrame)
270 AlignmentOrder[] arrOrders = allOrders
271 .toArray(new AlignmentOrder[allOrders.size()]);
272 Object[] newview = msa.getUpdatedView(allResults, arrOrders, '-');
273 SequenceI[] alignment = (SequenceI[]) newview[0];
274 HiddenColumns hidden = (HiddenColumns) newview[1];
275 Alignment al = new Alignment(alignment);
276 al.setProperty("Alignment Program", "hmmalign");
279 al.setDataset(dataset);
284 displayInNewFrame(al, allOrders, hidden);
289 * Displays the results in a new frame.
292 * The alignment containing the results.
294 * The order of the sequences in the alignment on which the jobs were
297 * Hidden columns in the previous alignment.
299 private void displayInNewFrame(AlignmentI al,
300 List<AlignmentOrder> alorders, HiddenColumns hidden)
302 AlignFrame af = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH,
303 AlignFrame.DEFAULT_HEIGHT);
305 // initialise with same renderer settings as in parent alignframe.
306 af.getFeatureRenderer().transferSettings(this.featureSettings);
308 if (allOrders.size() > 0)
310 addSortByMenuItems(af, allOrders);
313 // TODO: refactor retrieve and show as new splitFrame as Desktop method
316 * If alignment was requested from one half of a SplitFrame, show in a
317 * SplitFrame with the other pane similarly aligned.
319 AlignFrame requestedBy = this.af;
320 if (requestedBy != null && requestedBy.getSplitViewContainer() != null
321 && requestedBy.getSplitViewContainer()
322 .getComplement(requestedBy) != null)
324 AlignmentI complement = requestedBy.getSplitViewContainer()
325 .getComplement(requestedBy);
326 String complementTitle = requestedBy.getSplitViewContainer()
327 .getComplementTitle(requestedBy);
328 // becomes null if the alignment window was closed before the alignment
330 AlignmentI copyComplement = new Alignment(complement);
331 // todo should this be done by copy constructor?
332 copyComplement.setGapCharacter(complement.getGapCharacter());
333 // share the same dataset (and the mappings it holds)
334 copyComplement.setDataset(complement.getDataset());
335 copyComplement.alignAs(al);
336 if (copyComplement.getHeight() > 0)
338 af.setTitle(this.af.getTitle());
339 AlignFrame af2 = new AlignFrame(copyComplement,
340 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
341 af2.setTitle(complementTitle);
342 String linkedTitle = MessageManager
343 .getString("label.linked_view_title");
344 JInternalFrame splitFrame = new SplitFrame(
345 al.isNucleotide() ? af : af2, al.isNucleotide() ? af2 : af);
346 Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
352 * Not from SplitFrame, or failed to created a complementary alignment
354 Desktop.addInternalFrame(af, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
355 AlignFrame.DEFAULT_HEIGHT);
359 * Add sort order options to the AlignFrame menus.
364 protected void addSortByMenuItems(AlignFrame af,
365 List<AlignmentOrder> alorders)
368 if (alorders.size() == 1)
370 af.addSortByOrderMenuItem("hmmalign" + " Ordering", alorders.get(0));
374 // construct a non-redundant ordering set
375 List<String> names = new ArrayList<>();
376 for (int i = 0, l = alorders.size(); i < l; i++)
378 String orderName = " Region " + i;
383 if (alorders.get(i).equals(alorders.get(j)))
387 orderName += "," + j;
395 if (i == 0 && j == 1)
401 names.add(orderName);
404 for (int i = 0, l = alorders.size(); i < l; i++)
406 af.addSortByOrderMenuItem("hmmalign" + (names.get(i)) + " Ordering",
413 * Runs hmmalign, and waits for the results to be imported before continuing
415 public void hmmalignWaitTillComplete()
417 Thread loader = new Thread(this);
420 while (loader.isAlive())
425 } catch (Exception ex)