Skip to content

feat: add IntervalData - #245

Open
SophiaPerzan-DG wants to merge 15 commits into
mainfrom
diseq-pt4
Open

feat: add IntervalData#245
SophiaPerzan-DG wants to merge 15 commits into
mainfrom
diseq-pt4

Conversation

@SophiaPerzan-DG

@SophiaPerzan-DG SophiaPerzan-DG commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

DIS api compatibility with Interval, required for IntervalData:

  • chore: add .contains() to DIS api
  • chore: support 0-length liftover with DIS
  • chore: rename DIS flip_strand() to as_opposite_strand()
  • fix: InvalidConfig error when using DefaultDataManager without auth

also:

  • feat: update DIS lift_interval() to raise error in some instances
  • feat: add cut() to DIS api

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new IntervalData abstraction to bind an interval-like coordinate object (Interval or DisjointIntervalSequence) to an in-memory array and allow coordinated slicing/indexing, while also extending and tightening the DIS API around strand semantics and lifting behavior.

Changes:

  • Introduce IntervalData (implementation, tests, and documentation) and export it from genome_kit.
  • Extend DisjointIntervalSequence with cut(), add .contains(), rename strand helpers, and change lift_interval() to optionally require containment unless intersect_on_lift=True.
  • Update documentation and DIS tests to match the revised DIS semantics.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/test_interval_data.py Adds unit tests covering IntervalData indexing/slicing on Interval and DIS backends.
tests/test_diseq.py Updates strand-method tests, adds cut() tests, and expands lift_interval() tests for intersect_on_lift.
genome_kit/interval_data.py Implements the new IntervalData class and its slicing/lifting behavior.
genome_kit/diseq.py Adds cut()/contains(), renames strand APIs, and revises lift_interval()/gap lifting semantics.
genome_kit/data_manager.py Changes S3 client creation for unsigned requests (currently disables TLS verification).
genome_kit/init.py Exports IntervalData as part of the public package API.
docs-src/quickstart.rst Adds an anchor for track-related cross-references.
docs-src/interval_data.rst Adds new documentation page for IntervalData.
docs-src/index.rst Adds interval_data to docs table-of-contents.
docs-src/diseq.rst Updates DIS docs to on-/off-coordinate strand terminology and new lift/cut semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread genome_kit/diseq.py
Comment thread genome_kit/diseq.py Outdated
Comment thread genome_kit/diseq.py Outdated
Comment thread genome_kit/interval_data.py Outdated
Comment thread genome_kit/interval_data.py
def client(self):
if not hasattr(self, "_client"):
s3_client = boto3.client("s3") if self._require_auth else boto3.client("s3", config=Config(signature_version=UNSIGNED))
s3_client = boto3.client("s3") if self._require_auth else boto3.client("s3", config=Config(signature_version=UNSIGNED), verify=False)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do @declanyewlim 's solution instead: #246

You can rebase on that once merged.

Comment thread docs-src/interval_data.rst Outdated
def client(self):
if not hasattr(self, "_client"):
s3_client = boto3.client("s3") if self._require_auth else boto3.client("s3", config=Config(signature_version=UNSIGNED))
s3_client = boto3.client("s3") if self._require_auth else boto3.client("s3", config=Config(signature_version=UNSIGNED), verify=False)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do @declanyewlim 's solution instead: #246

You can rebase on that once merged.

Comment thread docs-src/interval_data.rst Outdated
:py:meth:`~genome_kit.IntervalData.from_interval` is an explicit alias for this
case and behaves identically to the constructor.

From a DisjointIntervalSequence

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be collapsed to the previous section. That's the point of them being interchangeable, we just need to mention that the numpy array indices map to the coordinate space of the dis.

Comment on lines +109 to +110
If your aligned axis is not where you need it, use ``axis`` to point at it, or
reorder the array up-front and leave ``axis`` at its default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant

Comment thread docs-src/interval_data.rst Outdated
Comment on lines +11 to +12
a genomic interval. Conceptually, it is similar to a
:py:class:`~genome_kit.GenomeTrack`, but in-memory and scoped to a single

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to expand a little bit more to help users select the right api for their use case.

And potentially add extensive documentation on gtrack into this doc. Currently we only have api docs so it's hard to understand gtrack holistically, and especially in comparison to IntervalData.

Comment on lines +246 to +250
If the genomic key is not fully contained within the DIS segment — it straddles
the segment edge, lands in an intron, or lies on a mismatched chromosome or
reference genome — the lift fails and :py:class:`~genome_kit.IntervalData`
surfaces it as an ``IndexError`` (``"... does not contain ..."``), matching the
behavior of an ``Interval``-backed :py:class:`~genome_kit.IntervalData`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels like this mostly belongs in the docstring.

Suggested change
If the genomic key is not fully contained within the DIS segment — it straddles
the segment edge, lands in an intron, or lies on a mismatched chromosome or
reference genome — the lift fails and :py:class:`~genome_kit.IntervalData`
surfaces it as an ``IndexError`` (``"... does not contain ..."``), matching the
behavior of an ``Interval``-backed :py:class:`~genome_kit.IntervalData`.
The genomic key must by fully contained within the DIS segment, otherwise an error is raised.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general this file feels too verbose (too many details)

Comment thread docs-src/interval_data.rst
Comment thread genome_kit/diseq.py Outdated
Comment thread genome_kit/diseq.py Outdated
return None
# It should only be permissible to have a single None when intersect_on_lift=True,
# since it's possible to lift an interval that is partially in a gap between coord intervals
assert lift_start is not None and lift_end is not None if not intersect_on_lift else True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asserts aren't guaranteed to raise

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know. This is just a sanity check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants