See the Actflow Toolbox for more information
Run the code yourself here: https://github.com/ColeLab/ActflowToolbox/blob/master/examples/HCP_example.ipynb

#Import packages and set variables
import numpy as np
import h5py
import pkg_resources
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
import sys
sys.path.insert(0, '../../')
#Used for plotting brain images inline
from wbplot import pscalar
import matplotlib.image as mpimg
%matplotlib inline
plt.rcParams['image.interpolation'] = 'none'
plt.rcParams['figure.figsize'] = 6,4
plt.rcParams.update({'font.size': 16})
plt.rcParams['image.aspect'] = 'equal'
plt.rcParams['image.cmap'] = 'seismic'
import ActflowToolbox as actflow
actflow_example_dir = pkg_resources.resource_filename('ActflowToolbox.examples', 'HCP_example_data/')
networkpartition_dir = pkg_resources.resource_filename('ActflowToolbox.dependencies', 'ColeAnticevicNetPartition/')
networkdef = np.loadtxt(networkpartition_dir + '/cortex_parcel_network_assignments.txt')
networkorder = np.asarray(sorted(range(len(networkdef)), key=lambda k: networkdef[k]))
networkorder.shape = (len(networkorder),1)
netorder=networkorder[:,0]
orderedNetworks = ['VIS1','VIS2','SMN','CON','DAN','LAN','FPN','AUD','DMN','PMM','VMM','ORA']
networkpalette = ['royalblue','slateblue','paleturquoise','darkorchid','limegreen',
'lightseagreen','yellow','orchid','r','peru','orange','olivedrab']
networkpalette = np.asarray(networkpalette)
subjNums = ['100206','108020','117930','126325','133928','143224','153934','164636','174437',
'183034','194443','204521','212823','268749','322224','385450','463040','529953',
'587664','656253','731140','814548','877269','978578','100408','108222','118124',
'126426','134021','144832']
numsubjs=np.shape(subjNums)[0]
numnodes=360
numtimepoints=1195
taskConditions = ['EMOTION:fear','EMOTION:neut','GAMBLING:win','GAMBLING:loss','LANGUAGE:story','LANGUAGE:math',
'MOTOR:cue','MOTOR:lf','MOTOR:rf','MOTOR:lh','MOTOR:rh','MOTOR:t','REASONING:rel',
'REASONING:match','SOCIAL:mental','SOCIAL:rnd','WM 0bk:body','WM 0bk:faces','WM 0bk:places',
'WM 0bk:tools','WM 2bk:body','WM 2bk:faces','WM 2bk:places','WM 2bk:tools']
#Load data
#Data from: https://www.humanconnectome.org/study/hcp-young-adult
#Preprocessed as described here: https://doi.org/10.1101/560730
#Load resting-state fMRI data; 30 HCP subjects, one run of resting-state fMRI each
restdata=np.zeros((numnodes,numtimepoints,numsubjs))
scount = 0
for subj in subjNums:
file_path=actflow_example_dir + 'HCP_example_restrun1_subj' + subj + '_data' + '.h5'
h5f = h5py.File(file_path,'r')
dataid = 'restdata'
restdata[:,:,scount] = h5f[dataid][:]
h5f.close()
scount += 1
#Load task GLM activations; 30 HCP subjects, 24 task conditions
file_path=actflow_example_dir + 'HCP_example_taskactivations_data' + '.h5'
h5f = h5py.File(file_path,'r')
dataid = 'taskbeta'
activations_bycond = h5f[dataid][:]
h5f.close()
%%time
#Run activity flow mapping with Pearson correlation FC
restFC_corr=np.zeros((numnodes,numnodes,numsubjs))
scount=0
for subj in subjNums:
restFC_corr[:,:,scount]=actflow.connectivity_estimation.corrcoefconn(restdata[:,:,scount])
scount += 1
print("==Activity flow mapping results, correlation-based resting-state FC, 24 task conditions==")
actflowOutput_restFCCorr_bycond = actflow.actflowcomp.actflowtest(activations_bycond, restFC_corr)
#Visualize FC matrix
fcmat=np.mean(restFC_corr[netorder,:,:][:,netorder,:],axis=2)
fig=actflow.tools.addNetColors_Seaborn(fcmat)
#Visualize predicted and actual activation patterns
plt.figure(figsize=[7,5])
ax = sns.heatmap(np.mean(actflowOutput_restFCCorr_bycond['actPredVector_bytask_bysubj'],axis=2)[netorder,:],center=0,cmap='seismic',cbar=True,yticklabels=100,xticklabels=taskConditions)
ax.figure.suptitle('Predicted activations, corr FC actflow')
ax.set(ylabel='Regions')
plt.figure(figsize=[7,5])
ax = sns.heatmap(np.mean(activations_bycond,axis=2)[netorder,:],center=0,cmap='seismic',cbar=True,yticklabels=100,xticklabels=taskConditions)
ax.figure.suptitle('Actual activations (24 conditions)')
ax.set(ylabel='Regions')
#Plotting brain surface images in-line, FC-based predictions
condNum=12 #condition 9 = relational reasoning
#RestFC predicted
inputdata=np.mean(actflowOutput_restFCCorr_bycond['actPredVector_bytask_bysubj'],axis=2)[:,condNum]
print('Min value: ', np.min(inputdata))
print('Max value: ', np.max(inputdata))
#flip hemispheres, since CAB-NP is ordered left-to-right, while wbplot uses right-to-left
inputdata_flipped=np.zeros(np.shape(inputdata))
inputdata_flipped[0:180]=inputdata[180:360]
inputdata_flipped[180:360]=inputdata[0:180]
file_out="out.png"
#Set to all reds if no negative values
if min(inputdata) >= 0:
colormap='Reds'
else:
colormap='seismic'
pscalar(
file_out=file_out,
pscalars=inputdata_flipped,
cmap=colormap,
transparent=True)
img = mpimg.imread(file_out)
plt.figure()
plt.axis('off')
plt.title('Corr. restFC actflow predictions (relational reasoning)')
plt.imshow(img)
#Actual activity
inputdata=np.mean(activations_bycond,axis=2)[:,condNum]
print('Min value: ', np.min(inputdata))
print('Max value: ', np.max(inputdata))
#flip hemispheres, since CAB-NP is ordered left-to-right, while wbplot uses right-to-left
inputdata_flipped=np.zeros(np.shape(inputdata))
inputdata_flipped[0:180]=inputdata[180:360]
inputdata_flipped[180:360]=inputdata[0:180]
file_out="out.png"
#Set to all reds if no negative values
if min(inputdata) >= 0:
colormap='Reds'
else:
colormap='seismic'
pscalar(
file_out=file_out,
pscalars=inputdata_flipped,
cmap=colormap,
transparent=True)
img = mpimg.imread(file_out)
plt.figure()
plt.axis('off')
plt.title('Actual activations (relational reasoning)')
plt.imshow(img)

