@@ -148,9 +148,7 @@ def aggregate_annotations(
148148 # and prophage predictions can extend beyond the original contig boundaries
149149 clean_contig_name = Record .remove_prophage_from_contig (contig )
150150 contig_len = contigs_len_dict [clean_contig_name ]
151- does_the_prophage_overrun = (
152- prophage_end > contig_len
153- )
151+ does_the_prophage_overrun = prophage_end > contig_len
154152
155153 if does_the_prophage_overrun :
156154 # We truncate as the prophage_end could overrun
@@ -177,7 +175,7 @@ def aggregate_annotations(
177175 if best_hit != "No hit" :
178176 best_hit = best_hit .replace (".faa" , "" )
179177 viphog_annotation = ";" .join (
180- [f"viphog={ best_hit } " , f' viphog_taxonomy={ row [" Label" ] } ' ]
178+ [f"viphog={ best_hit } " , f" viphog_taxonomy={ row [' Label' ] } " ]
181179 )
182180 # We need to remove all the virify prophage annotations, if any
183181 contig_name_clean = Record .remove_prophage_from_contig (contig )
@@ -212,6 +210,7 @@ def write_gff(
212210 virify_quality ,
213211 contigs_len_dict ,
214212 ena_mapping = None ,
213+ user_proteins = False ,
215214):
216215 """Generate a GFF3 file from VIRify output files with comprehensive viral sequence annotations.
217216
@@ -229,7 +228,8 @@ def write_gff(
229228 :param ena_mapping: Optional ENA contig mapping for renaming (ERZ accession will be used if provided)
230229 :param contigs_len_dict: Optional pre-loaded dictionary mapping contig names to lengths.
231230 If not provided, will be loaded from assembly_file.
232-
231+ :param ena_mapping: ENA mapping dict
232+ :param user_proteins: Flag used when users provide their "proteins"
233233 :return: None (writes GFF file to disk)
234234 """
235235 if ena_mapping :
@@ -307,13 +307,33 @@ def empty_if_number(string):
307307 # Collect all sequence-region headers
308308 sequence_regions = []
309309 used_contigs = set ()
310+
311+ missed_contigs = 0
312+
310313 for contig_name in viral_sequences .keys ():
311314 clean_contig_name = Record .remove_prophage_from_contig (contig_name )
312315 if clean_contig_name not in used_contigs :
313316 used_contigs .add (clean_contig_name )
314- contig_length = contigs_len_dict [clean_contig_name ]
317+ # Users may provide proteins for all the contigs, but VIRify only considers contigs
318+ # that are longer than 150K, so when users provide a proteins file (--user_proteins)
319+ # we allow mismatches here. Guard applies regardless of user_proteins to avoid
320+ # writing None as contig length in the GFF3 sequence-region directive.
321+ contig_length = contigs_len_dict .get (clean_contig_name )
322+ if contig_length is None :
323+ missed_contigs += 1
324+ continue
315325 sequence_regions .append ((clean_contig_name , contig_length ))
316326
327+ if missed_contigs > 0 :
328+ logging .warning (
329+ f"{ missed_contigs } contigs were not found in the assembly and were skipped"
330+ )
331+
332+ if not sequence_regions :
333+ raise ValueError (
334+ "All the contigs that came from the annotated viral sequences were discarded."
335+ )
336+
317337 # Sort sequence-region headers by contig name
318338 sequence_regions .sort (key = lambda x : x [0 ])
319339
@@ -331,7 +351,9 @@ def empty_if_number(string):
331351 element_category = "viral_sequence"
332352 id_ = f"ID={ clean_contig_name } |viral_sequence"
333353 start = 1
334- end = contigs_len_dict [clean_contig_name ]
354+ end = contigs_len_dict .get (clean_contig_name )
355+ if end is None :
356+ continue
335357 mobile_element_type = viral_seq_type
336358
337359 if "prophage" in viral_seq_type :
@@ -385,9 +407,12 @@ def empty_if_number(string):
385407 region_name = "_" .join (cds_id .split ("_" )[:- 1 ])
386408 cds_id = cds_id .replace ("prophage-0:" , "prophage-1:" )
387409
388- # TODO: review this rule.
389- if end > contigs_len_dict [contig_name ]:
390- end = contigs_len_dict [contig_name ]
410+ contig_len = contigs_len_dict .get (contig_name )
411+ if contig_len is None :
412+ continue
413+
414+ if end > contig_len :
415+ end = contig_len
391416
392417 quality = (
393418 virify_quality [region_name ]
@@ -570,6 +595,7 @@ def empty_if_number(string):
570595 )
571596
572597 logging .info ("Generating the gff output" )
598+
573599 write_gff (
574600 checkv_files ,
575601 taxonomy_files ,
@@ -580,4 +606,5 @@ def empty_if_number(string):
580606 virify_quality ,
581607 contigs_len_dict ,
582608 ena_mapping = ena_mapping ,
609+ user_proteins = args .use_proteins ,
583610 )
0 commit comments