1 // ==========================================================================
2 //                 SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 //       notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above copyright
13 //       notice, this list of conditions and the following disclaimer in the
14 //       documentation and/or other materials provided with the distribution.
15 //     * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 //       its contributors may be used to endorse or promote products derived
17 //       from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32 // Author: Manuel Holtgrewe <manuel.holtgrew@fu-berlin.de>
33 // Author: Andreas Gogol-Doering <andreas.doering@mdc-berlin.de>
34 // ==========================================================================
35 // Tests for the SeqAn module score.
36 // ==========================================================================
37 
38 // TODO(holtgrew): There could be one test header for each module header.
39 // TODO(holtgrew): Write-out-read-in only necessary once.
40 
41 #include <iostream>
42 #include <fstream>
43 #include <sstream>
44 
45 #define SEQAN_DEBUG
46 
47 
48 #include <seqan/basic.h>
49 #include <seqan/sequence.h>
50 #include <seqan/score.h>
51 // TODO(rmaerker): Remove when done with the tests.
52 #include <seqan/align.h>
53 
54 using namespace std;
55 using namespace seqan;
56 
57 // Helper function that compares two amino acid matrices for equality.
58 // TODO(holtgrew): If used somewhere else, put into some place to share.
59 template <typename TScore1, typename TScore2>
assertAminoAcidMatricesAreEqual(TScore1 const & mat1,TScore2 const & mat2)60 void assertAminoAcidMatricesAreEqual(TScore1 const & mat1, TScore2 const & mat2) {
61     for (AminoAcid a = 'A'; a <= '*'; ++a) {
62         for (AminoAcid b = 'A'; b <= '*'; ++b) {
63             SEQAN_ASSERT_EQ_MSG(
64                     score(mat1, a, b), score(mat2, a, b),
65                     "a = %c, b = %c", static_cast<char>(a),
66                     static_cast<char>(b));
67         }
68     }
69 }
70 
71 
72 // Performs SEQAN_ASSERT_EQ(0, x) for all cells x in matrix.
73 template<typename TScore>
assertAminoAcidMatrixIsDefaultInitialized(const TScore & matrix)74 void assertAminoAcidMatrixIsDefaultInitialized(const TScore &matrix) {
75     for (AminoAcid a = 'A'; a <= '*'; ++a) {
76         for (AminoAcid b = 'A'; b <= '*'; ++b) {
77             SEQAN_ASSERT_EQ(0, score(matrix, a, b));
78         }
79     }
80 }
81 
82 
83 // Test the default implementation for scoreGap* from score_base.h.
SEQAN_DEFINE_TEST(test_score_gap_open)84 SEQAN_DEFINE_TEST(test_score_gap_open) {
85     // TODO(holtgrew): The following *crashes* with edit distance score!  References to temporaries returned.
86     // We simply test this with an simple score, test default implementation.
87     SimpleScore simpleScore;
88     const CharString kSeq1 = "A";
89     const CharString kSeq2 = "A";
90     typedef Position<CharString>::Type TPos;
91     const TPos kPos1 = 0;
92     const TPos kPos2 = 0;
93 
94     SEQAN_ASSERT_EQ(scoreGapOpen(simpleScore),
95                     scoreGapOpenHorizontal(simpleScore, sequenceEntryForScore(simpleScore, kSeq1, kPos1),
96                                            sequenceEntryForScore(simpleScore, kSeq2, kPos2)));
97     SEQAN_ASSERT_EQ(scoreGapOpen(simpleScore),
98                     scoreGapOpenVertical(simpleScore, sequenceEntryForScore(simpleScore, kSeq1, kPos1),
99                                          sequenceEntryForScore(simpleScore, kSeq2, kPos2)));
100     SEQAN_ASSERT_EQ(scoreGapExtend(simpleScore),
101                     scoreGapExtendHorizontal(simpleScore, sequenceEntryForScore(simpleScore, kSeq1, kPos1),
102                                              sequenceEntryForScore(simpleScore, kSeq2, kPos2)));
103     SEQAN_ASSERT_EQ(scoreGapExtend(simpleScore),
104                     scoreGapExtendVertical(simpleScore, sequenceEntryForScore(simpleScore, kSeq1, kPos1),
105                                            sequenceEntryForScore(simpleScore, kSeq2, kPos2)));
106     SEQAN_ASSERT_EQ(scoreGap(simpleScore),
107                     scoreGapHorizontal(simpleScore, sequenceEntryForScore(simpleScore, kSeq1, kPos1),
108                                        sequenceEntryForScore(simpleScore, kSeq2, kPos2)));
109     SEQAN_ASSERT_EQ(scoreGap(simpleScore),
110                     scoreGapVertical(simpleScore, sequenceEntryForScore(simpleScore, kSeq1, kPos1),
111                                      sequenceEntryForScore(simpleScore, kSeq2, kPos2)));
112     SEQAN_ASSERT_EQ(score(simpleScore, kSeq1[kPos1], kSeq2[kPos2]),
113                     score(simpleScore, sequenceEntryForScore(simpleScore, kSeq1, kPos1),
114                           sequenceEntryForScore(simpleScore, kSeq2, kPos2)));
115 }
116 
117 
118 // Compare the built-in Blosum matrices against matrices from
119 // reference files.
SEQAN_DEFINE_TEST(test_score_matrix)120 SEQAN_DEFINE_TEST(test_score_matrix) {
121     // We test the scoring matrix with amino acids as the underlying
122     // sequence.  This should be the most common case.
123     typedef int TValue;
124     typedef Score<TValue, ScoreMatrix<AminoAcid, Default> > TScore;
125 
126     // Define path to BLOSUM62 matrix that we want to load.
127     // TODO(holtgrew): It should be easier to construct these paths.
128     String<char> pathToTestSrc = getAbsolutePath("/tests/score/");
129     String<char> pathToBlosum62(pathToTestSrc);
130     append(pathToBlosum62, "BLOSUM62");
131 
132     // Test with default constructor.
133     {
134         // Call appropriate constructor.
135         TScore matrixScore;
136         // Assert score state.
137         SEQAN_ASSERT_EQ(-1, scoreGap(matrixScore));
138         SEQAN_ASSERT_EQ(-1, scoreGapExtend(matrixScore));
139         SEQAN_ASSERT_EQ(-1, scoreGapOpen(matrixScore));
140         // Test function score().  The default score is TValue() == 0
141         // for all matches.
142         assertAminoAcidMatrixIsDefaultInitialized(matrixScore);
143     }
144 
145     // Test the const accessor functions.
146     {
147         // Call appropriate constructor.
148         const TScore matrixScore;
149         // Assert score state.
150         SEQAN_ASSERT_EQ(-1, scoreGap(matrixScore));
151         SEQAN_ASSERT_EQ(-1, scoreGapExtend(matrixScore));
152         SEQAN_ASSERT_EQ(-1, scoreGapOpen(matrixScore));
153         // Test function score().  The default score is TValue() == 0
154         // for all matches.
155         assertAminoAcidMatrixIsDefaultInitialized(matrixScore);
156     }
157 
158     // Test the setter functions.
159     {
160         // The test score value for the test.
161         const TValue kScoreValue = 42;
162         // Create a new score matrix.
163         TScore matrixScore;
164         // Test function score().  The default score is TValue() == 0
165         // for all matches.
166         assertAminoAcidMatrixIsDefaultInitialized(matrixScore);
167         // Set the score for a substitution and check the result.
168         setScore(matrixScore, AminoAcid('A'), AminoAcid('X'), kScoreValue);
169         SEQAN_ASSERT_EQ(kScoreValue,
170                         score(matrixScore, AminoAcid('A'), AminoAcid('X')));
171     }
172 
173     // Test with gap extension constructor.
174     {
175         // Define constant test data and call appropriate constructor.
176         const TValue kGapScore = 1;
177         TScore matrixScore(kGapScore);
178         // Assert score state.
179         SEQAN_ASSERT_EQ(kGapScore, scoreGap(matrixScore));
180         SEQAN_ASSERT_EQ(kGapScore, scoreGapExtend(matrixScore));
181         SEQAN_ASSERT_EQ(kGapScore, scoreGapOpen(matrixScore));
182         // Test function score().  The default score is TValue() == 0
183         // for all matches.
184         assertAminoAcidMatrixIsDefaultInitialized(matrixScore);
185     }
186 
187     // Test with gap extension and gap open constructor.
188     {
189         // Define constant test data and call appropriate constructor.
190         const TValue kGapExtensionScore = 1;
191         const TValue kGapOpenScore = 2;
192         TScore matrixScore(kGapExtensionScore, kGapOpenScore);
193         // Assert score state.
194         SEQAN_ASSERT_EQ(kGapExtensionScore, scoreGap(matrixScore));
195         SEQAN_ASSERT_EQ(kGapExtensionScore, scoreGapExtend(matrixScore));
196         SEQAN_ASSERT_EQ(kGapOpenScore, scoreGapOpen(matrixScore));
197         // Test function score().  The default score is TValue() == 0
198         // for all matches.
199         assertAminoAcidMatrixIsDefaultInitialized(matrixScore);
200     }
201 
202     // Test with path to file constructor.
203     {
204         // Call appropriate constructor.
205         const TScore matrixScore(toCString(pathToBlosum62));
206         // Assert score state.
207         SEQAN_ASSERT_EQ(-1, scoreGap(matrixScore));
208         SEQAN_ASSERT_EQ(-1, scoreGapExtend(matrixScore));
209         SEQAN_ASSERT_EQ(-1, scoreGapOpen(matrixScore));
210         // The resulting matrix from the file should be equal to the
211         // built-in BLOSUM62 matrix.
212         Blosum62 blosum62;
213         assertAminoAcidMatricesAreEqual(blosum62, matrixScore);
214     }
215 
216     // Test with path to file, gap extension constructor.
217     {
218         // Call appropriate constructor.
219         const TValue kGapScore = 1;
220         TScore matrixScore(toCString(pathToBlosum62), kGapScore);
221         // Assert score state.
222         SEQAN_ASSERT_EQ(kGapScore, scoreGap(matrixScore));
223         SEQAN_ASSERT_EQ(kGapScore, scoreGapExtend(matrixScore));
224         SEQAN_ASSERT_EQ(kGapScore, scoreGapOpen(matrixScore));
225         // The resulting matrix from the file should be equal to the
226         // built-in BLOSUM62 matrix.
227         Blosum62 blosum62;
228         assertAminoAcidMatricesAreEqual(blosum62, matrixScore);
229     }
230 
231     // Test with path to file, gap extension and gap open constructor.
232     {
233         // Define constant test data and call appropriate constructor.
234         const TValue kGapExtensionScore = 1;
235         const TValue kGapOpenScore = 2;
236         TScore matrixScore(toCString(pathToBlosum62), kGapExtensionScore, kGapOpenScore);
237         // Assert score state.
238         SEQAN_ASSERT_EQ(kGapExtensionScore, scoreGap(matrixScore));
239         SEQAN_ASSERT_EQ(kGapExtensionScore, scoreGapExtend(matrixScore));
240         SEQAN_ASSERT_EQ(kGapOpenScore, scoreGapOpen(matrixScore));
241         // The resulting matrix from the file should be equal to the
242         // built-in BLOSUM62 matrix.
243         Blosum62 blosum62;
244         assertAminoAcidMatricesAreEqual(blosum62, matrixScore);
245     }
246 }
247 
248 
249 // Test the File I/O code for score matrices.
SEQAN_DEFINE_TEST(test_score_matrix_file)250 SEQAN_DEFINE_TEST(test_score_matrix_file) {
251     // TODO(holtgrew): It should be easier to construct these paths.
252     // The path to the directory with the test's sources and fixtures.
253     String<char> pathToTestSrc = getAbsolutePath("/tests/score/");
254 
255     // Load fixture BLOSUM62 matrix.
256     // TODO(holtgrew): Should be done in a function.
257     Score<int, ScoreMatrix<> > sc;
258     String<char> meta;
259     String<char> pathToBlosum62(pathToTestSrc);
260     append(pathToTestSrc, "BLOSUM62");
261     // TODO(holtgrew): If the file does not exist, a bus error occurs, code should catch this case and print an error.
262     loadScoreMatrix(meta, sc, toCString(pathToTestSrc));
263 
264     // Compare fixture BLOSUM62 matrix to built-in one.
265     {
266         Blosum62 blosum62;
267         assertAminoAcidMatricesAreEqual(blosum62, sc);
268     }
269 
270     // Perform assertions on scores of the built-in Blosum62 matrix.
271     {
272         Blosum62 blosum62;
273         SEQAN_ASSERT_EQ(scoreGapExtend(blosum62), -1);
274         SEQAN_ASSERT_EQ(scoreGapOpen(blosum62), scoreGapExtend(blosum62));
275         SEQAN_ASSERT_EQ(scoreGap(blosum62), scoreGapExtend(blosum62));
276     }
277 
278     // Store and load the fixture BLOSUM62 matrix again.
279     {
280         const char *temp_filename = SEQAN_TEMP_FILENAME();
281         {
282             std::ofstream fl(temp_filename);
283             typename DirectionIterator<std::ofstream, Output>::Type it = directionIterator(fl, Output());
284             write(it, sc, meta);
285         }
286 
287         Score<int, ScoreMatrix<> > sc2;
288         String<char> meta2;
289         SEQAN_ASSERT(loadScoreMatrix(meta2, sc2, temp_filename));
290         assertAminoAcidMatricesAreEqual(sc, sc2);
291         SEQAN_ASSERT_EQ(meta, meta2);
292     }
293 
294     // Store and load the built-in matrix again.
295     {
296         const char *temp_filename = SEQAN_TEMP_FILENAME();
297         {
298             std::ofstream fl(temp_filename);
299             typename DirectionIterator<std::ofstream, Output>::Type it = directionIterator(fl, Output());
300             write(it, Blosum62());
301         }
302 
303         Score<int, ScoreMatrix<> > sc2;
304         SEQAN_ASSERT(loadScoreMatrix(sc2, temp_filename));
305         assertAminoAcidMatricesAreEqual(sc2, Blosum62());
306     }
307 
308     // Test setScore()
309     {
310         setScore(sc, 'A', '*', 100);
311         SEQAN_ASSERT_EQ(score(sc, 'A', '*'), 100);
312     }
313 }
314 
315 
316 // Testing the edit distance score is simple, the functions simply
317 // return the edit distance values.
SEQAN_DEFINE_TEST(test_score_edit)318 SEQAN_DEFINE_TEST(test_score_edit) {
319     // TODO(holtgrew): Break out each block into a test of its own.
320     // We will only test with int scores, the most common case.
321     typedef int TValue;
322     typedef Score<TValue, EditDistance> TScore;
323 
324     // Test the default constructor.
325     {
326         TScore editDistanceScore;
327         SEQAN_ASSERT_EQ(0, scoreMatch(editDistanceScore));
328         SEQAN_ASSERT_EQ(-1, scoreMismatch(editDistanceScore));
329         // TODO(holtgrew): FIXME! Does not compile because of reference to temporary.
330         // SEQAN_ASSERT_EQ(-1, scoreGap(editDistanceScore));
331         SEQAN_ASSERT_EQ(-1, scoreGapExtend(editDistanceScore));
332         SEQAN_ASSERT_EQ(-1, scoreGapOpen(editDistanceScore));
333         // Test function score().
334         SEQAN_ASSERT_EQ(0, score(editDistanceScore, 'A', 'A'));
335         SEQAN_ASSERT_EQ(-1, score(editDistanceScore, 'A', 'C'));
336     }
337 
338     // Test the const accessor functions.
339     {
340         const TScore editDistanceScore;
341         SEQAN_ASSERT_EQ(0, scoreMatch(editDistanceScore));
342         SEQAN_ASSERT_EQ(-1, scoreMismatch(editDistanceScore));
343         // TODO(holtgrew): FIXME! Does not compile because of reference to temporary.
344         // SEQAN_ASSERT_EQ(-1, scoreGap(editDistanceScore));
345         SEQAN_ASSERT_EQ(-1, scoreGapExtend(editDistanceScore));
346         SEQAN_ASSERT_EQ(-1, scoreGapOpen(editDistanceScore));
347         // Test function score().
348         SEQAN_ASSERT_EQ(0, score(editDistanceScore, 'A', 'A'));
349         SEQAN_ASSERT_EQ(-1, score(editDistanceScore, 'A', 'C'));
350     }
351 
352     // Test the shortcut.  Since the assignment operator is not
353     // overloaded, the following should not compile if the shortcut is
354     // not defined appropriately.
355     {
356         // TODO(holtgrew): Use a metaprogramming for type equality instead?, something like SEQAN_ASSERT(type-equals(x, y));?
357         Score<int, EditDistance> scoreEditDistance;
358         EditDistanceScore editDistanceScore;
359         scoreEditDistance = editDistanceScore;
360     }
361 }
362 
363 
364 // Score<TValue, Simple> is, you have guessed it, very simple.  Thus,
365 // we will simply use different constructors to construct Simple Score
366 // objects and call the scoring functions on them.
SEQAN_DEFINE_TEST(test_score_simple)367 SEQAN_DEFINE_TEST(test_score_simple) {
368     // TODO(holtgrew): Break out each block into a test of its own.
369     // We will only test with int scores, the most common case.
370     typedef int TValue;
371     typedef Score<TValue, Simple> TScore;
372 
373     // Test the default constructor.
374     {
375         TScore simpleScore;
376         SEQAN_ASSERT_EQ(0, scoreMatch(simpleScore));
377         SEQAN_ASSERT_EQ(-1, scoreMismatch(simpleScore));
378         SEQAN_ASSERT_EQ(-1, scoreGap(simpleScore));
379         SEQAN_ASSERT_EQ(-1, scoreGapExtend(simpleScore));
380         SEQAN_ASSERT_EQ(-1, scoreGapOpen(simpleScore));
381         // Test function score().
382         SEQAN_ASSERT_EQ(0, score(simpleScore, 'A', 'A'));
383         SEQAN_ASSERT_EQ(-1, score(simpleScore, 'A', 'C'));
384     }
385 
386     // Test the const member retrieval functions.
387     // TODO(holtgrew): Should these functions not be called getFUNCNAME?
388     {
389         const TScore simpleScore;
390         SEQAN_ASSERT_EQ(0, scoreMatch(simpleScore));
391         SEQAN_ASSERT_EQ(-1, scoreMismatch(simpleScore));
392         SEQAN_ASSERT_EQ(-1, scoreGap(simpleScore));
393         SEQAN_ASSERT_EQ(-1, scoreGapExtend(simpleScore));
394         SEQAN_ASSERT_EQ(-1, scoreGapOpen(simpleScore));
395         // Test function score().
396         SEQAN_ASSERT_EQ(0, score(simpleScore, 'A', 'A'));
397         SEQAN_ASSERT_EQ(-1, score(simpleScore, 'A', 'C'));
398     }
399 
400     // Test the non-const member retrieval functions with assignments.
401     {
402         const int kMatch = 1;
403         const int kMismatch = 2;
404         const int kGapExtension = 3;
405         const int kGapOpen = 4;
406         // Perform assignments.
407         TScore simpleScore;
408         setScoreMatch(simpleScore, kMatch);
409         setScoreMismatch(simpleScore, kMismatch);
410         setScoreGap(simpleScore, kGapExtension);
411         setScoreGapExtend(simpleScore, kGapExtension);
412         setScoreGapOpen(simpleScore, kGapOpen);
413         // Check results.
414         SEQAN_ASSERT_EQ(kMatch, scoreMatch(simpleScore));
415         SEQAN_ASSERT_EQ(kMismatch, scoreMismatch(simpleScore));
416         SEQAN_ASSERT_EQ(kGapExtension, scoreGap(simpleScore));
417         SEQAN_ASSERT_EQ(kGapExtension, scoreGapExtend(simpleScore));
418         SEQAN_ASSERT_EQ(kGapOpen, scoreGapOpen(simpleScore));
419     }
420 
421     // Test the constructor with match, mismatch, gap arguments.
422     {
423         // Define constant test data.
424         const int kMatch = 1;
425         const int kMismatch = 2;
426         const int kGap = 3;
427         // Construct the score and make assertions about its state.
428         TScore simpleScore(kMatch, kMismatch, kGap);
429         SEQAN_ASSERT_EQ(kMatch, scoreMatch(simpleScore));
430         SEQAN_ASSERT_EQ(kMismatch, scoreMismatch(simpleScore));
431         SEQAN_ASSERT_EQ(kGap, scoreGap(simpleScore));
432         SEQAN_ASSERT_EQ(kGap, scoreGapExtend(simpleScore));
433         SEQAN_ASSERT_EQ(kGap, scoreGapOpen(simpleScore));
434         // Test function score().
435         SEQAN_ASSERT_EQ(kMatch, score(simpleScore, 'A', 'A'));
436         SEQAN_ASSERT_EQ(kMismatch, score(simpleScore, 'A', 'C'));
437     }
438 
439     // Test the constructor with match, mismatch, gap extension, gap
440     // open arguments.
441     {
442         // Define constant test data.
443         const int kMatch = 1;
444         const int kMismatch = 2;
445         const int kGapExtension = 3;
446         const int kGapOpen = 4;
447         // Construct the score and make assertions about its state.
448         TScore simpleScore(kMatch, kMismatch, kGapExtension, kGapOpen);
449         SEQAN_ASSERT_EQ(kMatch, scoreMatch(simpleScore));
450         SEQAN_ASSERT_EQ(kMismatch, scoreMismatch(simpleScore));
451         SEQAN_ASSERT_EQ(kGapExtension, scoreGap(simpleScore));
452         SEQAN_ASSERT_EQ(kGapExtension, scoreGapExtend(simpleScore));
453         SEQAN_ASSERT_EQ(kGapOpen, scoreGapOpen(simpleScore));
454         // Test function score().
455         SEQAN_ASSERT_EQ(kMatch, score(simpleScore, 'A', 'A'));
456         SEQAN_ASSERT_EQ(kMismatch, score(simpleScore, 'A', 'C'));
457     }
458 
459     // Test the shortcut.  Since the assignment operator is not
460     // overloaded, the following should not compile if the shortcut is
461     // not defined appropriately.
462     {
463         // TODO(holtgrew): Use a metaprogramming for type equality instead?, something like SEQAN_ASSERT(type-equals(x, y));?
464         Score<int, Simple> scoreSimple;
465         SimpleScore simpleScore;
466         simpleScore = scoreSimple;
467     }
468 }
469 
470 
471 // Test the built-in data matrices by comparing them to the matrices
472 // from test data files.
SEQAN_DEFINE_TEST(test_score_matrix_data)473 SEQAN_DEFINE_TEST(test_score_matrix_data) {
474     // We test the scoring matrix with amino acids as the underlying
475     // sequence.  This should be the most common case.
476     typedef int TValue;
477     typedef Score<TValue, ScoreMatrix<AminoAcid, ScoreMatrixFile> > TScore;
478 
479     // TODO(holtgrew): It should be easier to construct these paths.
480     String<char> pathToTestSrc = getAbsolutePath("/tests/score/");
481 
482     // Test with BLOSUM30.
483     {
484         // The built-in BLOSUM30 matrix.
485         Blosum30 blosum30;
486         // Use a quick-and-dirty test that the matrix indeed is BLOSUM30.
487         SEQAN_ASSERT_EQ(0, score(blosum30, AminoAcid('A'), AminoAcid('N')));
488         SEQAN_ASSERT_EQ(1, score(blosum30, AminoAcid('V'), AminoAcid('A')));
489 
490         // Build path to BLOSUM30 matrix.
491         String<char> pathToBlosum30(pathToTestSrc);
492         append(pathToBlosum30, "BLOSUM30");
493         // Load matrix.
494         TScore loadedBlosum30(toCString(pathToBlosum30));
495         // Compare loaded with built-in matrix.
496         assertAminoAcidMatricesAreEqual(loadedBlosum30, blosum30);
497     }
498 
499     // Test with BLOSUM45.
500     {
501         // The built-in BLOSUM45 matrix.
502         Blosum45 blosum45;
503         // Use a quick-and-dirty test that the matrix indeed is BLOSUM45.
504         SEQAN_ASSERT_EQ(-1, score(blosum45, AminoAcid('A'), AminoAcid('N')));
505         SEQAN_ASSERT_EQ(0, score(blosum45, AminoAcid('V'), AminoAcid('A')));
506 
507         // Build path to BLOSUM45 matrix.
508         String<char> pathToBlosum45(pathToTestSrc);
509         append(pathToBlosum45, "BLOSUM45");
510         // Load matrix.
511         TScore loadedBlosum45(toCString(pathToBlosum45));
512         // Compare loaded with built-in matrix.
513         assertAminoAcidMatricesAreEqual(loadedBlosum45, blosum45);
514     }
515 
516     // Test with BLOSUM62.
517     {
518         // The built-in BLOSUM62 matrix.
519         Blosum62 blosum62;
520         // Use a quick-and-dirty test that the matrix indeed is BLOSUM62.
521         SEQAN_ASSERT_EQ(-2, score(blosum62, AminoAcid('A'), AminoAcid('N')));
522         SEQAN_ASSERT_EQ(0, score(blosum62, AminoAcid('V'), AminoAcid('A')));
523 
524         // Build path to BLOSUM62 matrix.
525         String<char> pathToBlosum62(pathToTestSrc);
526         append(pathToBlosum62, "BLOSUM62");
527         // Load matrix.
528         TScore loadedBlosum62(toCString(pathToBlosum62));
529         // Compare loaded with built-in matrix.
530         assertAminoAcidMatricesAreEqual(loadedBlosum62, blosum62);
531     }
532 
533     // Test with BLOSUM80.
534     {
535         // The built-in BLOSUM80 matrix.
536         Blosum80 blosum80;
537         // Use a quick-and-dirty test that the matrix indeed is BLOSUM80.
538         SEQAN_ASSERT_EQ(-3, score(blosum80, AminoAcid('A'), AminoAcid('N')));
539         SEQAN_ASSERT_EQ(-1, score(blosum80, AminoAcid('V'), AminoAcid('A')));
540 
541         // Build path to BLOSUM80 matrix.
542         String<char> pathToBlosum80(pathToTestSrc);
543         append(pathToBlosum80, "BLOSUM80");
544         // Load matrix.
545         TScore loadedBlosum80(toCString(pathToBlosum80));
546         // Compare loaded with built-in matrix.
547         assertAminoAcidMatricesAreEqual(loadedBlosum80, blosum80);
548     }
549 
550     // Test with PAM40.
551     {
552         // The built-in PAM40 matrix.
553         Pam40 pam40;
554         // Use a quick-and-dirty test that the matrix indeed is PAM40.
555         SEQAN_ASSERT_EQ(-3, score(pam40, AminoAcid('A'), AminoAcid('N')));
556         SEQAN_ASSERT_EQ(-2, score(pam40, AminoAcid('V'), AminoAcid('A')));
557 
558         // Build path to PAM40 matrix.
559         String<char> pathToPam40(pathToTestSrc);
560         append(pathToPam40, "PAM40");
561         // Load matrix.
562         TScore loadedPam40(toCString(pathToPam40));
563         // Compare loaded with built-in matrix.
564         assertAminoAcidMatricesAreEqual(loadedPam40, pam40);
565     }
566 
567     // Test with PAM120.
568     {
569         // The built-in PAM120 matrix.
570         Pam120 pam120;
571         // Use a quick-and-dirty test that the matrix indeed is PAM120.
572         SEQAN_ASSERT_EQ(-1, score(pam120, AminoAcid('A'), AminoAcid('N')));
573         SEQAN_ASSERT_EQ(0, score(pam120, AminoAcid('V'), AminoAcid('A')));
574 
575         // Build path to PAM120 matrix.
576         String<char> pathToPam120(pathToTestSrc);
577         append(pathToPam120, "PAM120");
578         // Load matrix.
579         TScore loadedPam120(toCString(pathToPam120));
580         // Compare loaded with built-in matrix.
581         assertAminoAcidMatricesAreEqual(loadedPam120, pam120);
582     }
583 
584     // Test with PAM200.
585     {
586         // The built-in PAM200 matrix.
587         Pam200 pam200;
588         // Use a quick-and-dirty test that the matrix indeed is PAM200.
589         SEQAN_ASSERT_EQ(0, score(pam200, AminoAcid('A'), AminoAcid('N')));
590         SEQAN_ASSERT_EQ(0, score(pam200, AminoAcid('V'), AminoAcid('A')));
591 
592         // Build path to PAM200 matrix.
593         String<char> pathToPam200(pathToTestSrc);
594         append(pathToPam200, "PAM200");
595         // Load matrix.
596         TScore loadedPam200(toCString(pathToPam200));
597         // Compare loaded with built-in matrix.
598         assertAminoAcidMatricesAreEqual(loadedPam200, pam200);
599     }
600 
601     // Test with PAM250.
602     {
603         // The built-in PAM250 matrix.
604         Pam250 pam250;
605         // Use a quick-and-dirty test that the matrix indeed is PAM250.
606         SEQAN_ASSERT_EQ(0, score(pam250, AminoAcid('A'), AminoAcid('N')));
607         SEQAN_ASSERT_EQ(0, score(pam250, AminoAcid('V'), AminoAcid('A')));
608 
609         // Build path to PAM250 matrix.
610         String<char> pathToPam250(pathToTestSrc);
611         append(pathToPam250, "PAM250");
612         // Load matrix.
613         TScore loadedPam250(toCString(pathToPam250));
614         // Compare loaded with built-in matrix.
615         assertAminoAcidMatricesAreEqual(loadedPam250, pam250);
616     }
617 
618     // Test with VTML200.
619     {
620         // The built-in VTML200 matrix.
621         Vtml200 vtml200;
622         // Use a quick-and-dirty test that the matrix indeed is VTML200.
623         SEQAN_ASSERT_EQ(-1, score(vtml200, AminoAcid('A'), AminoAcid('N')));
624         SEQAN_ASSERT_EQ(0, score(vtml200, AminoAcid('V'), AminoAcid('A')));
625 
626         // Build path to VTML200 matrix.
627         String<char> pathToVTML200(pathToTestSrc);
628         append(pathToVTML200, "VTML200I");
629         // Load matrix.
630         TScore loadedVTML200(toCString(pathToVTML200));
631         // Compare loaded with built-in matrix.
632         assertAminoAcidMatricesAreEqual(loadedVTML200, vtml200);
633     }
634 }
635 
636 template <typename TScoreSpec>
testScoreSequenceEntryForScore()637 void testScoreSequenceEntryForScore()
638 {
639     typedef Score<int, TScoreSpec> TScoringScheme;
640     typedef typename SequenceEntryForScore<TScoringScheme, DnaString>::Type TEntry1;
641 
642     DnaString seq1 = "ACGTACG";
643     Dna5String seq2 = "ACGTNACNA";
644 
645     TScoringScheme scoringScheme;
646 
647     TEntry1 val1 = sequenceEntryForScore(scoringScheme, seq1, 0);
648     TEntry1 val2 = sequenceEntryForScore(scoringScheme, seq2, 0);
649 
650     SEQAN_ASSERT_EQ(val1, 'A');
651     SEQAN_ASSERT_EQ(val2, 'A');
652 
653     val1 = sequenceEntryForScore(scoringScheme, seq1, 4);
654     val2 = sequenceEntryForScore(scoringScheme, seq2, 4);
655 
656     SEQAN_ASSERT_EQ(val1, 'A');
657     SEQAN_ASSERT_EQ(val2, 'N');
658 }
659 
SEQAN_DEFINE_TEST(test_score_sequence_entry_for_score)660 SEQAN_DEFINE_TEST(test_score_sequence_entry_for_score)
661 {
662     testScoreSequenceEntryForScore<Simple>();
663     testScoreSequenceEntryForScore<ScoreMatrix<AminoAcid, Blosum62_> >();
664 }
665 
SEQAN_DEFINE_TEST(test_score_dynamic_score_matrix)666 SEQAN_DEFINE_TEST(test_score_dynamic_score_matrix)
667 {
668     Blosum62 blo;
669     SelectableAminoAcidMatrix sel;
670     SEQAN_ASSERT(getScoreMatrixId(sel) != AminoAcidScoreMatrixID::BLOSUM62);
671 
672     setScoreMatrixById(sel, AminoAcidScoreMatrixID::BLOSUM62);
673     SEQAN_ASSERT(getScoreMatrixId(sel) == AminoAcidScoreMatrixID::BLOSUM62);
674 
675     for (unsigned i = 0; i < ValueSize<AminoAcid>::VALUE; ++i)
676         for (unsigned j = 0; j < ValueSize<AminoAcid>::VALUE; ++j)
677             SEQAN_ASSERT_EQ(score(blo, static_cast<AminoAcid>(i), static_cast<AminoAcid>(j)),
678                             score(sel, static_cast<AminoAcid>(i), static_cast<AminoAcid>(j)));
679 }
680 
SEQAN_BEGIN_TESTSUITE(test_score)681 SEQAN_BEGIN_TESTSUITE(test_score) {
682     // Call the tests for this module.
683     SEQAN_CALL_TEST(test_score_gap_open);
684     SEQAN_CALL_TEST(test_score_simple);
685     SEQAN_CALL_TEST(test_score_edit);
686     SEQAN_CALL_TEST(test_score_matrix);
687     SEQAN_CALL_TEST(test_score_matrix_file);
688     SEQAN_CALL_TEST(test_score_matrix_data);
689     SEQAN_CALL_TEST(test_score_sequence_entry_for_score);
690     SEQAN_CALL_TEST(test_score_dynamic_score_matrix);
691 }
692 SEQAN_END_TESTSUITE
693