@@ -1325,6 +1325,35 @@ def _extract_tracts_as_n_full_length(
13251325 return "" .join (c for c in seq if c != "-" )
13261326
13271327
1328+ def _extract_full_length_non_opposite (
1329+ aligned_seq : str ,
1330+ allegiances : List [Tuple [int , str ]],
1331+ keep_clade : str ,
1332+ ) -> str :
1333+ """
1334+ Build a full-length (degapped) sequence where positions are kept for a clade
1335+ whenever they are NOT confidently assigned to the opposite clade.
1336+
1337+ keep_clade == "ia": keep any position that is not classified as "ib"
1338+ keep_clade == "ib": keep any position that is not classified as "ia"
1339+ Everything else at non-kept positions becomes N. Gaps are removed.
1340+ """
1341+ pos_to_all = {p : a for (p , a ) in allegiances }
1342+ seq_out : List [str ] = []
1343+ for idx , b in enumerate (aligned_seq ):
1344+ if b == "-" :
1345+ continue
1346+ pos = idx + 1
1347+ a = pos_to_all .get (pos , "other" )
1348+ if keep_clade == "ia" :
1349+ keep = (a != "ib" )
1350+ elif keep_clade == "ib" :
1351+ keep = (a != "ia" )
1352+ else :
1353+ keep = True
1354+ seq_out .append (b if keep else "N" )
1355+ return "" .join (seq_out )
1356+
13281357def _extract_tract_sequences (
13291358 out_dir : Path ,
13301359 results : List [dict ],
@@ -1378,18 +1407,18 @@ def _extract_tract_sequences(
13781407 n_skip_no_seq += 1
13791408 continue
13801409
1381- # ref1 (Ia) file: keep only ia tract bases; Ib + other → N .
1382- # ref2 (Ib) file: keep only ib tract bases; Ia + other → N .
1410+ # ref1 (Ia) file: keep clade I bases and all positions not confidently Ib .
1411+ # ref2 (Ib) file: keep clade IIb bases and all positions not confidently Ia .
13831412 safe_id = _safe_fasta_id (sample_id )
1384- seq1 = _extract_tracts_as_n_full_length (aligned_seq , merged_tracts , keep_clade = "ia" )
1413+ seq1 = _extract_full_length_non_opposite (aligned_seq , allegiances , keep_clade = "ia" )
13851414 len1 = len (seq1 )
13861415 non_n1 = sum (1 for b in seq1 .upper () if b in "ACGT" )
13871416 cov1 = (100.0 * non_n1 / len1 ) if len1 else 0.0
13881417 fh1 .write (f">{ safe_id } _{ ref1_label } _tract_HC_{ cov1 :.2f} %\n " )
13891418 for i in range (0 , len1 , line_len ):
13901419 fh1 .write (seq1 [i : i + line_len ] + "\n " )
13911420
1392- seq2 = _extract_tracts_as_n_full_length (aligned_seq , merged_tracts , keep_clade = "ib" )
1421+ seq2 = _extract_full_length_non_opposite (aligned_seq , allegiances , keep_clade = "ib" )
13931422 len2 = len (seq2 )
13941423 non_n2 = sum (1 for b in seq2 .upper () if b in "ACGT" )
13951424 cov2 = (100.0 * non_n2 / len2 ) if len2 else 0.0
0 commit comments