Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 14:43:25 GMT
  2. Package jalview.io

File HMMFileTest.java

 

Code metrics

20
259
13
1
531
420
23
0.09
19.92
13
1.77

Classes

Class Line # Actions
HMMFileTest 26 259 23
0.993150799.3%
 

Contributing tests

This file is covered by 10 tests. .

Source view

1    package jalview.io;
2   
3    import static org.testng.Assert.assertEquals;
4    import static org.testng.Assert.assertFalse;
5    import static org.testng.Assert.assertNotNull;
6    import static org.testng.Assert.assertNull;
7    import static org.testng.Assert.assertTrue;
8   
9    import jalview.datamodel.HMMNode;
10    import jalview.datamodel.HiddenMarkovModel;
11   
12    import java.io.BufferedReader;
13    import java.io.File;
14    import java.io.FileNotFoundException;
15    import java.io.FileReader;
16    import java.io.IOException;
17    import java.util.ArrayList;
18    import java.util.List;
19    import java.util.Scanner;
20   
21    import org.testng.annotations.BeforeClass;
22    import org.testng.annotations.Test;
23   
24    import junit.extensions.PA;
25   
 
26    public class HMMFileTest {
27   
28    HMMFile fn3;
29   
30    HMMFile pKinase;
31   
32    HMMFile made1;
33   
 
34  1 toggle @BeforeClass(alwaysRun = true)
35    public void setUp() throws IOException
36    {
37  1 fn3 = new HMMFile("test/jalview/io/test_fn3_hmm.txt",
38    DataSourceType.FILE);
39   
40  1 pKinase = new HMMFile("test/jalview/io/test_PKinase_hmm.txt",
41    DataSourceType.FILE);
42   
43  1 made1 = new HMMFile("test/jalview/io/test_MADE1_hmm.txt",
44    DataSourceType.FILE);
45    }
46   
 
47  1 toggle @Test(groups = "Functional")
48    public void testParse() throws IOException
49    {
50  1 HiddenMarkovModel hmm = pKinase.getHMM();
51  1 assertEquals(hmm.getName(), "Pkinase");
52  1 assertEquals(hmm.getProperty(HMMFile.ACCESSION_NUMBER), "PF00069.17");
53  1 assertEquals(hmm.getProperty(HMMFile.DESCRIPTION),
54    "Protein kinase domain");
55  1 assertEquals(hmm.getLength(), 260);
56  1 assertNull(hmm.getProperty(HMMFile.MAX_LENGTH));
57  1 assertEquals(hmm.getAlphabetType(), "amino");
58  1 assertFalse(hmm.getBooleanProperty(HMMFile.REFERENCE_ANNOTATION));
59  1 assertFalse(hmm.getBooleanProperty(HMMFile.MASKED_VALUE));
60  1 assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_RESIDUE));
61  1 assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_STRUCTURE));
62  1 assertTrue(hmm.getBooleanProperty(HMMFile.MAP));
63  1 assertEquals(hmm.getProperty(HMMFile.DATE), "Thu Jun 16 11:44:06 2011");
64  1 assertNull(hmm.getProperty(HMMFile.COMMAND_LOG));
65  1 assertEquals(hmm.getProperty(HMMFile.NUMBER_OF_SEQUENCES), "54");
66  1 assertEquals(hmm.getProperty(HMMFile.EFF_NUMBER_OF_SEQUENCES),
67    "3.358521");
68  1 assertEquals(hmm.getProperty(HMMFile.CHECK_SUM), "3106786190");
69  1 assertEquals(hmm.getProperty(HMMFile.GATHERING_THRESHOLD),
70    "70.30 70.30");
71  1 assertEquals(hmm.getProperty(HMMFile.TRUSTED_CUTOFF), "70.30 70.30");
72  1 assertEquals(hmm.getProperty(HMMFile.NOISE_CUTOFF), "70.20 70.20");
73   
74  1 assertEquals(hmm.getSymbols(), "ACDEFGHIKLMNPQRSTVWY");
75   
76  1 assertEquals(hmm.getMatchEmissionProbability(0, 'Y'), 0.16102, 0.001d);
77  1 assertEquals(hmm.getMatchEmissionProbability(11, 'P'), 0.0130, 0.001d);
78  1 assertEquals(hmm.getMatchEmissionProbability(24, 'I'), 0.02583, 0.001d);
79  1 assertEquals(hmm.getMatchEmissionProbability(83, 'C'), 0.008549,
80    0.001d);
81  1 assertEquals(hmm.getMatchEmissionProbability(332, 'E'), 0.07998,
82    0.001d);
83  1 assertEquals(hmm.getMatchEmissionProbability(381, 'D'), 0.014465,
84    0.001d);
85  1 assertEquals(hmm.getMatchEmissionProbability(475, 'Y'), 0.02213,
86    0.001d);
87   
88  1 assertEquals(hmm.getInsertEmissionProbability(1, 'C'), 0.012, 0.001d);
89  1 assertEquals(hmm.getInsertEmissionProbability(14, 'H'), 0.02411,
90    0.001d);
91  1 assertEquals(hmm.getInsertEmissionProbability(23, 'L'), 0.06764,
92    0.001d);
93  1 assertEquals(hmm.getInsertEmissionProbability(90, 'D'), 0.0623, 0.001d);
94  1 assertEquals(hmm.getInsertEmissionProbability(374, 'T'), 0.0623,
95    0.001d);
96  1 assertEquals(hmm.getInsertEmissionProbability(470, 'P'), 0.0647,
97    0.001d);
98   
99  1 assertEquals(hmm.getStateTransitionProbability(2, 6), 0.3848, 0.001d);
100  1 assertEquals(hmm.getStateTransitionProbability(38, 3), 0.5382, 0.001d);
101  1 assertEquals(hmm.getStateTransitionProbability(305, 3), 0.2916, 0.001d);
102  1 assertEquals(hmm.getStateTransitionProbability(380, 0), 0.99, 0.001d);
103  1 assertEquals(hmm.getStateTransitionProbability(453, 1), 0.0066, 0.001d);
104   
105  1 assertEquals(hmm.getNodeMapPosition(3), 3);
106  1 assertEquals(hmm.getReferenceAnnotation(7), '-');
107  1 assertEquals(hmm.getConsensusResidue(23), 't');
108  1 assertEquals(hmm.getMaskedValue(30), '-');
109  1 assertEquals(hmm.getConsensusStructure(56), 'S');
110   
111  1 assertEquals(hmm.getNodeMapPosition(78), 136);
112  1 assertEquals(hmm.getReferenceAnnotation(93), '-');
113  1 assertEquals(hmm.getConsensusResidue(145), 'a');
114  1 assertEquals(hmm.getMaskedValue(183), '-');
115  1 assertEquals(hmm.getConsensusStructure(240), 'H');
116    }
117   
118    /**
119    * Test that Jalview can parse an HMM file even with a bunch of 'mandatory'
120    * fields missing (including no MAP annotation or // terminator line)
121    *
122    * @throws IOException
123    */
 
