import csv
import sys
global y
def main():
y = 0
x = 0
# Check for command-line usage
if len(sys.argv) != 3:
sys.exit("Usage: python dna.py data.csv sequence.txt")
# TODO: Read database file into a variable
people = []
data = sys.argv[1]
with open(data) as f:
check = csv.DictReader(f)
for row in check:
x += 1
if x > 5:
with open(data) as g:
reader = csv.DictReader(g)
for row in reader:
person = {
"name": row["name"],
"AGATC":int(row["AGATC"]),
"TTTTTTCT":int(row["TTTTTTCT"]),
"AATG": int(row["AATG"]),
"TCTAG":int(row["TCTAG"]),
"GATA":int(row["GATA"]),
"TATC": int(row["TATC"]),
"GAAA":int(row["GAAA"]),
"TCTG":int(row["TCTG"])
}
people.append(person)
else:
with open(data) as h:
reader = csv.DictReader(h)
for row in reader:
person = {
"name": row["name"],
"AGATC":int(row["AGATC"]),
"AATG": int(row["AATG"]),
"TATC": int(row["TATC"])
}
people.append(person)
fil = open(sys.argv[2])
# Read DNA sequence file into a variable
syn = fil.read()
# TODO: Find longest match of each STR in DNA sequence
AGATC = longest_match(syn, "AGATC")
AATG = longest_match(syn, "AATG")
TATC = longest_match(syn, "TATC")
# TODO: Check database for matching profiles
for person in people:
if int(person["AGATC"]) == AGATC:
if int(person["AATG"]) == AATG:
if int(person["TATC"]) == TATC:
val = person["name"]
print(f"{val}")
y += 1
if y == 0:
print("No match")
return
def longest_match(sequence, subsequence):
"""Returns length of longest run of subsequence in sequence."""
# Initialize variables
longest_run = 0
subsequence_length = len(subsequence)
sequence_length = len(sequence)
# Check each character in sequence for most consecutive runs of subsequence
for i in range(sequence_length):
# Initialize count of consecutive runs
count = 0
# Check for a subsequence match in a "substring" (a subset of characters) within sequence
# If a match, move substring to next potential match in sequence
# Continue moving substring and checking for matches until out of consecutive matches
while True:
# Adjust substring start and end
start = i + count * subsequence_length
end = start + subsequence_length
# If there is a match in the substring
if sequence[start:end] == subsequence:
count += 1
# If there is no match in the substring
else:
break
# Update most consecutive matches found
longest_run = max(longest_run, count)
# After checking for runs at each character in seqeuence, return longest run found
return longest_run
main()
1 Answer
Updated 2023-06-09:
OK, I ran check50
for your updated code using this command:
check50 cs50/problems/2023/x/dna
When I do, I only get the error for databases/large.csv
and sequences/18.txt
. Your program outputs Harry
and you are supposed to get No match
. This isn't a surprise -- it's the same output shown in the project instructions.
I did not look at all of your code, but found an area that needs significant attention. You only get the longest match for 3 gene sequences: AGATC, AATG and TATC.
There are 8 gene sequences in the large.csv
database. You also need to check the 5 additional gene sequences. They are: TTTTTTCT, TCTAG, GATA, GAAA, and TCTG
. I'm surprised you got most of the matches correct when checking the large database.
Here are a few thoughts to consider before you add more checks.
- All of the gene sequences hard-coded. There are all kinds
of reasons not to do that. The biggest reason -- you have to modify
your code anytime the input changes. If you hard code everything, you will need 8 variables to hold the longest match counts and 8
if
blocks to test them against each profile. - You also see this in your code blocks to read the database file. There are 2 different blocks based on the number of lines in the file. (This is also not good practice -- there should only be 1 read block, and it should be based on the genes on the header line -- not the number of lines!!)
- Hint: look at the
.fieldnames
attribute in thecsv.DictReader
documentation. This will let you capture the sequences on the database header row and use throughout your program.