-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApproximatePatternMatching.py
More file actions
66 lines (57 loc) · 2.98 KB
/
Copy pathApproximatePatternMatching.py
File metadata and controls
66 lines (57 loc) · 2.98 KB
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
from HammingDistance import HammingDistance
from lib.bm_preproc import BoyerMoore as bm
from BoyerMooreMatching import BoyerMooreExactMatching
from Indexing import queryIndex, Index
def NaiveApproximatePatternMatching(Pattern, Genome, d=2):
'''Naive, goes one nucleotide at a time checking all possible positions'''
positions = []
for i in range(len(Genome) - len(Pattern) + 1):
current = Genome[i: i + len(Pattern)]
if HammingDistance(current, Pattern) <= d:
positions.append(i)
return positions
def BoyerMooreApproximatePatternMatching(Pattern, Genome, d=2): # d is the distance meaning allowed mismatches
# split pattern into d + 1 segments
# this means at least one of the segments of pattern will match exactly somewhere in the genome
# (the pigeonhole principle) https://www.coursera.org/learn/dna-sequencing/lecture/QSGKX/lecture-pigeonhole-principle
num_segments = d + 1
segment_length = round(len(Pattern) / num_segments)
all_matches = set()
for i in range(num_segments):
start = i * segment_length
end = min((i + 1) * segment_length, len(Pattern))
curr_segment = Pattern[start:end]
processed_segment = bm(curr_segment)
matches = BoyerMooreExactMatching(curr_segment, processed_segment, Genome) # exact match positions of the segment in the genome
# Extend matching segments to see if whole pattern matches
for m in matches:
if start > m or m - start + len(Pattern) > len(Genome):
continue
window_to_check = Genome[m - start: m - start + len(Pattern)]
mismatches = HammingDistance(Pattern, window_to_check)
if mismatches <= d:
all_matches.add(m - start)
return list(all_matches)
def IndexApproximatePatternMatching(Pattern, Genome, d=2, k=8):
indexed_genome = Index(Genome, k)
# d is the distance meaning allowed mismatches
# split pattern into d + 1 segments
# this means at least one of the segments of pattern will match exactly somewhere in the genome
# (the pigeonhole principle) https://www.coursera.org/learn/dna-sequencing/lecture/QSGKX/lecture-pigeonhole-principle
num_segments = d + 1
segment_length = round(len(Pattern) / num_segments)
all_matches = set()
for i in range(num_segments):
start = i * segment_length
end = min((i + 1) * segment_length, len(Pattern))
curr_segment = Pattern[start:end]
matches = queryIndex(curr_segment, Genome, indexed_genome) # exact match positions of the segment in the genome
# Extend matching segments to see if whole pattern matches
for m in matches:
if start > m or m - start + len(Pattern) > len(Genome):
continue
window_to_check = Genome[m - start: m - start + len(Pattern)]
mismatches = HammingDistance(Pattern, window_to_check)
if mismatches <= d:
all_matches.add(m - start)
return list(all_matches)