124  1 toggle @Test(groups = "Functional")
125    public void testParse_minimalFile() throws IOException
126    {
127    /*
128    * ALPH is absent, alphabet inferred from HMM header line
129    * Optional COMPO line is absent
130    * first line after HMM is a guide line for readability
131    * next line is BEGIN node insert emissions
132    * next line is BEGIN node transitions
133    * next line is first sequence node match emissions 1.1 1.2 1.3
134    * next line is first sequence node insert emissions 1.4 1.5 1.6
135    * last line is first sequence node transitions
136    */
137    //@formatter:off
138  1 String hmmData =
139    "HMMER3\n" +
140    "HMM P M J\n" +
141    // both spec and parser require a line after the HMM line
142    " m->m m->i m->d i->m i->i d->m d->d\n" +
143    " 0.1 0.2 0.3\n" +
144    " 0.4 0.5 0.6 0.7 0.8 0.9 0.95\n" +
145    " 1 1.1 1.2 1.3 - - - - -\n" +
146    " 1.4 1.5 1.6\n" +
147    " 1.7 1.8 1.9 2.0 2.1 2.2 2.3\n" +
148    " 2 1.01 1.02 1.03 - - - - -\n" +
149    " 1.04 1.05 1.06\n" +
150    " 1.7 1.8 1.9 2.0 2.1 2.2 2.3\n";
151    //@formatter:on
152  1 HMMFile parser = new HMMFile(hmmData, DataSourceType.PASTE);
153  1 HiddenMarkovModel hmm = parser.getHMM();
154  1 assertNotNull(hmm);
155  1 assertEquals(hmm.getSymbols(), "PMJ");
156    // no LENG property: this should return node count excluding BEGIN node
157  1 assertEquals(hmm.getLength(), 2);
158   
159    // node 1 (implicitly mapped to column 0)
160  1 double prob = hmm.getMatchEmissionProbability(0, 'p');
161  1 assertEquals(prob, Math.pow(Math.E, -1.1));
162  1 prob = hmm.getInsertEmissionProbability(0, 'J');
163  1 assertEquals(prob, Math.pow(Math.E, -1.6));
164   
165    // node 2 (implicitly mapped to column 1)
166  1 prob = hmm.getMatchEmissionProbability(1, 'M');
167  1 assertEquals(prob, Math.pow(Math.E, -1.02));
168  1 prob = hmm.getInsertEmissionProbability(1, 'm');
169  1 assertEquals(prob, Math.pow(Math.E, -1.05));
170    }
171   
 
