Skip to content

Multi-species awareness: remaining pages & backend confirm/keyword paths #1298

Description

@jss367

Multi-species awareness: remaining pages & backend surfaces

Follow-up to #1294 (multi-subject burst review) and the Compare subject-aware work. A photo can now legitimately carry two different species (multiple MegaDetector boxes, predictions keyed to detection_id, photo.subjects[], multi-valued species keywords). Burst review and Compare were updated; the rest of the app still collapses a photo to one species or one "primary" detection.

Shared root cause

Three legacy reducers, still consumed everywhere despite subjects[] now existing:

  1. confirmed_species = alphabetically-first keyword per photo (vireo/pipeline.py:395).
  2. species_top5 flattens all detections' predictions into one per-photo list (vireo/pipeline.py:329), feeding a single-winner encounter vote (vireo/encounters.py:800).
  3. ROW_NUMBER() OVER (PARTITION BY photo_id ORDER BY confidence DESC) ... rn=1 — keeps only the single most-confident species. Powers highlights, browse summary, readiness pills, iNat prepare.

Actively wrong (data loss / core feature broken)

  • accept_prediction(replace_species=True) (db.py:14099) — replace does DELETE ... photo_keywords WHERE photo_id=? AND keyword_id IN (all species), not detection-scoped. Accepting the teal with "replace" erases a wigeon keyword confirmed on the other detection. Data loss.
  • /api/encounters/species (app.py:23527) — one species slot per burst. Confirming a second real species trips is_replacement and untags the first; _auto_detach_burst_for_species treats two species as a grouping error. A burst genuinely holding two species can't hold both.
  • pipeline_rapid_review.htmlphotoSpecies() = single confirmed_species; one keyword applied to whole burst; photo drops out of "Needs species" after any one tag. Can't tag a second species.
  • cull.htmltopSpeciesForPhoto = species_top5[0]; speciesForEncounter collapses encounter to one species; keep/reject tallies attribute the photo wholly to one species.
  • highlights.html / /api/highlightsget_highlights_candidates collapses each photo to one species (accepted-keyword rn=1 + top-1 prediction); confirm endpoint skips photos with any species keyword as "already confirmed."
  • Lightbox iNat submission (_navbar.htmlapi_inat_prepareget_top_prediction_for_photo) — prefills only one taxon for a two-species photo.

Silently incomplete (second species disappears, no wrong claim)

  • map.html / get_geolocated_photos (db.py:7675) — SQL collapses each photo to one species; marker/legend/popup show one.
  • review.html — cards are per-detection (good), but disagreement/conflict badges compare each prediction against the photo's whole keyword set ignoring detection_id; consensus grouping by timestamp can merge co-occurring subjects.
  • pipeline.html readiness pillscount_primary_detections_in_scope / count_primary_classify_stale use WHERE rn=1; under-count multi-subject classify work. (Partially addressed by ae8faca — verify.)
  • browse.html "Top Species" summary (get_browse_summary, db.py:7522) — rn=1 top-1 collapse. Grid cards themselves are fine.
  • encounter_species_label (encounters.py:800) — single winner per encounter; second species invisible at encounter level.
  • Export {species} token (export.py:248, browse.html:8484) — uses species_list[0]. Naming/routing only; embedded keywords complete.

Already correct (no change)

life_list, stats top-species, keywords, best_batch, audit, location_review, lightroom, XMP sidecar sync, and the prediction-resolution layer (update_prediction_status, accept_prediction sibling-rejection are detection-scoped). misses / photo_editor fine for species.

Suggested sequencing

  1. accept_prediction replace-scoping + /api/encounters/species (data loss / core feature).
  2. rapid review + cull + highlights (review workflows).
  3. map, pipeline pills, browse summary, export naming (reporting/cosmetic).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions