Skip to content

Text before the first '>' header becomes an extra transcript with predicted ORFs #213

Open

Description

@adamjohnwright

What happens. If a transcript FASTA file has any text before its first > header line, TransDecoder.LongOrfs (6.0.0, and current master) treats that text as an extra transcript, named after the first word of the text, and predicts ORFs on it. There is no warning. The text also changes base_freqs.dat, which TransDecoder.Predict uses for scoring.

Reproduction. Three RefSeq mRNAs (NM_000546.6 TP53, NM_002046.7 GAPDH, NM_000207.3 INS), with and without a 1,437-byte block of ; comment lines in front, e.g. ;This file holds three RefSeq mRNA sequences that were downloaded…:

cat comment_block.txt mrna.fa > mrna.commented.fa
TransDecoder.LongOrfs -t mrna.fa
TransDecoder.LongOrfs -t mrna.commented.fa
6.0.0 mrna.fa mrna.commented.fa
ORFs in longest_orfs.pep 10 16 (6 on a "transcript" named ;This)
base_freqs.dat A / C / G / T 1903 / 2359 / 2359 / 1903 2040 / 2418 / 2418 / 2040

The real transcripts' ORFs are unchanged. Current master behaves the same way: 22 ORFs without the comment block, 28 with it, 6 of them on the comment text.

Cause. Fasta_reader::next() reads with $/ = "\n>", so the first chunk is everything before the first header. It is only skipped when it contains no word characters, which covers leading whitespace but not text.

Possible fix. On the first read only, skip a chunk that doesn't start with > but ends right before a header. This also covers the existing leading-whitespace case:

--- a/PerlLib/Fasta_reader.pm
+++ b/PerlLib/Fasta_reader.pm
@@ -42,6 +42,14 @@ sub next {
     $/="\n>";
     my $filehandle = $self->{fileHandle};
     my $next_text_input = <$filehandle>;
+
+	unless ($self->{_read_first_record}) {
+		$self->{_read_first_record} = 1;
+		## skip any text before the first '>' header line (e.g. ';' comment lines)
+		if (defined($next_text_input) && $next_text_input !~ /^>/ && $next_text_input =~ /\n>$/) {
+			$next_text_input = <$filehandle>;
+		}
+	}
     
 	if (defined($next_text_input) && $next_text_input !~ /\w/) {

With this change on master, longest_orfs.pep, .cds, .gff3 and base_freqs.dat are byte-identical with and without the comment block, for the three mRNAs and for a small synthetic file. In __testing, make gives the same result with and without the change (the single_best target currently differs from its expected file on master either way).

The same Fasta_reader.pm (with an identical next()) is in Trinity's PerlLib, so the fix may apply there too.

I'm happy to open a pull request if that would help.

Context. We found this while testing tools with the FAIR Header Reference genome (FHR) metadata standard, which stores provenance as ; comment lines before the first record (https://doi.org/10.1093/bib/bbae122). But any file with text before the first header is affected.

This report was prepared with an AI coding assistant (Claude Code) and checked by me.

Activity

  1. brianjohnhaas commented on Oct 20, 2026

    @brianjohnhaas
    Contributor
  2. adamjohnwright commented on Oct 20, 2026

    @adamjohnwright
    Author

    Thank you @brianjohnhaas, much appreciated! In case it's useful, the same Fasta_reader.pm is in Trinity's PerlLib.

  3. brianjohnhaas commented on Oct 20, 2026

    @brianjohnhaas
    Contributor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions