diff --git a/src/convert/command.rs b/src/convert/command.rs index ea20904..4f06f7b 100644 --- a/src/convert/command.rs +++ b/src/convert/command.rs @@ -1,5 +1,6 @@ //! Functionality related to the `ngs convert` command itself. +use std::num::NonZeroUsize; use std::path::PathBuf; use anyhow::bail; @@ -31,8 +32,8 @@ pub struct ConvertArgs { to: PathBuf, /// Number of records to process before exiting the conversion. - #[arg(short = 'n', long, value_name = "USIZE")] - num_records: Option, + #[arg(short = 'n', long, value_name = "NonZeroUsize")] + num_records: Option, /// If available, the FASTA reference file used to generate the file. #[arg(short, long)] diff --git a/src/derive/command/encoding.rs b/src/derive/command/encoding.rs index 7489365..1949a6c 100644 --- a/src/derive/command/encoding.rs +++ b/src/derive/command/encoding.rs @@ -6,6 +6,7 @@ use noodles::bam; use num_format::{Locale, ToFormattedString}; use std::collections::HashSet; use std::io::BufReader; +use std::num::NonZeroUsize; use std::path::PathBuf; use tracing::info; @@ -21,8 +22,8 @@ pub struct DeriveEncodingArgs { src: PathBuf, /// Examine the first `n` records in the file. - #[arg(short, long, value_name = "USIZE")] - num_records: Option, + #[arg(short, long, value_name = "NonZeroUsize")] + num_records: Option, } /// Main function for the `ngs derive encoding` subcommand. diff --git a/src/derive/command/endedness.rs b/src/derive/command/endedness.rs index 78082c7..da14afd 100644 --- a/src/derive/command/endedness.rs +++ b/src/derive/command/endedness.rs @@ -4,6 +4,7 @@ use anyhow::Context; use clap::Args; use num_format::{Locale, ToFormattedString}; use std::collections::{HashMap, HashSet}; +use std::num::NonZeroUsize; use std::path::PathBuf; use std::sync::Arc; use tracing::{info, trace}; @@ -24,9 +25,9 @@ pub struct DeriveEndednessArgs { #[arg(value_name = "BAM")] src: PathBuf, - /// Only examine the first n records in the file. - #[arg(short, long, value_name = "USIZE")] - num_records: Option, + /// Examine the first `n` records in the file. + #[arg(short, long, value_name = "NonZeroUsize")] + num_records: Option, /// Distance from 0.5 split between number of f+l- reads and f-l+ reads /// allowed to be called 'Paired-End'. The default value of `0.0` is only appropriate diff --git a/src/derive/command/instrument.rs b/src/derive/command/instrument.rs index a0776f8..ccbe520 100644 --- a/src/derive/command/instrument.rs +++ b/src/derive/command/instrument.rs @@ -4,6 +4,7 @@ use anyhow::bail; use clap::Args; use num_format::{Locale, ToFormattedString}; use std::collections::HashSet; +use std::num::NonZeroUsize; use std::path::PathBuf; use tracing::info; @@ -21,9 +22,10 @@ pub struct DeriveInstrumentArgs { #[arg(value_name = "BAM")] src: PathBuf, - /// Only examine the first n records in the file. - #[arg(short, long, value_name = "USIZE")] - num_records: Option, + /// Examine the first `n` records in the file. + /// If `0`, all records are examined. + #[arg(short, long, value_name = "USIZE", default_value = "10000000")] + num_records: usize, } /// Main function for the `ngs derive instrument` subcommand. @@ -41,7 +43,10 @@ pub fn derive(args: DeriveInstrumentArgs) -> anyhow::Result<()> { // (1) Collect instrument names and flowcell names from reads within the // file. Support for sampling only a portion of the reads is provided. - let num_records = NumberOfRecords::from(args.num_records); + let num_records = match args.num_records { + 0 => NumberOfRecords::All, + _ => NumberOfRecords::Some(NonZeroUsize::new(args.num_records).unwrap()), + }; let mut counter = RecordCounter::default(); for result in reader.records(&header.parsed) { diff --git a/src/derive/command/readlen.rs b/src/derive/command/readlen.rs index f5c2246..031abe4 100644 --- a/src/derive/command/readlen.rs +++ b/src/derive/command/readlen.rs @@ -4,6 +4,7 @@ use anyhow::Context; use clap::Args; use num_format::{Locale, ToFormattedString}; use std::collections::HashMap; +use std::num::NonZeroUsize; use std::path::PathBuf; use tracing::info; @@ -21,9 +22,10 @@ pub struct DeriveReadlenArgs { #[arg(value_name = "BAM")] src: PathBuf, - /// Only examine the first n records in the file. - #[arg(short, long, value_name = "USIZE")] - num_records: Option, + /// Examine the first `n` records in the file. + /// If `0`, all records are examined. + #[arg(short, long, value_name = "USIZE", default_value = "10000000")] + num_records: usize, /// Majority vote cutoff value as a fraction between [0.0, 1.0]. #[arg(short, long, value_name = "F64", default_value = "0.7")] @@ -46,7 +48,10 @@ pub fn derive(args: DeriveReadlenArgs) -> anyhow::Result<()> { // (1) Collect read lengths from reads within the // file. Support for sampling only a portion of the reads is provided. - let num_records = NumberOfRecords::from(args.num_records); + let num_records = match args.num_records { + 0 => NumberOfRecords::All, + _ => NumberOfRecords::Some(NonZeroUsize::new(args.num_records).unwrap()), + }; let mut counter = RecordCounter::default(); for result in reader.records(&header.parsed) { diff --git a/src/qc/command.rs b/src/qc/command.rs index d628c00..c6993d7 100644 --- a/src/qc/command.rs +++ b/src/qc/command.rs @@ -1,6 +1,7 @@ //! Functionality related to the `ngs qc` command itself. use std::fs::File; +use std::num::NonZeroUsize; use std::path::PathBuf; use std::rc::Rc; @@ -50,8 +51,8 @@ pub struct QcArgs { /// to process per sequence in the second pass. /// /// This is generally only used for testing purposes. - #[arg(short = 'n', long, value_name = "USIZE")] - num_records: Option, + #[arg(short = 'n', long, value_name = "NonZeroUsize")] + num_records: Option, /// Directory to output files to. Defaults to current working directory. #[arg(short = 'o', long, value_name = "PATH")] diff --git a/src/utils/args.rs b/src/utils/args.rs index 094819a..7bd3ce0 100644 --- a/src/utils/args.rs +++ b/src/utils/args.rs @@ -1,6 +1,7 @@ //! Utilities related to the parsing of arguments. use std::fmt::Display; +use std::num::NonZeroUsize; use noodles::{bgzf::writer::CompressionLevel, sam::record::MappingQuality}; use tracing::debug; @@ -17,11 +18,11 @@ pub enum NumberOfRecords { /// Designates that we should review _some_ of the records in the file. The /// exact count of records is stored in the `usize`. - Some(usize), + Some(NonZeroUsize), } -impl From> for NumberOfRecords { - fn from(num_records: Option) -> Self { +impl From> for NumberOfRecords { + fn from(num_records: Option) -> Self { match num_records { Some(n) => { debug!("Reading a maximum of {} records.", n); diff --git a/src/utils/display.rs b/src/utils/display.rs index 7ee4f56..1ffbbca 100644 --- a/src/utils/display.rs +++ b/src/utils/display.rs @@ -74,7 +74,7 @@ impl RecordCounter { /// (if it exists, otherwise it loops forever). pub fn time_to_break(&self, limit: &NumberOfRecords) -> bool { match limit { - NumberOfRecords::Some(v) => self.count >= *v, + NumberOfRecords::Some(v) => self.count >= ::from(*v), NumberOfRecords::All => false, } }