Beispiel #1
0
def plot_retino_image(mesh_path, name, tf=None, tex=None, curv=None, mask=None,
                     vmin=0, vmax=0):
    """Custom function to plot mesh in the case of retinotopic mapping  

    Parameters
    ----------
    mesh_path: string, path of the mesh to plot
    name: string, object identifier
    tf: (4, 4)  array
        affine transformation that has to be applied to the mesh
    tex: array of shape (mes.n_vertices),
         texture to plot on the surface
    curv: array of shape (mes.n_vertices),
          curvature texture to plot on the surface
    mask: array of shape (mes.n_vertices),
          A mask for functional regions of interest
    vmin, vmax: bounds for color clipping
    """
    vertices, triangles =  mesh_arrays(mesh_path)
    af_coord = np.hstack((vertices, np.ones((vertices.shape[0], 1))))
    if tf is not None:
        af_coord = np.dot(af_coord, tf.T)
    
    vertices = af_coord[:, :3]
    x, y, z = vertices.T

    # it is expected that the curvature takes values between 0 and 1
    if curv is not None:
        cmin = 2 * curv.min() - curv.max()
        cmax = 2 * curv.max() - curv.min()
        mlab.triangular_mesh(x, y, z, triangles, transparent=False, opacity=1.,
                             name=name, scalars=curv, colormap="bone",
                             vmin=cmin, vmax=cmax)
    else:
        mlab.triangular_mesh(x, y, z, triangles, transparent=False, opacity=1.,
                             name=name)
    if tex is not None:
        if mask is not None:
            tex[mask == 0] = vmin - 1

        func_mesh = mlab.pipeline.triangular_mesh_source(x, y, z,
                                                  triangles,
                                                  scalars=tex)
        thresh = mlab.pipeline.threshold(func_mesh, low=vmin)
        mlab.pipeline.surface(thresh, colormap="jet", vmin=vmin,
                              vmax=vmax, transparent=True,
                              opacity=.8)
        mlab.scalarbar(thresh)
Beispiel #2
0
def plot_mesh(mesh, name, tf=None, tex=None):
    """ old version -- probably deprecated
    """
    vertices, triangles =  mesh_arrays(mesh)
    af_coord = np.hstack((vertices, np.ones((vertices.shape[0], 1))))
    if tf is not None:
        af_coord = np.dot(af_coord, tf.T)
    
    vertices = af_coord[:, :3]
    x, y, z = vertices.T
    # show with mayavi

    if tex is None:
        mlab.triangular_mesh(x, y, z, triangles, transparent=False, opacity=1.,
                             name=name, color=(0.5, 0.5, 0.))
    else:
        mlab.triangular_mesh(x, y, z, triangles, transparent=False, opacity=1.,
                             name=name, scalars=tex)
def find_fovea(mesh, side, mask, xy):
    """Small utility that returns the assumed fovea position on a mesh
    of a certain hemisphere"""
    from .group_analysis import resample_from_average
    REF_LEFT = np.arange(163842) == 71785
    REF_RIGHT = np.arange(163842) == 129181
    binary_texture = REF_LEFT if side == 'left' else REF_RIGHT
    binary_texture_path =  '/tmp/fovea.gii'
    save_texture(binary_texture_path, binary_texture, intent='none')
    subject_path = op.join(op.dirname(mesh), '..')

    # resample from the average to the individual space
    resampled = resample_from_average(binary_texture_path, subject_path,
                                      side, verbose=True)

    # get the vertices of the mesh
    vertices, _ = mep.mesh_arrays(mesh)
    point = vertices[load_texture(resampled).argmax()]
    sq_dist = ((vertices - point) ** 2). sum(1)

    # find the point on the mask
    fovea = xy[np.argmin(sq_dist[mask])]
    return fovea
