Ejemplo n.º 1
0
def load_surf_bold_mask(bold_files, mesh_file, mask_file=None):
    from pyhrf.tools._io import read_mesh, read_texture, discard_bad_data

    logger.info('Load mesh: ' + mesh_file)
    coords, triangles, coord_sys = read_mesh(mesh_file)
    logger.debug('Build graph...')
    fgraph = graph_from_mesh(triangles)
    assert graph_is_sane(fgraph)

    logger.info('Mesh has %d nodes', len(fgraph))

    logger.debug('Compute length of edges ... ')
    edges_l = np.array([np.array([distance(coords[i],
                                           coords[n],
                                           coord_sys.xform)
                                  for n in nl])
                        for i, nl in enumerate(fgraph)], dtype=object)

    if mask_file is None or not op.exists(mask_file):
        logger.warning('Mask file %s does not exist. Taking '
                       'all nodes ...', mask_file)
        mask = np.ones(len(fgraph))
        mask_meta_obj = None
        mask_loaded_from_file = False
    else:
        mask, mask_meta_obj = read_texture(mask_file)
        mask_loaded_from_file = True

    if not (np.round(mask) == mask).all():
        raise Exception("Mask is not n-ary")

    if len(mask) != len(fgraph):
        raise Exception('Size of mask (%d) is different from size '
                        'of graph (%d)' % (len(mask), len(fgraph)))

    mask = mask.astype(np.int32)
    if mask.min() == -1:
        mask += 1

    # Split graph into rois:
    graphs = {}
    edge_lengths = {}
    for roi_id in np.unique(mask):
        mroi = np.where(mask == roi_id)
        graph, _ = sub_graph(fgraph, mroi[0])
        edge_lengths[roi_id] = edges_l[mroi]
        graphs[roi_id] = graph

    # Load BOLD:
    last_scan = 0
    session_scans = []
    bolds = []
    for bold_file in bold_files:
        logger.info('load bold: %s', bold_file)
        bold, _ = read_texture(bold_file)
        logger.info('bold shape: %s', str(bold.shape))
        bolds.append(bold)
        session_scans.append(np.arange(last_scan, last_scan + bold.shape[0],
                                       dtype=int))
        last_scan += bold.shape[0]

    bold = np.concatenate(tuple(bolds))
    if len(fgraph) != bold.shape[1]:
        raise Exception('Nb positions not consistent between BOLD (%d) '
                        'and mesh (%d)' % (bold.shape[1], len(fgraph)))

    # discard bad data (bold with var=0 and nan values):
    discard_bad_data(bold, mask, time_axis=0)

    return mask, mask_meta_obj, mask_loaded_from_file, bold, session_scans, \
        graphs, edge_lengths
