Beispiel #1
0
    def __call__(self, data):
        '''
        Parameters
        ----------
        data: np.ndarray
            Surface data to be plotted. Should have the same number of data
            points as the surface
        
        Returns
        -------
        rgba: np.ndarray
            Bitmap with RGBA values that can be plotted.
        '''
        self._pre_setup()
        x, y, msk, xi, yi = self._grid_def
        olay = griddata(x, y, data, xi, yi)
        olay[-msk] = np.nan

        o_rgba = flat_surface_data2rgba(olay, self._range_, self._threshold,
                                        self._color_map)
        o_rgba[-msk] = np.nan  # apply the mask again, to be sure

        if not self._underlay is None:
            o_msk = -np.isnan(np.sum(o_rgba, 2))

            u_rgba = self._underlay
            u_msk = np.logical_and(-o_msk, msk)

            o_rgba[u_msk] = u_rgba[u_msk]

        return o_rgba
Beispiel #2
0
    def __call__(self, data):
        '''
        Parameters
        ----------
        data: np.ndarray
            Surface data to be plotted. Should have the same number of data
            points as the surface
        
        Returns
        -------
        rgba: np.ndarray
            Bitmap with RGBA values that can be plotted.
        '''
        self._pre_setup()
        x, y, msk, xi, yi = self._grid_def
        olay = griddata(x, y, data, xi, yi)
        olay[-msk] = np.nan

        o_rgba = flat_surface_data2rgba(olay, self._range_ , self._threshold,
                                                self._color_map)
        o_rgba[-msk] = np.nan # apply the mask again, to be sure

        if self._underlay is not None:
            o_msk = -np.isnan(np.sum(o_rgba, 2))

            u_rgba = self._underlay
            u_msk = np.logical_and(-o_msk, msk)

            o_rgba[u_msk] = u_rgba[u_msk]

        return o_rgba
Beispiel #3
0
    def _set_underlay_from_curvature(self):
        if self._curvature is None:
            raise ValueError("Curvature is not set")

        if self._grid_def is None:
            self._set_grid_def()

        x, y, msk, xi, yi = self._grid_def

        ulay = griddata(x, y, self._curvature, xi, yi, interp='linear')
        ulay[-msk] = np.nan

        rgba = flat_surface_curvature2rgba(ulay)
        self.set_underlay(rgba)
Beispiel #4
0
    def _set_underlay_from_curvature(self):
        if self._curvature is None:
            raise ValueError("Curvature is not set")

        if self._grid_def is None:
            self._set_grid_def()

        x, y, msk, xi, yi = self._grid_def

        ulay = griddata(x, y, self._curvature, xi, yi, interp='linear')
        ulay[-msk] = np.nan

        rgba = flat_surface_curvature2rgba(ulay)
        self.set_underlay(rgba)
Beispiel #5
0
    def __call__(self, data):
        '''
        Parameters
        ----------
        data: np.ndarray
            Surface data to be plotted. Should have the same number of data
            points as the surface
        
        Returns
        -------
        rgba: np.ndarray
            Bitmap with RGBA values that can be plotted.
        '''
        self._pre_setup()

        expected_shape = (self._surface.nvertices,)
        if data.shape != expected_shape:
            raise ValueError('data shape was expected to be %s based on '
                             'the number of nodes of the surface, '
                             'found %s' % (
                                 expected_shape, data.shape))

        x, y, msk, xi, yi = self._grid_def
        olay = griddata(x, y, data, xi, yi, interp='linear')
        nan_msk = np.logical_not(msk)
        olay[nan_msk] = np.nan
        o_rgba = flat_surface_data2rgba(olay, self._range_, self._threshold,
                                        self._color_map)
        o_rgba[nan_msk] = np.nan  # apply the mask again, to be sure

        if self._underlay is not None:
            o_msk = -np.isnan(np.sum(o_rgba, 2))

            u_rgba = self._underlay
            u_msk = np.logical_and(np.logical_not(o_msk), msk)

            o_rgba[u_msk] = u_rgba[u_msk]

        return o_rgba