172  1 toggle @Test(groups = "Functional")
173    public void testParseHeaderLines_amino() throws IOException
174    {
175  1 FileReader fr = new FileReader(
176    new File("test/jalview/io/test_fn3_hmm.txt"));
177  1 BufferedReader br = new BufferedReader(fr);
178  1 HiddenMarkovModel hmm = new HiddenMarkovModel();
179  1 HMMFile testee = new HMMFile();
180  1 PA.setValue(testee, "hmm", hmm);
181  1 testee.parseHeaderLines(br);
182  1 br.close();
183  1 fr.close();
184   
185  1 assertEquals(hmm.getName(), "fn3");
186  1 assertEquals(hmm.getProperty(HMMFile.ACCESSION_NUMBER), "PF00041.13");
187  1 assertEquals(hmm.getProperty(HMMFile.DESCRIPTION),
188    "Fibronectin type III domain");
189  1 assertEquals(hmm.getProperty(HMMFile.LENGTH), "86");
190  1 assertNull(hmm.getProperty(HMMFile.MAX_LENGTH));
191  1 assertEquals(hmm.getAlphabetType(), "amino");
192  1 assertFalse(hmm.getBooleanProperty(HMMFile.REFERENCE_ANNOTATION));
193  1 assertFalse(hmm.getBooleanProperty(HMMFile.MASKED_VALUE));
194  1 assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_RESIDUE));
195  1 assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_STRUCTURE));
196   
197  1 assertTrue(hmm.getBooleanProperty(HMMFile.MAP));
198  1 assertEquals(hmm.getProperty(HMMFile.DATE), "Fri Jun 20 08:22:31 2014");
199  1 assertNull(hmm.getProperty(HMMFile.COMMAND_LOG));
200  1 assertEquals(hmm.getProperty(HMMFile.NUMBER_OF_SEQUENCES), "106");
201  1 assertEquals(hmm.getProperty(HMMFile.EFF_NUMBER_OF_SEQUENCES),
202    "11.415833");
203  1 assertEquals(hmm.getProperty(HMMFile.CHECK_SUM), "3564431818");
204  1 assertEquals(hmm.getProperty(HMMFile.GATHERING_THRESHOLD), "8.00 7.20");
205  1 assertEquals(hmm.getProperty(HMMFile.TRUSTED_CUTOFF), "8.00 7.20");
206  1 assertEquals(hmm.getProperty(HMMFile.NOISE_CUTOFF), "7.90 7.90");
207  1 assertEquals(hmm.getViterbi(), "-9.7737 0.71847");
208  1 assertEquals(hmm.getMSV(), "-9.4043 0.71847");
209  1 assertEquals(hmm.getForward(), "-3.8341 0.71847");
210    }
211   
 
