def test_overlaps_nested(self, start_shift, closed, other_closed): start, shift = start_shift interval1 = Interval(start, start + 3 * shift, other_closed) interval2 = Interval(start + shift, start + 2 * shift, closed) # nested intervals should always overlap assert interval1.overlaps(interval2)
def test_overlaps_disjoint(self, start_shift, closed, other_closed): start, shift = start_shift interval1 = Interval(start, start + shift, other_closed) interval2 = Interval(start + 2 * shift, start + 3 * shift, closed) # disjoint intervals should never overlap assert not interval1.overlaps(interval2)
def test_overlaps_endpoint(self, start_shift, closed, other_closed): start, shift = start_shift interval1 = Interval(start, start + shift, other_closed) interval2 = Interval(start + shift, start + 2 * shift, closed) # overlap if shared endpoint is closed for both (overlap at a point) result = interval1.overlaps(interval2) expected = interval1.closed_right and interval2.closed_left assert result == expected
def gather_stayed(genome: Genome, new_positions: NewPositions) -> Stayed: if not new_positions: return {0: GenomeSegment(start=0, size=len(genome))} occupied_by_jumping = get_occupied_by_jumps(new_positions) non_jumping_count = genome.len - sum(map(len, occupied_by_jumping)) if non_jumping_count == 0: logging.info("All the genes jumped!") return {} assert non_jumping_count > 0 jumping_positions = sorted(itertools.chain.from_iterable( new_positions.values()), key=lambda pos: pos.start) didnt_jump = get_didnt_jump(genome, jumping_positions) stayed = {} last_filled = 0 # TODO: Use the last filled to set the key in the 'stayed' dictionary occupied_iter = iter( map(lambda segment: segment.make_interval(), occupied_by_jumping)) non_jumping_iter = iter(didnt_jump) occupied = non_jumping = None try: occupied: Optional[Interval] = next(occupied_iter) non_jumping: Optional[GenomeSegment] = next(non_jumping_iter) assert non_jumping is not None assert occupied is not None while True: non_jumping_interval = Interval(left=last_filled, right=last_filled + non_jumping.size) if not non_jumping_interval.overlaps(occupied): if non_jumping_interval >= occupied: last_filled = occupied.right occupied: Interval = next(occupied_iter) else: stayed[last_filled] = non_jumping last_filled += non_jumping.size non_jumping = None non_jumping: GenomeSegment = next(non_jumping_iter) else: if non_jumping_interval.left < occupied.left: step = occupied.left - non_jumping_interval.left assert step > 0, f"occ: {occupied}, non_jump: {non_jumping_interval}" stayed[last_filled] = non_jumping.prefix(step) non_jumping = non_jumping.suffix(step) last_filled = occupied.right occupied: Interval = next(occupied_iter) except StopIteration: if non_jumping is not None: stayed[last_filled] = non_jumping last_filled += non_jumping.size for non_jumping in non_jumping_iter: # Exhaust the iterator stayed[last_filled] = non_jumping last_filled += non_jumping.size return stayed
def test_overlaps_invalid_type(self, other): interval = Interval(0, 1) msg = '`other` must be an Interval, got {other}'.format( other=type(other).__name__) with tm.assert_raises_regex(TypeError, msg): interval.overlaps(other)
def test_overlaps_self(self, start_shift, closed): start, shift = start_shift interval = Interval(start, start + shift, closed) assert interval.overlaps(interval)
def test_interval_overlaps_interval(self, ivl_side, oth_side, ivl_range): # class Interval: # def overlaps(self, other: Interval) -> bool assert Interval(1, 3).overlaps(Interval(1.5, 2.5)) assert Interval(1, 3).overlaps(Interval(1, 2)) assert Interval(1, 3).overlaps(Interval(2, 3)) assert Interval(1, 3).overlaps(Interval(0.5, 2.5)) assert Interval(1, 3).overlaps(Interval(1.5, 3.5)) assert not Interval(1, 3).overlaps(Interval(-1, 1)) assert not Interval(1, 3).overlaps(Interval(3, 5)) ivl = Interval(*ivl_range, closed=ivl_side) other = Interval(1, 3, closed=oth_side) should_overlap = { # idx_side: # ivl_side: {ivl_range: expected_result} 'right': { 'right': { (-1, 1): False, (1, 3): True, (3, 5): False }, 'left': { (-1, 1): False, (1, 3): True, (3, 5): True }, 'both': { (-1, 1): False, (1, 3): True, (3, 5): True }, 'neither': { (-1, 1): False, (1, 3): True, (3, 5): False }, }, 'left': { 'right': { (-1, 1): True, (1, 3): True, (3, 5): False }, 'left': { (-1, 1): False, (1, 3): True, (3, 5): False }, 'both': { (-1, 1): True, (1, 3): True, (3, 5): False }, 'neither': { (-1, 1): False, (1, 3): True, (3, 5): False }, }, 'both': { 'right': { (-1, 1): True, (1, 3): True, (3, 5): False }, 'left': { (-1, 1): False, (1, 3): True, (3, 5): True }, 'both': { (-1, 1): True, (1, 3): True, (3, 5): True }, 'neither': { (-1, 1): False, (1, 3): True, (3, 5): False }, }, 'neither': { 'right': { (-1, 1): False, (1, 3): True, (3, 5): False }, 'left': { (-1, 1): False, (1, 3): True, (3, 5): False }, 'both': { (-1, 1): False, (1, 3): True, (3, 5): False }, 'neither': { (-1, 1): False, (1, 3): True, (3, 5): False }, } } result = ivl.overlaps(other) expected = should_overlap[oth_side][ivl_side][ivl_range] other_result = other.overlaps(ivl) assert result == expected == other_result
def test_interval_overlaps_intervalIndex(self, idx_side, ivl_side, ivl_range): # class Interval: # def overlaps(self, other: IntervalIndex) -> IntegerArray1D # class IntervalIndex: # def overlaps(self, other: Interval) -> IntegerArray1D idx = IntervalIndex.from_tuples([(0, 1), (2, 3), (1, 3)], closed=idx_side) ivl = Interval(*ivl_range, closed=ivl_side) should_overlap = { # idx_side: # ivl_side: {ivl_range: expected_result} 'right': { 'right': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, 'left': { (1, 3): [0, 1, 2], (1, 2): [0, 2], (0, 2): [0, 2], (3, 4): [1, 2] }, 'both': { (1, 3): [0, 1, 2], (1, 2): [0, 2], (0, 2): [0, 2], (3, 4): [1, 2] }, 'neither': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, }, 'left': { 'right': { (1, 3): [1, 2], (1, 2): [1, 2], (0, 2): [0, 1, 2], (3, 4): [] }, 'left': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, 'both': { (1, 3): [1, 2], (1, 2): [1, 2], (0, 2): [0, 1, 2], (3, 4): [] }, 'neither': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, }, 'both': { 'right': { (1, 3): [1, 2], (1, 2): [1, 2], (0, 2): [0, 1, 2], (3, 4): [] }, 'left': { (1, 3): [0, 1, 2], (1, 2): [0, 2], (0, 2): [0, 2], (3, 4): [1, 2] }, 'both': { (1, 3): [0, 1, 2], (1, 2): [0, 1, 2], (0, 2): [0, 1, 2], (3, 4): [1, 2] }, 'neither': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, }, 'neither': { 'right': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, 'left': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, 'both': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, 'neither': { (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): [] }, } } result = ivl.overlaps(idx) expected = np.array(should_overlap[idx_side][ivl_side][ivl_range]) other_result = idx.overlaps(ivl) tm.assert_numpy_array_equal(result, expected) tm.assert_numpy_array_equal(other_result, expected)
def test_overlaps_invalid_type(self, other): interval = Interval(0, 1) msg = '`other` must be an Interval, got {other}'.format( other=type(other).__name__) with pytest.raises(TypeError, match=msg): interval.overlaps(other)