Skip to content

fix: keep group index and result position apart in grouped estimation (#318) - #322

Open
MohammadYusif wants to merge 1 commit into
GWeindel:develfrom
MohammadYusif:fix/issue-318
Open

fix: keep group index and result position apart in grouped estimation (#318)#322
MohammadYusif wants to merge 1 commit into
GWeindel:develfrom
MohammadYusif:fix/issue-318

Conversation

@MohammadYusif

Copy link
Copy Markdown

Summary

  • EventModel._estim_probs_groups collects the per-group results in a list built positionally
    over np.unique(groups), but then indexes that list with the group itself. The two only
    coincide when every declared group occurs in the data — as soon as a group declared in
    channel_map/time_map has no trial left (a level absent after trial rejection, a
    participant subset missing a condition), event probabilities are written onto the wrong
    trials and the loop ends on IndexError: list index out of range.
  • The per-group log-likelihoods had the same problem from the other direction: they were
    returned as a compacted array over only the groups present in the data, while
    group_labels covers every declared group, so group_lkh — and the traces_group /
    xrtraces built from it in EM — silently stopped lining up with the groups they describe.
  • This keeps the position in the result list and the group index separate, and sizes the
    likelihood array on the declared groups, leaving nan for a group without trials.

As mentioned in the issue, the alternative would be to reject a declared group without
trials outright. I went with indexing by position because a model fitted on the full data
and then transformed on a subset that happens to miss a condition is a legitimate case, but
happy to switch if you'd rather not allow empty groups at all.

Changes

  • hmp/models/event.py: in _estim_probs_groups, iterate with
    enumerate(data_groups) so the result position and the group index stay apart;
    pre-size likelihood on the declared groups (np.zeros(self.channel_map.shape[0]) * np.nan)
    and fill it by group, so group_lkh stays aligned with group_labels; sum it with
    np.nansum, which is unchanged whenever every group is present.
  • tests/test_fixed.py: test_grouping_absent_group fits the same trials twice with fully
    independent per-group parameters — once coded 0/2 with the declared group 1 left
    without trials, once coded 0/1 with only the two occurring groups declared — and
    asserts the likelihood and both parameter arrays match, that the group likelihoods are
    reported for every declared group, and that the empty one is nan.

Fixes #318

…GWeindel#318)

_estim_probs_groups collected the per-group results in a list built by
iterating over np.unique(groups), but then indexed that list with the group
itself. Both only coincide when every declared group occurs in the data: as
soon as a group declared in the channel/time maps has no trial left, the
positional list and the group index disagree, event probabilities are written
to the wrong trials and the loop ends on an IndexError.

The per-group log-likelihoods had the same problem. They were returned as a
compacted array over the groups present in the data, while group_labels covers
every declared group, so group_lkh (and the EM traces built from it) silently
stopped lining up with the groups they describe.

Keep the position in the result list and the group index separate, and size the
likelihood array on the declared groups, leaving nan for a group without trials.
@GWeindel

GWeindel commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Hi @MohammadYusif

Thank you for your pull request, could we maybe have a quick online meeting regarding your suggestion? You can send me an email at gabriel.weindel@unil.ch

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.

IndexError when a declared group has no trials

2 participants