%%time
#Run activity flow mapping with combinedFC
restFC_combFC=np.zeros((numnodes,numnodes,numsubjs))
scount=0
for subj in subjNums:
restFC_combFC[:,:,scount]=actflow.connectivity_estimation.combinedFC(restdata[:,:,scount])
scount += 1
print("==Activity flow mapping results, combinedFC-based resting-state FC, 24 task conditions==")
actflowOutput_restFCcombFC_bycond = actflow.actflowcomp.actflowtest(activations_bycond, restFC_combFC)
%%time
#Run multiple-regression FC using only the combinedFC-validated connections
#This adjusts the weights to better optimize for prediction, rather than using abstract r-values
#(see Cole, Michael W, Takuya Ito, Danielle S Bassett, and Douglas H Schultz. (2016). “Activity Flow over Resting-State Networks Shapes Cognitive Task Activations.” Nature Neuroscience 19 (12): 1718–26. doi:10.1038/nn.4406.)
restFC_mregCombFC=np.zeros((numnodes,numnodes,numsubjs))
scount=0
for subj in subjNums:
restFC_mregCombFC[:,:,scount]=actflow.connectivity_estimation.multregconn(restdata[:,:,scount],conn_mask=(restFC_combFC[:,:,scount]!=0))
scount += 1
print("==Activity flow mapping results, combinedFC+multreg-based resting-state FC, 24 task conditions==")
actflowOutput_restFCcombFCmultreg_bycond = actflow.actflowcomp.actflowtest(activations_bycond, restFC_mregCombFC)
#Visualize FC matrix
fcmat=np.mean(restFC_mregCombFC[netorder,:,:][:,netorder,:],axis=2)
fig=actflow.tools.addNetColors_Seaborn(fcmat)
#Visualize predicted and actual activation patterns
plt.figure(figsize=[7,5])
ax = sns.heatmap(np.mean(actflowOutput_restFCcombFCmultreg_bycond['actPredVector_bytask_bysubj'],axis=2)[netorder,:],center=0,cmap='seismic',cbar=True,yticklabels=100,xticklabels=taskConditions)
ax.figure.suptitle('Predicted activations, combinedFC actflow')
ax.set(ylabel='Regions')
plt.figure(figsize=[7,5])
ax = sns.heatmap(np.mean(activations_bycond,axis=2)[netorder,:],center=0,cmap='seismic',cbar=True,yticklabels=100,xticklabels=taskConditions)
ax.figure.suptitle('Actual activations (24 conditions)')
ax.set(ylabel='Regions')
#Plotting brain surface images in-line, FC-based predictions
condNum=12 #condition 9 = relational reasoning
#RestFC predicted
inputdata=np.mean(actflowOutput_restFCcombFCmultreg_bycond['actPredVector_bytask_bysubj'],axis=2)[:,condNum]
print('Min value: ', np.min(inputdata))
print('Max value: ', np.max(inputdata))
#flip hemispheres, since CAB-NP is ordered left-to-right, while wbplot uses right-to-left
inputdata_flipped=np.zeros(np.shape(inputdata))
inputdata_flipped[0:180]=inputdata[180:360]
inputdata_flipped[180:360]=inputdata[0:180]
file_out="out.png"
#Set to all reds if no negative values
if min(inputdata) >= 0:
colormap='Reds'
else:
colormap='seismic'
pscalar(
file_out=file_out,
pscalars=inputdata_flipped,
cmap=colormap,
transparent=True)
img = mpimg.imread(file_out)
plt.figure()
plt.axis('off')
plt.title('CombinedFC restFC actflow predictions (relational reasoning)')
plt.imshow(img)
#Actual activity
inputdata=np.mean(activations_bycond,axis=2)[:,condNum]
print('Min value: ', np.min(inputdata))
print('Max value: ', np.max(inputdata))
#flip hemispheres, since CAB-NP is ordered left-to-right, while wbplot uses right-to-left
inputdata_flipped=np.zeros(np.shape(inputdata))
inputdata_flipped[0:180]=inputdata[180:360]
inputdata_flipped[180:360]=inputdata[0:180]
file_out="out.png"
#Set to all reds if no negative values
if min(inputdata) >= 0:
colormap='Reds'
else:
colormap='seismic'
pscalar(
file_out=file_out,
pscalars=inputdata_flipped,
cmap=colormap,
transparent=True)
img = mpimg.imread(file_out)
plt.figure()
plt.axis('off')
plt.title('Actual activations (relational reasoning)')
plt.imshow(img)
%%time
#Run activity flow mapping with ten subjects (to reduce processing time)
#Calculate multiple-regression FC
restFC_mreg=np.zeros((numnodes,numnodes,numsubjs))
for scount in np.arange(numsubjs):
restFC_mreg[:,:,scount]=actflow.connectivity_estimation.multregconn(restdata[:,:,scount])
print("==Activity flow mapping results, multiple-regression-based resting-state FC, 24 task conditions==")
actflowOutput_restFCMReg_bycond = actflow.actflowcomp.actflowtest(activations_bycond, restFC_mreg)
#Visualize multreg FC matrix
fcmat=np.mean(restFC_mreg[netorder,:,:][:,netorder,:],axis=2)
fig=actflow.tools.addNetColors_Seaborn(fcmat)
#Visualize predicted and actual activation patterns, with multiple-regression FC
plt.figure(figsize=[7,5])
ax = sns.heatmap(np.mean(actflowOutput_restFCMReg_bycond['actPredVector_bytask_bysubj'],axis=2)[netorder,:],center=0,cmap='seismic',cbar=True,cbar_kws={'label': 'Activation'},yticklabels=100,xticklabels=taskConditions)
ax.figure.suptitle('Predicted activations, multreg FC actflow')
ax.set(ylabel='Regions')
plt.figure(figsize=[7,5])
#Activation (z-score)
ax = sns.heatmap(np.mean(activations_bycond,axis=2)[netorder,:],center=0,cmap='seismic',cbar=True,cbar_kws={'label': 'Activation'},yticklabels=100,xticklabels=taskConditions)
ax.figure.suptitle('Actual activations (24 conditions)')
ax.set(ylabel='Regions')
#Plotting brain surface images in-line, FC-based predictions
condNum=12 #condition 9 = relational reasoning
#RestFC predicted
inputdata=np.mean(actflowOutput_restFCMReg_bycond['actPredVector_bytask_bysubj'],axis=2)[:,condNum]
print('Min value: ', np.min(inputdata))
print('Max value: ', np.max(inputdata))
#flip hemispheres, since CAB-NP is ordered left-to-right, while wbplot uses right-to-left
inputdata_flipped=np.zeros(np.shape(inputdata))
inputdata_flipped[0:180]=inputdata[180:360]
inputdata_flipped[180:360]=inputdata[0:180]
file_out="out.png"
#Set to all reds if no negative values
if min(inputdata) >= 0:
colormap='Reds'
else:
colormap='seismic'
pscalar(
file_out=file_out,
pscalars=inputdata_flipped,
cmap=colormap,
transparent=True)
img = mpimg.imread(file_out)
plt.figure()
plt.axis('off')
plt.title('Multreg restFC actflow predictions (relational reasoning)')
plt.imshow(img)
#Actual activity
inputdata=np.mean(activations_bycond,axis=2)[:,condNum]
print('Min value: ', np.min(inputdata))
print('Max value: ', np.max(inputdata))
#flip hemispheres, since CAB-NP is ordered left-to-right, while wbplot uses right-to-left
inputdata_flipped=np.zeros(np.shape(inputdata))
inputdata_flipped[0:180]=inputdata[180:360]
inputdata_flipped[180:360]=inputdata[0:180]
file_out="out.png"
#Set to all reds if no negative values
if min(inputdata) >= 0:
colormap='Reds'
else:
colormap='seismic'
pscalar(
file_out=file_out,
pscalars=inputdata_flipped,
cmap=colormap,
transparent=True)
img = mpimg.imread(file_out)
plt.figure()
plt.axis('off')
plt.title('Actual activations (relational reasoning)')
plt.imshow(img)
print("===Compare resting-state multregFC actflow predictions to resting-state corrFC actflow prediction, 10 subjects only===")
model_compare_RestMultRegFCVsRestCorrFC_Actflow = actflow.model_compare(target_actvect=actflowOutput_restFCCorr_bycond['actVect_actual_group'][:,:,0:10], model1_actvect=actflowOutput_restFCMReg_bycond['actPredVector_bytask_bysubj'], model2_actvect=actflowOutput_restFCCorr_bycond['actPredVector_bytask_bysubj'][:,:,0:10], full_report=False, print_report=True)
print("===Compare TASK CONDITIONS SEPARATE, resting-state multregFC actflow predictions to resting-state corrFC actflow prediction, 10 subjects only===")
model_compare_RestMultRegFCVsRestCorrFC_Actflow_nodewise = actflow.model_compare(target_actvect=actflowOutput_restFCCorr_bycond['actVect_actual_group'][:,:,0:10], model1_actvect=actflowOutput_restFCMReg_bycond['actPredVector_bytask_bysubj'], model2_actvect=actflowOutput_restFCCorr_bycond['actPredVector_bytask_bysubj'][:,:,0:10], comparison_type='nodewise_compthenavg', full_report=False, print_report=True)
ax = sns.scatterplot(np.arange(24),np.mean(model_compare_RestMultRegFCVsRestCorrFC_Actflow_nodewise['corr_nodewise_compthenavg_bycond'],axis=1), s=100)
ax.figure.suptitle('Pred.-to-actual accuracies for each condition (whole-brain activity patterns)')
ax.set(ylabel='Pearson correlation')
ax.set(xlabel='Task condition')
ax = sns.scatterplot(np.arange(24),np.mean(model_compare_RestMultRegFCVsRestCorrFC_Actflow_nodewise['R2_nodewise_compthenavg_bycond'],axis=1), s=100)
ax.figure.suptitle('Pred.-to-actual accuracies for each condition (whole-brain activity patterns)')
ax.set(ylabel='R^2 (unscaled % variance)')
ax.set(xlabel='Task condition')
print("===Compare REGIONS SEPARATE (24-condition response profiles), resting-state multregFC actflow predictions to resting-state corrFC actflow prediction, 10 subjects only===")
model_compare_RestMultRegFCVsRestCorrFC_Actflow_condwise = actflow.model_compare(target_actvect=actflowOutput_restFCCorr_bycond['actVect_actual_group'][:,:,0:10], model1_actvect=actflowOutput_restFCMReg_bycond['actPredVector_bytask_bysubj'], model2_actvect=actflowOutput_restFCCorr_bycond['actPredVector_bytask_bysubj'][:,:,0:10], comparison_type='conditionwise_compthenavg', full_report=False, print_report=True)
plt.figure(figsize=[7,5])
ax = sns.scatterplot(np.arange(360),np.mean(model_compare_RestMultRegFCVsRestCorrFC_Actflow_condwise['corr_conditionwise_compthenavg_bynode'],axis=1), s=50)
ax.figure.suptitle('Pred.-to-actual accuracies for each region (24-condition response profiles)')
ax.set(ylabel='Pearson correlation')
ax.set(xlabel='Region')
plt.figure(figsize=[7,5])
ax = sns.scatterplot(np.arange(360),np.mean(model_compare_RestMultRegFCVsRestCorrFC_Actflow_condwise['R2_conditionwise_compthenavg_bynode'],axis=1), s=50)
ax.figure.suptitle('Pred.-to-actual accuracies for each region (24-condition response profiles)')
ax.set(ylabel='R^2 (unscaled % variance)')
ax.set(xlabel='Region')
It is known that fMRI has some inherent spatial smoothness that blurs data spatially due to local vasculature. This smoothness is thought to extend somewhere between 2 mm and 5 mm (Malonek and Grinvald 1996; Logothetis and Wandell 2004). In theory this could result in some circularity to the actflow predictions (e.g., the target region's activity blurs into a source region's activity). The code below demonstrates an approach to remove any region within 10 mm of each to-be-predicted target region, removing any potential circularity due to vascular spatial smoothness. Note that there was only a small reduction in prediction accuracy in the results below (likely due to having fewer predictors), suggesting spatial smoothness results in minor (if any) prediction circularity.
#Load dictionary listing which parcels to exclude for each target
networkdefdir = pkg_resources.resource_filename('ActflowToolbox', 'network_definitions/')
inputfilename = networkdefdir+'parcels_to_remove_indices_cortexonly_data.h5'
h5f = h5py.File(inputfilename,'r')
parcels_to_remove={}
for parcelInt in range(numnodes):
outname1 = 'parcels_to_remove_indices'+'/'+str(parcelInt)
parcels_to_remove[parcelInt] = h5f[outname1][:].copy()
h5f.close()
%%time
#Calculate multiple-regression FC, excluding parcels within 10 mm of each target parcel
restFC_mreg_parcelnoncirc=np.zeros((numnodes,numnodes,numsubjs))
for scount in np.arange(numsubjs):
restFC_mreg_parcelnoncirc[:,:,scount]=actflow.connectivity_estimation.multregconn(restdata[:,:,scount], parcelstoexclude_bytarget=parcels_to_remove)
print("==Activity flow mapping results, multiple-regression-based resting-state FC (parcel non-circular), 24 task conditions==")
actflowOutput_restFCMReg_parcelnoncirc_bycond = actflow.actflowcomp.actflowtest(activations_bycond, restFC_mreg_parcelnoncirc)
#Visualize multreg noncircular FC matrix
fcmat=np.mean(restFC_mreg_parcelnoncirc[netorder,:,:][:,netorder,:],axis=2)
fig=actflow.tools.addNetColors_Seaborn(fcmat)