Skip to content

Add TemporalSpan model#1601

Open
horatiualmasan wants to merge 5 commits into
mainfrom
horatiu-lig-9805-import-activitynet-style-event-annotations
Open

Add TemporalSpan model#1601
horatiualmasan wants to merge 5 commits into
mainfrom
horatiu-lig-9805-import-activitynet-style-event-annotations

Conversation

@horatiualmasan

@horatiualmasan horatiualmasan commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What has changed and why?

Adds a generic temporal_span table to store optional start/end times (seconds) on any sample-backed entity, and wires it into annotations as a first step toward video event annotations (e.g. ActivityNet).

How has it been tested?

new tests

Did you update CHANGELOG.md?

  • Yes
  • Not needed (internal change)

Summary by CodeRabbit

  • New Features
    • Added temporal span support for classification annotations, with optional start_time_s/end_time_s inputs.
    • Temporal span details are now included in annotation responses/payloads and are eagerly loaded where applicable.
    • Temporal span data is persisted, updated, and deep-copied with related annotation content.
  • Bug Fixes
    • Temporal span records are now cleaned up when annotations or datasets are deleted.
  • Tests
    • Added tests covering creation, response visibility, validation errors (missing/invalid ranges), and deletion cleanup.

@horatiualmasan horatiualmasan requested a review from a team as a code owner July 7, 2026 14:56
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b51b38fe-3c09-4fbf-8406-60a557c29a9d

📥 Commits

Reviewing files that changed from the base of the PR and between bd48016 and f668678.

📒 Files selected for processing (1)
  • lightly_studio/src/lightly_studio/models/annotation/annotation_base.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • lightly_studio/src/lightly_studio/models/annotation/annotation_base.py

📝 Walkthrough

Walkthrough

Adds temporal span storage and annotation fields, wires temporal spans through create/update/delete/query paths, updates dataset copy/delete behavior, and adds resolver tests.

Changes

Temporal span feature

Layer / File(s) Summary
Temporal span schema, model, and migration
lightly_studio/src/lightly_studio/models/temporal_span.py, lightly_studio/src/lightly_studio/migrations/versions/1783435200_c3d4e5f6a7b8_add_temporal_span.py, lightly_studio/src/lightly_studio/api/db_tables.py
Adds TemporalSpanTable/TemporalSpanView, a migration creating and dropping temporal_span, and table registration.
Annotation model integration
lightly_studio/src/lightly_studio/models/annotation/annotation_base.py
Adds temporal_span_details, optional start_time_s/end_time_s on AnnotationCreate, and temporal_span_details on AnnotationView.
Creation and validation
lightly_studio/src/lightly_studio/resolvers/annotation_resolver/create_many.py
Adds temporal-span validation and persists TemporalSpanTable rows for CLASSIFICATION annotations during bulk creation.
Update, delete, and query wiring
lightly_studio/src/lightly_studio/resolvers/annotation_resolver/annotation_helper.py, delete_annotation.py, delete_annotations.py, get_all_by_collection_id_and_parent_sample_ids.py, get_all_with_payload.py, get_by_id_with_payload.py
Reinserts temporal span rows on update, deletes them on annotation delete, and eager-loads them in annotation query paths.
Dataset deep-copy, delete, and coverage
lightly_studio/src/lightly_studio/resolvers/dataset_resolver/deep_copy.py, delete_dataset.py, table_coverage_utils.py
Copies and deletes TemporalSpanTable rows during dataset operations and increments the handled-table coverage count.
Tests
lightly_studio/tests/resolvers/test_create_many_temporal_span.py
Adds tests for valid/invalid temporal span creation and deletion behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: JonasWurst, MalteEbner

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is specific and related to the new TemporalSpan model, though it omits the broader annotation and migration changes.
Description check ✅ Passed The description matches the required template and includes change summary, testing, and changelog status.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch horatiu-lig-9805-import-activitynet-style-event-annotations

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (3)
lightly_studio/tests/resolvers/test_create_many_temporal_span.py (1)

124-161: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Missing boundary test for start_time_s == end_time_s.