Ejemplo n.º 2
0
def load_fmri_surf_data(boldFiles, meshFile, roiMaskFile=None):
    """ Load FMRI BOLD surface data from files.

    Arguments:
    boldFiles --  pathes to 2D texture data files (ie multisession data).
    roiMaskFile -- a path to a 1D texture data file.
    meshFile -- a path to a mesh file

    Return:
    A tuple (graphs, bolds, sessionScans, roiMask, dataHeader)
    graphs -- a dict {roiId:roiGraph}. Each roiGraph is a list of neighbours list
    bold -- a dict {roiId:bold}. Each bold is a 2D numpy float array
            with axes [time,position]
    sessionScans -- a list of scan indexes for every session
    roiMask -- a 1D numpy int array defining ROIs (0 stands for the background)
    dataHeader -- the header from the BOLD data file
    """

    #Load ROIs:
    pyhrf.verbose(1, 'load roi mask: ' + roiMaskFile)
    #roiMask = Texture.read(roiMaskFile).data.astype(int)
    roiMask,_ = read_texture(roiMaskFile)
    pyhrf.verbose(1, 'roi mask shape: ' + str(roiMask.shape))

    #Load BOLD:
    lastScan = 0
    sessionScans = []
    bolds = []
    for boldFile in boldFiles:
        pyhrf.verbose(1, 'load bold: ' + boldFile)
        b,_ = read_texture(boldFile)
        pyhrf.verbose(1, 'bold shape: ' + str(b.shape))
        bolds.append(b)
        sessionScans.append(np.arange(lastScan, lastScan+b.shape[0], dtype=int))
        lastScan += b.shape[0]
    bold = np.concatenate(tuple(bolds))

    # discard bad data (bold with var=0 and nan values):
    discard_bad_data(bold, roiMask, time_axis=0)

    #Load mesh:
    pyhrf.verbose(1, 'load mesh: ' + meshFile)
    coords,triangles,coord_sys = read_mesh(meshFile)
    #from soma import aims
    # mesh = aims.read(meshFile)
    # triangles = [t.arraydata() for t in mesh.polygon().list()]

    pyhrf.verbose(3, 'building graph ... ')
    wholeGraph = graph_from_mesh(triangles)
    assert graph_is_sane(wholeGraph)
    pyhrf.verbose(1, 'Mesh has %d nodes' %len(wholeGraph))
    assert len(roiMask) == len(wholeGraph)

    assert bold.shape[1] == len(wholeGraph)

    pyhrf.verbose(3, 'Computing length of edges ... ')
    edges_l = np.array([np.array([distance(coords[i],coords[n],coord_sys.xform) \
                                      for n in nl]) \
                            for i,nl in enumerate(wholeGraph)], dtype=object)

    #Split bold and graph into rois:
    roiBold = {}
    graphs = {}
    edge_lengthes = {}
    for roiId in np.unique(roiMask):
        mroi = np.where(roiMask==roiId)
        g, nm = sub_graph(wholeGraph, mroi[0])
        edge_lengthes[roiId] = edges_l[mroi]
        graphs[roiId] = g
        roiBold[roiId] = bold[:, mroi[0]].astype(np.float32)

    return graphs, roiBold, sessionScans, roiMask, edge_lengthes
Ejemplo n.º 3
0
def parcellation_ward_spatial(func_data, n_clusters, graph=None):
    """
    Make parcellation based upon ward hierarchical clustering from scikit-learn
    Inputs: - func_data: functional data: array of shape
              (nb_positions, dim_feature_1, [dim_feature2, ...])
            - n_clusters: chosen number of clusters to create
            - graph: adjacency list defining neighbours
              (if None, no connectivity defined: clustering is spatially
            independent)
    Output: parcellation labels
    """
    from sklearn.cluster import Ward
    from pyhrf.graph import graph_to_sparse_matrix, sub_graph
    #from pyhrf.tools import cartesian
    # print 'graph:'
    # print graph
    if graph is not None:

        #print 'connectivity;'
        #print connectivity.todense()
        labels = np.zeros(len(graph), dtype=np.int32)

        ccs = connected_components(graph)
        n_tot = len(graph) * 1.

        ncs = np.zeros(len(ccs), dtype=np.int32)
        for icc,cc in enumerate(ccs):
            nc = int(np.round(n_clusters * len(cc)/n_tot))
            if nc == 0:
                nc = 1
            ncs[icc] = nc

        max_nc = np.argmax(ncs)
        ncs[max_nc] = n_clusters - sum(ncs[0:max_nc]) - sum(ncs[max_nc+1:])

        assert sum(ncs) == n_clusters
        assert (ncs > 0).all()

        pyhrf.verbose(1, 'Found %d connected components (CC) of sizes: %s' \
            %(len(ccs), ' ,'.join([str(len(cc)) for cc in ccs])))
        pyhrf.verbose(1, 'Nb of clusters to search in each CC: %s' \
                        %' ,'.join(map(str,ncs)))

        for nc,cc in zip(ncs,ccs):
            #print 'cc:', len(cc)
            #print 'cartesian:', list(cartesian(cc,cc))
            if len(cc) < 2:
                continue

            if len(cc) < len(graph):
                cc_graph,_ = sub_graph(graph, cc)
            else:
                cc_graph = graph

            cc_connectivity = graph_to_sparse_matrix(cc_graph)

                #print 'compute subslice ...'