def retino_template(xy, ring, wedge, mesh, mask_, verbose=False, side='left'):
    """"""
    if ring is None:
        center = find_fovea(mesh, side, mask_, xy)
    else:
        center = get_ring_minimum(xy, ring, 0) # - np.pi / 2)
    ecc = np.sqrt(np.sum((xy - center) ** 2, 1))
    angle = - np.arctan2(xy.T[1] - center[1], xy.T[0] - center[0])
    radius = np.sqrt(np.mean(ecc ** 2)) * 1.2

    def retino_polar(angle, ecc, radius, scale=1.):
        """"""
        a1, a2, a3 = scale * np.pi *.2, scale * np.pi *.3, scale * np.pi * .4
        delta = .2 * 4. / radius ** 2
        corr = angle * (radius ** 2 / 4 - (ecc - radius / 2) ** 2)
        angle_ = angle - delta * corr
        mask = (ecc < radius) * (np.abs(angle_) < a3)
        polar = np.zeros_like(angle_)
        slope = np.pi / (2 * a1)
        b1 = 2 * slope * a1
        polar = slope * angle_
        polar[angle_ > a1] = b1 - slope * angle_[angle_ >  a1]
        polar[angle_ > a2] = slope * angle_[angle_ > a2] - 2 * slope * (a2 - a1)
        
        polar[angle_ < - a1] = - b1 - slope * angle_[angle_ < - a1]
        polar[angle_ < - a2] = slope * (angle_[angle_ < - a2] + 2 * (a2 - a1))
        polar[mask == 0] = 0
        maps = {'V1v': mask * (angle_ < 0) * (angle_ > - a1),
                'V1d': mask * (angle_ > 0) * (angle_ < a1),
                'V2v': mask * (angle_ < -a1) * (angle_ > - a2),
                'V2d': mask * (angle_ > a1) * (angle_ < a2),
                'V3v': mask * (angle_ < - a2) * (angle_ > - a3),
                'V3d': mask * (angle_ > a2) * (angle_ < a3),
                }
        return mask, polar, maps

    vmin, vmax = 0., np.pi
    if side == 'left':
        vmin, vmax = -np.pi, 0.

    best_score = - np.inf
    # 2-dimensional search of the best rotation/scaling
    for scale in [1.]:
        for theta in np.linspace(0, 2 * np.pi, 100):
            angle_ = angle + theta
            angle_[angle_ > np.pi] -= 2 * np.pi
            mask, polar, maps = retino_polar(angle_, ecc, radius, scale)
            if mask.sum() == 0:
                continue
            if side == 'left':
                polar -= np.pi / 2
            else:
                polar += np.pi / 2
            weight = mask * (polar > vmin) * (polar < vmax)
            score =  1. - np.sum(
                weight[mask] * (wedge[mask] - polar[mask]) ** 2)/\
                np.sum(weight[mask] * (wedge[mask]) ** 2)
            score = np.corrcoef(wedge[mask], polar[mask])[0, 1]
            if score > best_score:
                best_score = score
                best_polar = polar
                best_theta = theta
                visual_maps = maps
                best_mask = mask
                best_corr = np.corrcoef(wedge[mask], polar[mask])[0, 1]

    if verbose:
        print best_theta, best_corr    
        import matplotlib.pyplot as plt
        plt.figure(figsize = (10, 5))
        coord, tri = mep.mesh_arrays(mesh)
        coord, tri = coord[mask_], tri[mask_[tri].all(1)]
        tri = np.hstack((0, np.cumsum(mask_)[:-1]))[tri]
        plt.subplot(1, 3, 1)
        plt.tripcolor(xy.T[0], xy.T[1], tri, best_polar * best_mask, 
                      vmin=vmin, vmax=vmax)
        plt.plot(center[0], center[1], '+k', linewidth=4)
        plt.subplot(1, 3, 2)
        plt.tripcolor(xy.T[0], xy.T[1], tri, wedge, vmin=vmin, vmax=vmax)
        plt.plot(center[0], center[1], '+k', linewidth=4)
        plt.subplot(1, 3, 3)
        if ring is not None:
            plt.tripcolor(xy.T[0], xy.T[1], tri, ring)
        plt.plot(center[0], center[1], '+k', linewidth=4)
    
    return mask, polar, visual_maps