Skip to content
This repository has been archived by the owner on Dec 23, 2024. It is now read-only.

style: reformat code and add doc tests #12

Merged
merged 19 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions barkit-extract/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
FileRead(#[from] std::io::Error),
#[error("No match")]
PatternNotMatched,
#[error("Fancy regex error: {0}")]
FancyRegex(#[from] fancy_regex::Error),
}

impl Clone for Error {
Expand All @@ -32,6 +34,7 @@
}
Error::FileRead(err) => Error::FileRead(err.kind().into()),
Error::PatternNotMatched => Error::PatternNotMatched,
Error::FancyRegex(err) => Error::FancyRegex(err.clone()),

Check warning on line 37 in barkit-extract/src/error.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/error.rs#L37

Added line #L37 was not covered by tests
}
}
}
6 changes: 3 additions & 3 deletions barkit-extract/src/fastq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
}
}

pub fn get_output_compression_type(gz: &bool, bgz: &bool, mgz: &bool, lz4: &bool) -> Self {
pub fn select(gz: &bool, bgz: &bool, mgz: &bool, lz4: &bool) -> Self {

Check warning on line 47 in barkit-extract/src/fastq.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/fastq.rs#L47

Added line #L47 was not covered by tests
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved
match (gz, bgz, mgz, lz4) {
(true, false, false, false) => Self::Gzip,
(false, true, false, false) => Self::Mgzip,
Expand All @@ -54,7 +54,7 @@
}
}

fn get_input_compression_type(path: &Path) -> CompressionType {
fn detect(path: &Path) -> CompressionType {

Check warning on line 57 in barkit-extract/src/fastq.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/fastq.rs#L57

Added line #L57 was not covered by tests
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved
let mut buffer = [0u8; 16];

File::open(path)
Expand Down Expand Up @@ -95,7 +95,7 @@

let buffer_size_in_bytes = get_reader_buffer_size(&file, buffer_size_in_megabytes)?;

let decoder: Box<dyn Read> = match CompressionType::get_input_compression_type(path) {
let decoder: Box<dyn Read> = match CompressionType::detect(path) {

Check warning on line 98 in barkit-extract/src/fastq.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/fastq.rs#L98

Added line #L98 was not covered by tests
CompressionType::Gzip | CompressionType::Mgzip => Box::new(MultiGzDecoder::new(file)),
CompressionType::Lz4 => Box::new(Decoder::new(file)?),
CompressionType::Bgzf => Box::new(
Expand Down
2 changes: 1 addition & 1 deletion barkit-extract/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod barcode;
pub mod parse;
pub mod error;
pub mod fastq;
pub mod logger;
Expand Down
116 changes: 99 additions & 17 deletions barkit-extract/src/logger.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,107 @@
use console::Emoji;
use indicatif::{ProgressBar, ProgressStyle};
use std::time::Instant;

use crate::error::Error;
use crate::fastq;
use console::{style, Emoji};
use indicatif::{HumanDuration, ProgressBar, ProgressStyle};

pub static SPARKLE: Emoji<'_, '_> = Emoji("✨ ", ":-)");
static PROGRESS_BAR_TEMPLATE: &str = "{spinner:.green} [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {per_sec} ({eta})";

pub fn create_progress_bar(
fastq_file: &str,
threads: usize,
max_memory: Option<usize>,
) -> Result<ProgressBar, Error> {
let progress_bar_style = ProgressStyle::with_template(
"{spinner:.green} [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {per_sec} ({eta})",
).expect("Failed to parse a progress bar template")
.progress_chars("##-");
pub struct Logger {
/// Index of the current step
current: usize,

let read_num = fastq::get_reads_count(fastq_file, threads, max_memory) as u64;
/// Total number of steps
total: usize,

let progress_bar = ProgressBar::new(read_num as u64);
progress_bar.set_style(progress_bar_style.clone());
/// If true, logs will not be displayed
quiet: bool,

Ok(progress_bar)
/// Start time of execution
execution_start: Instant,

/// Progress bar
progress_bar: Option<ProgressBar>,
}

impl Logger {
/// Creates `Logger` instance with default values.
///
/// # Example
///
/// ```
/// use barkit_extract::logger::Logger;
///
/// let logger = Logger::new(3, false);
/// ```
pub fn new(total: usize, quiet: bool) -> Self {

Check warning on line 36 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L36

Added line #L36 was not covered by tests
Self {
current: 0,
total,
quiet,
execution_start: Instant::now(),

Check warning on line 41 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L41

Added line #L41 was not covered by tests
progress_bar: None
}
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved
}

/// Prints logging message for the current step.
///
/// # Example
///
/// ```
/// use barkit_extract::logger::Logger;
///
/// let mut logger = Logger::new(2, false);
///
/// logger.message("first logging message");
/// // Output: "[1/2] first logging message"
///
/// logger.message("second logging message");
/// // Output: "[2/2] second logging message"
///
/// logger.message("third logging message");
/// // Output: "Warning: Current step exceeds total steps."
/// ```
pub fn message(&mut self, text: &str) {
if self.current < self.total {
self.current += 1;
if !self.quiet {
println!("{} {}", style(format!("[{}/{}]", self.current, self.total)).bold().dim(), text);

Check warning on line 68 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L64-L68

Added lines #L64 - L68 were not covered by tests
}
} else {
// Optionally handle the case where `current` exceeds `total`
eprintln!("Warning: Current step exceeds total steps.");

Check warning on line 72 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L72

Added line #L72 was not covered by tests
}
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved
}

/// Increments progress in the progress bar
pub fn increment_progress(&self, done_lines: usize) {
if let Some(ref pb) = self.progress_bar {
pb.inc(done_lines as u64)

Check warning on line 79 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L77-L79

Added lines #L77 - L79 were not covered by tests
}
}
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved

/// Sets progress bar instance with specified length
pub fn set_progress_bar(&mut self, size: usize) {
if !self.quiet {
let progress_bar_style = ProgressStyle::with_template(PROGRESS_BAR_TEMPLATE)

Check warning on line 86 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L84-L86

Added lines #L84 - L86 were not covered by tests
.expect("Failed to parse a progress bar template")
.progress_chars("##-");

let progress_bar = ProgressBar::new(size as u64);
progress_bar.set_style(progress_bar_style);

Check warning on line 91 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L90-L91

Added lines #L90 - L91 were not covered by tests

self.progress_bar = Some(progress_bar);

Check warning on line 93 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L93

Added line #L93 was not covered by tests
}
}
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved

/// Prints a final message when all steps are completed
pub fn final_message(&self) {
if self.progress_bar.is_some() {

Check warning on line 99 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L98-L99

Added lines #L98 - L99 were not covered by tests
println!(
"{} Done in {}",
SPARKLE,
HumanDuration(self.execution_start.elapsed())

Check warning on line 103 in barkit-extract/src/logger.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/logger.rs#L103

Added line #L103 was not covered by tests
)
}
}
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved
}
80 changes: 5 additions & 75 deletions barkit-extract/src/barcode.rs → barkit-extract/src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::pattern;
use regex::bytes::{Captures, Regex};
use crate::pattern::BarcodeRegex;
use regex::bytes::Captures;
Comment on lines +3 to +4
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove outdated import statement.

The import of BarcodeRegex is outdated and should be removed to prevent compilation errors, as the BarcodeRegex struct has been removed from the codebase.

- use crate::pattern::BarcodeRegex;
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
use crate::pattern::BarcodeRegex;
use regex::bytes::Captures;
use regex::bytes::Captures;


use seq_io::fastq::{OwnedRecord, Record, RefRecord};
use std::{fmt, str};
use std::str;

use crate::error::Error;

Expand All @@ -29,76 +29,6 @@
table
};

#[derive(Clone)]
pub enum BarcodeType {
Umi,
Sample,
Cell,
}

impl fmt::Display for BarcodeType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let barcode_str = match self {
BarcodeType::Umi => "UMI",
BarcodeType::Sample => "SB",
BarcodeType::Cell => "CB",
};
write!(f, "{}", barcode_str)
}
}

impl BarcodeType {
fn get_barcode_type(name: &str) -> Result<Self, Error> {
match name {
"UMI" => Ok(BarcodeType::Umi),
"SB" => Ok(BarcodeType::Sample),
"CB" => Ok(BarcodeType::Cell),
_ => Err(Error::UnexpectedCaptureGroupName(name.to_owned())),
}
}
}

#[derive(Clone)]
pub struct BarcodeRegex {
regex: Regex,
barcode_types: Vec<BarcodeType>,
}

impl BarcodeRegex {
pub fn new(pattern: &str, max_error: usize) -> Result<Self, Error> {
let fuzzy_pattern = pattern::get_with_errors(pattern, &max_error);
let regex = Regex::new(&fuzzy_pattern)?;
let barcode_types = Self::parse_capture_groups(&regex)?;
Ok(Self {
regex,
barcode_types,
})
}

pub fn get_captures<'a>(&'a self, read_seq: &'a [u8]) -> Result<Captures, Error> {
match self.regex.captures(read_seq) {
Some(capture) => Ok(capture),
None => Err(Error::PatternNotMatched),
}
}

fn parse_capture_groups(regex: &Regex) -> Result<Vec<BarcodeType>, Error> {
let mut capture_groups = Vec::<BarcodeType>::new();
for capture_group in regex
.capture_names()
.collect::<Vec<_>>()
.into_iter()
.flatten()
{
capture_groups.push(BarcodeType::get_barcode_type(capture_group)?)
}
if capture_groups.is_empty() {
return Err(Error::BarcodeCaptureGroupNotFound(regex.to_string()));
}
Ok(capture_groups)
}
}

pub struct BarcodeParser {
barcode_regex: BarcodeRegex,
skip_trimming: bool,
Expand Down Expand Up @@ -161,7 +91,7 @@
let seq = record.seq().to_vec();
let qual = record.qual().to_vec();

for barcode in &self.barcode_regex.barcode_types {
for barcode in &self.barcode_regex.get_barcode_types() {

Check warning on line 94 in barkit-extract/src/parse.rs

View check run for this annotation

Codecov / codecov/patch

barkit-extract/src/parse.rs#L94

Added line #L94 was not covered by tests
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved
let barcode_name = barcode.to_string();
let (barcode_start, barcode_end) =
get_barcode_match_positions(&barcode_name, captures)?;
Expand Down Expand Up @@ -245,7 +175,7 @@
mod tests {
use rstest::rstest;

use crate::barcode::get_reverse_complement;
use crate::parse::get_reverse_complement;
nsyzrantsev marked this conversation as resolved.
Show resolved Hide resolved

#[rstest]
#[case(b"", b"")]
Expand Down
Loading
Loading