Beispiel #6
0
    def __call__(self, data):
        '''
        Parameters
        ----------
        data: np.ndarray
            Surface data to be plotted. Should have the same number of data
            points as the surface
        
        Returns
        -------
        rgba: np.ndarray
            Bitmap with RGBA values that can be plotted.
        '''
        self._pre_setup()

        expected_shape = (self._surface.nvertices, )
        if data.shape != expected_shape:
            raise ValueError('data shape was expected to be %s based on '
                             'the number of nodes of the surface, '
                             'found %s' % (expected_shape, data.shape))

        x, y, msk, xi, yi = self._grid_def
        olay = griddata(x, y, data, xi, yi, interp='linear')
        nan_msk = np.logical_not(msk)
        olay[nan_msk] = np.nan
        o_rgba = flat_surface_data2rgba(olay, self._range_, self._threshold,
                                        self._color_map)
        o_rgba[nan_msk] = np.nan  # apply the mask again, to be sure

        if self._underlay is not None:
            o_msk = -np.isnan(np.sum(o_rgba, 2))

            u_rgba = self._underlay
            u_msk = np.logical_and(np.logical_not(o_msk), msk)

            o_rgba[u_msk] = u_rgba[u_msk]

        return o_rgba
Beispiel #7
0
def plot_head_topography(topography,
                         sensorlocations,
                         plotsensors=False,
                         resolution=51,
                         masked=True,
                         plothead=True,
                         plothead_kwargs=None,
                         **kwargs):
    """Plot distribution to a head surface, derived from some sensor locations.

    The sensor locations are first projected onto the best fitting sphere and
    finally projected onto a circle (by simply ignoring the z-axis).

    Parameters
    ----------
    topography : array
      A vector of some values corresponding to each sensor.
    sensorlocations : (nsensors x 3) array
      3D coordinates of each sensor. The order of the sensors has to match
      with the `topography` vector.
    plotsensors : bool
      If True, sensor will be plotted on their projected coordinates.
      No sensor are shown otherwise.
    plothead : bool
      If True, a head outline is plotted.
    plothead_kwargs : dict
      Additional keyword arguments passed to `plot_head_outline()`.
    resolution : int
      Number of surface samples along both x and y-axis.
    masked : bool
      If True, all surface sample extending to head outline will be
      masked.
    **kwargs
      All additional arguments will be passed to `pylab.imshow()`.

    Returns
    -------
    (map, head, sensors)
      The corresponding matplotlib objects are returned if plotted, ie.
      if plothead is set to `False`, `head` will be `None`.

          map
            The colormap that makes the actual plot, a
            matplotlib.image.AxesImage instance.
          head
            What is returned by `plot_head_outline()`.
          sensors
            The dots marking the electrodes, a matplotlib.lines.Line2d
            instance.
    """
    # give sane defaults
    if plothead_kwargs is None:
        plothead_kwargs = {}

    # error function to fit the sensor locations to a sphere
    def err(params):
        r, cx, cy, cz = params
        return (sensorlocations[:, 0] - cx) ** 2 \
               + (sensorlocations[:, 1] - cy) ** 2 \
               + (sensorlocations[:, 2] - cz) ** 2 \
               - r ** 2

    # initial guess of sphere parameters (radius and center)
    params = (1, 0, 0, 0)

    # do fit
    (r, cx, cy, cz), stuff = leastsq(err, params)

    # size of each square
    ssh = float(r) / resolution  # half-size
    ss = ssh * 2.0  # full-size

    # Generate a grid and interpolate using the griddata module
    x = np.arange(cx - r, cx + r, ss) + ssh
    y = np.arange(cy - r, cy + r, ss) + ssh
    x, y = pl.meshgrid(x, y)

    # project the sensor locations onto the sphere
    sphere_center = np.array((cx, cy, cz))
    sproj = sensorlocations - sphere_center
    sproj = r * sproj / np.c_[np.sqrt(np.sum(sproj**2, axis=1))]
    sproj += sphere_center

    # fit topology onto xy projection of sphere
    topo = griddata(sproj[:, 0],
                    sproj[:, 1],
                    np.ravel(np.array(topography)),
                    x,
                    y,
                    interp='nn' if externals.versions['matplotlib'] < '1.4.0'
                    else 'linear')

    # mask values outside the head
    if masked:
        notinhead = np.greater_equal((x - cx)**2 + (y - cy)**2, (1.0 * r)**2)
        topo = ma.masked_where(notinhead, topo)

    # show surface
    map = pl.imshow(topo, origin="lower", extent=(-r, r, -r, r), **kwargs)
    pl.axis('off')

    if plothead:
        # plot scaled head outline
        head = plot_head_outline(scale=r,
                                 shift=(cx / 2.0, cy / 2.0),
                                 **plothead_kwargs)
    else:
        head = None

    if plotsensors:
        # plot projected sensor locations

        # reorder sensors so the ones below plotted first
        # TODO: please fix with more elegant solution
        zenum = [x[::-1] for x in enumerate(sproj[:, 2].tolist())]
        zenum.sort()
        indx = [x[1] for x in zenum]
        sensors = pl.plot(sproj[indx, 0] - cx / 2.0, sproj[indx, 1] - cy / 2.0,
                          'wo')
    else:
        sensors = None

    return map, head, sensors