The parametrize list covers less-than violation (3.0, 2.0) but not the equality boundary case, which is often where off-by-one validation bugs hide.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lightly_studio/tests/resolvers/test_create_many_temporal_span.py` around
lines 124 - 161, The invalid temporal span test in
test_create_many__invalid_temporal_span is missing the equality boundary case
for start_time_s and end_time_s. Update the parametrize list to include a case
where both values are equal and assert the same ValueError path, so
annotation_resolver.create_many is covered for the non-strict boundary as well
as the existing less-than and missing-value cases.
lightly_studio/src/lightly_studio/models/temporal_span.py (1)

19-34: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Consider a DB-level check constraint for temporal ordering.

Nothing here enforces end_time_s >= start_time_s or non-negative values at the schema level; if upstream validation (_validate_optional_temporal_span, referenced in the create_many resolver layer) is ever bypassed, invalid rows could still be persisted.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lightly_studio/src/lightly_studio/models/temporal_span.py` around lines 19 -
34, Add a database-level constraint to TemporalSpanTable so invalid spans cannot
be persisted even if upstream validation is bypassed. Update the
TemporalSpanTable model to enforce non-negative start_time_s/end_time_s and
require end_time_s to be greater than or equal to start_time_s, using the
model’s table/schema constraints rather than relying only on
_validate_optional_temporal_span in the resolver layer.
lightly_studio/src/lightly_studio/resolvers/annotation_resolver/create_many.py (1)

122-137: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Stale comment now understates scope.

The comment # Bulk save object detection annotations at Line 134 now precedes three bulk_save_objects calls (object detection, segmentation, temporal spans), not just object detection.

✏️ Suggested tweak
-    # Bulk save object detection annotations
+    # Bulk save type-specific annotation details
     session.bulk_save_objects(object_detection_annotations)
     session.bulk_save_objects(segmentation_annotations)
     session.bulk_save_objects(temporal_spans)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@lightly_studio/src/lightly_studio/resolvers/annotation_resolver/create_many.py`
around lines 122 - 137, The bulk-save comment is stale and only describes object
detection, but the following calls in create_many.py now save object detection,
segmentation, and temporal spans. Update the comment near the bulk_save_objects
calls in create_many() to accurately describe all three annotation collections
being persisted, so the label matches the full scope of the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@lightly_studio/src/lightly_studio/models/temporal_span.py`:
- Around line 19-34: Add a database-level constraint to TemporalSpanTable so
invalid spans cannot be persisted even if upstream validation is bypassed.
Update the TemporalSpanTable model to enforce non-negative
start_time_s/end_time_s and require end_time_s to be greater than or equal to
start_time_s, using the model’s table/schema constraints rather than relying
only on _validate_optional_temporal_span in the resolver layer.

In
`@lightly_studio/src/lightly_studio/resolvers/annotation_resolver/create_many.py`:
- Around line 122-137: The bulk-save comment is stale and only describes object
detection, but the following calls in create_many.py now save object detection,
segmentation, and temporal spans. Update the comment near the bulk_save_objects
calls in create_many() to accurately describe all three annotation collections
being persisted, so the label matches the full scope of the code.

In `@lightly_studio/tests/resolvers/test_create_many_temporal_span.py`:
- Around line 124-161: The invalid temporal span test in
test_create_many__invalid_temporal_span is missing the equality boundary case
for start_time_s and end_time_s. Update the parametrize list to include a case
where both values are equal and assert the same ValueError path, so
annotation_resolver.create_many is covered for the non-strict boundary as well
as the existing less-than and missing-value cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4c13eb43-d24b-405d-a4a6-ecf9b9a16045

📥 Commits

Reviewing files that changed from the base of the PR and between be506db and d211bce.

📒 Files selected for processing (13)
  • lightly_studio/src/lightly_studio/api/db_tables.py
  • lightly_studio/src/lightly_studio/migrations/versions/1783435200_c3d4e5f6a7b8_add_temporal_span.py
  • lightly_studio/src/lightly_studio/models/annotation/annotation_base.py
  • lightly_studio/src/lightly_studio/models/temporal_span.py
  • lightly_studio/src/lightly_studio/resolvers/annotation_resolver/annotation_helper.py
  • lightly_studio/src/lightly_studio/resolvers/annotation_resolver/create_many.py
  • lightly_studio/src/lightly_studio/resolvers/annotation_resolver/delete_annotation.py
  • lightly_studio/src/lightly_studio/resolvers/annotation_resolver/delete_annotations.py
  • lightly_studio/src/lightly_studio/resolvers/annotation_resolver/get_all_by_collection_id_and_parent_sample_ids.py
  • lightly_studio/src/lightly_studio/resolvers/dataset_resolver/deep_copy.py
  • lightly_studio/src/lightly_studio/resolvers/dataset_resolver/delete_dataset.py
  • lightly_studio/src/lightly_studio/resolvers/dataset_resolver/table_coverage_utils.py
  • lightly_studio/tests/resolvers/test_create_many_temporal_span.py

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.

1 participant