212  1 toggle @Test(groups = "Functional")
213    public void testParseHeaderLines_dna() throws IOException
214    {
215  1 FileReader fr = new FileReader(
216    new File("test/jalview/io/test_MADE1_hmm.txt"));
217  1 BufferedReader br = new BufferedReader(fr);
218  1 HiddenMarkovModel hmm = new HiddenMarkovModel();
219  1 HMMFile testee = new HMMFile();
220  1 PA.setValue(testee, "hmm", hmm);
221  1 testee.parseHeaderLines(br);
222  1 br.close();
223  1 fr.close();
224   
225  1 assertEquals(hmm.getName(), "MADE1");
226  1 assertEquals(hmm.getProperty(HMMFile.ACCESSION_NUMBER),
227    "DF0000629.2");
228  1 assertEquals(hmm.getProperty(HMMFile.DESCRIPTION),
229    "MADE1 (MAriner Derived Element 1), a TcMar-Mariner DNA transposon");
230  1 assertEquals(hmm.getProperty(HMMFile.LENGTH), "80");
231  1 assertEquals(hmm.getProperty(HMMFile.MAX_LENGTH), "426");
232  1 assertEquals(hmm.getAlphabetType(), "DNA");
233  1 assertTrue(hmm.getBooleanProperty(HMMFile.REFERENCE_ANNOTATION));
234  1 assertFalse(hmm.getBooleanProperty(HMMFile.MASKED_VALUE));
235  1 assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_RESIDUE));
236  1 assertFalse(hmm.getBooleanProperty(HMMFile.CONSENSUS_STRUCTURE));
237  1 assertTrue(hmm.getBooleanProperty(HMMFile.MAP));
238  1 assertEquals(hmm.getProperty(HMMFile.DATE), "Tue Feb 19 20:33:41 2013");
239  1 assertNull(hmm.getProperty(HMMFile.COMMAND_LOG));
240  1 assertEquals(hmm.getProperty(HMMFile.NUMBER_OF_SEQUENCES), "1997");
241  1 assertEquals(hmm.getProperty(HMMFile.EFF_NUMBER_OF_SEQUENCES), "3.911818");
242  1 assertEquals(hmm.getProperty(HMMFile.CHECK_SUM), "3015610723");
243  1 assertEquals(hmm.getProperty(HMMFile.GATHERING_THRESHOLD),
244    "2.324 4.234");
245  1 assertEquals(hmm.getProperty(HMMFile.TRUSTED_CUTOFF), "2.343 1.212");
246  1 assertEquals(hmm.getProperty(HMMFile.NOISE_CUTOFF), "2.354 5.456");
247  1 assertEquals(hmm.getViterbi(), "-9.3632 0.71858");
248  1 assertEquals(hmm.getMSV(), "-8.5786 0.71858");
249  1 assertEquals(hmm.getForward(), "-3.4823 0.71858");
250    }
251   
 
