Improve the style of this code to make use of the PEP 8 style guide and Python 3.12 best practices. Suggest ways to make the code more clear.
```python
# https://dodona.be/nl/courses/3363/series/36080/activities/1128421449
from Bio import SeqIO
nucleotides = ['A', 'C', 'G', 'T']
def most_frequent_kmers(s: str, k: int, d: int) -> set:
"""
>>> most_frequent_kmers('ACGTTGCATGTCGCATGATGCATGAGAGCT', 4, 1)
{'ACAT', 'ATGT'}
>>> most_frequent_kmers('AACAAGCTGATAAACATTTAAAGAG', 5, 1)
{'TTAAA', 'TTTAA', 'TTTTA', 'TAAAA'}
>>> most_frequent_kmers('AAAATTTTTTTT', 3, 0)
{}
>>> most_frequent_kmers('CAT', 1, 0)
{}
>>> from Bio import SeqIO
>>> most_frequent_kmers(*SeqIO.parse('data/09-data.fna', 'fasta'), 10, 2)
{'CCGGCGGCCG', 'CGGCCGCCGG'}
"""
if isinstance(s, SeqIO.SeqRecord):
s = s.seq
neighborhoods = []
for i in range(len(s) - k + 1):
# neighborhoods.extend(neighbors(s[i:i + k], d))
neighborhood = neighbors(s[i:i + k], d)
neighborhoods.extend(neighborhood)
neighborhoods.extend(map(reverse_complement, neighborhood))
# neighborhoods.extend(map(reverse_complement, neighborhoods))
count = [1 for _ in range(len(neighborhoods))]
index = [pattern_to_number(neighborhood) for _, neighborhood in enumerate(neighborhoods)]
index.sort()
for i in range(len(neighborhoods) - 1):
if index[i] == index[i + 1]:
count[i + 1] = count[i] + 1
max_count = max(count)
return {number_to_pattern(index[i], k) for i in range(len(neighborhoods)) if count[i] == max_count}
def neighbors(s: str, d: int):
if d == 0:
return {s}
if len(s) == 1:
return {'A', 'C', 'G', 'T'}
neighborhood = set()
suffix_neighbors = neighbors(s[1:], d)
for text in suffix_neighbors:
if hamming_distance(s[1:], text) < d:
for x in ['A', 'C', 'G', 'T']:
neighborhood.add(x + text)
else:
neighborhood.add(s[0] + text)
return neighborhood
def pattern_to_number(pattern):
result = 0
for _, symbol in enumerate(pattern):
result = (result * 4) + nucleotides.index(symbol)
return result
def number_to_pattern(index, k):
if k == 1:
return nucleotides[index]
return number_to_pattern(index // 4, k - 1) + nucleotides[index % 4]
def approximate_pattern_count(s: str, pattern: str, d: int) -> int:
count = 0
for i in range(len(s) - len(pattern) + 1):
pattern_ = s[i:i + len(pattern)]
count += hamming_distance(pattern, pattern_) <= d
return count
def hamming_distance(s: {str, SeqIO}, t: {str, SeqIO}) -> int:
"""Return how many mismatches there are between two strings. This is called the Hamming distance
>>> hamming_distance('GGGCCGTTGGT', 'GGACCGTTGAC')
3
>>> hamming_distance('AAAA', 'TTTT')
4
>>> hamming_distance('ACGTACGT', 'TACGTACG')
8
>>> hamming_distance('ACGTACGT', 'CCCCCCCC')
6
>>> from Bio import SeqIO
>>> hamming_distance(*SeqIO.parse('data/06-data.fna', 'fasta'))
859
"""
# Convert SeqRecords to strings
if isinstance(s, SeqIO.SeqRecord):
s = s.seq
t = t.seq
# https://stackoverflow.com/a/27109562
return sum(s_ != t_ for s_, t_ in zip(s, t))
def reverse_complement(s):
"""Return the reverse complement
>>> reverse_complement('GTCA')
'TGAC'
>>> reverse_complement('CGATATATCCATAG')
'CTATGGATATATCG'
>>> from Bio import SeqIO
>>> reverse_complement(*SeqIO.parse('data/02-data.fna', 'fasta'))
'ACCGGGTTTT'
"""
complement = dict(zip('ACGT', 'TGCA'))
return ''.join([complement[base] for base in s[::-1]])
if __name__ == "__main__":
import doctest
doctest.testmod()
```