Make BAS evaluation runnable: four defects, none of which allowed a single file to load - #23
Merged
Merged
Conversation
…ingle file to load
BAS evaluation was as non-functional as GS-HOTA was, for a different set of reasons. Not
one of the ten released BAS files could be read by the loader that ships to read them.
1. WRONG TOP-LEVEL KEY
_parse_bas reads data["annotations"]; the files key the event array "actions".
KeyError on the first line of every file. Now accepts either.
2. WRONG LABEL CASE
BAS_LABELS declares Title Case ("High Pass"); the data is UPPER CASE ("HIGH PASS").
Unknown labels *raise* rather than being skipped, so this would have failed on the
first event of every file once (1) was past. The label sets are identical, so this is
purely casing: labels are now matched case-insensitively and canonicalised to the
documented Title Case spelling. An genuinely unrecognised label still raises --
silently dropping events would understate recall.
3. A THIRD PERIOD IN A DIFFERENT FORMAT
117092, 132831 and 132877 each carry a further block of events whose gameTime omits
the half prefix entirely ("90:01" rather than "1 - 0:01") and whose position continues
past 5,400,000 ms. That is 1007, 691 and 431 events respectively -- 2,129 events, all
of which crashed the split with "not enough values to unpack". 117092's metadata does
declare EXTRA_FIRST_HALF and EXTRA_SECOND_HALF, so these look like genuine extra time.
The period is now inferred from position instead of dropping the events.
4. `position` IS ABSOLUTE, NOT PER-HALF -- AND THE DOCS SAY OTHERWISE
Verified on 117093: half-2 events run 2,700,760..5,506,280 ms with gameTime
"2 - 45:00".."2 - 91:46". They do not restart near zero; both the clock and position
are absolute from the start of the match.
docs/format-bas.md and the paper both state "milliseconds from kickoff of the half
indicated in gameTime" and give a cross-reference formula of floor(position/40).
Following either misaligns every half-2 event by 45 minutes.
Event.image_id used t_ms directly, so it put every half-2 event 67,500 frames late. It
now derives from a new Event.t_ms_in_half. That property is explicitly documented as
APPROXIMATE: it subtracts a nominal 45-minute half, whereas real halves run over -- in
this data half-2 in-half times reach ~48 minutes and a few sit slightly before the
nominal boundary, giving small negative values. Frame-exact work should use the
per-period frameStart in <match>_tracker_box_metadata.xml.
The docs/paper wording is NOT changed here; which of the two is authoritative is a call
for the author. tests/test_bas_map_identity.py pins the observed behaviour so a future
data release that switches to per-half timing fails loudly instead of silently.
VERIFICATION -- tests/test_bas_map_identity.py, or `make bas-map-test`:
23,663 events parse across all ten matches (previously zero)
mAP@1s = 1.0000, mAP@5s = 1.0000 scoring ground truth against itself
all 12 classes at 1.0 individually
As with GS-HOTA, a perfect-prediction score validates parsing, matching and the AP
computation. It does not exercise the partial-match path, which needs real predictions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AtomScott
force-pushed
the
fix/bas-evaluator
branch
from
August 10, 2026 18:17
6ba699a to
2e9c414
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Companion to #21. BAS evaluation was as non-functional as GS-HOTA, for a different set of reasons: not one of the ten released BAS files could be read by the loader that ships to read them.
1. Wrong top-level key
_parse_basreadsdata["annotations"]; the files key the event arrayactions.KeyErroron the first line of every file. Now accepts either.2. Wrong label case
BAS_LABELSdeclares Title Case ("High Pass"); the data is UPPER CASE ("HIGH PASS"). Unknown labels raise rather than being skipped, so this fails on the first event of every file once (1) is past.The label sets are identical — purely casing. Labels are now matched case-insensitively and canonicalised to the documented Title Case spelling. A genuinely unrecognised label still raises; silently dropping events would understate recall.
3. A third period in a different format
117092,132831and132877each carry a further block of events whosegameTimeomits the half prefix ("90:01"rather than"1 - 0:01") and whosepositioncontinues past 5,400,000 ms:2,129 events that crashed the
gameTimesplit with "not enough values to unpack".117092's metadata does declareEXTRA_FIRST_HALFandEXTRA_SECOND_HALF, so these look like genuine extra time. The period is now inferred frompositionrather than the events being dropped.4.
positionis absolute, not per-half — and the docs say otherwiseVerified on
117093:Half 2 does not restart near zero. Both the clock and
positionare absolute from the start of the match.docs/format-bas.mdandsections/02_dataset.texboth state "apositionfield giving milliseconds from kickoff of the half indicated ingameTime", and the paper gives the cross-reference formula⌊position/40⌋. Following either misaligns every half-2 event by 45 minutes.Event.image_idusedt_msdirectly, so it placed every half-2 event 67,500 frames late. It now derives from a newEvent.t_ms_in_half, documented as approximate: it subtracts a nominal 45-minute half, while real halves run over — half-2 in-half times reach ~48 minutes here, and a few events sit slightly before the nominal boundary, giving small negative values. Frame-exact work should use the per-periodframeStartin<match>_tracker_box_metadata.xml.I have not changed the docs or the paper. Which of the two is authoritative is your call — the data could be relabelled to per-half, or the documentation corrected.
tests/test_bas_map_identity.pypins the observed behaviour so that a future data release switching to per-half timing fails loudly rather than silently.Verification
make bas-map-test:As with GS-HOTA, a perfect-prediction score validates parsing, matching and the AP computation. It does not exercise the partial-match path — that needs real predictions.
Note on the test
The test pins
sys.pathto its own checkout. Without that it silently exercises whatever working tree the venv's editable install points at — which bit me while writing it, and would bite anyone running tests from a second clone.🤖 Generated with Claude Code