/
LocalSequenceAligner.cs
99 lines (82 loc) · 3.65 KB
/
LocalSequenceAligner.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;
using System.Collections.Generic;
using System.Linq;
using EdlinSoftware.DataStructures.Collections;
namespace EdlinSoftware.Algorithms.Collections.SequenceAlignment
{
/// <summary>
/// Represents algorithm of local alignment of two sequences.
/// </summary>
/// <typeparam name="TSymbol">Type of symbols in sequences.</typeparam>
public class LocalSequenceAligner<TSymbol> : SequenceAligner<TSymbol>
{
public LocalSequenceAligner(TSymbol alignSymbol, Func<TSymbol, TSymbol, decimal> penalty, BestChoiceDelegate bestChoice = null)
: base(alignSymbol, penalty, bestChoice)
{}
public override ISequenceAlignment<TSymbol> Align(IList<TSymbol> firstSequence, IList<TSymbol> secondSequence)
{
firstSequence = firstSequence ?? new TSymbol[0];
secondSequence = secondSequence ?? new TSymbol[0];
var alignmentMatrix = GetAlignmentMatrix(firstSequence, secondSequence, false);
var alignment = new SequenceAlignment<TSymbol>();
ReconstructSequences(alignment, alignmentMatrix, firstSequence, secondSequence);
return alignment;
}
private void ReconstructSequences(SequenceAlignment<TSymbol> alignment, decimal[,] alignmentMatrix, IList<TSymbol> firstSequence, IList<TSymbol> secondSequence)
{
var firstAlignedSequence = new LinkedList<TSymbol>();
var secondAlignedSequence = new LinkedList<TSymbol>();
var bestPosition = GetAlignmentMatrixBestPosition(alignmentMatrix);
var i = bestPosition.Item1;
var j = bestPosition.Item2;
alignment.Penalty = alignmentMatrix[i, j];
while ((i > 0) && (j > 0))
{
if (alignmentMatrix[i, j] == 0.0m)
{
break;
}
if (alignmentMatrix[i, j] == alignmentMatrix[i - 1, j - 1] + Penalty(firstSequence[i - 1], secondSequence[j - 1]))
{
firstAlignedSequence.AddFirst(firstSequence[i - 1]);
secondAlignedSequence.AddFirst(secondSequence[j - 1]);
i--;
j--;
}
else if (alignmentMatrix[i, j] == alignmentMatrix[i, j - 1] + Penalty(AlignSymbol, secondSequence[j - 1]))
{
firstAlignedSequence.AddFirst(AlignSymbol);
secondAlignedSequence.AddFirst(secondSequence[j - 1]);
j--;
}
else
{
firstAlignedSequence.AddFirst(firstSequence[i - 1]);
secondAlignedSequence.AddFirst(AlignSymbol);
i--;
}
}
alignment.FirstAlignedSequence = firstAlignedSequence.ToArray();
alignment.SecondAlignedSequence = secondAlignedSequence.ToArray();
}
private Tuple<int, int> GetAlignmentMatrixBestPosition(decimal[,] alignmentMatrix)
{
var bestValue = alignmentMatrix[0, 0];
var bestRow = 0;
var bestCol = 0;
for (int i = 0; i < alignmentMatrix.GetLength(0); i++)
{
for (int j = 0; j < alignmentMatrix.GetLength(1); j++)
{
if (BestChoice(alignmentMatrix[i, j], bestValue) == alignmentMatrix[i, j])
{
bestValue = alignmentMatrix[i, j];
bestRow = i;
bestCol = j;
}
}
}
return Tuple.Create(bestRow, bestCol);
}
}
}