seqfu by-comment

by-comment selects FASTA and FASTQ records by the comment after the sequence identifier. It can search raw comment text, compare embedded key=value attributes, or evaluate arithmetic and boolean expressions over those attributes. To match identifiers instead, use seqfu by-id.

Usage:
  by-comment [options] [-e PATTERN]... [--where PREDICATE]... [--attribute-type KEY:TYPE]... [<item>...]

Comment text:
  -e, --pattern PATTERN       Add a pattern; may be repeated
  -f, --patterns-file FILE    Read one pattern per line
  --logic MODE                Combine patterns: any|all [default: any]
  -F, --fixed-string          Treat patterns as literal strings
  -x, --exact                 Match the complete comment
  -i, --ignore-case           Ignore case
  --has-comment               Require a non-empty comment
  --no-comment                Require an empty comment

Attributes:
  --where PREDICATE           Add a typed test; may be repeated
  --where-file FILE           Read one predicate per line
  --where-logic MODE          Combine predicates: any|all [default: all]
  --expr EXPRESSION           Evaluate a kexpr expression
  --expr-file FILE            Read one expression from FILE
  --attribute-separator CHAR  Key/value separator [default: =]
  --decimal-separator CHAR    Decimal separator [default: .]
  --thousands-separator CHAR  Grouping separator [default: ,]
  --attribute-type KEY:TYPE   Force string|integer|float; may be repeated
  --duplicate-keys MODE       Resolve first|last|error [default: last]
  --invalid-value MODE        Failed typed conversion: false|error [default: false]

Input and output:
  -1, --r1 FILE              Paired-end R1 FASTQ
  -2, --r2 FILE              Paired-end R2 FASTQ
  --interleaved              Treat one input as interleaved FASTQ
  --pair-mode MODE           Match either or both mates: any|both [default: any]
  -o, --output FILE          Write to FILE (gzip if .gz)
  -O, --output-r2 FILE       Write selected R2 reads to FILE
  --interleaved-output       Override inferred R2 filename
  --gzip-level INT           Gzip compression level [default: 6]

Other:
  -v, --invert-match         Invert the final selection
  -t, --threads INT          Worker threads [default: 1]
  --batch-size INT           Records or pairs per batch [default: 4096]
  --stats                    Print counts to stderr
  --verbose                  Print input and output routing to stderr
  -h, --help                 Show this help

Search comment text

A positional pattern is a pure Nim regular expression matched anywhere in the comment. A command-line pattern or a pattern file can contain multiple alternatives; --logic all requires all text patterns to match the same comment. -F treats them as literal strings and -x matches the whole comment.

seqfu by-comment 'complete genome' assemblies.fa
seqfu by-comment -i -F -e circular -e complete --logic all assemblies.fa
seqfu by-comment -f comment-patterns.txt reads.fastq.gz
seqfu by-comment --no-comment assemblies.fa

Pattern files contain one pattern per line. Blank lines and lines beginning with # are ignored. With no input file, the command reads standard input; - names it explicitly. Use -e when a positional pattern could be confused with an input path.

Compare attributes

The parser finds key=value fields anywhere in a comment. Keys begin with a letter or _ and can also contain digits, _, -, and .. Unquoted values end at whitespace or ;; single- or double-quoted values can contain spaces and can escape their quote or a backslash with \. Other prose is ignored.

For example, description="complete circular genome" len=2,203 gc=0.49 contains three attributes. Numeric parsing is strict and independent of the system locale: 2,203 is 2203, while malformed grouping such as 2,20 remains a string for --where equality and regex tests. A numeric-looking malformed value makes an expression false (or errors with --invalid-value error). Integer overflow never wraps.

--where accepts these comparisons:

Form Meaning
KEY = VALUE, KEY != VALUE Numeric equality when both values are numbers; otherwise raw string equality
KEY < VALUE, <=, >, >= Numeric ordering
KEY ~ REGEX, KEY !~ REGEX Pure Nim regex search on the raw value
KEY exists, KEY missing Presence or absence

Missing keys fail ordinary comparisons, including != and !~. By default, multiple --where tests use AND; --where-logic any switches to OR. Text, --where, and --expr groups are combined with AND.

seqfu by-comment --where 'len >= 2000' --where 'gc < 0.5' assemblies.fa
seqfu by-comment --where 'status = complete' assemblies.fa
seqfu by-comment --where 'taxonomy exists' assemblies.fa
seqfu by-comment --where-file predicates.txt assemblies.fa

Use --attribute-type sample:string when sample=001 must not compare numerically equal to sample=1. --duplicate-keys chooses the first or last value, or errors on a duplicate. --invalid-value error turns failed typed conversion into a diagnostic. Custom decimal and thousands separators can be supplied explicitly.

Evaluate expressions

--expr uses kexpr for arithmetic, parentheses, comparisons, and boolean operators. It uses == for equality, whereas --where uses =. An expression can also be read from --expr-file; the two options are mutually exclusive.

seqfu by-comment --expr '(len >= 2000 && gc < 0.5) || score >= 3' assemblies.fa
seqfu by-comment --expr 'len * gc >= 1000' assemblies.fa
seqfu by-comment --expr 'status == "complete"' assemblies.fa

Expression variable names map - and . in attribute keys to _; for example, read-count becomes read_count. A collision after mapping is an error. A missing expression variable makes the expression false for that record, not zero. Use --where 'KEY missing' for an explicit absence test.

Paired reads and files

Pass two FASTQ files with -1 and -2, or one interleaved FASTQ with --interleaved. The complete predicate is tested on each mate. By default, either mate may match; --pair-mode both requires both. Selected pairs are always emitted together and are interleaved on standard output.

seqfu by-comment --where 'score >= 3' -1 reads_R1.fq.gz -2 reads_R2.fq.gz \
  -o selected_R1.fq.gz -O selected_R2.fq.gz
seqfu by-comment --expr 'len >= 2000' --interleaved reads.fq.gz \
  --pair-mode both -o selected.fq.gz

With -o but no -O, an R2 filename is inferred from _R1/_R2 or _1./_2.. If neither pattern applies, pairs stay interleaved in the single output file. --interleaved-output forces that behavior. A .gz output suffix enables gzip compression. -t enables bounded, ordered parallel matching; the default single-thread path avoids copying records into batches.