nilearn / nistats

Modeling and statistical inference on fMRI data in Python
BSD 3-Clause "New" or "Revised" License
95 stars 55 forks source link

Add support for explicit fixed effects #394

Closed adelavega closed 4 years ago

adelavega commented 4 years ago

This is adds a class FixedEffectsModel which computes fixed effects statistics given matching lists of effect_maps and variance_maps nifti-images or paths.

The background for doing this is that in fitlins, we compute each step in a multi-level model separately. Nistats already supports fixed-effects for muli-session designs but only as part of FirstLevelModel, which is not flexible enough for our purposes.

I emulated SecondLevelModel, and abstracted the logic for learning a mask from inputs into a function _learn_masker that is used by both classes.

Given how much of the logic is repeated, it would make sense to abstract more of it into functions, or to make a class which both SecondLevel and FixedEffects models abstract from, which includes this shared logic.

Also, I wasn't sure if it would be possible to support other types of inputs (e.g. pandas df), so I only added suppots for nifti images, or paths to images. Need to also add memory caching for the fixed-effects contrast computation, and potentially abstract that logic for use by FirstLevelModel.

Closes #281

adelavega commented 4 years ago

I tested this PR on this example: https://nistats.github.io/auto_examples/02_first_level_models/plot_fiac_analysis.html#sphx-glr-auto-examples-02-first-level-models-plot-fiac-analysis-py

The z-stat map from computing the effect and variances separately for each run, and combining using FixedEffectsModel was identical to that produced by FirstLevelModel.

adelavega commented 4 years ago

cc: @effigies @tyarkoni

effigies commented 4 years ago

From an API perspective, SecondLevelModel and FixedEffectsModel seems like a strange dichotomy. As a user, what I mean by second level is "Process statistical maps, not BOLD series", and not necessarily "Perform a random effects analysis".

For intuitiveness, I would say either:

1) Allow SecondLevelModel to take a parameter indicating that it should perform a fixed- or random-effects meta-analysis. 2) Create FixedEffectsModel and RandomEffectsModel classes, and deprecate SecondLevelModel as an alias for RandomEffectsModel.

adelavega commented 4 years ago

I was just having the exact same thought myself, good idea.

bthirion commented 4 years ago

Thx for this ! Recently, I tried a different approach, based on a function rather than a class: my philosophy is that fixed effects inference is something that eats first-level statistics and returns a more condensed version of these statistcis, hence I implemented it as a function. Please take a look at #386

adelavega commented 4 years ago

ah, always check open PRs! I think a function approach would work for us. It's not really a model that is being run or fit.

adelavega commented 4 years ago

Given the other PR, I'll close this, but I left a few comments over there.

@effigies I'll try to implement this into fitlins (i.e. only run a SecondLevelModel if needed, otherwise use this function to compute FEMA contrasts). Do you know what stats we need to pass forward in fitlins? Looks like FEMA only outputs effects + variances + t (seems OK to me, but not sure if expecting more)

effigies commented 4 years ago

@adelavega I think you should be able to calculate p-values and z-scores from those three.