Skip to content

Commit 6b5475c

Browse files
committed
hotfix primary alignments with hard clipped incomplete DNA read sequences
1 parent c5d74cc commit 6b5475c

2 files changed

Lines changed: 39 additions & 26 deletions

File tree

src/svirlpool/localassembly/consensus.py

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -300,26 +300,43 @@ def get_full_read_sequences_of_alignments(
300300
f"Not all read sequences could be acquired: {found}/{total} found. "
301301
f"Missing read(s): {', '.join(missing)}."
302302
)
303-
# for all other alignments, just add the sequence and reverse flag
303+
# for all other alignments, just add the sequence and reverse flag.
304+
# Only accept alignments whose query_sequence length matches the inferred
305+
# read length — otherwise the stored sequence would be a hard-clipped
306+
# fragment rather than the full read DNA.
307+
expected_readnames: set[str] = {
308+
aln.query_name for crID in crIDs for aln in dict_alignments[crID]
309+
}
304310
for crID in crIDs:
305311
for aln in dict_alignments[crID]:
306-
if aln.query_name not in dict_read_sequences:
307-
seq = (
308-
Seq(aln.query_sequence).reverse_complement()
309-
if aln.is_reverse
310-
else Seq(aln.query_sequence)
311-
)
312-
qualities = (
313-
{"phred_quality": aln.query_qualities}
314-
if aln.query_qualities
315-
else None
316-
)
317-
dict_read_sequences[aln.query_name] = SeqRecord(
318-
seq=seq,
319-
letter_annotations=qualities,
320-
id=aln.query_name,
321-
name=aln.query_name,
322-
)
312+
if aln.query_name in dict_read_sequences:
313+
continue
314+
if not aln.query_sequence:
315+
continue
316+
if aln.infer_read_length() != len(aln.query_sequence):
317+
continue
318+
seq = (
319+
Seq(aln.query_sequence).reverse_complement()
320+
if aln.is_reverse
321+
else Seq(aln.query_sequence)
322+
)
323+
qualities = (
324+
{"phred_quality": aln.query_qualities} if aln.query_qualities else None
325+
)
326+
dict_read_sequences[aln.query_name] = SeqRecord(
327+
seq=seq,
328+
letter_annotations=qualities,
329+
id=aln.query_name,
330+
name=aln.query_name,
331+
)
332+
333+
unresolved = [rn for rn in expected_readnames if rn not in dict_read_sequences]
334+
if unresolved:
335+
log.warning(
336+
f"Could not acquire full-length read sequence for {len(unresolved)}/"
337+
f"{len(expected_readnames)} read(s): {', '.join(unresolved)}. "
338+
"These reads will be excluded from the trimmed read set."
339+
)
323340
return dict_read_sequences
324341

325342

@@ -536,15 +553,11 @@ def trim_reads(
536553
for crID in dict_alignments.keys():
537554
for aln in dict_alignments[crID]:
538555
if aln.query_name in intervals:
539-
# fixed this :)
540-
# if aln.cigartuples[-1][0] ==5 or aln.cigartuples[-1][0] == 5:
541-
# raise(f"hard clipped read {read_aug_name} found in alignments. The complete DNA sequence of the read cannot be extracted.")
542556
if aln.query_name in cut_reads:
543557
continue
544-
if aln.infer_read_length() != len(read_records[aln.query_name]):
545-
raise ValueError(
546-
f"read length of {aln.query_name} does not match the length of the read record. read length from alignment: {aln.infer_read_length()}, read length from read record: {len(read_records[aln.query_name])}"
547-
)
558+
if aln.query_name not in read_records:
559+
# full-length read sequence could not be acquired; skip
560+
continue
548561
start, end, ref_start_chr, ref_start, ref_end_chr, ref_end = intervals[
549562
aln.query_name
550563
]

src/svirlpool/scripts/cut_reads_from_alns.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def cut_reads(
6363
continue
6464
if aln.infer_read_length() != len(read_records[aln.query_name]):
6565
raise ValueError(
66-
f"read length of {aln.query_name} does not match the length of the read record. read length from alignment: {aln.infer_read_length()}, read length from read record: {len(read_records[aln.query_name])}"
66+
f"read length of {aln.query_name} does not match the length of the read record. read length from alignment: {aln.infer_read_length()}, read length from read record: {len(read_records[aln.query_name])}. The cigar string of the alignment is {aln.cigarstring}. This should not happen. Please check your alignments and read records for consistency."
6767
)
6868
start, end, ref_start, ref_end = intervals[aln.query_name]
6969
record = read_records[aln.query_name][start:end]

0 commit comments

Comments
 (0)