252  1 toggle @Test(groups = "Functional")
253    public void testFillList() throws IOException
254    {
255  1 Scanner scanner1 = new Scanner("1.3 2.4 5.3 3.9 9.8 4.7 4.3 2.3 6.9");
256  1 ArrayList<Double> filledArray = new ArrayList<>();
257   
258  1 filledArray.add(0.27253);
259  1 filledArray.add(0.0907);
260  1 filledArray.add(0.00499);
261  1 filledArray.add(0.02024);
262  1 filledArray.add(0.00005);
263  1 filledArray.add(0.00909);
264  1 filledArray.add(0.01357);
265  1 filledArray.add(0.10026);
266  1 filledArray.add(0.001);
267   
268  1 double[] testList = HMMFile.parseDoubles(scanner1, 9);
269   
270  10 for (int i = 0; i < 9; i++)
271    {
272  9 assertEquals(testList[i], filledArray.get(i), 0.001d);
273    }
274   
275  1 filledArray.clear();
276  1 scanner1.close();
277   
278  1 Scanner scanner2 = new Scanner(
279    "1.346 5.554 35.345 5.64 1.4");
280  1 filledArray.add(0.2603);
281  1 filledArray.add(0.00387);
282  1 filledArray.add(0d);
283  1 filledArray.add(0.00355);
284  1 filledArray.add(0.2466);
285   
286  1 testList = HMMFile.parseDoubles(scanner2, 5);
287   
288  6 for (int i = 0; i < 5; i++)
289    {
290  5 assertEquals(testList[i], filledArray.get(i), 0.001d);
291    }
292    }
293   
 
294  1 toggle @Test(groups = "Functional")
295    public void testParseModel() throws IOException
296    {
297  1 FileReader fr = new FileReader(
298    new File("test/jalview/io/test_MADE1_hmm.txt"));
299  1 BufferedReader br = new BufferedReader(fr);
300  1 HiddenMarkovModel testHMM = new HiddenMarkovModel();
301  1 String line = null;
302  1 do
303    {
304  23 line = br.readLine(); // skip header lines up to HMM plus one
305  23 } while (!line.startsWith("HMM "));
306  1 br.readLine();
307   
308  1 made1.parseModel(br);
309  1 testHMM = made1.getHMM();
310   
311  1 br.close();
312  1 fr.close();
313   
314  1 assertEquals(testHMM.getMatchEmissionProbability(1, 'C'), 0.09267,
315    0.001d);
316  1 assertEquals(testHMM.getMatchEmissionProbability(25, 'G'), 0.07327,
317    0.001d);
318  1 assertEquals(testHMM.getMatchEmissionProbability(1092, 'C'), 0.04184,
319    0.001d);
320  1 assertEquals(testHMM.getMatchEmissionProbability(1107, 'G'), 0.07,
321    0.001d);
322   
323  1 assertEquals(testHMM.getInsertEmissionProbability(0, 'G'), 0.25,
324    0.001d);
325  1 assertEquals(testHMM.getInsertEmissionProbability(247, 'T'), 0.2776,
326    0.001d);
327  1 assertEquals(testHMM.getInsertEmissionProbability(1096, 'T'), 0.25,
328    0.001d);
329  1 assertEquals(testHMM.getInsertEmissionProbability(1111, 'T'), 0.25,
330    0.001d);
331   
332  1 assertEquals(testHMM.getStateTransitionProbability(1, 0), 0.9634,
333    0.001d);
334  1 assertEquals(testHMM.getStateTransitionProbability(5, 1), 0.0203,
335    0.001d);
336  1 assertEquals(testHMM.getStateTransitionProbability(14, 3), 0.2515,
337    0.001d);
338  1 assertEquals(testHMM.getStateTransitionProbability(65, 4), 0.78808,
339    0.001d);
340  1 assertEquals(testHMM.getStateTransitionProbability(1080, 2), 0.01845,
341    0.001d);
342  1 assertEquals(testHMM.getStateTransitionProbability(1111, 6),
343    Double.NEGATIVE_INFINITY);
344    }
345   
 
