feat(sequences): endpoint to update a sequence's azimuth and recompute triangulation
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 29
- Forks
- 14
- Avg merge
- 9d 1h
- Merged PRs (30d)
- 5
Description
Objective
Today, a sequence's azimuth (Sequence.sequence_azimuth) is computed once, at sequence creation, from the center of the first detection's bounding box — see resolve_cone (src/app/services/cones.py) called in src/app/api/api_v1/endpoints/detections.py (~L582-590). It never changes afterward.
We want to be able to refine that azimuth after the fact. Two future sources will need this (handled in separate issues ):
- an operator clicking the fire origin point in the frontend, and/or
- a CV algorithm estimating the fire origin automatically.
This issue covers the backend workflow only: exposing a clean API entry point that updates the azimuth and keeps the triangulation state consistent.
Note:The source of the new azimuth is not tracked or persisted in this issue.
Current behavior
sequence_azimuth (and cone_angle) feed the whole triangulation pipeline:
_attach_sequence_to_alert(src/app/api/api_v1/endpoints/detections.py, ~L392) — builds detection cones, finds overlapping sequences, and creates/merges/links alerts.refresh_alert_state(src/app/services/alerts.py, ~L21) — recomputes an alert's bounds and lat/lon from its member sequences viacompute_overlap(src/app/services/overlap.py).
There is no route to change a sequence's azimuth. The only sequence mutations exposed are PATCH /sequences/{id}/label and DELETE /sequences/{id} (src/app/api/api_v1/endpoints/sequences.py). Both, notably, already re-run the alert/triangulation reconciliation after mutating — that's the pattern to follow.
Expected behavior
Expose a new endpoint (suggested: PATCH /sequences/{sequence_id}/azimuth) that, when the azimuth of a sequence is updated:
- Persists the new
sequence_azimuth. - Recomputes all triangulations involving this sequence (its cone changes, so overlaps with other sequences change).
- Reconciles the linked alerts — create / update / remove
AlertSequencelinks and alert lat-lon as needed, exactly as sequence creation and labeling already do. - Leaves the triangulation state consistent across the affected alerts (no orphaned links, no stale alert locations).
The endpoint must be usable both by the frontend (operator refinement) and by an automated CV pipeline (service/admin token).
A suggested approach (can be challenged)
- Add a
SequenceAzimuthrequest schema insrc/app/schemas/sequences.pyvalidatingsequence_azimuthin[0, 360)(mirror the model constraint oncamera_azimuth). - In the endpoint: fetch the sequence, persist the new azimuth, then re-run the same attach/reconcile flow the creation path uses. Note for the implementer: the triangulation entry point
_attach_sequence_to_alertcurrently lives inside the detections endpoint module and is already imported cross-module bysrc/app/services/validation.py(~L371). Reusing it here (rather than duplicating the logic) likely warrants extracting it into a service module (e.g.app/services/triangulation.pyor extendingapp/services/alerts.py). ? - After re-attaching, refresh every previously- and newly-linked alert via
refresh_alert_stateso alert bounds and location stay correct — including deleting an alert that ends up empty (already handled insiderefresh_alert_state).
Auth / roles
Allowed: ADMIN and USER (the acknowledging role).
AGENT must NOT have access. (This intentionally differs from /label, which is ADMIN + AGENT.)
Non-admins are scoped to their own organization -> you might use verify_org_rights (src/app/api/api_v1/endpoints/sequences.py).
Open question to resolve during implementation -> cone angle
Refining the azimuth by clicking a fire origin point conceptually collapses the detection to (near) a point, whereas cone_angle today encodes the bbox width (src/app/services/cones.py) and directly drives cone overlap. So:
- Is updating
cone_anglerelevant when the azimuth is refined? - If yes, what value —> should the endpoint accept a
cone_angle, or should a refined azimuth always snap to a fixed, narrow opening angle (a constant insrc/app/core/config.py)?
Acceptance criteria
- New authenticated endpoint updates
sequence_azimuthon a sequence and persists it. - Auth enforced:
ADMIN+USERallowed,AGENTforbidden (403), non-admins limited to their org. - Input validated to
[0, 360). - After the update, alert links and alert location/bounds are recomputed and left consistent (links added/updated/removed; empty alerts deleted).
-
cone_anglebehavior decided and implemented per the open question above. - Tests cover: azimuth change that (a) keeps the same alert, (b) breaks an existing overlap/link, (c) creates a new overlap/link, and (d) empties and deletes an alert. Follow the existing endpoint tests in
src/tests/endpoints/.
Happy to discuss it 🖌️
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the sequence mutation routes in src/app/api/api_v1/endpoints/sequences.py and the creation flow in src/app/api/api_v1/endpoints/detections.py, then read refresh_alert_state in src/app/services/alerts.py and cone logic in src/app/services/cones.py. Review schemas in src/app/schemas/sequences.py and endpoint tests under src/tests/endpoints/. Done means the authenticated update handles the listed overlap and alert-link cases, with cone_angle behavior resolved and covered by tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fastapi, postgresql, python
- Domain
- api, authentication, backend, databases, testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100