Skip to content

Commit 4f7130f

Browse files
authored
fix(htsget): overlap behavior for enclosed regions (#212)
* chore(dep): drop unused calamus * chore(dep): constrain minimal compatible linkml version * sec(dep): floor pynacl>=1.6.2 to protect from CVE-2025-69277 * chore(dep): declare explicit imports * chore(dep): cap typer for sphinx-click compat * docs(cli): fix out of date cli path * chore(dep): update lock file * test(c4gh): adapt to new key-generation api * chore(c4gh): drop unnecessary comment * test: add check for preserved links post-removal * fix(api): preserve links upon remove * test(htsget): add overlap test for fully contained region * fix(htsget): consider contained interval as overlap
1 parent dda85ea commit 4f7130f

2 files changed

Lines changed: 13 additions & 6 deletions

File tree

src/modos/genomics/region.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,13 @@ def from_pysam(
131131
raise ValueError("Record must have coordinates")
132132

133133
def overlaps(self, other: Region) -> bool:
134-
"""Checks if other in self.
135-
This check if any portion of other overlaps with self.
134+
"""Checks if any portion of other overlaps with self.
135+
136+
Uses half-open interval semantics, so adjacent regions
137+
(e.g. [10, 20) and [20, 30)) do not overlap.
136138
"""
137139
same_chrom = self.chrom == other.chrom
138-
starts_in = self.start <= other.start <= self.end
139-
ends_in = self.start <= other.end <= self.end
140-
141-
return same_chrom and (starts_in or ends_in)
140+
return same_chrom and self.start < other.end and other.start < self.end
142141

143142
def contains(self, other: Region) -> bool:
144143
"""Checks if other is fully contained in self."""

tests/test_region.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ def test_overlap():
2222
assert not region3.overlaps(region1)
2323

2424

25+
def test_overlap_contained_region():
26+
"""A region fully contained in another overlaps it, both ways."""
27+
outer = Region(chrom="chr1", start=10, end=100)
28+
inner = Region(chrom="chr1", start=40, end=50)
29+
assert outer.overlaps(inner)
30+
assert inner.overlaps(outer)
31+
32+
2533
def test_contain():
2634
region1 = Region(chrom="chr1", start=10, end=20)
2735
region2 = Region(chrom="chr1", start=15, end=18)

0 commit comments

Comments
 (0)