346  1 toggle @Test(groups = "Functional")
347    public void testParseAnnotations()
348    {
349  1 HMMFile testFile = new HMMFile();
350  1 HiddenMarkovModel hmm = new HiddenMarkovModel();
351  1 PA.setValue(testFile, "hmm", hmm);
352   
353  1 List<HMMNode> nodes = new ArrayList<>();
354  1 nodes.add(new HMMNode()); // BEGIN node
355   
356  1 hmm.setProperty(HMMFile.CONSENSUS_RESIDUE, "yes");
357  1 hmm.setProperty(HMMFile.MAP, "yes");
358  1 hmm.setProperty(HMMFile.REFERENCE_ANNOTATION, "yes");
359  1 hmm.setProperty(HMMFile.CONSENSUS_STRUCTURE, "yes");
360  1 hmm.setProperty(HMMFile.MASKED_VALUE, "yes");
361  1 Scanner scanner = new Scanner("1345 t t t t");
362  1 HMMNode node = new HMMNode();
363  1 nodes.add(node);
364  1 testFile.parseAnnotations(scanner, node);
365   
366  1 hmm.setProperty(HMMFile.CONSENSUS_RESIDUE, "yes");
367  1 hmm.setProperty(HMMFile.MAP, "no");
368  1 hmm.setProperty(HMMFile.REFERENCE_ANNOTATION, "yes");
369  1 hmm.setProperty(HMMFile.CONSENSUS_STRUCTURE, "no");
370  1 hmm.setProperty(HMMFile.MASKED_VALUE, "no");
371  1 Scanner scanner2 = new Scanner("- y x - -");
372  1 node = new HMMNode();
373  1 nodes.add(node);
374  1 testFile.parseAnnotations(scanner2, node);
375   
376  1 hmm.setNodes(nodes);
377   
378  1 assertEquals(hmm.getNodeMapPosition(1), 1345);
379  1 assertEquals(hmm.getConsensusResidue(1), 't');
380  1 assertEquals(hmm.getReferenceAnnotation(1), 't');
381  1 assertEquals(hmm.getMaskedValue(1), 't');
382  1 assertEquals(hmm.getConsensusStructure(1), 't');
383   
384  1 scanner.close();
385    }
386   
387    /**
388    * tests to see if file produced by the output matches the file from the input
389    *
390    * @throws IOException
391    */
 
392  1 toggle @Test(groups = "Functional")
393    public void testPrint_roundTrip() throws IOException
394    {
395  1 String output = pKinase.print();
396  1 HMMFile pKinaseClone = new HMMFile(
397    new FileParse(output, DataSourceType.PASTE));
398  1 HiddenMarkovModel pKinaseHMM = pKinase.getHMM();
399  1 HiddenMarkovModel pKinaseCloneHMM = pKinaseClone.getHMM();
400   
401  1 checkModelsMatch(pKinaseHMM, pKinaseCloneHMM);
402    }
403   
404    /**
405    * A helper method to check two HMM models have the same values
406    *
407    * @param model1
408    * @param model2
409    */
 
410  1 toggle protected void checkModelsMatch(HiddenMarkovModel model1,
411    HiddenMarkovModel model2)
412    {
413  1 assertEquals(model1.getLength(), model2.getLength());
414   
415  261 for (int i = 0; i < model1.getLength(); i++)
416    {
417  260 String msg = "For Node" + i;
418  260 assertEquals(model1.getNode(i).getMatchEmissions(),
419    model2.getNode(i).getMatchEmissions(), msg);
420  260 assertEquals(model1.getNode(i).getInsertEmissions(),
421    model2.getNode(i).getInsertEmissions(), msg);
422  260 assertEquals(model1.getNode(i).getStateTransitions(),
423    model2.getNode(i).getStateTransitions(), msg);
424   
425  260 if (i > 0)
426    {
427  259 assertEquals(model1.getNodeMapPosition(i),
428    model2.getNodeMapPosition(i), msg);
429  259 assertEquals(model1.getReferenceAnnotation(i),
430    model2.getReferenceAnnotation(i), msg);
431  259 assertEquals(model1.getConsensusResidue(i),
432    model2.getConsensusResidue(i), msg);
433    }
434    }
435    }
436   
 