#                sub_slice = tuple(np.array(list(cartesian(cc,cc))).T) #indexes of the subpart of the connectivity matrix
                #print 'sub_slice:'
                #print sub_slice
                #print 'subslice connectivity matrix ...'
                #cc_connectivity = connectivity.tolil()[sub_slice].reshape((len(cc),len(cc))).tocoo() #indexes applied to the matrix connectivity (coo unsubscriptable)
            #print 'cc_connectivity'
            #print cc_connectivity.todense()
            cc_data = func_data[cc]
            pyhrf.verbose(2, 'Launch spatial Ward (nclusters=%d) '\
                              ' on data of shape %s' %(nc, str(cc_data.shape)))
            ward_object = Ward(n_clusters=nc, connectivity=cc_connectivity).fit(cc_data)
            labels[cc] += ward_object.labels_ + 1 + labels.max()
    else:
        ward_object = Ward(n_clusters=n_clusters).fit(func_data) # connectivity=None
        labels = ward_object.labels_ + 1

    return labels
Ejemplo n.º 4
0
def parcellation_ward_spatial(func_data, n_clusters, graph=None):
    """
    Make parcellation based upon ward hierarchical clustering from scikit-learn
    Inputs: - func_data: functional data: array of shape
              (nb_positions, dim_feature_1, [dim_feature2, ...])
            - n_clusters: chosen number of clusters to create
            - graph: adjacency list defining neighbours
              (if None, no connectivity defined: clustering is spatially
            independent)
    Output: parcellation labels
    """
    try:
        # sklearn version < 0.17
        from sklearn.cluster import Ward as AgglomerativeClustering
    except ImportError:
        from sklearn.cluster import AgglomerativeClustering

    from pyhrf.graph import graph_to_sparse_matrix, sub_graph
    if graph is not None:
        labels = np.zeros(len(graph), dtype=np.int32)
        ccs = connected_components(graph)
        n_tot = len(graph) * 1.
        ncs = np.zeros(len(ccs), dtype=np.int32)
        for icc, cc in enumerate(ccs):
            nc = int(np.round(n_clusters * len(cc) / n_tot))
            if nc == 0:
                nc = 1
            ncs[icc] = nc

        max_nc = np.argmax(ncs)
        ncs[max_nc] = n_clusters - sum(ncs[0:max_nc]) - sum(ncs[max_nc + 1:])

        assert sum(ncs) == n_clusters
        assert (ncs > 0).all()

        logger.info('Found %d connected components (CC) of sizes: %s', len(ccs),
                    ' ,'.join([str(len(cc)) for cc in ccs]))
        logger.info('Nb of clusters to search in each CC: %s',
                    ' ,'.join(map(str, ncs)))

        for nc, cc in zip(ncs, ccs):
            if len(cc) < 2:
                continue

            if len(cc) < len(graph):
                cc_graph, _ = sub_graph(graph, cc)
            else:
                cc_graph = graph

            cc_connectivity = graph_to_sparse_matrix(cc_graph)

            cc_data = func_data[cc]
            logger.info('Launch spatial Ward (nclusters=%d)  on data of shape %s',
                        nc, str(cc_data.shape))
            ward_object = AgglomerativeClustering(
                n_clusters=nc, connectivity=cc_connectivity
            ).fit(cc_data)
            labels[cc] += ward_object.labels_ + 1 + labels.max()
    else:
        ward_object = AgglomerativeClustering(
            n_clusters=n_clusters
        ).fit(func_data)  # connectivity=None
        labels = ward_object.labels_ + 1

    return labels
