Skip to content

Look up images by image_id when pairing with detections#153

Open
rhine3 wants to merge 1 commit into
mainfrom
fix/detection-image-pairing-mismatch
Open

Look up images by image_id when pairing with detections#153
rhine3 wants to merge 1 commit into
mainfrom
fix/detection-image-pairing-mismatch

Conversation

@rhine3

@rhine3 rhine3 commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

Fixes #152

Summary by CodeRabbit

  • Bug Fixes
    • Improved detection processing to consistently associate detected objects with the correct images, regardless of database retrieval order.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

save_detected_objects now pairs each detection payload with its database image using the corresponding explicit image ID instead of relying on database query ordering.

Changes

Detection image pairing

Layer / File(s) Summary
Resolve images by explicit ID
trapdata/db/models/detections.py
save_detected_objects builds an image_id-to-TrapImage lookup and iterates over input image IDs with their detection data before applying the existing per-image persistence flow.

Estimated code review effort: 1 (Trivial) | ~2 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: pairing detections with images by image_id.
Linked Issues check ✅ Passed The change matches issue #152 by pairing image_ids with detected objects and looking up each image by ID.
Out of Scope Changes check ✅ Passed The PR appears narrowly scoped to the detection-image pairing bug fix, with no unrelated changes shown.
✨ 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 fix/detection-image-pairing-mismatch

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.

@rhine3 rhine3 added the bug Something isn't working label Jul 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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.

Inline comments:
In `@trapdata/db/models/detections.py`:
- Around line 344-345: Update the loop pairing image_ids with
detected_objects_data to reject mismatched sequence lengths instead of silently
truncating via zip. Use strict zip behavior if supported by the project’s Python
version, or validate equal lengths before iteration, while preserving the
existing image lookup and processing logic.
- Around line 341-345: Validate that every requested ID in image_ids exists in
the fetched images set before the processing loop indexes images_by_id. In the
detection creation flow, compare image_ids against images_by_id keys and fail
fast with a clear error identifying missing IDs, while preserving the existing
loop for valid inputs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f60a3669-e9eb-4a3f-870d-02db56874e00

📥 Commits

Reviewing files that changed from the base of the PR and between a33746a and 609477b.

📒 Files selected for processing (1)
  • trapdata/db/models/detections.py

Comment on lines +341 to +345
images_by_id = {img.id: img for img in images}

# Process all images and create objects
for image, detected_objects in zip(images, detected_objects_data):
for image_id, detected_objects in zip(image_ids, detected_objects_data):
image = images_by_id[image_id]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

set -euo pipefail

printf '\n== detections.py around target lines ==\n'
sed -n '280,390p' trapdata/db/models/detections.py

printf '\n== search for image ID validation / missing IDs handling ==\n'
rg -n "missing.*image|image_ids|images_by_id|KeyError|domain error|not found|stale|deleted image|validate.*image" trapdata/db/models -S

printf '\n== outline of detections.py ==\n'
ast-grep outline trapdata/db/models/detections.py --view expanded

Repository: RolnickLab/ami-data-companion

Length of output: 8422


🏁 Script executed:

set -euo pipefail

sed -n '280,390p' trapdata/db/models/detections.py
rg -n "missing.*image|image_ids|images_by_id|KeyError|domain error|not found|stale|deleted image|validate.*image" trapdata/db/models -S

Repository: RolnickLab/ami-data-companion

Length of output: 4810


🏁 Script executed:

set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('trapdata/db/models/detections.py')
text = p.read_text()
lines = text.splitlines()
for i in range(280, 391):
    if i <= len(lines):
        print(f"{i:4}: {lines[i-1]}")
PY

printf '\n---\n'

rg -n "missing.*image|image_ids|images_by_id|KeyError|domain error|not found|stale|deleted image|validate.*image" trapdata/db/models -S

Repository: RolnickLab/ami-data-companion

Length of output: 5481


🏁 Script executed:

printf 'probe\n'

Repository: RolnickLab/ami-data-companion

Length of output: 173


🏁 Script executed:

set -euo pipefail

printf '\n== callers of save_detected_objects ==\n'
rg -n "save_detected_objects\(" -S .

