Clover icon

Coverage Report

  1. Project Clover database Wed Dec 3 2025 17:03:17 GMT
  2. Package jalview.hmmer

File HMMSearch.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
60% of files have more coverage

Code metrics

40
99
6
1
319
236
28
0.28
16.5
6
4.67

Classes

Class Line # Actions
HMMSearch 33 99 28
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    package jalview.hmmer;
2   
3    import jalview.bin.Cache;
4    import jalview.bin.Console;
5    import jalview.datamodel.Alignment;
6    import jalview.datamodel.AlignmentAnnotation;
7    import jalview.datamodel.AlignmentI;
8    import jalview.datamodel.Annotation;
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.io.DataSourceType;
15    import jalview.io.FileParse;
16    import jalview.io.StockholmFile;
17    import jalview.util.FileUtils;
18    import jalview.util.MessageManager;
19    import jalview.ws.params.ArgumentI;
20    import jalview.ws.params.simple.BooleanOption;
21    import jalview.ws.params.simple.Option;
22   
23    import java.io.BufferedReader;
24    import java.io.File;
25    import java.io.FileReader;
26    import java.io.IOException;
27    import java.util.ArrayList;
28    import java.util.Collections;
29    import java.util.List;
30   
31    import javax.swing.JOptionPane;
32   
 
33    public class HMMSearch extends Search
34    {
35   
36    boolean realign = false;
37   
38    boolean trim = false;
39   
40    boolean returnNoOfNewSeqs = false;
41   
42    int seqsToReturn = Integer.MAX_VALUE;
43   
44   
45    /**
46    * Constructor for the HMMSearchThread
47    *
48    * @param af
49    */
 
50  0 toggle public HMMSearch(AlignFrame af, List<ArgumentI> args)
51    {
52  0 super(af, args);
53    }
54   
55    /**
56    * Runs the HMMSearchThread: the data on the alignment or group is exported,
57    * then the command is executed in the command line and then the data is
58    * imported and displayed in a new frame. Call this method directly to execute
59    * synchronously, or via start() in a new Thread for asynchronously.
60    */
 
61  0 toggle @Override
62    public void run()
63    {
64  0 HiddenMarkovModel hmm = getHmmProfile();
65  0 if (hmm == null)
66    {
67    // shouldn't happen if we got this far
68  0 Console.error("Error: no hmm for hmmsearch");
69  0 return;
70    }
71   
72  0 SequenceI hmmSeq = hmm.getConsensusSequence();
73  0 long msgId = System.currentTimeMillis();
74  0 af.setProgressBar(MessageManager.getString("status.running_search"),
75    msgId);
76   
77  0 try
78    {
79  0 File hmmFile = FileUtils.createTempFile("hmm", ".hmm");
80  0 File hitsAlignmentFile = FileUtils.createTempFile("hitAlignment",
81    ".sto");
82  0 File searchOutputFile = FileUtils.createTempFile("searchOutput",
83    ".sto");
84   
85  0 exportHmm(hmm, hmmFile.getAbsoluteFile());
86   
87  0 boolean ran = runCommand(searchOutputFile, hitsAlignmentFile, hmmFile);
88  0 if (!ran)
89    {
90  0 JvOptionPane.showInternalMessageDialog(af, MessageManager
91    .formatMessage("warn.command_failed", "hmmsearch"));
92  0 return;
93    }
94   
95  0 importData(hmmSeq, hitsAlignmentFile, hmmFile, searchOutputFile);
96    // TODO make realignment of search results a step at this level
97    // and make it conditional on this.realign
98    } catch (IOException | InterruptedException e)
99    {
100  0 e.printStackTrace();
101    }
102    finally
103    {
104  0 af.setProgressBar("", msgId);
105    }
106    }
107   
108    /**
109    * Executes an hmmsearch with the given hmm as input. The database to be
110    * searched is a local file as specified by the 'Database' parameter, or the
111    * current alignment (written to file) if none is specified.
112    *
113    * @param searchOutputFile
114    * @param hitsAlignmentFile
115    * @param hmmFile
116    *
117    * @return
118    * @throws IOException
119    */
 
120  0 toggle private boolean runCommand(File searchOutputFile, File hitsAlignmentFile,
121    File hmmFile) throws IOException
122    {
123  0 String command = getCommandPath(HMMSEARCH);
124  0 if (command == null)
125    {
126  0 return false;
127    }
128   
129  0 List<String> args = new ArrayList<>();
130  0 args.add(command);
131  0 buildArguments(args, searchOutputFile, hitsAlignmentFile, hmmFile);
132   
133  0 return runCommand(args);
134    }
135   
136   
137    /**
138    * Imports the data from the temporary file to which the output of hmmsearch
139    * was directed. The results are optionally realigned using hmmalign.
140    *
141    * @param hmmSeq
142    */
 
143  0 toggle private void importData(SequenceI hmmSeq, File inputAlignmentTemp,
144    File hmmTemp, File searchOutputFile)
145    throws IOException, InterruptedException
146    {
147  0 BufferedReader br = new BufferedReader(
148    new FileReader(inputAlignmentTemp));
149  0 try
150    {
151  0 if (br.readLine() == null)
152    {
153  0 JOptionPane.showMessageDialog(af,
154    MessageManager.getString("label.no_sequences_found"));
155  0 return;
156    }
157  0 StockholmFile file = new StockholmFile(new FileParse(
158    inputAlignmentTemp.getAbsolutePath(), DataSourceType.FILE));
159  0 seqs = file.getSeqsAsArray();
160   
161  0 readDomainTable(searchOutputFile, false);
162   
163  0 if (searchAlignment)
164    {
165  0 recoverSequences(sequencesHash, seqs);
166    }
167   
168    // look for PP cons and ref seq in alignment only annotation
169  0 AlignmentAnnotation modelpos = null, ppcons = null;
170  0 for (AlignmentAnnotation aa : file.getAnnotations())
171    {
172  0 if (aa.sequenceRef == null)
173    {
174  0 if (aa.label.equals("Reference Positions")) // RF feature type in
175    // stockholm parser
176    {
177  0 modelpos = aa;
178    }
179  0 if (aa.label.equals("Posterior Probability"))
180    {
181  0 ppcons = aa;
182    }
183    }
184    }
185   
186   
187  0 int seqCount = Math.min(seqs.length, seqsToReturn);
188  0 SequenceI[] hmmAndSeqs = new SequenceI[seqCount + 1];
189  0 hmmSeq = hmmSeq.deriveSequence(); // otherwise all bad things happen
190  0 hmmAndSeqs[0] = hmmSeq;
191  0 System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqCount);
192  0 if (modelpos != null)
193    {
194    // TODO need - get ungapped sequence method
195  0 hmmSeq.setSequence(
196    hmmSeq.getDatasetSequence().getSequenceAsString());
197  0 Annotation[] refpos = modelpos.annotations;
198    // insert gaps to match with refseq positions
199  0 int gc = 0, lcol = 0;
200  0 for (int c = 0; c < refpos.length; c++)
201    {
202  0 if (refpos[c] != null && ("x".equals(refpos[c].displayCharacter)))
203    {
204  0 if (gc > 0)
205    {
206  0 hmmSeq.insertCharAt(lcol + 1, gc, '-');
207    }
208  0 gc = 0;
209  0 lcol = c;
210    }
211    else
212    {
213  0 gc++;
214    }
215    }
216    }
217   
218  0 if (realign)
219    {
220  0 realignResults(hmmAndSeqs);
221    }
222    else
223    {
224  0 AlignmentI al = new Alignment(hmmAndSeqs);
225  0 if (ppcons != null)
226    {
227  0 al.addAnnotation(ppcons);
228    }
229  0 if (modelpos != null)
230    {
231  0 al.addAnnotation(modelpos);
232    }
233  0 AlignFrame alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
234    AlignFrame.DEFAULT_HEIGHT);
235  0 String ttl = "hmmSearch of " + databaseName + " using "
236    + hmmSeq.getName();
237  0 Desktop.addInternalFrame(alignFrame, ttl, AlignFrame.DEFAULT_WIDTH,
238    AlignFrame.DEFAULT_HEIGHT);
239   
240  0 if (returnNoOfNewSeqs)
241    {
242  0 int nNew = checkForNewSequences();
243  0 JvOptionPane.showMessageDialog(af.alignPanel, nNew + " "
244    + MessageManager.getString("label.new_returned"));
245    }
246   
247    }
248   
249   
250  0 hmmTemp.delete();
251  0 inputAlignmentTemp.delete();
252  0 searchOutputFile.delete();
253    } finally
254    {
255  0 if (br != null)
256    {
257  0 br.close();
258    }
259    }
260    }
261   
 