Ejemplo n.º 5
0
    def test_single_surface_PFPS_ML(self):
        """PF estimation method : path sampling. ML on p(label|beta).
        topology from a surfacic RDI
        """
        # generate a field:
        beta = 0.4
        nbClasses = 2
        print 'generating potts ..., beta =', beta

        
        # grab surfacic data:
        from pyhrf.graph import graph_from_mesh, sub_graph, graph_is_sane
        from pyhrf.tools._io.tio import Texture
        from soma import aims
        print 'import done'
        roiId = 20
        mfn = pyhrf.get_data_file_name('right_hemisphere.mesh')
        print 'mesh file:', mfn
        mesh = aims.read(mfn)
        print 'mesh read'
        triangles = [t.arraydata() for t in mesh.polygon().list()]
        print 'building graph ... '
        wholeGraph = graph_from_mesh(triangles)
        
        roiMaskFile = pyhrf.get_data_file_name('roimask_gyrii_tuned.tex')
        roiMask = Texture.read(roiMaskFile).data.astype(int)
        mroi = np.where(roiMask==roiId)
        g, nm = sub_graph(wholeGraph, mroi[0])
        print "g:", len(g), len(g[0])

        nnodes = len(g)
        points = np.vstack([v.arraydata() for v in mesh.vertex().list()])
        weights = [[1./dist(points[j],points[k]) for k in g[j]]
                   for j in xrange(nnodes)]
        print "weights:", len(weights), len(weights[0])
        
        if 1:
            for j in xrange(nnodes):
                s = sum(weights[j]) * 1.
                for k in xrange(len(weights[j])):
                    weights[j][k] = weights[j][k]/s * len(weights[j])

        labels = genPotts(g, beta, nbClasses, weights=weights)
        print labels
        # partition function estimation
        gridLnz = Cpt_Vec_Estim_lnZ_Graph(g, nbClasses, 
                                          GraphWeight=weights)

        print 'gridLnz with weights:'
        print gridLnz

        # beta estimation
        be, pb = beta_estim_obs_field(g, labels, gridLnz, 'ML', weights)
        print 'betaML:', be

        weights = None
        gridLnz = Cpt_Vec_Estim_lnZ_Graph(g, nbClasses, 
                                          GraphWeight=weights)

        
        print 'gridLnz without weights:'
        print gridLnz

        # beta estimation
        be, pb = beta_estim_obs_field(g, labels, gridLnz, 'ML', weights)
        print 'betaML:', be

        gridPace = gridLnz[1][1] - gridLnz[1][0]
        assert abs(be-beta) <= gridPace
