3 import jalview.analysis.AlignmentSorter;
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.SplitFrame;
15 import jalview.io.DataSourceType;
16 import jalview.io.StockholmFile;
17 import jalview.util.MessageManager;
18 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
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;
27 import javax.swing.JInternalFrame;
29 public class HMMAlign extends HmmerCommand
31 static final String HMMALIGN = "hmmalign";
33 static final String ARG_TRIM = "--trim";
35 private final AlignmentI dataset;
38 * Constructor for the HMMAlignThread
43 public HMMAlign(AlignFrame af, List<ArgumentI> args)
46 if (alignment.getDataset() != null)
48 dataset = alignment.getDataset();
57 * Runs the HMMAlignThread: the data on the alignment or group is exported,
58 * then the command is executed in the command line and then the data is
59 * imported and displayed in a new frame (if true). The command is executed
60 * for each segment of the alignment. Call this method directly to execute
61 * synchronously, or via start() in a new Thread for asynchronously.
66 HiddenMarkovModel hmm = af.getSelectedHMM();
69 System.err.println("Can't run hmmalign as no HMM profile selected");
73 long msgId = System.currentTimeMillis();
74 af.setProgressBar(MessageManager.getString("status.running_hmmalign"),
77 AlignmentView msa = af.gatherSequencesForAlignment();
78 SequenceI[][] subAlignments = msa.getVisibleContigs(alignment.getGapCharacter());
80 List<AlignmentOrder> allOrders = new ArrayList<>();
82 SequenceI[][] allResults = new SequenceI[subAlignments.length][];
84 for (SequenceI[] seqs : subAlignments)
86 Hashtable sequencesHash = stashSequences(seqs);
89 File modelFile = createTempFile("hmm", ".hmm");
90 File alignmentFile = createTempFile("output", ".sto");
91 File resultFile = createTempFile("input", ".sto");
93 exportStockholm(seqs, alignmentFile.getAbsoluteFile(), null);
94 exportHmm(hmm, modelFile.getAbsoluteFile());
96 boolean ran = runCommand(modelFile, alignmentFile, resultFile);
99 JvOptionPane.showInternalMessageDialog(af,
100 MessageManager.getString("warn.hmmalign_failed"));
104 SequenceI[] result = importData(resultFile, allOrders);
105 recoverSequences(sequencesHash, result);
106 allResults[job] = result;
108 alignmentFile.delete();
110 } catch (IOException e)
117 String title = "hmmalign to " + hmm.getConsensusSequence().getName();
118 displayResults(allResults, allOrders, msa, title);
120 af.setProgressBar("", msgId);
124 * Executes the hmmalign command and returns true if successful, false if an
128 * the HMM to align to
129 * @param alignmentFile
130 * the sequences to align
132 * the file to hold the results of alignment
134 * @throws IOException
136 private boolean runCommand(File modelFile, File alignmentFile,
137 File resultFile) throws IOException
139 String command = getCommandPath(HMMALIGN);
144 List<String> args = new ArrayList<>();
149 for (ArgumentI arg : params)
151 String name = arg.getName();
152 if (MessageManager.getString("label.trim_termini").equals(name))
159 args.add(resultFile.getAbsolutePath());
160 args.add(modelFile.getAbsolutePath());
161 args.add(alignmentFile.getAbsolutePath());
163 return runCommand(args);
167 * Imports the data from the file holding the output of hmmalign
171 * a list of alignment orders to add to
174 * @throws IOException
176 private SequenceI[] importData(File resultFile,
177 List<AlignmentOrder> allOrders) throws IOException
179 StockholmFile file = new StockholmFile(resultFile.getAbsolutePath(),
180 DataSourceType.FILE);
181 SequenceI[] result = file.getSeqsAsArray();
182 AlignmentOrder msaorder = new AlignmentOrder(result);
183 AlignmentSorter.recoverOrder(result);
184 allOrders.add(msaorder);
190 * Displays the results of all 'jobs' in a new frame
198 private void displayResults(SequenceI[][] allResults,
199 List<AlignmentOrder> allOrders, AlignmentView msa, String title)
201 AlignmentOrder[] arrOrders = allOrders
202 .toArray(new AlignmentOrder[allOrders.size()]);
203 Object[] newview = msa.getUpdatedView(allResults, arrOrders,
204 alignment.getGapCharacter());
205 SequenceI[] seqs = (SequenceI[]) newview[0];
206 HiddenColumns hidden = (HiddenColumns) newview[1];
207 Alignment al = new Alignment(seqs);
208 al.setProperty("Alignment Program", "hmmalign");
211 al.setDataset(dataset);
215 * hack to ensure hmm set on alignment
217 if (al.getSequenceAt(0).isHMMConsensusSequence())
219 al.setHmmConsensus(al.getSequenceAt(0));
222 displayInNewFrame(al, allOrders, hidden, title);
226 * Displays the results in a new frame
229 * The alignment containing the results
231 * The order of the sequences in the alignment on which the jobs were
234 * Hidden columns in the previous alignment
237 private void displayInNewFrame(AlignmentI al,
238 List<AlignmentOrder> alorders, HiddenColumns hidden, String title)
240 AlignFrame alignFrame = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH,
241 AlignFrame.DEFAULT_HEIGHT);
242 alignFrame.setTitle(title);
244 FeatureRendererSettings featureSettings = af.getFeatureRenderer()
246 // initialise with same renderer settings as in parent alignframe.
247 alignFrame.getFeatureRenderer().transferSettings(featureSettings);
249 addSortByMenuItems(alignFrame, alorders);
251 // TODO: refactor retrieve and show as new splitFrame as Desktop method
254 * If alignment was requested from one half of a SplitFrame, show in a
255 * SplitFrame with the other pane similarly aligned.
257 AlignFrame requestedBy = this.af;
258 if (requestedBy != null && requestedBy.getSplitViewContainer() != null
259 && requestedBy.getSplitViewContainer()
260 .getComplement(requestedBy) != null)
262 AlignmentI complement = requestedBy.getSplitViewContainer()
263 .getComplement(requestedBy);
264 String complementTitle = requestedBy.getSplitViewContainer()
265 .getComplementTitle(requestedBy);
266 // becomes null if the alignment window was closed before the alignment
268 AlignmentI copyComplement = new Alignment(complement);
269 // todo should this be done by copy constructor?
270 copyComplement.setGapCharacter(complement.getGapCharacter());
271 // share the same dataset (and the mappings it holds)
272 copyComplement.setDataset(complement.getDataset());
273 copyComplement.alignAs(al);
274 if (copyComplement.getHeight() > 0)
276 alignFrame.setTitle(this.af.getTitle());
277 AlignFrame af2 = new AlignFrame(copyComplement,
278 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
279 af2.setTitle(complementTitle);
280 String linkedTitle = MessageManager
281 .getString("label.linked_view_title");
282 JInternalFrame splitFrame = new SplitFrame(
283 al.isNucleotide() ? alignFrame : af2, al.isNucleotide() ? af2 : alignFrame);
284 Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
290 * Not from SplitFrame, or failed to created a complementary alignment
292 Desktop.addInternalFrame(alignFrame, alignFrame.getTitle(), AlignFrame.DEFAULT_WIDTH,
293 AlignFrame.DEFAULT_HEIGHT);
297 * Adds sort order options to the AlignFrame menus
302 protected void addSortByMenuItems(AlignFrame alignFrame,
303 List<AlignmentOrder> alorders)
306 if (alorders.size() == 1)
308 alignFrame.addSortByOrderMenuItem("hmmalign" + " Ordering", alorders.get(0));
312 // construct a non-redundant ordering set
313 List<String> names = new ArrayList<>();
314 for (int i = 0, l = alorders.size(); i < l; i++)
316 String orderName = " Region " + i;
321 if (alorders.get(i).equals(alorders.get(j)))
325 orderName += "," + j;
333 if (i == 0 && j == 1)
339 names.add(orderName);
342 for (int i = 0, l = alorders.size(); i < l; i++)
344 alignFrame.addSortByOrderMenuItem("hmmalign" + (names.get(i)) + " Ordering",