/// Cleans a SE or PE read
Cleans a SE or PE read
Cleans a SE or PE read
fn clean_entry(lines:Vec<String>, min_length:usize, min_avg_qual:f32, min_trim_qual:u8, lines_per_read:u8, tx:std::sync::mpsc::Sender<String>) {
  let short_blank_string:String = String::with_capacity(100);
  let  long_blank_string:String = String::with_capacity(10000);
  let mut id1   :String = short_blank_string.clone();
  let mut id2   :String = short_blank_string.clone();
  let mut seq1  :String = long_blank_string.clone();
  let mut seq2  :String = long_blank_string.clone();
  let mut qual1 :String = long_blank_string.clone();
  let mut qual2 :String = long_blank_string.clone();
  let mut i = 0;
  for line in lines {
    //let line = wrapped_line.expect("ERROR: could not read line");
    match i % lines_per_read {
        // read ID
        0=>{
            // On the zeroth line, set the first ID...
            id1 = line;
            // ...but then reset all other fields
            id2   = short_blank_string.clone();
            seq1  = long_blank_string.clone();
            seq2  = long_blank_string.clone();
            qual1 = long_blank_string.clone();
            qual2 = long_blank_string.clone();
        }
        4=>{
            id2 = line;
        }
        // Sequence
        1=>{
            seq1 = line;
        }
        5=>{
            seq2 = line;
        }
        // Qual line. If we've gotten here, then we can also trim/filter/print
        // First qual line
        3=>{
            qual1 = line;
        }
        // Second qual line
        7=>{
            qual2 = line;
        }
        2=>{} // + line
        6=>{} // + line
        _=>{
          panic!("Internal error: somehow there are more than 8 lines per entry. The last line was line {} and contents were {}", i, line);
        }
    }
    // moment of truth: see trim the reads and then see
    // if they pass the filter.
    if (lines_per_read==4 && !qual1.is_empty())
     ||(lines_per_read==8 && !qual2.is_empty()) {
        // Trim
        let (seq1_trimmed, qual1_trimmed) = 
              trim(&seq1,&qual1,min_trim_qual);
        // If this is single end, go ahead and filter/print
        if lines_per_read==4 {
            if seq1_trimmed.len() >= min_length && avg_quality(&qual1_trimmed) >= min_avg_qual {
                tx.send(format!("{}\n{}\n+\n{}",
                     id1,seq1_trimmed,qual1_trimmed,
                     ))
                   .unwrap();
            }
        } 
        else if lines_per_read==8 {
          // trim second read
          let (seq2_trimmed, qual2_trimmed) = 
                trim(&seq2,&qual2,min_trim_qual);
          // Since we are at the second qual line, this is PE and we can
          // go ahead with filter/print and not check for the PE param.
          if seq2_trimmed.len() >= min_length && seq2_trimmed.len() >= min_length 
              && avg_quality(&qual1_trimmed) >= min_avg_qual 
              && avg_quality(&qual2_trimmed) >= min_avg_qual {
              tx.send(format!("{}\n{}\n+\n{}\n{}\n{}\n+\n{}",
                   id1,seq1_trimmed,qual1_trimmed,
                   id2,seq2_trimmed,qual2_trimmed
                   ))
               .unwrap();
          }
        }
        else {
          panic!("I do not understand {} lines per fastq entry", lines_per_read);
        }
    }
    i += 1;
  }
}
fn clean_entry ( lines : Vec < String > , min_length : usize , min_avg_qual : f32 , min_trim_qual : u8 , lines_per_read : u8 , tx : std :: sync :: mpsc :: Sender < String > ) { let short_blank_string : String = String :: with_capacity ( 100 ) ; let long_blank_string : String = String :: with_capacity ( 10000 ) ; let mut id1 : String = short_blank_string . clone ( ) ; let mut id2 : String = short_blank_string . clone ( ) ; let mut seq1 : String = long_blank_string . clone ( ) ; let mut seq2 : String = long_blank_string . clone ( ) ; let mut qual1 : String = long_blank_string . clone ( ) ; let mut qual2 : String = long_blank_string . clone ( ) ; let mut i = 0 ; for line in lines { //let line = wrapped_line.expect("ERROR: could not read line"); match i % lines_per_read { // read ID 0 => { // On the zeroth line, set the first ID... id1 = line ; // ...but then reset all other fields id2 = short_blank_string . clone ( ) ; seq1 = long_blank_string . clone ( ) ; seq2 = long_blank_string . clone ( ) ; qual1 = long_blank_string . clone ( ) ; qual2 = long_blank_string . clone ( ) ; } 4 => { id2 = line ; } // Sequence 1 => { seq1 = line ; } 5 => { seq2 = line ; } // Qual line. If we've gotten here, then we can also trim/filter/print // First qual line 3 => { qual1 = line ; } // Second qual line 7 => { qual2 = line ; } 2 => { } // + line 6 => { } // + line _ => { panic ! ( " " i line ) ; } } // moment of truth: see trim the reads and then see // if they pass the filter. if ( lines_per_read == 4 && ! qual1 . is_empty ( ) ) || ( lines_per_read == 8 && ! qual2 . is_empty ( ) ) { // Trim let ( seq1_trimmed , qual1_trimmed ) = trim ( & seq1 , & qual1 , min_trim_qual ) ; // If this is single end, go ahead and filter/print if lines_per_read == 4 { if seq1_trimmed . len ( ) >= min_length && avg_quality ( & qual1_trimmed ) >= min_avg_qual { tx . send ( format ! ( " \n \n \n " id1 seq1_trimmed qual1_trimmed ) ) . unwrap ( ) ; } } else if lines_per_read == 8 { // trim second read let ( seq2_trimmed , qual2_trimmed ) = trim ( & seq2 , & qual2 , min_trim_qual ) ; // Since we are at the second qual line, this is PE and we can // go ahead with filter/print and not check for the PE param. if seq2_trimmed . len ( ) >= min_length && seq2_trimmed . len ( ) >= min_length && avg_quality ( & qual1_trimmed ) >= min_avg_qual && avg_quality ( & qual2_trimmed ) >= min_avg_qual { tx . send ( format ! ( " \n \n \n \n \n \n \n " id1 seq1_trimmed qual1_trimmed id2 seq2_trimmed qual2_trimmed ) ) . unwrap ( ) ; } } else { panic ! ( " " lines_per_read ) ; } } i += 1 ; } }
Cleans a SE or PE read
Cleans a SE or PE read
lines
Vec<String>
min_length
usize
min_avg_qual
f32
min_trim_qual
u8
lines_per_read
u8
tx
std::sync::mpsc::Sender<String>