module Bio::Alignment::IteratePairs

Private Instance Methods

iterate_pairs(pairs,offset,length,regexp = //) click to toggle source

Mixin to iterate through ordered paired [operation, value] data and take subsets - e.g. broken down CIGAR and MD:Z tags. Can set a regexp for the operation; default matches everything

# File lib/bio-sam-mutation/bio/alignment/iterate_pairs.rb, line 5
def iterate_pairs(pairs,offset,length,regexp = //)
        offset = offset.to_i
        length - length.to_i
        total = 0
        new_array = []
        first = true
        pairs.each do |pair|
                new_pair = pair.dup
                if pair[1].is_a? String
                        pairlength = pair[1].length
                elsif pair[1].is_a? Integer
                        pairlength = pair[1]
                else
                        raise "Value for operation must be a string or integer"
                end
                # Only count pairs where first element matches a regexp.
                # e.g. for CIGAR:
                # ref M + ref D = ref length
                # query M + query I = query length
                if pair[0].match(regexp)
                        total += pairlength
                end
                # Just keep going until we get to the start of the subalignment
                if total < offset
                        next
                end
                # If the offset is partway through a pair, need to split it up.
                if first
                        # adjust the number in this pair; it will be added below
                        if pair[1].is_a? String
                                new_pair[1] = new_pair[1][total-offset..pairlength]
                        else
                                new_pair[1] = total - offset + 1  # Add one for bases
                        end
                end

                # Once we are at/beyond the end of the desired region:
                if total >= offset + length
                        # Special case where the whole subalignment is contained within one cigar element:
                        if first
                                if pair[1].is_a? String
                                        new_pair[1] = new_pair[1][total-offset-pairlength,length]
                                else
                                        new_pair[1] = length
                                end
                                new_array << new_pair
                                break
                        end
                # Adding the last part of the alignment
                        previous_total = total - pairlength
                        if pair[1].is_a? Integer
                                new_pair[1] = offset + length - previous_total - 1 #-1 extra for base arithmetic
                        else
                                new_pair[1] = new_pair[1][0..offset + length - previous_total]
                        end
                        new_array << new_pair
                        break
                end
                first = false
                new_array << new_pair
        end
        new_array
end