printf '\n== get_monitoring_session_image_ids definition ==\n'
sed -n '300,360p' trapdata/db/models/events.py

printf '\n== surrounding uses of image ids in events.py ==\n'
sed -n '140,190p' trapdata/db/models/events.py

Repository: RolnickLab/ami-data-companion

Length of output: 4378


🏁 Script executed:

set -euo pipefail

printf '\n== trapdata/ml/models/localization.py around save_detected_objects call ==\n'
sed -n '150,230p' trapdata/ml/models/localization.py

printf '\n== trapdata/api/queries.py save_detected_objects wrapper ==\n'
sed -n '1,80p' trapdata/api/queries.py

printf '\n== any other image-id list producer/consumer around detections ==\n'
rg -n "get_monitoring_session_image_ids|image_ids|detected_objects_data" trapdata -S

Repository: RolnickLab/ami-data-companion

Length of output: 11206


🏁 Script executed:

set -euo pipefail

printf '\n== custom exceptions / domain error patterns ==\n'
rg -n "class .*Error|raise .*Error|ValueError|LookupError|NotFound|Missing.*Error|domain error" trapdata -S

printf '\n== any helper for missing IDs / validation ==\n'
rg -n "validate.*id|missing ids|missing.*ids|check.*ids|raise.*missing" trapdata -S

Repository: RolnickLab/ami-data-companion

Length of output: 2796


Validate requested image IDs before indexing. images_by_id[image_id] will raise KeyError if the query returns a subset of image_ids; compare the requested IDs to the fetched set and fail fast with a clear error before creating detections.

🧰 Tools
🪛 Ruff (0.15.21)

[warning] 344-344: zip() without an explicit strict= parameter

Add explicit value for parameter strict=

(B905)

🤖 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 `@trapdata/db/models/detections.py` around lines 341 - 345, Validate that every
requested ID in image_ids exists in the fetched images set before the processing
loop indexes images_by_id. In the detection creation flow, compare image_ids
against images_by_id keys and fail fast with a clear error identifying missing
IDs, while preserving the existing loop for valid inputs.

Comment on lines +344 to +345
for image_id, detected_objects in zip(image_ids, detected_objects_data):
image = images_by_id[image_id]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant section with line numbers
sed -n '300,390p' trapdata/db/models/detections.py

# Search for image_ids / detected_objects_data usage and any length validations
rg -n "image_ids|detected_objects_data|zip\\(" trapdata/db/models/detections.py trapdata -g '!**/__pycache__/**'

Repository: RolnickLab/ami-data-companion

Length of output: 10086


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '150,220p' trapdata/ml/models/localization.py
printf '\n---- API QUERIES ----\n'
sed -n '1,90p' trapdata/api/queries.py
printf '\n---- DETECTIONS LENGTH CHECK SEARCH ----\n'
rg -n "len\\(.*image_ids|len\\(.*detected_objects_data|strict=True|mismatch" trapdata/db/models/detections.py trapdata/api/queries.py trapdata/ml/models/localization.py

Repository: RolnickLab/ami-data-companion

Length of output: 6268


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "save_detected_objects\\(" trapdata

Repository: RolnickLab/ami-data-companion

Length of output: 355


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '120,220p' trapdata/ml/models/base.py
printf '\n---- LOCALIZATION CLASS CONTEXT ----\n'
sed -n '1,220p' trapdata/ml/models/localization.py

Repository: RolnickLab/ami-data-companion

Length of output: 11683


Reject mismatched ID and payload lengths. zip() will silently drop extra detections if these sequences ever drift out of sync, so use strict=True or check lengths before iterating.

🧰 Tools
🪛 Ruff (0.15.21)

[warning] 344-344: zip() without an explicit strict= parameter

Add explicit value for parameter strict=

(B905)

🤖 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 `@trapdata/db/models/detections.py` around lines 344 - 345, Update the loop
pairing image_ids with detected_objects_data to reject mismatched sequence
lengths instead of silently truncating via zip. Use strict zip behavior if
supported by the project’s Python version, or validate equal lengths before
iteration, while preserving the existing image lookup and processing logic.

Source: Linters/SAST tools

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detections are associated with incorrect image

1 participant