pub fn find_ranges_single(
    read_pos: &i32,
    cigar: &record::CigarStringView,
    new_cigar: &mut record::CigarString,
    ref_len: &mut i32,
    long_softclip: &mut bool,
    max_softlen: &usize,
) -> Vec<(i32, i32)> {
    let mut ranges = Vec::new();
    let mut curr_range: (i32, i32) = (-1, -1);

    // This variable declares whether a new exon is reached
    // or the next cigar item corresponds to the current exon positions.
    let mut new_range: bool = true;

    // Set the current position to the base right before the beginning of the alignment
    // log::debug!("bam_pos: {}", *read_pos);
    let mut curr_pos = *read_pos - 1;
    // log::debug!("curr_pos: {}", curr_pos);
    let mut new_cigar_vec: Vec<record::Cigar> = Vec::<record::Cigar>::new();
    *ref_len = 0;
    for cigar_item in cigar.iter() {
        log::debug!("cigar item: {} {}", cigar_item.char(), cigar_item.len());
        let cigar_char = cigar_item.char();
        let cigar_len = cigar_item.len();
        // TODO: Do we need support hard-clip?
        match cigar_char {
            'M' | '=' | 'X' | 'I' | 'D' => {
                if new_range {
                    curr_range = (curr_pos + 1, -1);
                    new_range = false;
                }
                
                if cigar_char != 'I' {
                    // log::debug!("curr_pos: {}", curr_pos);
                    curr_pos = curr_pos + cigar_len as i32;
                    // log::debug!("ref_len:{} + cigar_len:{} = {}", *ref_len, cigar_len, *ref_len + cigar_len as i32);
                    *ref_len = *ref_len + cigar_len as i32;
                }

                // log::debug!("curr_pos: {}", curr_pos);
                curr_range.1 = curr_pos;
                
                // update the new cigar
                if new_cigar_vec.len() == 0 || cigar_char != new_cigar_vec.last().unwrap().char() {
                    new_cigar_vec.push(*cigar_item);
                } else {
                    let new_cigar_len = cigar_len + new_cigar_vec.last().unwrap().len();
                    new_cigar_vec.pop();
                    match cigar_char {
                        'M' => new_cigar_vec.push(record::Cigar::Match(new_cigar_len)),
                        '=' => new_cigar_vec.push(record::Cigar::Equal(new_cigar_len)),
                        'X' => new_cigar_vec.push(record::Cigar::Diff(new_cigar_len)),
                        'I' => new_cigar_vec.push(record::Cigar::Ins(new_cigar_len)),
                        'D' => new_cigar_vec.push(record::Cigar::Del(new_cigar_len)),
                        _ => log::warn!("Unexpected cigar item: {}", new_cigar_len),
                    }
                }
            }
            // Observing N means that the rest of
            // the cigar belongs to another exon
            'N' => {
                new_range = true;
                ranges.push(curr_range);
                log::debug!("RANGE {} {}", curr_range.0, curr_range.1);
                curr_pos = curr_pos + cigar_len as i32;
                // log::debug!("curr_pos: {}", curr_pos);
                // log::debug!("len:{} + cigar_len:{} = {}", *ref_len, cigar_len, *ref_len + cigar_len as i32);
                *ref_len = *ref_len + cigar_len as i32;
            }
            // Soft clipped bases don't consume reference bases
            'S' => {
                new_cigar_vec.push(*cigar_item);
                if cigar_len > *max_softlen as u32 {
                    *long_softclip = true;
                }
            }
            _ => log::warn!("Unexpected cigar char! {}", cigar_char),
        }
        // log::debug!("{} {}", curr_range.0, curr_range.1);
    }
    ranges.push(curr_range);
    log::debug!("RANGE {} {}", curr_range.0, curr_range.1);
    log::debug!("REF_LEN {}", *ref_len);
    *new_cigar = record::CigarString(new_cigar_vec);
    return ranges;
}
/// Returns a vector of ranges in exons covered by the input alignment. 
/// Each range is a tuple in format of (start, end) and both coordinates are inclusive.
///
/// # Arguments
///
/// * `read_pos` - INPUT. The alignment position of the input BAM record
/// * `cigar` - INPUT. The CIGAR string view of the BAM record
/// * `new_cigar_view` - OUTPUT. The CIGAR string for the alignment projected to the transcriptome
/// * `ref_len` - OUTPUT. The number of reference bases covered by the input alignment
/// * `long_softclip` - OUTPUT. Whether the total number of soft-clipped bases is above the threshold
/// * `max_softlen` - INPUT. The maximum number of soft-clipped bases allowed
Returns a vector of ranges in exons covered by the input alignment.
Each range is a tuple in format of (start, end) and both coordinates are inclusive.
Returns a vector of ranges in exons covered by the input alignment . Each range is a tuple in format of ( start end ) and both coordinates are inclusive .
pub fn find_ranges_single(
    read_pos: &i32,
    cigar: &record::CigarStringView,
    new_cigar: &mut record::CigarString,
    ref_len: &mut i32,
    long_softclip: &mut bool,
    max_softlen: &usize,
) -> Vec<(i32, i32)> {
    let mut ranges = Vec::new();
    let mut curr_range: (i32, i32) = (-1, -1);
    // This variable declares whether a new exon is reached
    // or the next cigar item corresponds to the current exon positions.
    let mut new_range: bool = true;
    // Set the current position to the base right before the beginning of the alignment
    // log::debug!("bam_pos: {}", *read_pos);
    let mut curr_pos = *read_pos - 1;
    // log::debug!("curr_pos: {}", curr_pos);
    let mut new_cigar_vec: Vec<record::Cigar> = Vec::<record::Cigar>::new();
    *ref_len = 0;
    for cigar_item in cigar.iter() {
        log::debug!("cigar item: {} {}", cigar_item.char(), cigar_item.len());
        let cigar_char = cigar_item.char();
        let cigar_len = cigar_item.len();
        // TODO: Do we need support hard-clip?
        match cigar_char {
            'M' | '=' | 'X' | 'I' | 'D' => {
                if new_range {
                    curr_range = (curr_pos + 1, -1);
                    new_range = false;
                }
                if cigar_char != 'I' {
                    // log::debug!("curr_pos: {}", curr_pos);
                    curr_pos = curr_pos + cigar_len as i32;
                    // log::debug!("ref_len:{} + cigar_len:{} = {}", *ref_len, cigar_len, *ref_len + cigar_len as i32);
                    *ref_len = *ref_len + cigar_len as i32;
                }
                // log::debug!("curr_pos: {}", curr_pos);
                curr_range.1 = curr_pos;
                // update the new cigar
                if new_cigar_vec.len() == 0 || cigar_char != new_cigar_vec.last().unwrap().char() {
                    new_cigar_vec.push(*cigar_item);
                } else {
                    let new_cigar_len = cigar_len + new_cigar_vec.last().unwrap().len();
                    new_cigar_vec.pop();
                    match cigar_char {
                        'M' => new_cigar_vec.push(record::Cigar::Match(new_cigar_len)),
                        '=' => new_cigar_vec.push(record::Cigar::Equal(new_cigar_len)),
                        'X' => new_cigar_vec.push(record::Cigar::Diff(new_cigar_len)),
                        'I' => new_cigar_vec.push(record::Cigar::Ins(new_cigar_len)),
                        'D' => new_cigar_vec.push(record::Cigar::Del(new_cigar_len)),
                        _ => log::warn!("Unexpected cigar item: {}", new_cigar_len),
                    }
                }
            }
            // Observing N means that the rest of
            // the cigar belongs to another exon
            'N' => {
                new_range = true;
                ranges.push(curr_range);
                log::debug!("RANGE {} {}", curr_range.0, curr_range.1);
                curr_pos = curr_pos + cigar_len as i32;
                // log::debug!("curr_pos: {}", curr_pos);
                // log::debug!("len:{} + cigar_len:{} = {}", *ref_len, cigar_len, *ref_len + cigar_len as i32);
                *ref_len = *ref_len + cigar_len as i32;
            }
            // Soft clipped bases don't consume reference bases
            'S' => {
                new_cigar_vec.push(*cigar_item);
                if cigar_len > *max_softlen as u32 {
                    *long_softclip = true;
                }
            }
            _ => log::warn!("Unexpected cigar char! {}", cigar_char),
        }
        // log::debug!("{} {}", curr_range.0, curr_range.1);
    }
    ranges.push(curr_range);
    log::debug!("RANGE {} {}", curr_range.0, curr_range.1);
    log::debug!("REF_LEN {}", *ref_len);
    *new_cigar = record::CigarString(new_cigar_vec);
    return ranges;
}
pub fn find_ranges_single ( read_pos : & i32 , cigar : & record :: CigarStringView , new_cigar : & mut record :: CigarString , ref_len : & mut i32 , long_softclip : & mut bool , max_softlen : & usize , ) -> Vec < ( i32 , i32 ) > { let mut ranges = Vec :: new ( ) ; let mut curr_range : ( i32 , i32 ) = ( - 1 , - 1 ) ; // This variable declares whether a new exon is reached // or the next cigar item corresponds to the current exon positions. let mut new_range : bool = true ; // Set the current position to the base right before the beginning of the alignment // log::debug!("bam_pos: {}", *read_pos); let mut curr_pos = * read_pos - 1 ; // log::debug!("curr_pos: {}", curr_pos); let mut new_cigar_vec : Vec < record :: Cigar > = Vec :: < record :: Cigar > :: new ( ) ; * ref_len = 0 ; for cigar_item in cigar . iter ( ) { log :: debug ! ( " " cigar_item char ( ) cigar_item len ( ) ) ; let cigar_char = cigar_item . char ( ) ; let cigar_len = cigar_item . len ( ) ; // TODO: Do we need support hard-clip? match cigar_char { 'M' | '=' | 'X' | 'I' | 'D' => { if new_range { curr_range = ( curr_pos + 1 , - 1 ) ; new_range = false ; } if cigar_char != 'I' { // log::debug!("curr_pos: {}", curr_pos); curr_pos = curr_pos + cigar_len as i32 ; // log::debug!("ref_len:{} + cigar_len:{} = {}", *ref_len, cigar_len, *ref_len + cigar_len as i32); * ref_len = * ref_len + cigar_len as i32 ; } // log::debug!("curr_pos: {}", curr_pos); curr_range . 1 = curr_pos ; // update the new cigar if new_cigar_vec . len ( ) == 0 || cigar_char != new_cigar_vec . last ( ) . unwrap ( ) . char ( ) { new_cigar_vec . push ( * cigar_item ) ; } else { let new_cigar_len = cigar_len + new_cigar_vec . last ( ) . unwrap ( ) . len ( ) ; new_cigar_vec . pop ( ) ; match cigar_char { 'M' => new_cigar_vec . push ( record :: Cigar :: Match ( new_cigar_len ) ) , '=' => new_cigar_vec . push ( record :: Cigar :: Equal ( new_cigar_len ) ) , 'X' => new_cigar_vec . push ( record :: Cigar :: Diff ( new_cigar_len ) ) , 'I' => new_cigar_vec . push ( record :: Cigar :: Ins ( new_cigar_len ) ) , 'D' => new_cigar_vec . push ( record :: Cigar :: Del ( new_cigar_len ) ) , _ => log :: warn ! ( " " new_cigar_len ) , } } } // Observing N means that the rest of // the cigar belongs to another exon 'N' => { new_range = true ; ranges . push ( curr_range ) ; log :: debug ! ( " " curr_range 0 curr_range 1 ) ; curr_pos = curr_pos + cigar_len as i32 ; // log::debug!("curr_pos: {}", curr_pos); // log::debug!("len:{} + cigar_len:{} = {}", *ref_len, cigar_len, *ref_len + cigar_len as i32); * ref_len = * ref_len + cigar_len as i32 ; } // Soft clipped bases don't consume reference bases 'S' => { new_cigar_vec . push ( * cigar_item ) ; if cigar_len > * max_softlen as u32 { * long_softclip = true ; } } _ => log :: warn ! ( " " cigar_char ) , } // log::debug!("{} {}", curr_range.0, curr_range.1); } ranges . push ( curr_range ) ; log :: debug ! ( " " curr_range 0 curr_range 1 ) ; log :: debug ! ( " " ref_len ) ; * new_cigar = record :: CigarString ( new_cigar_vec ) ; return ranges ; }
Returns a vector of ranges in exons covered by the input alignment.
Returns a vector of ranges in exons covered by the input alignment .
read_pos
&i32
cigar
&record::CigarStringView
new_cigar
&mut record::CigarString
ref_len
&mut i32
long_softclip
&mut bool
max_softlen
&usize