def test_designmat(tmpdir): mat1 = Design_Matrix({ 'X':[1, 4, 2, 7, 5, 9, 2, 1, 3, 2], 'Y':[3, 0, 0, 6, 9, 9, 10, 10, 1, 10], 'Z':[2, 2, 2, 2, 7, 0, 1, 3, 3, 2], 'intercept':[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, sampling_rate=2.0,polys=['intercept']) mat2 = Design_Matrix({ 'X':[9, 9, 2, 7, 5, 0, 1, 1, 1, 2], 'Y':[3, 3, 3, 6, 9, 0, 1, 10, 1, 10], 'Z':[2, 6, 3, 2, 7, 0, 1, 7, 8, 8], 'intercept':[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, sampling_rate=2.0, polys=['intercept']) # Appending # Basic horz cat new_mat = mat1.append(mat1,axis=1) assert new_mat.shape == (mat1.shape[0], mat1.shape[1] + mat2.shape[1]) both_cols = list(mat1.columns) + list(mat1.columns) assert all(new_mat.columns == both_cols) # Basic vert cat new_mat = mat1.append(mat1,axis=0) assert new_mat.shape == (mat1.shape[0]*2, mat1.shape[1]+1) # Advanced vert cat new_mat = mat1.append(mat1,axis=0,keep_separate=False) assert new_mat.shape == (mat1.shape[0]*2,mat1.shape[1]) # More advanced vert cat new_mat = mat1.append(mat1,axis=0,add_poly=2) assert new_mat.shape == (mat1.shape[0]*2, 9) #convolution doesn't affect intercept assert all(mat1.convolve().iloc[:, -1] == mat1.iloc[:, -1]) #but it still works assert (mat1.convolve().iloc[:, :3].values != mat1.iloc[:, :3].values).any() #Test vifs expectedVifs = np.array([ 1.03984251, 1.02889877, 1.02261945]) assert np.allclose(expectedVifs,mat1.vif()) #poly mat1.add_poly(order=4).shape[1] == mat1.shape[1]+4 mat1.add_poly(order=4, include_lower=False).shape[1] == mat1.shape[1]+1 #zscore z = mat1.zscore(columns=['X', 'Z']) assert (z['Y'] == mat1['Y']).all() assert z.shape == mat1.shape # clean mat = Design_Matrix({ 'X':[1, 4, 2, 7, 5, 9, 2, 1, 3, 2], 'A':[1, 4, 2, 7, 5, 9, 2, 1, 3, 2], 'Y':[3, 0, 0, 6, 9, 9, 10, 10, 1, 10], 'Z':[2, 2, 2, 2, 7, 0, 1, 3, 3, 2], 'C':[1, 4, 2, 7, 5, 9, 2, 1, 3, 2], 'intercept':[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, sampling_rate=2.0,polys=['intercept']) mat = mat[['X','A','Y','Z','C','intercept']] assert all(mat.clean().columns == ['X','Y','Z','intercept']) # replace data mat = Design_Matrix({ 'X':[1, 4, 2, 7, 5, 9, 2, 1, 3, 2], 'A':[1, 4, 2, 7, 5, 9, 2, 1, 3, 2], 'Y':[3, 0, 0, 6, 9, 9, 10, 10, 1, 10], 'Z':[2, 2, 2, 2, 7, 0, 1, 3, 3, 2], 'C':[1, 4, 2, 7, 5, 9, 2, 1, 3, 2] }, sampling_rate=2.0) mat = mat.replace_data(np.ones((mat.shape[0],mat.shape[1]-1)),column_names=['a','b','c','d']) assert(np.allclose(mat.values,1)) assert(all(mat.columns == ['a','b','c','d'])) #DCT basis_mat mat = Design_Matrix(np.random.randint(2,size=(500,3)),sampling_rate=2.0) mat = mat.add_dct_basis() assert len(mat.polys) == 11 assert mat.shape[1] == 14 #Up and down sampling mat = Design_Matrix(np.random.randint(2,size=(500,4)),sampling_rate=2.0,columns=['a','b','c','d']) target = 1 assert mat.upsample(target).shape[0] == mat.shape[0]*2 - target*2 target = 4 assert mat.downsample(target).shape[0] == mat.shape[0]/2
# 5) Append it to the master Design Matrix keeping things separated by run all_runs = all_runs.append(full, axis=0, unique_cols=cov.columns) all_runs.heatmap(vmin=-1, vmax=1) ######################################################################### # We can see the left most columns of our multi-run design matrix contain our conditions of interest (stacked across all runs), the middle columns includes separate run-wise nuisiance covariates (motion, spikes) and the right most columns contain run specific polynomials (intercept, trends, etc). ######################################################################### # Data Diagnostics # ---------------- # # Let's actually check if our design is estimable. Design Matrix provides a few tools for cleaning up highly correlated columns (resulting in failure if trying to perform regression), replacing data, and computing collinearity. By default the `clean` method will drop any columns correlated at r >= .95 all_runs_cleaned = all_runs.clean(verbose=True) all_runs_cleaned.heatmap(vmin=-1, vmax=1) ######################################################################### # Whoops, looks like above some of our polynomials and dct basis functions are highly correlated, but the clean method detected that and dropped them for us. In practice you'll often include polynomials or dct basis functions rather than both, but this was just an illustrative example. ######################################################################### # Estimating a first-level model # ------------------------------ # # You can now set this multi-run Design Matrix as the `X` attribute of a Brain_Data object containing EPI data for these four runs and estimate a regression in just a few lines of code. # This code is commented because we don't actually have niftis loaded for the purposes of this tutorial # See the other tutorials for more details on working with nifti files and Brain_Data objects # Assuming you already loaded up Nifti images like this