Skip to content

Capture printed-on-card and multi-image stimulus metadata (Identifying Pictures, Sounds, Story Recall v2) - #330

Merged
wilke0818 merged 2 commits into
mainfrom
feat/image-stimulus-metadata
Aug 28, 2026
Merged

wilke0818 merged 2 commits into
mainfrom
feat/image-stimulus-metadata

Conversation

@wilke0818

Copy link
Copy Markdown
Contributor

What

Capture stimulus targets that live on the shown image for several tasks — previously the sidecars carried only the image URL (or nothing), dropping the actual target.

task change
Identifying Pictures (peds, 37) printed WORD per card → speech_type: read, stimulus_text = the word (WER-scorable; several are sight words like "MY"/"GO"/"ONE" that can't be named from the picture), image asset kept
Noisy / Silly / Long Sounds (peds) printed sound token per card ("aa aa aa", "puh puh puh.....", "Ahhhhhh... (take a breath)...") → stays non-lexical, verbatim token as stimulus_text, image asset kept
Story Recall v2 (adult) wordless 10-panel picture story → one scalar template URL StoryRecall_{n}.jpg + companion stimulus_asset_n_images count

Design points

  • No lists. The multi-image sequence is a single scalar template URL plus an integer count, so the sidecar stays flat / parquet-friendly (no nested column).
  • stimulus_asset_n_images is present only for sequences; its absence is the documented signal that stimulus_asset is a single, directly-resolvable image.
  • Format contract documented in metadata.json: an inapplicable optional field is an absent key in a JSON sidecar and a null/None value in a parquet/TSV column — the two are equivalent.
  • Wordless ⇒ language-independent: every language uses the same Story Recall panels; only stimulus_text differs (Spanish narrative already resolves from the es-419 static bank).
  • The bundler casts the count to nullable Int64 so it renders as 10 (not 10.0) with missing rows as empty cells.

How the words/tokens were obtained

Transcribed directly from the pinned redcap images (no OCR pipeline) and hand-verified.

Tests

tests/test_task_prompts.py — identifying-pictures read targets, sound-card tokens, Story Recall sequence + n_images, single-image tasks omit the count, and a bundling TSV round-trip proving absent-key == null-cell and the integer render. 39/39 pass.

Follow-up

The Int64 cast is a stopgap; a general declared-dtype schema for all packaged artifacts (TSV + parquet) is tracked in #329.

wilke0818 and others added 2 commits August 24, 2026 17:43
…istry

Several image-based tasks encode their target on the shown image, where it was
being dropped from the sidecars (the metadata carried only the image URL):

- Identifying Pictures (peds): each of the 37 flashcards prints the target WORD.
  Several are sight words ("MY", "GO", "ONE") that cannot be named from the
  picture, so this is a read (WER-scorable) target. Transcribed once into an
  index-keyed bank; speech_type -> read, stimulus_text = the word, kept the
  pinned image asset.
- Noisy / Silly / Long Sounds (peds): each card prints the target sound token
  (e.g. "aa aa aa", "puh puh puh.....", "Ahhhhhh... (take a breath)..."). These
  stay non-lexical (a sound repeated to the time limit, not a WER target); the
  verbatim token is captured as stimulus_text, image asset kept.
- Story Recall v2 (adult): the participant views a wordless 10-panel picture
  story before retelling. Recorded as ONE scalar template URL (StoryRecall_{n}.jpg)
  plus a companion stimulus_asset_n_images count -- never a list, so the sidecar
  stays flat/parquet-friendly. Wordless => language-independent (same panels for
  every language; only the reference narrative differs). The Spanish narrative
  already resolves from the es-419 static bank.

Field-format contract documented in resources/metadata.json: an inapplicable
optional field is an absent key in a JSON sidecar and a null/None value in a
parquet/TSV column -- the two are equivalent. The metadata bundler casts
stimulus_asset_n_images to nullable Int64 so the count renders as an integer
(not 10.0) with missing rows as empty cells; proven by a round-trip test.

Tests: identifying-pictures read targets, sound-card tokens, story-recall
sequence + n_images, single-image tasks omit the count, and a bundling
TSV round-trip proving absent-key == null-cell. Task-prompt suite 39/39.

A general declared-dtype schema for all packaged artifacts (this Int64 cast is a
stopgap) is tracked in #329.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…banks

- Extract _raw_github_url so _asset_url and _asset_sequence_url build the
  commit-pinned GitHub URL in one place (no drift in host/encoding/pinning).
- _asset_url now returns None for any '{n}'-templated path, so a multi-image
  sequence can never be percent-encoded into a broken single URL regardless of
  task ptype; _asset_sequence_url owns those. Regression test added.
- @lru_cache _bank so a bank's JSON is parsed once, not per recording (hot loop
  in large pediatric builds).

Deliberately kept: the stimulus_asset_n_images Int64 cast in commands.py (a
stopgap folded into #329's general dtype schema), and _bank raising on a missing
vendored bank (fail-loud beats silently shipping empty stimulus_text).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wilke0818
wilke0818 requested a review from Evan8456 August 25, 2026 17:56
@wilke0818

Copy link
Copy Markdown
Contributor Author

@Evan8456 Mostly standard, does a weird thing with story_recall where we use *_n for the image of the story so we don't have to use lists of URLs since I removed the list of prompts from before though we could return to that if you think this solution is a bit wack

@Evan8456

Copy link
Copy Markdown
Contributor

seems reasonable. I think urls are more troublesome long term, might be the less of 2 evils.

@wilke0818
wilke0818 merged commit 3505749 into main Aug 28, 2026
1 check passed
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.

2 participants