FASTQ is a notoriously bad format. This is because it uses the same @
character for the id line as it does for quality scores. Deciding what is a quality score and what is an id is a tricky endeavor with many pitfalls.
I'd like your opinion of my while 1
approach in the function read_fastq
.
This works, but I'd like your tips and ideas on ways of improving it.
def read_fastq(fileH):
"""
takes a fastq file as input
yields idSeq, sequence and score
for each fastq entry
"""
#initialize the idSeq, sequence, score and index
idSeq, sequence, score = None, None, None
"""
main loop structure:
An outer while loop will run until the file runs out of lines.
If the line starts with @ and score exists, yield the id, sequence and score.
this is where the yielding happens in our loop, it could be considered where each
round of the loop ends
The first id is recorded on the first iteration.
If there is no sequence, begin an inner while loop,
read lines into sequence until we hit a + character, and break out of inner while loop
if there is no score, begin an inner while loop where we will increment score until we have
the same number of characters as sequence, this prevents interpretting a header as a score
"""
while 1:
line = fileH.readline()
#break if we hit the end of the file
if not line:
break
if line.startswith('@') and score:
#before yielding the sequence, remove non-ascii characters
sequence = legalChar(sequence)
yield idSeq, sequence, score
#reset to default values
sequence = None
score = None
idSeq = line.rstrip()
elif not idSeq:
#get our first idSeq
idSeq = line.rstrip()
continue
elif not sequence:
sequence = ""
while not line.startswith('+'):
sequence += line.rstrip().replace(' ', '')
line = fileH.readline()
elif not score:
score = []
#begin collecting our score, only collect as many chars as in our sequence
while 1:
score += line.rstrip().replace(' ', '')
if len(score) >= len(sequence):
break
else:
line = fileH.readline()
#yield our final idSeq, sequence and score
yield idSeq, sequence, score