262  0 toggle private int checkForNewSequences()
263    {
264  0 int nNew = seqs.length;
265   
266  0 for (SequenceI resultSeq : seqs)
267    {
268  0 for (SequenceI aliSeq : alignment.getSequencesArray())
269    {
270  0 if (resultSeq.getName().equals(aliSeq.getName()))
271    {
272  0 nNew--;
273  0 break;
274    }
275    }
276    }
277   
278  0 return nNew;
279   
280    }
281   
282    /**
283    * Realigns the given sequences using hmmalign, to the HMM profile sequence
284    * which is the first in the array, and opens the results in a new frame
285    *
286    * @param hmmAndSeqs
287    */
 
288  0 toggle protected void realignResults(SequenceI[] hmmAndSeqs)
289    {
290    /*
291    * and align the search results to the HMM profile
292    */
293  0 AlignmentI al = new Alignment(hmmAndSeqs);
294  0 AlignFrame frame = new AlignFrame(al, 1, 1);
295  0 List<ArgumentI> alignArgs = new ArrayList<>();
296  0 String alignTo = hmmAndSeqs[0].getName();
297  0 List<String> options = Collections.singletonList(alignTo);
298  0 Option option = new Option(MessageManager.getString("label.use_hmm"),
299    "", true, alignTo, alignTo, options, null);
300  0 alignArgs.add(option);
301  0 if (trim)
302    {
303  0 alignArgs.add(new BooleanOption(
304    MessageManager.getString(TRIM_TERMINI_KEY),
305    MessageManager.getString("label.trim_termini_desc"), true,
306    true, true, null));
307    }
308  0 HmmerCommand hmmalign = new HMMAlign(frame, alignArgs);
309  0 hmmalign.run();
310   
311  0 if (returnNoOfNewSeqs)
312    {
313  0 int nNew = checkForNewSequences();
314  0 JvOptionPane.showMessageDialog(frame.alignPanel,
315    nNew + " " + MessageManager.getString("label.new_returned"));
316    }
317    }
318   
319    }