437  1 toggle @Test(groups = "Functional")
438    public void testAppendProperties() throws FileNotFoundException
439    {
440  1 StringBuilder sb = new StringBuilder();
441  1 fn3.appendProperties(sb);
442   
443  1 Scanner testScanner = new Scanner(sb.toString());
444   
445  1 String[] expected = new String[] { "HMMER3/f [3.1b1 | May 2013]",
446    "NAME fn3", "ACC PF00041.13",
447    "DESC Fibronectin type III domain", "LENG 86", "ALPH amino",
448    "RF no", "MM no", "CONS yes", "CS yes", "MAP yes",
449    "DATE Fri Jun 20 08:22:31 2014", "NSEQ 106", "EFFN 11.415833",
450    "CKSUM 3564431818", "GA 8.00 7.20", "TC 8.00 7.20",
451    "NC 7.90 7.90", "STATS LOCAL MSV -9.4043 0.71847",
452    "STATS LOCAL VITERBI -9.7737 0.71847",
453    "STATS LOCAL FORWARD -3.8341 0.71847" };
454   
455  1 for (String value : expected)
456    {
457  21 assertEquals(testScanner.nextLine(), value);
458    }
459   
460  1 testScanner.close();
461    }
462   
 
463  1 toggle @Test(groups = "Functional")
464    public void testAppendModelAsString() throws FileNotFoundException
465    {
466  1 StringBuilder sb = new StringBuilder();
467  1 fn3.appendModelAsString(sb);
468  1 String string = sb.toString();
469   
470  1 assertEquals(findValue(2, 2, 2, string), "4.42225");
471  1 assertEquals(findValue(12, 14, 1, string), "2.79307");
472  1 assertEquals(findValue(6, 24, 3, string), "0.48576");
473  1 assertEquals(findValue(19, 33, 2, string), "4.58477");
474  1 assertEquals(findValue(20, 64, 2, string), "3.61505");
475  1 assertEquals(findValue(3, 72, 3, string), "6.81068");
476  1 assertEquals(findValue(10, 80, 2, string), "2.69355");
477  1 assertEquals(findValue(16, 65, 1, string), "2.81003");
478  1 assertEquals(findValue(14, 3, 1, string), "2.69012");
479  1 assertEquals(findValue(11, 32, 1, string), "4.34805");
480    }
481   
482    /**
483    * A helper method to find a token in the model string
484    *
485    * @param symbolIndex
486    * index of symbol being searched. First symbol has index 1.
487    * @param nodeIndex
488    * index of node being searched. Begin node has index 0. First node
489    * has index 1.
490    * @param line
491    * index of line being searched in node. First line has index 1.
492    * @param model
493    * string model being searched
494    * @return value at specified position
495    */
 
496  10 toggle private String findValue(int symbolIndex, int nodeIndex, int line,
497    String model)
498    {
499  10 String value = "";
500  10 Scanner scanner = new Scanner(model);
501  10 scanner.nextLine();
502  10 scanner.nextLine();
503   
504  18 for (int lineIndex = 0; lineIndex < line - 1; lineIndex++)
505    {
506  8 scanner.nextLine();
507    }
508  399 for (int node = 0; node < nodeIndex; node++)
509    {
510  389 scanner.nextLine();
511  389 scanner.nextLine();
512  389 scanner.nextLine();
513    }
514   
515  123 for (int symbol = 0; symbol < symbolIndex; symbol++)
516    {
517  113 value = scanner.next();
518  113 if ("COMPO".equals(value))
519    {
520  0 scanner.next();
521    }
522  113 else if (value.length() < 7)
523    {
524  4 scanner.next();
525    }
526    }
527  10 scanner.close();
528  10 return value;
529    }
530    }
531