#!/usr/bin/env python # Jacob Joseph # June 19, 2007 import sys class combined: """A greedy heuristic for combining all blast alignments between a pair of sequences, to calculate a 'combined' coverage. Add an alignment only if it does not conflict with an already specified alignment. The caller is responsible for insertion order.""" # List of available ranges seq_0_avail = None seq_1_avail = None coverage = None # keep blast score and ff_bool for convenience bit_score = None e_value = None ff_bool = None def __init__(self, bit_score=None, e_value=None, ff_bool=None): self.seq_0_avail = [ (1, sys.maxint) ] self.seq_1_avail = [ (1, sys.maxint) ] self.coverage = 0.0 self.bit_score = bit_score self.e_value = e_value self.ff_bool = ff_bool def set_unavail( self, seq_0_position, seq_1_position, seq_start_0, seq_end_0, seq_start_1, seq_end_1): self.seq_0_avail.remove( seq_0_position) (ss0, se0) = seq_0_position if ss0 != seq_start_0: self.seq_0_avail.append( (ss0, seq_start_0 - 1)) if se0 != seq_end_0: self.seq_0_avail.append( (seq_end_0 + 1, se0)) self.seq_1_avail.remove( seq_1_position) (ss1, se1) = seq_1_position if ss1 != seq_start_1: self.seq_1_avail.append( (ss1, seq_start_1 - 1)) if se1 != seq_end_1: self.seq_1_avail.append( (seq_end_1 + 1, se1)) return def add(self, seq_start_0, seq_end_0, seq_start_1, seq_end_1, coverage): self.coverage += coverage return def add_unless_conflict( self, seq_start_0, seq_end_0, seq_start_1, seq_end_1, coverage): seq_0_position = None for (ss0, se0) in self.seq_0_avail: if seq_start_0 >= ss0 and seq_end_0 <= se0: seq_0_position = (ss0, se0) seq_1_position = None for (ss1, se1) in self.seq_1_avail: if seq_start_1 >= ss1 and seq_end_1 <= se1: seq_1_position = (ss1, se1) if seq_0_position and seq_1_position: self.set_unavail( seq_0_position, seq_1_position, seq_start_0, seq_end_0, seq_start_1, seq_end_1) self.add(seq_start_0, seq_end_0, seq_start_0, seq_end_1, coverage) return