Example #1
0
def test_volumetric_input():
    mask_image = nib.load(
        tflow.get("MNI152Lin", resolution="02", desc="brain", suffix="mask"))
    n_voxels = (mask_image.get_fdata() != 0).sum()
    n_subjects = 3
    data = np.random.rand(n_subjects, n_voxels)
    model = FixedEffect(1)
    contrast = np.ones(3)

    slm = SLM(model, contrast, surf=mask_image)
    slm.fit(data)
Example #2
0
def test_SLM():
    """Tests the SLM model using a grid of parameters

    Raises
    ------
    Exception
        First exception that occurs in computing the SLM.
    """
    samples = 10
    predictors = 3

    grid = list(create_parameter_grid(samples, predictors))
    Y = np.random.rand(samples, 10242, predictors)

    for i in range(len(grid)):
        # Skip exceptions that we know error.
        if grid[i]["surf"] is None:
            if grid[i]["correction"] is not None and "rft" in grid[i][
                    "correction"]:
                continue
        if grid[i]["Y_idx"] > 1 and grid[i]["two_tailed"] is False:
            continue

        try:
            slm = SLM(
                model=grid[i]["model"],
                contrast=grid[i]["contrast"],
                surf=grid[i]["surf"],
                mask=grid[i]["mask"],
                correction=grid[i]["correction"],
                two_tailed=grid[i]["two_tailed"],
            )
            slm.fit(Y[:, :, 0:grid[i]["Y_idx"]])
        except Exception as e:
            print("Error on run:", i)
            print("SLM failed with the following parameters:")
            print("Model: ", grid[i]["model"])
            print("Contrast: ", grid[i]["contrast"])
            print("Surface: ", grid[i]["surf"])
            print("Mask: ", grid[i]["mask"])
            print("Correction: ", grid[i]["correction"])
            print("Two_tailed: ", grid[i]["two_tailed"])
            print("Y_idx: ", grid[i]["Y_idx"])
            raise e
Example #3
0
model = term_intercept + term_age + term_iq

###################################################################
# We can also add interaction effects to the model by multiplying terms.

model_interaction = term_intercept + term_age + term_iq + term_age * term_iq

###################################################################
# Now, lets imagine we have some cortical marker (e.g. cortical thickness) for
# each subject and we want to evaluate whether this marker changes with age
# whilst correcting for effects of sex and age-sex interactions.

from brainstat.stats.SLM import SLM

slm = SLM(model_interaction, -age, surf=pial_left, correction="rft", mask=mask)
slm.fit(thickness)
print(slm.t.shape)  # These are the t-values of the model.
print(slm.P["pval"]["P"])  # These are the random field theory derived p-values.

###################################################################
# By default BrainStat uses a two-tailed test. If you want to get a one-tailed
# test, simply specify it in the SLM model as follows:

slm_two_tails = SLM(
    model_interaction, -age, surf=pial_left, correction="rft", two_tailed=False
)
slm_two_tails.fit(thickness)

###################################################################
# Now, imagine that instead of using a fixed effects model, you would prefer a
# mixed effects model wherein handedness is a random variable. This is simple to
term_age = FixedEffect(demographics.AGE_AT_SCAN)
term_sex = FixedEffect(demographics.SEX)
term_subject = MixedEffect(demographics.SUB_ID)
model = term_age + term_sex + term_age * term_sex + term_subject

contrast_age = -model.mean.AGE_AT_SCAN
slm = SLM(
    model,
    contrast_age,
    surf="fsaverage5",
    mask=mask,
    correction=["fdr", "rft"],
    two_tailed=False,
    cluster_threshold=0.01,
)
slm.fit(thickness)

###################################################################
# Genetics
# --------
#
# For genetic decoding we use the Allen Human Brain Atlas through the abagen
# toolbox. Note that abagen only accepts parcellated data. Here is a minimal
# example of how we use abagen to get the genetic expression of the 100 regions
# of the Schaefer atlas and how to plot this expression to a matrix. Please note
# that downloading the dataset and running this analysis can take several
# minutes.

import copy

