From ab6e452c3c2e482023d896f29300c27c1d79ae1f Mon Sep 17 00:00:00 2001 From: benjamincjackson Date: Thu, 13 Nov 2025 21:11:58 +0000 Subject: [PATCH] v0.13.1 --- assembly.go | 20 ++++++++++++++------ cli.go | 2 +- content.go | 22 +++++++++++++++------- fasta.go | 19 +++++++++++++++---- fasta_test.go | 8 ++++---- len.go | 20 ++++++++++++++------ names.go | 20 ++++++++++++++------ num.go | 20 ++++++++++++++------ 8 files changed, 91 insertions(+), 40 deletions(-) diff --git a/assembly.go b/assembly.go index 005bf58..109ad13 100644 --- a/assembly.go +++ b/assembly.go @@ -58,12 +58,7 @@ func (args assembly) writeHeader(w io.Writer) error { func (args assembly) writeBody(w io.Writer) error { for _, input := range args.inputs { - reader, file, err := getReaderFile(input) - if err != nil { - return err - } - defer file.Close() - err = assemblyRecords(input, reader, args, w) + err := writeBodyLineAssembly(w, input, args) if err != nil { return err } @@ -71,6 +66,19 @@ func (args assembly) writeBody(w io.Writer) error { return nil } +func writeBodyLineAssembly(w io.Writer, input string, args assembly) error { + reader, file, err := getReaderFile(input) + if err != nil { + return err + } + defer file.Close() + err = assemblyRecords(input, reader, args, w) + if err != nil { + return err + } + return nil +} + func assemblyRecords(inputPath string, r *Reader, args assembly, w io.Writer) error { contigLengths := make([]int64, 0) var totalLength int64 = 0 diff --git a/cli.go b/cli.go index 9fac05a..be838c9 100644 --- a/cli.go +++ b/cli.go @@ -13,7 +13,7 @@ var ( Use: "fastats {command}", Short: "Very simple statistics from fasta files", Long: ``, - Version: "0.13.0", + Version: "0.13.1", CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true}, Run: func(cmd *cobra.Command, args []string) { if licences { diff --git a/content.go b/content.go index 6e604d7..97b6e8f 100644 --- a/content.go +++ b/content.go @@ -69,12 +69,7 @@ func (args content) writeHeader(w io.Writer) error { func (args content) writeBody(w io.Writer) error { for _, input := range args.inputs { - reader, file, err := getReaderFile(input) - if err != nil { - return err - } - defer file.Close() - err = contentRecords(input, reader, args, w) + err := writeBodyLineContent(w, input, args) if err != nil { return err } @@ -82,6 +77,19 @@ func (args content) writeBody(w io.Writer) error { return nil } +func writeBodyLineContent(w io.Writer, input string, args content) error { + reader, file, err := getReaderFile(input) + if err != nil { + return err + } + defer file.Close() + err = contentRecords(input, reader, args, w) + if err != nil { + return err + } + return nil +} + func contentRecords(inputPath string, r *Reader, args content, w io.Writer) error { // initiate a count for the total length of the file @@ -92,7 +100,7 @@ func contentRecords(inputPath string, r *Reader, args content, w io.Writer) erro // iterate over every record in the fasta file for { - record, err := r.Read() + record, err := r.ReadCalcBaseCounts() if err == io.EOF { break } diff --git a/fasta.go b/fasta.go index acff1c0..ad02941 100644 --- a/fasta.go +++ b/fasta.go @@ -33,9 +33,18 @@ func NewZReader(f io.Reader) *Reader { return &Reader{bufio.NewReader(rz)} } -// Read reads one fasta record's info from the underlying reader. The final record is returned with error = nil, -// and the next call to Read() returns an empty Record struct and error = io.EOF. func (r *Reader) Read() (Record, error) { + return r.read(false) +} + +func (r *Reader) ReadCalcBaseCounts() (Record, error) { + return r.read(true) +} + +// read reads one fasta record's info from the underlying reader. The final record is returned with error = nil, +// and the next call to read() returns an empty Record struct and error = io.EOF. +// Base content is optionally counted +func (r *Reader) read(calcBaseCounts bool) (Record, error) { var ( line, peek []byte @@ -120,8 +129,10 @@ func (r *Reader) Read() (Record, error) { line = line[:len(line)-drop] } - for _, b := range line { - bases[b]++ + if calcBaseCounts { + for _, b := range line { + bases[b]++ + } } seqLength += int64(len(line)) } diff --git a/fasta_test.go b/fasta_test.go index 0a43994..56b245a 100644 --- a/fasta_test.go +++ b/fasta_test.go @@ -34,7 +34,7 @@ AT BaseCounts: bc, } - record, err := r.Read() + record, err := r.ReadCalcBaseCounts() if err != nil { t.Error(err) } @@ -53,7 +53,7 @@ AT Len: 20, BaseCounts: bc, } - record, err = r.Read() + record, err = r.ReadCalcBaseCounts() if err != nil { t.Error(err) } @@ -72,7 +72,7 @@ AT Len: 2, BaseCounts: bc, } - record, err = r.Read() + record, err = r.ReadCalcBaseCounts() if err != nil { t.Error(err) } @@ -82,7 +82,7 @@ AT } expected = Record{} - record, err = r.Read() + record, err = r.ReadCalcBaseCounts() if !errors.Is(err, io.EOF) { t.Error(err) } diff --git a/len.go b/len.go index 5e1974c..a21aa4a 100644 --- a/len.go +++ b/len.go @@ -48,12 +48,7 @@ func (args length) writeHeader(w io.Writer) error { func (args length) writeBody(w io.Writer) error { for _, input := range args.inputs { - reader, file, err := getReaderFile(input) - if err != nil { - return err - } - defer file.Close() - err = lengthRecords(input, reader, args, w) + err := writeBodyLineLen(w, input, args) if err != nil { return err } @@ -61,6 +56,19 @@ func (args length) writeBody(w io.Writer) error { return nil } +func writeBodyLineLen(w io.Writer, input string, args length) error { + reader, file, err := getReaderFile(input) + if err != nil { + return err + } + defer file.Close() + err = lengthRecords(input, reader, args, w) + if err != nil { + return err + } + return nil +} + func lengthRecords(inputPath string, r *Reader, args length, w io.Writer) error { // initiate a count for the length of each record diff --git a/names.go b/names.go index 2cb04b8..5e0290a 100644 --- a/names.go +++ b/names.go @@ -22,12 +22,7 @@ func (args names) writeHeader(w io.Writer) error { func (args names) writeBody(w io.Writer) error { for _, input := range args.inputs { - reader, file, err := getReaderFile(input) - if err != nil { - return err - } - defer file.Close() - err = namesRecords(input, reader, args, w) + err := writeBodyLineNames(w, input, args) if err != nil { return err } @@ -35,6 +30,19 @@ func (args names) writeBody(w io.Writer) error { return nil } +func writeBodyLineNames(w io.Writer, input string, args names) error { + reader, file, err := getReaderFile(input) + if err != nil { + return err + } + defer file.Close() + err = namesRecords(input, reader, args, w) + if err != nil { + return err + } + return nil +} + func namesRecords(inputPath string, r *Reader, args names, w io.Writer) error { // iterate over every record in the fasta file diff --git a/num.go b/num.go index 654fa2d..dc5fe2f 100644 --- a/num.go +++ b/num.go @@ -16,12 +16,7 @@ func (args num) writeHeader(w io.Writer) error { func (args num) writeBody(w io.Writer) error { for _, input := range args.inputs { - reader, file, err := getReaderFile(input) - if err != nil { - return err - } - defer file.Close() - err = numRecords(input, reader, args, w) + err := writeBodyLineNum(w, input, args) if err != nil { return err } @@ -29,6 +24,19 @@ func (args num) writeBody(w io.Writer) error { return nil } +func writeBodyLineNum(w io.Writer, input string, args num) error { + reader, file, err := getReaderFile(input) + if err != nil { + return err + } + defer file.Close() + err = numRecords(input, reader, args, w) + if err != nil { + return err + } + return nil +} + func numRecords(inputPath string, r *Reader, args num, w io.Writer) error { // initiate a count for the number of records var c_total int64 = 0