Beispiel #8
0
def plot_head_topography(topography, sensorlocations, plotsensors=False,
                       resolution=51, masked=True, plothead=True,
                       plothead_kwargs=None, **kwargs):
    """Plot distribution to a head surface, derived from some sensor locations.

    The sensor locations are first projected onto the best fitting sphere and
    finally projected onto a circle (by simply ignoring the z-axis).

    Parameters
    ----------
    topography : array
      A vector of some values corresponding to each sensor.
    sensorlocations : (nsensors x 3) array
      3D coordinates of each sensor. The order of the sensors has to match
      with the `topography` vector.
    plotsensors : bool
      If True, sensor will be plotted on their projected coordinates.
      No sensor are shown otherwise.
    plothead : bool
      If True, a head outline is plotted.
    plothead_kwargs : dict
      Additional keyword arguments passed to `plot_head_outline()`.
    resolution : int
      Number of surface samples along both x and y-axis.
    masked : bool
      If True, all surface sample extending to head outline will be
      masked.
    **kwargs
      All additional arguments will be passed to `pylab.imshow()`.

    Returns
    -------
    (map, head, sensors)
      The corresponding matplotlib objects are returned if plotted, ie.
      if plothead is set to `False`, `head` will be `None`.

          map
            The colormap that makes the actual plot, a
            matplotlib.image.AxesImage instance.
          head
            What is returned by `plot_head_outline()`.
          sensors
            The dots marking the electrodes, a matplotlib.lines.Line2d
            instance.
    """
    # give sane defaults
    if plothead_kwargs is None:
        plothead_kwargs = {}

    # error function to fit the sensor locations to a sphere
    def err(params):
        r, cx, cy, cz = params
        return (sensorlocations[:, 0] - cx) ** 2 \
               + (sensorlocations[:, 1] - cy) ** 2 \
               + (sensorlocations[:, 2] - cz) ** 2 \
               - r ** 2

    # initial guess of sphere parameters (radius and center)
    params = (1, 0, 0, 0)

    # do fit
    (r, cx, cy, cz), stuff = leastsq(err, params)

    # size of each square
    ssh = float(r) / resolution         # half-size
    ss = ssh * 2.0                      # full-size

    # Generate a grid and interpolate using the griddata module
    x = np.arange(cx - r, cx + r, ss) + ssh
    y = np.arange(cy - r, cy + r, ss) + ssh
    x, y = pl.meshgrid(x, y)

    # project the sensor locations onto the sphere
    sphere_center = np.array((cx, cy, cz))
    sproj = sensorlocations - sphere_center
    sproj = r * sproj / np.c_[np.sqrt(np.sum(sproj ** 2, axis=1))]
    sproj += sphere_center

    # fit topology onto xy projection of sphere
    topo = griddata(sproj[:, 0], sproj[:, 1],
                    np.ravel(np.array(topography)), x, y,
                    interp='nn' if externals.versions['matplotlib'] < '1.4.0'
                           else 'linear')

    # mask values outside the head
    if masked:
        notinhead = np.greater_equal((x - cx) ** 2 + (y - cy) ** 2,
                                    (1.0 * r) ** 2)
        topo = ma.masked_where(notinhead, topo)

    # show surface
    map = pl.imshow(topo, origin="lower", extent=(-r, r, -r, r), **kwargs)
    pl.axis('off')

    if plothead:
        # plot scaled head outline
        head = plot_head_outline(scale=r, shift=(cx/2.0, cy/2.0), **plothead_kwargs)
    else:
        head = None

    if plotsensors:
        # plot projected sensor locations

        # reorder sensors so the ones below plotted first
        # TODO: please fix with more elegant solution
        zenum = [x[::-1] for x in enumerate(sproj[:, 2].tolist())]
        zenum.sort()
        indx = [ x[1] for x in zenum ]
        sensors = pl.plot(sproj[indx, 0] - cx/2.0, sproj[indx, 1] - cy/2.0, 'wo')
    else:
        sensors = None

    return map, head, sensors