Ejemplo n.º 6
0
def load_surf_bold_mask(bold_files, mesh_file, mask_file=None):
    from pyhrf.tools._io import read_mesh, read_texture, discard_bad_data

    logger.info('Load mesh: ' + mesh_file)
    coords, triangles, coord_sys = read_mesh(mesh_file)
    logger.debug('Build graph...')
    fgraph = graph_from_mesh(triangles)
    assert graph_is_sane(fgraph)

    logger.info('Mesh has %d nodes', len(fgraph))

    logger.debug('Compute length of edges ... ')
    edges_l = np.array([
        np.array([distance(coords[i], coords[n], coord_sys.xform) for n in nl])
        for i, nl in enumerate(fgraph)
    ],
                       dtype=object)

    if mask_file is None or not op.exists(mask_file):
        logger.warning('Mask file %s does not exist. Taking '
                       'all nodes ...', mask_file)
        mask = np.ones(len(fgraph))
        mask_meta_obj = None
        mask_loaded_from_file = False
    else:
        mask, mask_meta_obj = read_texture(mask_file)
        mask_loaded_from_file = True

    if not (np.round(mask) == mask).all():
        raise Exception("Mask is not n-ary")

    if len(mask) != len(fgraph):
        raise Exception('Size of mask (%d) is different from size '
                        'of graph (%d)' % (len(mask), len(fgraph)))

    mask = mask.astype(np.int32)
    if mask.min() == -1:
        mask += 1

    # Split graph into rois:
    graphs = {}
    edge_lengths = {}
    for roi_id in np.unique(mask):
        mroi = np.where(mask == roi_id)
        graph, _ = sub_graph(fgraph, mroi[0])
        edge_lengths[roi_id] = edges_l[mroi]
        graphs[roi_id] = graph

    # Load BOLD:
    last_scan = 0
    session_scans = []
    bolds = []
    for bold_file in bold_files:
        logger.info('load bold: %s', bold_file)
        bold, _ = read_texture(bold_file)
        logger.info('bold shape: %s', str(bold.shape))
        bolds.append(bold)
        session_scans.append(
            np.arange(last_scan, last_scan + bold.shape[0], dtype=int))
        last_scan += bold.shape[0]

    bold = np.concatenate(tuple(bolds))
    if len(fgraph) != bold.shape[1]:
        raise Exception('Nb positions not consistent between BOLD (%d) '
                        'and mesh (%d)' % (bold.shape[1], len(fgraph)))

    # discard bad data (bold with var=0 and nan values):
    discard_bad_data(bold, mask, time_axis=0)

    return mask, mask_meta_obj, mask_loaded_from_file, bold, session_scans, \
        graphs, edge_lengths
Ejemplo n.º 7
0
def parcellation_ward_spatial(func_data, n_clusters, graph=None):
    """
    Make parcellation based upon ward hierarchical clustering from scikit-learn
    Inputs: - func_data: functional data: array of shape
              (nb_positions, dim_feature_1, [dim_feature2, ...])
            - n_clusters: chosen number of clusters to create
            - graph: adjacency list defining neighbours
              (if None, no connectivity defined: clustering is spatially
            independent)
    Output: parcellation labels
    """
    try:
        # sklearn version < 0.17
        from sklearn.cluster import Ward as AgglomerativeClustering
    except ImportError:
        from sklearn.cluster import AgglomerativeClustering

    from pyhrf.graph import graph_to_sparse_matrix, sub_graph
    if graph is not None:
        labels = np.zeros(len(graph), dtype=np.int32)
        ccs = connected_components(graph)
        n_tot = len(graph) * 1.
        ncs = np.zeros(len(ccs), dtype=np.int32)
        for icc, cc in enumerate(ccs):
            nc = int(np.round(n_clusters * len(cc) / n_tot))
            if nc == 0:
                nc = 1
            ncs[icc] = nc

        max_nc = np.argmax(ncs)
        ncs[max_nc] = n_clusters - sum(ncs[0:max_nc]) - sum(ncs[max_nc + 1:])

        assert sum(ncs) == n_clusters
        assert (ncs > 0).all()

        logger.info('Found %d connected components (CC) of sizes: %s',
                    len(ccs), ' ,'.join([str(len(cc)) for cc in ccs]))
        logger.info('Nb of clusters to search in each CC: %s',
                    ' ,'.join(map(str, ncs)))

        for nc, cc in zip(ncs, ccs):
            if len(cc) < 2:
                continue

            if len(cc) < len(graph):
                cc_graph, _ = sub_graph(graph, cc)
            else:
                cc_graph = graph

            cc_connectivity = graph_to_sparse_matrix(cc_graph)

            cc_data = func_data[cc]
            logger.info(
                'Launch spatial Ward (nclusters=%d)  on data of shape %s', nc,
                str(cc_data.shape))
            ward_object = AgglomerativeClustering(
                n_clusters=nc, connectivity=cc_connectivity).fit(cc_data)
            labels[cc] += ward_object.labels_ + 1 + labels.max()
    else:
        ward_object = AgglomerativeClustering(n_clusters=n_clusters).fit(
            func_data)  # connectivity=None
        labels = ward_object.labels_ + 1

    return labels