def compute_BSA_ipmi(domain, lbeta, dmax, thq=0.5, smin=5, ths=0, theta=3.0, bdensity=0, model="gam_gauss", verbose=0): """ Compute the Bayesian Structural Activation patterns with approach described in IPMI'07 paper Parameters ---------- domsin: StructuredDomain instance, Description of the spatial context of the data lbeta: an array of shape (nbnodes, subjects): the multi-subject statistical maps thq = 0.5 (float): posterior significance threshold should be in [0,1] smin = 5 (int): minimal size of the regions to validate them theta = 3.0 (float): first level threshold bdensity=0 if bdensity=1, the variable p in ouput contains the likelihood of the data under H1 on the set of input nodes model: string, model used to infer the prior p-values can be 'gamma_gauss' or 'gauss_mixture' verbose=0 : verbosity mode Returns ------- crmap: array of shape (nnodes): the resulting group-level labelling of the space LR: instance of sbf.LandmarkRegions, that describes the ROIs found in inter-subject inference bf: list of nipy.neurospin.spatial_models.hroi.Nroi instances representing individual ROIs p: array of shape (nnodes): likelihood of the data under H1 over some sampling grid Note ---- This is historically the first version, but probably not the most optimal It should not be changed for historical reason """ nbsubj = lbeta.shape[1] nvox = domain.size bf, gf0, sub, gfc = compute_individual_regions( domain, lbeta, smin, theta, 'gam_gauss', verbose) crmap = -np.ones(nvox, np.int) u = [] AF = sbf.LandmarkRegions(bf[0].domain, 0, [], []) p = np.zeros(nvox) if len(sub)<1: return crmap, AF, bf, u, p # inter-subject analysis # use the DPMM (core part) dim = domain.em_dim sub = np.concatenate(sub).astype(np.int) gfc = np.concatenate(gfc) gf0 = np.concatenate(gf0) p = np.zeros(np.size(nvox)) g0 = 1./(np.sum(domain.local_volume)) g1 = g0 dof = 1000 prior_precision = 1./(dmax*dmax)*np.ones((1,dim)) if bdensity: spatial_coords = domain.coord else: spatial_coords = gfc p,q = dpmm(gfc, 0.5, g0, g1, dof, prior_precision, 1-gf0, sub, 100, spatial_coords, nis=300) # inference valid = q>thq # remove non-significant regions for s in range(nbsubj): bfs = bf[s] if bfs.k>0: # is not None valids = -np.ones(bfs.k).astype('bool') valids[bfs.isleaf()] = valid[sub==s] valids = bfs.make_forest().propagate_upward_and(valids) bfs.select(valids) if bfs.k>0: # is not None bfs.merge_descending() bfs.make_feature('position', domain.coord) pos = bfs.representative_feature('position', 'cumulated_mean') bfs.set_roi_feature('position', pos) # compute probabilitsic correspondences across subjects gc = _hierarchical_asso(bf, np.sqrt(2)*dmax) if gc == []: return crmap,AF,bf,p # make hard clusters through clustering u, cost = average_link_graph_segment(gc, 0.2, gc.V*1.0/nbsubj) q = 0 for s in range(nbsubj): if bf[s].k>0: # is not None bf[s].set_roi_feature('label', u[q:q+bf[s].k]) q += bf[s].k LR, mlabel = sbf.build_LR(bf, ths=ths) if LR is not None: crmap = LR.map_label(domain.coord, pval=0.95, dmax=dmax) return crmap, LR, bf, p
def bsa_dpmm2(bf, gf0, sub, gfc, dmax, thq, ths, verbose): """ Estimation of the population level model of activation density using dpmm and inference Parameters ---------- bf list of nipy.neurospin.spatial_models.hroi.HierarchicalROI instances representing individual ROIs let nr be the number of terminal regions across subjects gf0, array of shape (nr) the mixture-based prior probability that the terminal regions are true positives sub, array of shape (nr) the subject index associated with the terminal regions gfc, array of shape (nr, coord.shape[1]) the coordinates of the of the terminal regions dmax float>0: expected cluster std in the common space in units of coord thq = 0.5 (float in the [0,1] interval) p-value of the prevalence test ths=0, float in the rannge [0,nsubj] null hypothesis on region prevalence that is rejected during inference verbose=0, verbosity mode Returns ------- crmap: array of shape (nnodes): the resulting group-level labelling of the space LR: a instance of sbf.LandmarkRegions that describes the ROIs found in inter-subject inference If no such thing can be defined LR is set to None bf: List of nipy.neurospin.spatial_models.hroi.Nroi instances representing individual ROIs Coclust: array of shape (nr,nr): co-labelling matrix that gives for each pair of cross_subject regions how likely they are in the same class according to the model """ dom = bf[0].domain n_subj = len(bf) crmap = -np.ones(dom.size, np.int) LR = None p = np.zeros(dom.size) if len(sub)<1: return crmap,LR,bf,p sub = np.concatenate(sub).astype(np.int) gfc = np.concatenate(gfc) gf0 = np.concatenate(gf0) # prepare the DPMM g0 = 1./(np.sum(dom.local_volume)) g1 = g0 prior_precision = 1./(dmax*dmax)*np.ones((1, dom.em_dim), np.float) dof = 10 burnin = 100 nis = 300 q, p, CoClust = dpmm(gfc, .5, g0, g1, dof, prior_precision, 1-gf0, sub, burnin, nis=nis, co_clust=True) cg = fg.wgraph_from_coo_matrix(CoClust) cg.remove_edges(cg.weights>.5) u = cg.cc() u[p<g0] = u.max()+1+np.arange(np.sum(p<g0)) if verbose: cg.show(gfc) # append some information to the hroi in each subject for s in range(n_subj): bfs = bf[s] if bfs!=None: leaves = bfs.isleaf() us = -np.ones(bfs.k).astype(np.int) lq = np.zeros(bfs.k) lq[leaves] = q[sub==s] bfs.set_roi_feature('posterior_proba', lq) lq = np.zeros(bfs.k) lq[leaves] = 1-gf0[sub==s] bfs.set_roi_feature('prior_proba', lq) us[leaves] = u[sub==s] # when parent regions has similarly labelled children, # include it also us = bfs.make_forest().propagate_upward(us) bfs.set_roi_feature('label', us) # derive the group-level landmarks # with a threshold on the number of subjects # that are represented in each one LR, nl = sbf.build_LR(bf, thq, ths, dmax, verbose=verbose) # make a group-level map of the landmark position crmap = -np.ones(dom.size) # not implemented at the moment return crmap, LR, bf, CoClust
def compute_BSA_dev (Fbeta, lbeta, coord, dmax, xyz, affine=np.eye(4), shape=None, thq=0.9,smin=5, ths=0, theta=3.0, g0=1.0, bdensity=0, verbose=0): """ Compute the Bayesian Structural Activation paterns Parameters ---------- Fbeta : nipy.neurospin.graph.field.Field instance an describing the spatial relationships in the dataset. nbnodes = Fbeta.V lbeta: an array of shape (nbnodes, subjects): the multi-subject statistical maps coord array of shape (nnodes,3): spatial coordinates of the nodes xyz array of shape (nnodes,3): the grid coordinates of the field affine=np.eye(4), array of shape(4,4) coordinate-defining affine transformation shape=None, tuple of length 3 defining the size of the grid implicit to the discrete ROI definition thq = 0.5 (float): posterior significance threshold should be in [0,1] smin = 5 (int): minimal size of the regions to validate them theta = 3.0 (float): first level threshold g0 = 1.0 (float): constant values of the uniform density over the (compact) volume of interest bdensity=0 if bdensity=1, the variable p in ouput contains the likelihood of the data under H1 on the set of input nodes verbose=0 : verbosity mode Results ------- crmap: array of shape (nnodes): the resulting group-level labelling of the space LR: a instance of sbf.Landmrak_regions that describes the ROIs found in inter-subject inference If no such thing can be defined LR is set to None bf: List of nipy.neurospin.spatial_models.hroi.Nroi instances representing individual ROIs p: array of shape (nnodes): likelihood of the data under H1 over some sampling grid Note ---- This version is probably the best one to date the intra subject Gamma-Gaussian MM has been replaces by a Gaussian MM which is probably mroe robust """ bf = [] gfc = [] gf0 = [] sub = [] gc = [] nsubj = lbeta.shape[1] nvox = lbeta.shape[0] # intra-subject analysis: get the blobs, # with their position and their significance for s in range(nsubj): # description in terms of blobs beta = np.reshape(lbeta[:,s],(nvox,1)) Fbeta.set_field(beta) nroi = hroi.NROI_from_field(Fbeta, affine, shape, xyz, refdim=0, th=theta,smin=smin) bf.append(nroi) if nroi!=None: sub.append(s*np.ones(nroi.k)) nroi.set_discrete_feature_from_index('activation',beta) bfm = nroi.discrete_to_roi_features('activation','average') # compute the region position nroi.set_discrete_feature_from_index('position',coord) bfc = nroi.discrete_to_roi_features('position', 'cumulated_average') gfc.append(bfc) # compute the prior proba of being null beta = np.squeeze(beta) beta = beta[beta!=0] alpha = 0.01 prior_strength = 100 fixed_scale = True bfp = en.three_classes_GMM_fit(beta, bfm, alpha, prior_strength,verbose,fixed_scale) bf0 = bfp[:,1] gf0.append(bf0) crmap = -np.ones(nvox, np.int) u = [] AF = [] p = np.zeros(nvox) if len(sub)<1: return crmap,AF,bf,u,p # inter-subject analysis # use the DPMM (core part) sub = np.concatenate(sub).astype(np.int) gfc = np.concatenate(gfc) gf0 = np.concatenate(gf0) p = np.zeros(np.size(nvox)) g1 = g0 dof = 0 prior_precision = 1./(dmax*dmax)*np.ones((1,3), np.int) if bdensity: spatial_coords = coord else: spatial_coords = gfc p,q = fc.fdp(gfc, 0.5, g0, g1, dof,prior_precision, 1-gf0, sub, 100, spatial_coords,10,1000) valid = q>thq if verbose: import matplotlib.pylab as mp mp.figure() mp.plot(1-gf0,q,'.') print np.sum(valid),np.size(valid) # remove non-significant regions for s in range(nsubj): bfs = bf[s] if bfs!=None: valids = valid[sub==s] valids = bfs.propagate_upward_and(valids) bfs.clean(valids) bfs.merge_descending() # re-compute the region position bfs.set_discrete_feature_from_index('position',coord) bfc = bfs.discrete_to_roi_features('position', 'cumulated_average') # Alan's choice #beta = np.reshape(lbeta[:,s],(nvox,1)) #bfsc = coord[bfs.feature_argmax(beta)] #bfs.set_roi_feature(bfsc,'position') # compute a model of between-regions associations gc = _hierarchical_asso(bf,np.sqrt(2)*dmax) # Infer the group-level clusters if gc == []: return crmap,AF,bf,p # either replicator dynamics or agglomerative clustering #u = sbf.segment_graph_rd(gc,1) u,cost = average_link_graph_segment(gc,0.1,gc.V*1.0/nsubj) q = 0 for s in range(nsubj): if bf[s]!=None: bf[s].set_roi_feature('label',u[q:q+bf[s].k]) q += bf[s].k LR,mlabel = sbf.build_LR(bf,ths) if LR!=None: crmap = LR.map_label(coord,pval = 0.95,dmax=dmax) return crmap,LR,bf,p
def bsa_dpmm(bf, gf0, sub, gfc, dmax, thq, ths, verbose=0): """ Estimation of the population level model of activation density using dpmm and inference Parameters ---------- bf list of nipy.neurospin.spatial_models.hroi.HierarchicalROI instances representing individual ROIs let nr be the number of terminal regions across subjects gf0, array of shape (nr) the mixture-based prior probability that the terminal regions are true positives sub, array of shape (nr) the subject index associated with the terminal regions gfc, array of shape (nr, coord.shape[1]) the coordinates of the of the terminal regions dmax float>0: expected cluster std in the common space in units of coord thq = 0.5 (float in the [0,1] interval) p-value of the prevalence test ths=0, float in the rannge [0,nsubj] null hypothesis on region prevalence that is rejected during inference verbose=0, verbosity mode Returns ------- crmap: array of shape (nnodes): the resulting group-level labelling of the space LR: a instance of sbf.LandmarkRegions that describes the ROIs found in inter-subject inference If no such thing can be defined LR is set to None bf: List of nipy.neurospin.spatial_models.hroi.Nroi instances representing individual ROIs p: array of shape (nnodes): likelihood of the data under H1 over some sampling grid """ dom = bf[0].domain n_subj = len(bf) crmap = -np.ones(dom.size, np.int) LR = None p = np.zeros(dom.size) if len(sub)<1: return crmap, LR, bf, p sub = np.concatenate(sub).astype(np.int) gfc = np.concatenate(gfc) gf0 = np.concatenate(gf0) g0 = 1./dom.local_volume.sum() # prepare the DPMM dim = dom.em_dim g1 = g0 prior_precision = 1./(dmax*dmax)*np.ones((1,dim)) dof = 10 burnin = 100 nis = 1000 # nis = number of iterations to estimate p #nii = 100 ## nii = number of iterations to estimate q #p,q = fc.fdp(gfc, 0.5, g0, g1, dof, prior_precision, 1-gf0, # sub, burnin, coord, nis, nii) p, q = dpmm(gfc, 0.5, g0, g1, dof, prior_precision, 1-gf0, sub, burnin, dom.coord, nis) if verbose: import matplotlib.pylab as mp mp.figure() mp.plot(1-gf0,q,'.') h1,c1 = mp.histogram((1-gf0),bins=100) h2,c2 = mp.histogram(q,bins=100) mp.figure() mp.bar(c1[:len(h1)],h1,width=0.005) mp.bar(c2[:len(h2)]+0.003,h2,width=0.005,color='r') print 'Number of candidate regions %i, regions found %i' % ( np.size(q), q.sum()) from nipy.neurospin.graph.field import field_from_coo_matrix_and_data Fbeta = field_from_coo_matrix_and_data(dom.topology, p) _, _, _, label = Fbeta.custom_watershed(0, g0) # append some information to the hroi in each subject for s in range(n_subj): bfs = bf[s] if bfs.k>0 : leaves = bfs.isleaf() us = -np.ones(bfs.k).astype(np.int) # set posterior proba lq = np.zeros(bfs.k) lq[leaves] = q[sub==s] bfs.set_roi_feature('posterior_proba', lq) # set prior proba lq = np.zeros(bfs.k) lq[leaves] = 1-gf0[sub==s] bfs.set_roi_feature('prior_proba', lq) pos = bfs.representative_feature('position', 'mean') midx = [np.argmin(np.sum((dom.coord-pos[k])**2,1)) for k in range(bfs.k)] j = label[np.array(midx)] us[leaves] = j[leaves] # when parent regions has similarly labelled children, # include it also us = bfs.make_forest().propagate_upward(us) bfs.set_roi_feature('label',us) # derive the group-level landmarks # with a threshold on the number of subjects # that are represented in each one LR, nl = sbf.build_LR(bf, thq, ths, dmax, verbose=verbose) # make a group-level map of the landmark position crmap = _relabel_(label, nl) return crmap, LR, bf, p
def compute_BSA_ipmi(Fbeta,lbeta, coord,dmax, xyz, affine=np.eye(4), shape=None, thq=0.5, smin=5, ths=0, theta=3.0, g0=1.0, bdensity=0, verbose=0): """ Compute the Bayesian Structural Activation patterns with approach described in IPMI'07 paper Parameters ---------- Fbeta : nipy.neurospin.graph.field.Field instance an describing the spatial relationships in the dataset. nbnodes = Fbeta.V lbeta: an array of shape (nbnodes, subjects): the multi-subject statistical maps coord array of shape (nnodes,3): spatial coordinates of the nodes xyz array of shape (nnodes,3): the grid coordinates of the field affine=np.eye(4), array of shape(4,4) coordinate-defining affine transformation shape=None, tuple of length 3 defining the size of the grid implicit to the discrete ROI definition thq = 0.5 (float): posterior significance threshold should be in [0,1] smin = 5 (int): minimal size of the regions to validate them theta = 3.0 (float): first level threshold g0 = 1.0 (float): constant values of the uniform density over the (compact) volume of interest bdensity=0 if bdensity=1, the variable p in ouput contains the likelihood of the data under H1 on the set of input nodes verbose=0 : verbosity mode Results ------- crmap: array of shape (nnodes): the resulting group-level labelling of the space LR: a instance of sbf.Landmrak_regions that describes the ROIs found in inter-subject inference If no such thing can be defined LR is set to None bf: List of nipy.neurospin.spatial_models.hroi.Nroi instances representing individual ROIs p: array of shape (nnodes): likelihood of the data under H1 over some sampling grid Note ---- This is historically the first version, but probably not the most optimal It should not be changed for historical reason """ bf = [] gfc = [] gf0 = [] sub = [] gc = [] nbsubj = lbeta.shape[1] nvox = lbeta.shape[0] # intra-subject part: compute the blobs # and assess their significance for s in range(nbsubj): beta = np.reshape(lbeta[:,s],(nvox,1)) Fbeta.set_field(beta) nroi = hroi.NROI_from_field(Fbeta, affine, shape, xyz, refdim=0, th=theta, smin=smin) bf.append(nroi) if nroi!=None: sub.append(s*np.ones(nroi.k)) # find some way to avoid coordinate averaging nroi.set_discrete_feature_from_index('activation',beta) bfm = nroi.discrete_to_roi_features('activation','average') nroi.set_discrete_feature_from_index('position',coord) bfc = nroi.discrete_to_roi_features('position', 'cumulated_average') gfc.append(bfc) # get some prior on the significance of the regions beta = np.reshape(beta,(nvox)) beta = beta[beta!=0] # use a Gamma-Gaussian Mixture Model bfp = en.Gamma_Gaussian_fit(beta,bfm,verbose) bf0 = bfp[:,1] gf0.append(bf0) crmap = -np.ones(nvox, np.int) u = [] AF = [] p = np.zeros(nvox) if len(sub)<1: return crmap,AF,bf,u,p # inter-subject analysis # use the DPMM (core part) sub = np.concatenate(sub).astype(np.int) gfc = np.concatenate(gfc) gf0 = np.concatenate(gf0) p = np.zeros(np.size(nvox)) g1 = g0 dof = 0 prior_precision = 1./(dmax*dmax)*np.ones((1,3), np.float) if bdensity: spatial_coords = coord else: spatial_coords = gfc p,q = fc.fdp(gfc, 0.5, g0, g1,dof, prior_precision, 1-gf0, sub, 100, spatial_coords,10,1000) # inference valid = q>thq if verbose>1: import matplotlib.pylab as mp mp.figure() mp.plot(1-gf0,q,'.') print np.sum(valid),np.size(valid) # remove non-significant regions for s in range(nbsubj): bfs = bf[s] if bfs!=None: valids = valid[sub==s] valids = bfs.propagate_upward_and(valids) bfs.clean(valids) if bfs!=None: bfs.merge_descending() bfs.set_discrete_feature_from_index('position',coord) bfs.discrete_to_roi_features('position','cumulated_average') # compute probabilitsic correspondences across subjects gc = _hierarchical_asso(bf,np.sqrt(2)*dmax) if gc == []: return crmap,AF,bf,p # make hard clusters # choose one solution... #u = sbf.segment_graph_rd(gc,1) u,cost = average_link_graph_segment(gc,0.2,gc.V*1.0/nbsubj) q = 0 for s in range(nbsubj): if bf[s]!=None: bf[s].set_roi_feature('label',u[q:q+bf[s].k]) q += bf[s].k LR,mlabel = sbf.build_LR(bf,ths) if LR!=None: crmap = LR.map_label(coord,pval=0.95,dmax=dmax) return crmap,LR,bf,p