import matplotlib.pyplot as plt
Example #5
0
def generate_test_data():
    pial, mask, age, iq, thickness = load_training_data(n=20)
    fixed_model = FixedEffect(1) + FixedEffect(age, "age")
    mixed_model = (
        FixedEffect(1)
        + FixedEffect(age, "age")
        + MixedEffect(iq, name_ran="iq")
        + MixedEffect(1, name_ran="Identity")
    )

    variates_2 = np.concatenate(
        (thickness[:, :, None], np.random.random_sample(thickness.shape)[:, :, None]),
        axis=2,
    )
    variates_3 = np.concatenate(
        (
            thickness[:, :, None],
            np.random.rand(thickness.shape[0], thickness.shape[1], 2),
        ),
        axis=2,
    )

    # Params 1: No surface, fixed effect.
    # Params 2: One-tailed mixed with theta/dr changes.
    # Params 3: With surface. and RFT correction.
    parameters = [
        {
            "Y": [thickness, variates_2, variates_3],
            "model": [fixed_model],
            "contrast": [-age],
            "correction": [None, "fdr"],
            "surf": [None],
            "mask": [mask],
            "niter": [1],
            "thetalim": [0.01],
            "drlim": [0.1],
            "two_tailed": [True],
            "cluster_threshold": [0.001],
        },
        {
            "Y": [thickness],
            "model": [mixed_model],
            "contrast": [-age],
            "correction": ["fdr"],
            "surf": [None, pial],
            "mask": [mask],
            "niter": [1],
            "thetalim": [0.01, 0.05],
            "drlim": [0.1, 0.2],
            "two_tailed": [False],
            "cluster_threshold": [0.001],
        },
        {
            "Y": [thickness],
            "model": [fixed_model, mixed_model],
            "contrast": [-age],
            "surf": [pial],
            "mask": [mask],
            "correction": [None, ["fdr", "rft"]],
            "niter": [1],
            "thetalim": [0.01],
            "drlim": [0.1],
            "two_tailed": [True],
            "cluster_threshold": [0.001, 1.2],
        },
    ]

    test_num = 0
    for params in ParameterGrid(parameters):
        test_num += 1
        slm = SLM(
            params["model"],
            params["contrast"],
            params["surf"],
            params["mask"],
            correction=params["correction"],
            niter=params["niter"],
            thetalim=params["thetalim"],
            drlim=params["drlim"],
            two_tailed=params["two_tailed"],
            cluster_threshold=params["cluster_threshold"],
        )
        slm.fit(params["Y"])

        # Save input/output
        if isinstance(params["model"], FixedEffect):
            params["model"] = age[:, None]
        else:
            params["model"] = np.concatenate((age[:, None], iq[:, None]), axis=1)
        dict2pkl(params, "slm", test_num, input=True)
        slm2files(slm, "slm", test_num, input=False)
Example #6
0
def dummy_test(infile, expfile):

    # load input test data
    ifile = open(infile, "br")
    idic = pickle.load(ifile)
    ifile.close()

    slm = SLM(FixedEffect(1), FixedEffect(1))
    # Data are saved a little differently from the actual input due to compatibility with MATLAB.
    # Data wrangle a bit to bring it back into the Python input format.
    for key in idic.keys():
        if key == "Y":
            # Y is input for slm.fit(), not a property.
            continue
        if key == "model":
            # Model is saved as a matrix rather than a Fixed/MixedEffect
            if idic[key].shape[1] == 1:
                idic[key] = FixedEffect(1) + FixedEffect(idic[key])
            else:
                idic[key] = (FixedEffect(1) + FixedEffect(idic[key][:, 0]) +
                             MixedEffect(idic[key][:, 1]) + MixedEffect(1))
        setattr(slm, key, idic[key])
        if key == "surf" and slm.surf is not None:
            slm.surf["tri"] += 1

    slm.fit(idic["Y"])

    # load expected outout data
    efile = open(expfile, "br")
    out = pickle.load(efile)
    efile.close()

    # Format of self.P changed since files were created -- alter out to match some changes.
    # Combine the list outputs, sort with pandas, and return to list.
    if "P" in out:
        out["P"]["pval"]["C"] = _onetailed_to_twotailed(
            out["P"]["pval"]["C"][0], out["P"]["pval"]["C"][1])

        for key1 in ["peak", "clus"]:
            P_tmp = []
            none_squeeze = lambda x: np.squeeze(x) if x is not None else None
            for i in range(len(out["P"][key1]["P"])):
                tail_dict = {
                    key: none_squeeze(value[i])
                    for key, value in out["P"][key1].items()
                }
                if tail_dict["P"] is not None:
                    if tail_dict["P"].size == 1:
                        P_tmp.append(pd.DataFrame.from_dict([tail_dict]))
                    else:
                        P_tmp.append(pd.DataFrame.from_dict(tail_dict))
                        P_tmp[i].sort_values(by="P", ascending=True)
                else:
                    P_tmp.append(pd.DataFrame(columns=tail_dict.keys()))
            out["P"][key1] = P_tmp

    testout = []

    skip_keys = ["model", "correction", "_tri", "surf"]

    for key in out.keys():
        if key in skip_keys:
            continue
        if key == "P":
            testout.append(recursive_comparison(out[key], getattr(slm, key)))
        elif out[key] is not None:
            comp = np.allclose(out[key],
                               getattr(slm, key),
                               rtol=1e-05,
                               equal_nan=True)
            testout.append(comp)

    assert all(flag == True for (flag) in testout)
Example #7
0
# the lifespan. To do this, we can use the model we defined before, and a
# contrast in observations (here: age). Then we simply initialize an SLM model
# and fit it to the cortical thickness data.

from brainstat.stats.SLM import SLM

contrast_age = demographics.AGE_AT_SCAN
slm_age = SLM(
    model,
    contrast_age,
    surf="fsaverage5",
    mask=mask,
    correction=["fdr", "rft"],
    cluster_threshold=0.01,
)
slm_age.fit(thickness)

###################################################################
# The resulting model, slm_age, will contain the t-statistic map, p-values
# derived with the requested corrections, and a myriad of other properties (see
# the API for more details). Lets plot the t-values and p-values on the surface.
# We'll do this a few times throughout the tutorial so lets define a function to
# do this.


def plot_slm_results(slm, plot_peak=False, plot_fdr=False):

    handles = [local_plot_hemispheres(slm.t, ["t-values"], (-4, 4), "bwr")]

    plot_pvalues = [np.copy(slm.P["pval"]["C"])]
    labels = ["Cluster p-values"]