Skip to content

Script for matching User Edits - #2038

Merged
BryonLewis merged 2 commits into
mainfrom
user-edit-scripts
Nov 3, 2026
Merged

BryonLewis merged 2 commits into
mainfrom
user-edit-scripts

Conversation

@BryonLewis

Copy link
Copy Markdown
Collaborator

Summary

Adds a way to find out which user last saved each track in a DIVE dataset. Users ask for this regularly ("which human made which annotations?"). The data was already there: each saved track version's rev_created points at a revisionLogItem entry that records the author. Until now, joining the two meant digging through MongoDB by hand.

This PR adds:

  • GET /dive_annotation/track/authors: a new endpoint that lists each track visible at a revision with the revision that saved it and that revision's author.
  • samples/scripts/userEdits/trackAuthors.py: a uv script for ops and admin work that needs more than the API exposes: full version history, per-feature frames, frame-to-image-name mapping, and a dump of the revision log.

A save rewrites the whole track, so the author is the last user to change the track, not necessarily the creator of every detection. The route description and docs say so.

Endpoint: GET /dive_annotation/track/authors

GET /dive_annotation/track/authors?folderId=<id>[&revision=<n>][&set=<name>][&limit=&offset=&sort=]

Example row:

{
  "id": 1, "begin": 0, "end": 33, "featureCount": 34, "rev_created": 17,
  "author_id": "…", "author_name": "jdoe", "created": "…",
  "description": "Import VIAME_CSV from output_tracks.csv"
}
  • description shows where a version came from: save is a manual edit in the annotator, Import <type> from <file> is an uploaded file or pipeline output.
  • revision and set behave exactly as they do on /track. The visibility query is pulled out of BaseItem.list() into a shared BaseItem.list_query(), which both routes use.
  • features are not returned. Mongo counts them in the projection (featureCount), so long tracks don't bloat the response.
  • Authors come from one revisionLogItem query covering every distinct revision on the page.
  • Paged with limit/offset, with the total in the Girder-Total-Count header.
  • Requires READ access on the dataset, the same as /dive_annotation/revision, which already exposes author names.
  • Route parameters come from a shared annotation_params() helper, also used by /track and /group, so they can't drift apart.

Sample script: samples/scripts/userEdits/trackAuthors.py

Reads MongoDB directly. It bypasses Girder access control, so it's meant for admins; everyone else should use the endpoint. Track fields use the same names as the endpoint, so output built on the script keeps working after switching to the API.

  • By default, lists the current version of each track. --all-versions includes replaced and deleted versions.
  • --features adds each feature's frame, image name, keyframe and interpolate flags.
  • --revisions adds the dataset's full revision log.
  • For image-sequence datasets, maps frames to image names the same way the server's valid_images does: png/jpg/jpeg only, names sorted with numbers in numeric order, and clones followed back to their source media through foreign_media_id.
  • --container <name> finds the Mongo container's IP with docker inspect, since the default docker-compose doesn't publish port 27017. It fails after 5 seconds with a hint if Mongo can't be reached.

Docs

  • docs/scripting/Endpoints.md: documents dive_annotation/track/authors.
  • samples/scripts/userEdits/README.md: usage, output format, when to use the API instead, and the Mongo access caveat.

Testing

  • New unit tests in server/tests/test_track_authors.py: authors are matched to the right tracks, features are left out of the projection, one revision-log query covers the page, and a track with no revision-log entry is still listed with an empty author. test_annotation_rollback.py still passes.
  • Lint (flake8/black/isort with the repo config) passes on the changed server files.
  • Ran against a local dev stack (MongoDB 5.0):
    • Image-sequence dataset (326 images): 17 current tracks, the same as the sample script. Paging and revision= return the expected tracks.
    • Video dataset with 30,000 current tracks: track_authors returns in about 0.5s.
    • The route is registered with the same parameters as /track and rejects requests that aren't logged in. A logged-in HTTP request has not been tested yet.

Known limitations

  • featureCount uses a $size expression in the find projection, which needs MongoDB 4.4+. docker-compose pins 5.0.
  • Only tracks are covered, not groups.
  • The script's created timestamps are written without a timezone; they are UTC.

@BryonLewis
BryonLewis merged commit 664e1ce into main Nov 3, 2026
3 checks passed
@BryonLewis
BryonLewis deleted the user-edit-scripts branch November 3, 2026 13:08
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