Esempio n. 1
0
 def set_linestyle(self, v):
     if v is None or v == 'None':
         self._nodraw = True
     else:
         self._nodraw = False
         LineCollection.set_linestyle(self, v)
     self._cz_linesytle_name = v
Esempio n. 2
0
 def set_linestyle(self, v):
     if v is None or v == 'None':
        self._nodraw = True
     else:
        self._nodraw = False
        LineCollection.set_linestyle(self, v)
     self._cz_linesytle_name = v
Esempio n. 3
0
def plotcf(grid, phase, modulus, darken=None, axes=None, linestylep="solid", linewidthp=1, color="k", **kwargs):
    r"""Plot the modulus of a complex valued function
    :math:`f:\mathbb{R} \rightarrow \mathbb{C}`
    together with its phase in a color coded fashion.

    :param grid: The grid nodes of the real domain R
    :param phase: The phase of the complex domain result f(grid)
    :param modulus: The modulus of the complex domain result f(grid)
    :param darken: Whether to take into account the modulus of the data to darken colors.
    :param axes: The axes instance used for plotting.
    :param linestylep: The line style of the phase curve.
    :param linewidthp: The line width of the phase curve.
    :param color: The color of the phase curve.
    """
    # Color mapping
    rgb_colors = color_map(modulus, phase=phase, modulus=modulus, darken=darken)

    # Put all the vertical line into a collection
    segments = [array([[node, 0], [node, value]]) for node, value in zip(grid, modulus)]
    line_segments = LineCollection(segments)

    # Set some properties of the lines
    rgb_colors = line_segments.to_rgba(rgb_colors)
    line_segments.set_color(rgb_colors[0])
    line_segments.set_linestyle(linestylep)
    line_segments.set_linewidth(linewidthp)

    # Plot to the given axis instance or retrieve the current one
    if axes is None:
        axes = gca()

    # Plot the phase
    axes.add_collection(line_segments)
    # Plot the modulus
    axes.plot(grid, modulus, color=color, **kwargs)
Esempio n. 4
0
    def draw_shp_polygons(self, shp_filepath, linewidths=0.2, colors='k', antialiaseds=None, linestyles='solid'):
        """
        Draw a shapefile containing polygons
        """   
        # Read the shapefile as shapes and records. For each polygon in shapes, draw its boundaries
        r = shapefile.Reader(shp_filepath)
        shapes = r.shapes()
        records = r.records()

        for record, shape in zip(records, shapes):
            lons, lats = zip(*shape.points)
            data = [(x, y) for x, y in zip(*self(lons, lats))]
            
            # shape.parts is a list containing the starting index of each part of shape (e.g. a lake inside the shape) on xy_pts. If shape contains only 1 part, a list containing 0 is returned.
            if len(shape.parts) == 1: 
                segs = [data, ]
            else:
                segs = []
                for npart in range(1, len(shape.parts)):
                    ix1 = shape.parts[npart-1]
                    ix2 = shape.parts[npart]
                    segs.append(data[ix1:ix2])
                    
                segs.append(data[ix2: ])
            
            lines = LineCollection(segs, antialiaseds = [1, ])
            lines.set_edgecolors(colors)
            lines.set_linestyle(linestyles)
            lines.set_linewidth(linewidths)
            self.ax.add_collection(lines)
Esempio n. 5
0
    def loadlines(self,
                  name,
                  curdir='beijingJson',
                  zorder=None,
                  linewidth=0.5,
                  color='k',
                  antialiased=1,
                  ax=None,
                  default_encoding='utf-8',
                  linestyle='-',
                  linesalpha=1):
        # get current axes instance (if none specified).
        filename = curdir + '/' + name + '.json'
        coords = json.load(codecs.open(filename, 'r', 'utf-8'))
        coords = self.projectcoords(coords)

        ax = ax or self._check_ax()
        # make LineCollections for each polygon.
        lines = LineCollection(coords, antialiaseds=(1, ))
        lines.set_color(color)
        lines.set_linewidth(linewidth)
        lines.set_linestyle(linestyle)
        lines.set_alpha(linesalpha)
        lines.set_label('_nolabel_')
        if zorder is not None:
            lines.set_zorder(zorder)
        ax.add_collection(lines)
        # set axes limits to fit map region.
        self.set_axes_limits(ax=ax)
        # clip boundaries to map limbs
        lines, c = self._cliplimb(ax, lines)
        self.__dict__[name] = coords
        return lines
Esempio n. 6
0
def plotcf(grid,
           phase,
           modulus,
           darken=None,
           axes=None,
           linestylep="solid",
           linewidthp=1,
           color="k",
           **kwargs):
    r"""Plot the modulus of a complex valued function
    :math:`f:\mathbb{R} \rightarrow \mathbb{C}`
    together with its phase in a color coded fashion.

    :param grid: The grid nodes of the real domain R
    :param phase: The phase of the complex domain result f(grid)
    :param modulus: The modulus of the complex domain result f(grid)
    :param darken: Whether to take into account the modulus of the data to darken colors.
    :param axes: The axes instance used for plotting.
    :param linestylep: The line style of the phase curve.
    :param linewidthp: The line width of the phase curve.
    :param color: The color of the phase curve.
    """
    # Color mapping
    rgb_colors = color_map(modulus,
                           phase=phase,
                           modulus=modulus,
                           darken=darken)

    # Put all the vertical line into a collection
    segments = [
        array([[node, 0], [node, value]])
        for node, value in zip(grid, modulus)
    ]
    line_segments = LineCollection(segments)

    # Set some properties of the lines
    rgb_colors = line_segments.to_rgba(rgb_colors)
    line_segments.set_color(rgb_colors[0])
    line_segments.set_linestyle(linestylep)
    line_segments.set_linewidth(linewidthp)

    # Plot to the given axis instance or retrieve the current one
    if axes is None:
        axes = gca()

    # Plot the phase
    axes.add_collection(line_segments)
    # Plot the modulus
    axes.plot(grid, modulus, color=color, **kwargs)
Esempio n. 7
0
def generate_colored_lines(x,y,cval, color = ['orange','black'], ls = '-', lw = lw):

    cmap     = ListedColormap([color[0], 'purple', color[1]])
    norm     = BoundaryNorm([-0.1, 0.1, 0.9, 1.1], cmap.N)

    points   =  np.array([x, y]).T.reshape(-1,1,2)
    segments =  np.concatenate([points[:-1], points[1:]], axis=1)



    lc = LineCollection(segments, cmap = cmap, norm = norm)
    lc.set_array(cval)
    lc.set_linewidth(lw)
    lc.set_linestyle(ls)
    

    return lc
Esempio n. 8
0
    def plotTrajectoryGradient(self):
        '''Plots the state trajectory with gradient colors to show time progression'''

        points = np.array([self.trajectory[:, 0],
                           self.trajectory[:, 1]]).T.reshape(-1, 1, 2)
        segments = np.concatenate([points[:-1], points[1:]], axis=1)

        # Create a continuous norm to map from data points to colors

        norm = plt.Normalize(self.trajectory[:, 0].min(),
                             self.trajectory[:, 0].max())
        lc = LineCollection(segments, cmap='viridis', norm=norm)
        # Set the values used for colormapping
        lc.set_array(self.trajectory[:, 0])
        lc.set_linewidth(1.5)
        lc.set_linestyle('--')

        self.ax.add_collection(lc)
Esempio n. 9
0
def stemcf(grid, phase, modulus, darken=False, axes=None, linestylep="solid", linewidthp=2, color=None, markerp="o", **kwargs):
    r"""
    Stemplot the modulus of a complex valued function :math:`f:I \rightarrow C` together with its phase in a color coded fashion.

    :param grid: The grid nodes of the real domain R
    :param phase: The phase of the complex domain result f(grid)
    :param modulus: The modulus of the complex domain result f(grid)
    :param darken: Whether to take into account the modulus of the data to darken colors.
    :param axes: The axes instance used for plotting.
    :param linestylep: The line style of the phase curve.
    :param linewidthp: The line width of the phase curve.
    :param color: The color of the stemmed markers.
    :param markerp: The shape of the stemmed markers.

    .. note:: Additional keyword arguments are passe to the plot function.
    """
    # Color mapping
    rgb_colors = color_map(grid, phase=phase, modulus=modulus, darken=darken)

    # Put all the vertical line into a collection
    segments = [ array([[node,0], [node,value]]) for node, value in zip(grid, modulus) ]
    line_segments = LineCollection(segments)

    # Set some properties of the lines
    rgb_colors = line_segments.to_rgba(rgb_colors)
    line_segments.set_color(rgb_colors[0])
    line_segments.set_linestyle(linestylep)
    line_segments.set_linewidth(linewidthp)

    # Plot to the given axis instance or retrieve the current one
    if axes is None:
        axes = gca()

    # Plot the phase
    axes.add_collection(line_segments)
    # Plot the modulus
    if color is None:
        # Scatter has a problem with complex data type, make sure values are purely real
        axes.scatter(grid, real(modulus), c=rgb_colors[0], **kwargs)
    else:
        axes.plot(grid, modulus, linestyle="", marker=markerp, color=color, **kwargs)
    # Plot the ground line
    axes.plot(grid, zeros(grid.shape), linestyle=linestylep, color="k", **kwargs)
Esempio n. 10
0
def stemcf(grid, phase, modulus, darken=None, axes=None, linestylep="solid", linewidthp=2, color=None, markerp="o", **kwargs):
    r"""Stemplot the modulus of a complex valued function :math:`f:I -> \mathbb{C}` together with its phase in a color coded fashion.
    Additional keyword arguments are passed to the plot function.

    :param grid: The grid nodes of the real domain grid :math:`\Gamma`
    :param phase: The phase of the complex domain result :math:`f(\Gamma)`
    :param modulus: The modulus of the complex domain result :math:`f(\Gamma)`
    :param darken: Whether to take into account the modulus of the data to darken colors.
    :param axes: The axes instance used for plotting.
    :param linestylep: The line style of the phase curve.
    :param linewidthp: The line width of the phase curve.
    :param color: The color of the stemmed markers.
    :param markerp: The shape of the stemmed markers.
    """
    # Color mapping
    rgb_colors = color_map(grid, phase=phase, modulus=modulus, darken=darken)

    # Put all the vertical line into a collection
    segments = [array([[node, 0], [node, value]]) for node, value in zip(grid, modulus)]
    line_segments = LineCollection(segments)

    # Set some properties of the lines
    rgb_colors = line_segments.to_rgba(rgb_colors)
    line_segments.set_color(rgb_colors[0])
    line_segments.set_linestyle(linestylep)
    line_segments.set_linewidth(linewidthp)

    # Plot to the given axis instance or retrieve the current one
    if axes is None:
        axes = gca()

    # Plot the phase
    axes.add_collection(line_segments)
    # Plot the modulus
    if color is None:
        # Scatter has a problem with complex data type, make sure values are purely real
        axes.scatter(grid, real(modulus), c=rgb_colors[0], **kwargs)
    else:
        axes.plot(grid, modulus, linestyle="", marker=markerp, color=color, **kwargs)
    # Plot the ground line
    axes.plot(grid, zeros(grid.shape), linestyle=linestylep, color="k", **kwargs)
Esempio n. 11
0
    def draw_shp_polygons(self,
                          shp_filepath,
                          linewidths=0.2,
                          colors='k',
                          antialiaseds=None,
                          linestyles='solid'):
        """
        Draw a shapefile containing polygons
        """
        # Read the shapefile as shapes and records. For each polygon in shapes, draw its boundaries
        r = shapefile.Reader(shp_filepath)
        shapes = r.shapes()
        records = r.records()

        for record, shape in zip(records, shapes):
            lons, lats = zip(*shape.points)
            data = [(x, y) for x, y in zip(*self(lons, lats))]

            # shape.parts is a list containing the starting index of each part of shape (e.g. a lake inside the shape) on xy_pts. If shape contains only 1 part, a list containing 0 is returned.
            if len(shape.parts) == 1:
                segs = [
                    data,
                ]
            else:
                segs = []
                for npart in range(1, len(shape.parts)):
                    ix1 = shape.parts[npart - 1]
                    ix2 = shape.parts[npart]
                    segs.append(data[ix1:ix2])

                segs.append(data[ix2:])

            lines = LineCollection(segs, antialiaseds=[
                1,
            ])
            lines.set_edgecolors(colors)
            lines.set_linestyle(linestyles)
            lines.set_linewidth(linewidths)
            self.ax.add_collection(lines)
Esempio n. 12
0
def plot_volume(sim, vol=None, center=None, size=None,
                options=None, plot3D=False, label=None):

    options = options if options else def_plot_options

    fig=plt.gcf()
    ax=fig.gca(projection='3d') if plot3D else fig.gca()

    if vol:
       center, size = vol.center, vol.size
    v0=np.array([center.x, center.y])
    dx,dy=np.array([0.5*size.x,0.0]), np.array([0.0,0.5*size.y])
    if plot3D:
        zmin,zmax = ax.get_zlim3d()
        z0 = zmin + options['zrel']*(zmax-zmin)

    ##################################################
    # add polygon(s) to the plot to represent the volume
    ##################################################
    def add_to_plot(c):
        ax.add_collection3d(c,zs=z0,zdir='z') if plot3D else ax.add_collection(c)

    if size.x==0.0 or size.y==0.0:    # zero thickness, plot as line
        polygon = [ v0+dx+dy, v0-dx-dy ]
        add_to_plot( LineCollection( [polygon], colors=options['line_color'],
                                     linewidths=options['line_width'],
                                     linestyles=options['line_style']
                                   )
                   )
    else:
        if options['fill_color'] != 'none': # first copy: faces, no edges
            polygon = np.array([v0+dx+dy, v0-dx+dy, v0-dx-dy, v0+dx-dy])
            pc=PolyCollection( [polygon], linewidths=0.0)
            pc.set_color(options['fill_color'])
            pc.set_alpha(options['alpha'])
            add_to_plot(pc)
        if options['boundary_width']>0.0: # second copy: edges, no faces
            closed_polygon = np.array([v0+dx+dy, v0-dx+dy, v0-dx-dy, v0+dx-dy, v0+dx+dy])
            lc=LineCollection([closed_polygon])
            lc.set_linestyle(options['boundary_style'])
            lc.set_linewidth(options['boundary_width'])
            lc.set_edgecolor(options['boundary_color'])
            add_to_plot(lc)

    ######################################################################
    # attempt to autodetermine text rotation and alignment
    ######################################################################
    if label:
        x0, y0, r, h, v = np.mean(ax.get_xlim()),np.mean(ax.get_ylim()), 0, 'center', 'center'
        if size.y==0.0:
            v = 'bottom' if center.y>y0 else 'top'
        elif size.x==0.0:
            r, h = (270,'left') if center.x>x0 else (90,'right')
        if plot3D:
            ax.text(center.x, center.y, z0, label, rotation=r,
                    fontsize=options['fontsize'], color=options['line_color'],
                    horizontalalignment=h, verticalalignment=v)
        else:
            ax.text(center.x, center.y, label, rotation=r,
                    fontsize=options['fontsize'], color=options['line_color'],
                    horizontalalignment=h, verticalalignment=v)
Esempio n. 13
0
def plot_subregion(sim,
                   vol=None,
                   center=None,
                   size=None,
                   plot3D=False,
                   label=None,
                   section=None,
                   options=None):
    """
    Add polygons representing subregions of meep geometries
    to the current 2D or 3D geometry visualization.
    """

    #---------------------------------------------------------------
    #- fetch values of relevant options for the specified section
    #--------------------------------------------------------------
    keys = [
        'linecolor', 'linewidth', 'linestyle', 'fillcolor', 'alpha',
        'fontsize', 'zmin', 'latex'
    ]
    vals = vis_opts(keys, section=section, overrides=options)
    linecolor, linewidth, linestyle, fillcolor = vals[0:4]
    alpha, fontsize, zbar, latex = vals[4:8]

    fig = plt.gcf()
    ax = fig.gca(projection='3d') if plot3D else fig.gca()

    #--------------------------------------------------------------
    # unpack subregion geometry
    #--------------------------------------------------------------
    if vol:
        center, size = vol.center, vol.size
    v0 = np.array([center[0], center[1]])
    dx, dy = np.array([0.5 * size[0], 0.0]), np.array([0.0, 0.5 * size[1]])
    if plot3D:
        zmin, zmax = ax.get_zlim3d()
        z0 = 0.0

    #--------------------------------------------------------------
    # add polygon(s) to the plot to represent the volume
    #--------------------------------------------------------------
    def add_to_plot(c):
        ax.add_collection3d(c, zs=z0,
                            zdir='z') if plot3D else ax.add_collection(c)

    if size[0] == 0.0 or size[1] == 0.0:
        #========================================
        # region has zero thickness: plot as line
        #========================================
        polygon = [v0 + dx + dy, v0 - dx - dy]
        add_to_plot(
            LineCollection([polygon],
                           colors=linecolor,
                           linewidths=linewidth,
                           linestyles=linestyle))
    else:
        #========================================
        # plot as polygon, with separate passes
        # for the perimeter and the interior
        #========================================
        if fillcolor:  # first copy: faces, no edges
            polygon = np.array(
                [v0 + dx + dy, v0 - dx + dy, v0 - dx - dy, v0 + dx - dy])
            pc = PolyCollection([polygon], linewidths=0.0)
            pc.set_color(fillcolor)
            pc.set_alpha(alpha)
            add_to_plot(pc)
        if linewidth > 0.0:  # second copy: edges, no faces
            closed_polygon = np.array([
                v0 + dx + dy, v0 - dx + dy, v0 - dx - dy, v0 + dx - dy,
                v0 + dx + dy
            ])
            lc = LineCollection([closed_polygon])
            lc.set_linestyle(linestyle)
            lc.set_linewidth(linewidth)
            lc.set_edgecolor(linecolor)
            add_to_plot(lc)

    #####################################################################
    if label and fontsize > 0:
        plt.rc('text', usetex=latex)
        if latex:
            label = label.replace('_', '\_')
        x0, y0, r, h, v = np.mean(ax.get_xlim()), np.mean(
            ax.get_ylim()), 0, 'center', 'center'
        if size[1] == 0.0:
            v = 'bottom' if center[1] > y0 else 'top'
        elif size[0] == 0.0:
            r, h = (270, 'left') if center[0] > x0 else (90, 'right')
        if plot3D:
            ax.text(center[0],
                    center[1],
                    z0,
                    label,
                    rotation=r,
                    fontsize=fontsize,
                    color=linecolor,
                    horizontalalignment=h,
                    verticalalignment=v)
        else:
            ax.text(center[0],
                    center[1],
                    label,
                    rotation=r,
                    fontsize=fontsize,
                    color=linecolor,
                    horizontalalignment=h,
                    verticalalignment=v)
Esempio n. 14
0
def _plot_skeleton(neuron, color, method, ax, **kwargs):
    """Plot skeleton."""
    depth_coloring = kwargs.get('depth_coloring', False)
    linewidth = kwargs.get('linewidth', kwargs.get('lw', .5))
    linestyle = kwargs.get('linestyle', kwargs.get('ls', '-'))
    alpha = kwargs.get('alpha', .9)
    norm = kwargs.get('norm')
    plot_soma = kwargs.get('soma', True)
    group_neurons = kwargs.get('group_neurons', False)

    # Generate by-segment coordinates
    coords = segments_to_coords(neuron,
                                neuron.segments,
                                modifier=(1, 1, 1))

    if method == '2d':
        if not depth_coloring:
            # We have to add (None, None, None) to the end of each
            # slab to make that line discontinuous there
            coords = np.vstack(
                [np.append(t, [[None] * 3], axis=0) for t in coords])

            this_line = mlines.Line2D(coords[:, 0], coords[:, 1],
                                      lw=linewidth, ls=linestyle,
                                      alpha=alpha, color=color,
                                      label=f'{getattr(neuron, "name", "NA")} - #{neuron.id}')
            ax.add_line(this_line)
        else:
            coords = tn_pairs_to_coords(neuron, modifier=(1, 1, 1))
            lc = LineCollection(coords[:, :, [0, 1]],
                                cmap='jet',
                                norm=norm)
            lc.set_array(neuron.nodes.loc[neuron.nodes.parent_id >= 0, 'z'].values)
            lc.set_linewidth(linewidth)
            lc.set_alpha(alpha)
            lc.set_linestyle(linestyle)
            lc.set_label(f'{getattr(neuron, "name", "NA")} - #{neuron.id}')
            ax.add_collection(lc)

        if plot_soma and not isinstance(neuron.soma, type(None)):
            soma = utils.make_iterable(neuron.soma)
            # If soma detection is messed up we might end up producing
            # dozens of soma which will freeze the kernel
            if len(soma) >= 10:
                logger.warning(f'{neuron.id} - {len(soma)} somas found.')
            for s in soma:
                n = neuron.nodes.set_index('node_id').loc[s]
                r = getattr(n, neuron.soma_radius) if isinstance(neuron.soma_radius, str) else neuron.soma_radius

                if depth_coloring:
                    color = mpl.cm.jet(norm(n.z))

                s = mpatches.Circle((int(n.x), int(n.y)), radius=r,
                                    alpha=alpha, fill=True, fc=color,
                                    zorder=4, edgecolor='none')
                ax.add_patch(s)
        return None, None

    elif method in ['3d', '3d_complex']:
        # For simple scenes, add whole neurons at a time -> will speed
        # up rendering
        if method == '3d':
            if depth_coloring:
                this_coords = tn_pairs_to_coords(neuron,
                                                 modifier=(1, 1, 1))[:, :, [0, 1, 2]]
            else:
                this_coords = [c[:, [0, 1, 2]] for c in coords]

            lc = Line3DCollection(this_coords,
                                  color=color,
                                  label=neuron.id,
                                  alpha=alpha,
                                  cmap=mpl.cm.jet if depth_coloring else None,
                                  lw=linewidth,
                                  linestyle=linestyle)
            if group_neurons:
                lc.set_gid(neuron.id)
            # Need to get this before adding data
            line3D_collection = ax.add_collection3d(lc)

        # For complex scenes, add each segment as a single collection
        # -> helps preventing Z-order errors
        elif method == '3d_complex':
            for c in coords:
                lc = Line3DCollection([c],
                                      color=color,
                                      lw=linewidth,
                                      alpha=alpha,
                                      linestyle=linestyle)
                if group_neurons:
                    lc.set_gid(neuron.id)
                ax.add_collection3d(lc)
            line3D_collection = None

        surf3D_collections = []
        if plot_soma and not isinstance(neuron.soma, type(None)):
            soma = utils.make_iterable(neuron.soma)
            # If soma detection is messed up we might end up producing
            # dozens of soma which will freeze the kernel
            if len(soma) >= 5:
                logger.warning(f'Neuron {neuron.id} appears to have {len(soma)}'
                               ' somas. Skipping plotting its somas.')
            else:
                for s in soma:
                    n = neuron.nodes.set_index('node_id').loc[s]
                    r = getattr(n, neuron.soma_radius) if isinstance(neuron.soma_radius, str) else neuron.soma_radius

                    resolution = 20
                    u = np.linspace(0, 2 * np.pi, resolution)
                    v = np.linspace(0, np.pi, resolution)
                    x = r * np.outer(np.cos(u), np.sin(v)) + n.x
                    y = r * np.outer(np.sin(u), np.sin(v)) + n.y
                    z = r * np.outer(np.ones(np.size(u)), np.cos(v)) + n.z
                    surf = ax.plot_surface(x, y, z,
                                           color=color,
                                           shade=False,
                                           alpha=alpha)
                    if group_neurons:
                        surf.set_gid(neuron.id)

                    surf3D_collections.append(surf)

        return line3D_collection, surf3D_collections
Esempio n. 15
0
class ScatterLayerArtist(MatplotlibLayerArtist):

    _layer_state_cls = ScatterLayerState

    def __init__(self, axes, viewer_state, layer_state=None, layer=None):

        super(ScatterLayerArtist, self).__init__(axes, viewer_state,
                                                 layer_state=layer_state, layer=layer)

        # Watch for changes in the viewer state which would require the
        # layers to be redrawn
        self._viewer_state.add_global_callback(self._update_scatter)
        self.state.add_global_callback(self._update_scatter)

        # Scatter
        self.scatter_artist = self.axes.scatter([], [])
        self.plot_artist = self.axes.plot([], [], 'o', mec='none')[0]
        self.errorbar_artist = self.axes.errorbar([], [], fmt='none')
        self.vector_artist = None
        self.line_collection = LineCollection(np.zeros((0, 2, 2)))
        self.axes.add_collection(self.line_collection)

        # Scatter density
        self.density_auto_limits = DensityMapLimits()
        self.density_artist = ScatterDensityArtist(self.axes, [], [], color='white',
                                                   vmin=self.density_auto_limits.min,
                                                   vmax=self.density_auto_limits.max)
        self.axes.add_artist(self.density_artist)

        self.mpl_artists = [self.scatter_artist, self.plot_artist,
                            self.errorbar_artist, self.vector_artist,
                            self.line_collection, self.density_artist]
        self.errorbar_index = 2
        self.vector_index = 3

        self.reset_cache()

    def reset_cache(self):
        self._last_viewer_state = {}
        self._last_layer_state = {}

    @defer_draw
    def _update_data(self, changed):

        # Layer artist has been cleared already
        if len(self.mpl_artists) == 0:
            return

        try:
            x = self.layer[self._viewer_state.x_att].ravel()
        except (IncompatibleAttribute, IndexError):
            # The following includes a call to self.clear()
            self.disable_invalid_attributes(self._viewer_state.x_att)
            return
        else:
            self.enable()

        try:
            y = self.layer[self._viewer_state.y_att].ravel()
        except (IncompatibleAttribute, IndexError):
            # The following includes a call to self.clear()
            self.disable_invalid_attributes(self._viewer_state.y_att)
            return
        else:
            self.enable()

        if self.state.markers_visible:
            if self.state.density_map:
                self.density_artist.set_xy(x, y)
                self.plot_artist.set_data([], [])
                self.scatter_artist.set_offsets(np.zeros((0, 2)))
            else:
                if self.state.cmap_mode == 'Fixed' and self.state.size_mode == 'Fixed':
                    # In this case we use Matplotlib's plot function because it has much
                    # better performance than scatter.
                    self.plot_artist.set_data(x, y)
                    self.scatter_artist.set_offsets(np.zeros((0, 2)))
                    self.density_artist.set_xy([], [])
                else:
                    self.plot_artist.set_data([], [])
                    offsets = np.vstack((x, y)).transpose()
                    self.scatter_artist.set_offsets(offsets)
                    self.density_artist.set_xy([], [])
        else:
            self.plot_artist.set_data([], [])
            self.scatter_artist.set_offsets(np.zeros((0, 2)))
            self.density_artist.set_xy([], [])

        if self.state.line_visible:
            if self.state.cmap_mode == 'Fixed':
                points = np.array([x, y]).transpose()
                self.line_collection.set_segments([points])
            else:
                # In the case where we want to color the line, we need to over
                # sample the line by a factor of two so that we can assign the
                # correct colors to segments - if we didn't do this, then
                # segments on one side of a point would be a different color
                # from the other side. With oversampling, we can have half a
                # segment on either side of a point be the same color as a
                # point
                x_fine = np.zeros(len(x) * 2 - 1, dtype=float)
                y_fine = np.zeros(len(y) * 2 - 1, dtype=float)
                x_fine[::2] = x
                x_fine[1::2] = 0.5 * (x[1:] + x[:-1])
                y_fine[::2] = y
                y_fine[1::2] = 0.5 * (y[1:] + y[:-1])
                points = np.array([x_fine, y_fine]).transpose().reshape(-1, 1, 2)
                segments = np.concatenate([points[:-1], points[1:]], axis=1)
                self.line_collection.set_segments(segments)
        else:
            self.line_collection.set_segments(np.zeros((0, 2, 2)))

        for eartist in list(self.errorbar_artist[2]):
            if eartist is not None:
                try:
                    eartist.remove()
                except ValueError:
                    pass
                except AttributeError:  # Matplotlib < 1.5
                    pass

        if self.vector_artist is not None:
            self.vector_artist.remove()
            self.vector_artist = None

        if self.state.vector_visible:

            if self.state.vx_att is not None and self.state.vy_att is not None:

                vx = self.layer[self.state.vx_att].ravel()
                vy = self.layer[self.state.vy_att].ravel()

                if self.state.vector_mode == 'Polar':
                    ang = vx
                    length = vy
                    # assume ang is anti clockwise from the x axis
                    vx = length * np.cos(np.radians(ang))
                    vy = length * np.sin(np.radians(ang))

            else:
                vx = None
                vy = None

            if self.state.vector_arrowhead:
                hw = 3
                hl = 5
            else:
                hw = 1
                hl = 0

            v = np.hypot(vx, vy)
            vmax = np.nanmax(v)
            vx = vx / vmax
            vy = vy / vmax

            self.vector_artist = self.axes.quiver(x, y, vx, vy, units='width',
                                                  pivot=self.state.vector_origin,
                                                  headwidth=hw, headlength=hl,
                                                  scale_units='width',
                                                  scale=10 / self.state.vector_scaling)
            self.mpl_artists[self.vector_index] = self.vector_artist

        if self.state.xerr_visible or self.state.yerr_visible:

            if self.state.xerr_visible and self.state.xerr_att is not None:
                xerr = self.layer[self.state.xerr_att].ravel()
            else:
                xerr = None

            if self.state.yerr_visible and self.state.yerr_att is not None:
                yerr = self.layer[self.state.yerr_att].ravel()
            else:
                yerr = None

            self.errorbar_artist = self.axes.errorbar(x, y, fmt='none',
                                                      xerr=xerr, yerr=yerr)
            self.mpl_artists[self.errorbar_index] = self.errorbar_artist

    @defer_draw
    def _update_visual_attributes(self, changed, force=False):

        if not self.enabled:
            return

        if self.state.markers_visible:

            if self.state.density_map:

                if self.state.cmap_mode == 'Fixed':
                    if force or 'color' in changed or 'cmap_mode' in changed:
                        self.density_artist.set_color(self.state.color)
                        self.density_artist.set_c(None)
                        self.density_artist.set_clim(self.density_auto_limits.min,
                                                     self.density_auto_limits.max)
                elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                    c = self.layer[self.state.cmap_att].ravel()
                    set_mpl_artist_cmap(self.density_artist, c, self.state)

                if force or 'stretch' in changed:
                    self.density_artist.set_norm(ImageNormalize(stretch=STRETCHES[self.state.stretch]()))

                if force or 'dpi' in changed:
                    self.density_artist.set_dpi(self._viewer_state.dpi)

                if force or 'density_contrast' in changed:
                    self.density_auto_limits.contrast = self.state.density_contrast
                    self.density_artist.stale = True

            else:

                if self.state.cmap_mode == 'Fixed' and self.state.size_mode == 'Fixed':

                    if force or 'color' in changed:
                        self.plot_artist.set_color(self.state.color)

                    if force or 'size' in changed or 'size_scaling' in changed:
                        self.plot_artist.set_markersize(self.state.size *
                                                        self.state.size_scaling)

                else:

                    # TEMPORARY: Matplotlib has a bug that causes set_alpha to
                    # change the colors back: https://github.com/matplotlib/matplotlib/issues/8953
                    if 'alpha' in changed:
                        force = True

                    if self.state.cmap_mode == 'Fixed':
                        if force or 'color' in changed or 'cmap_mode' in changed:
                            self.scatter_artist.set_facecolors(self.state.color)
                            self.scatter_artist.set_edgecolor('none')
                    elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                        c = self.layer[self.state.cmap_att].ravel()
                        set_mpl_artist_cmap(self.scatter_artist, c, self.state)
                        self.scatter_artist.set_edgecolor('none')

                    if force or any(prop in changed for prop in MARKER_PROPERTIES):

                        if self.state.size_mode == 'Fixed':
                            s = self.state.size * self.state.size_scaling
                            s = broadcast_to(s, self.scatter_artist.get_sizes().shape)
                        else:
                            s = self.layer[self.state.size_att].ravel()
                            s = ((s - self.state.size_vmin) /
                                 (self.state.size_vmax - self.state.size_vmin)) * 30
                            s *= self.state.size_scaling

                        # Note, we need to square here because for scatter, s is actually
                        # proportional to the marker area, not radius.
                        self.scatter_artist.set_sizes(s ** 2)

        if self.state.line_visible:

            if self.state.cmap_mode == 'Fixed':
                if force or 'color' in changed or 'cmap_mode' in changed:
                    self.line_collection.set_array(None)
                    self.line_collection.set_color(self.state.color)
            elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                # Higher up we oversampled the points in the line so that
                # half a segment on either side of each point has the right
                # color, so we need to also oversample the color here.
                c = self.layer[self.state.cmap_att].ravel()
                cnew = np.zeros((len(c) - 1) * 2)
                cnew[::2] = c[:-1]
                cnew[1::2] = c[1:]
                set_mpl_artist_cmap(self.line_collection, cnew, self.state)

            if force or 'linewidth' in changed:
                self.line_collection.set_linewidth(self.state.linewidth)

            if force or 'linestyle' in changed:
                self.line_collection.set_linestyle(self.state.linestyle)

        if self.state.vector_visible and self.vector_artist is not None:

            if self.state.cmap_mode == 'Fixed':
                if force or 'color' in changed or 'cmap_mode' in changed:
                    self.vector_artist.set_array(None)
                    self.vector_artist.set_color(self.state.color)
            elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                c = self.layer[self.state.cmap_att].ravel()
                set_mpl_artist_cmap(self.vector_artist, c, self.state)

        if self.state.xerr_visible or self.state.yerr_visible:

            for eartist in list(self.errorbar_artist[2]):

                if eartist is None:
                    continue

                if self.state.cmap_mode == 'Fixed':
                    if force or 'color' in changed or 'cmap_mode' in changed:
                        eartist.set_color(self.state.color)
                elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                    c = self.layer[self.state.cmap_att].ravel()
                    set_mpl_artist_cmap(eartist, c, self.state)

                if force or 'alpha' in changed:
                    eartist.set_alpha(self.state.alpha)

                if force or 'visible' in changed:
                    eartist.set_visible(self.state.visible)

                if force or 'zorder' in changed:
                    eartist.set_zorder(self.state.zorder)

        for artist in [self.scatter_artist, self.plot_artist,
                       self.vector_artist, self.line_collection,
                       self.density_artist]:

            if artist is None:
                continue

            if force or 'alpha' in changed:
                artist.set_alpha(self.state.alpha)

            if force or 'zorder' in changed:
                artist.set_zorder(self.state.zorder)

            if force or 'visible' in changed:
                artist.set_visible(self.state.visible)

        self.redraw()

    @defer_draw
    def _update_scatter(self, force=False, **kwargs):

        if (self._viewer_state.x_att is None or
            self._viewer_state.y_att is None or
                self.state.layer is None):
            return

        # Figure out which attributes are different from before. Ideally we shouldn't
        # need this but currently this method is called multiple times if an
        # attribute is changed due to x_att changing then hist_x_min, hist_x_max, etc.
        # If we can solve this so that _update_histogram is really only called once
        # then we could consider simplifying this. Until then, we manually keep track
        # of which properties have changed.

        changed = set()

        if not force:

            for key, value in self._viewer_state.as_dict().items():
                if value != self._last_viewer_state.get(key, None):
                    changed.add(key)

            for key, value in self.state.as_dict().items():
                if value != self._last_layer_state.get(key, None):
                    changed.add(key)

        self._last_viewer_state.update(self._viewer_state.as_dict())
        self._last_layer_state.update(self.state.as_dict())

        if force or len(changed & DATA_PROPERTIES) > 0:
            self._update_data(changed)
            force = True

        if force or len(changed & VISUAL_PROPERTIES) > 0:
            self._update_visual_attributes(changed, force=force)

    def get_layer_color(self):
        if self.state.cmap_mode == 'Fixed':
            return self.state.color
        else:
            return self.state.cmap

    @defer_draw
    def update(self):
        self._update_scatter(force=True)
        self.redraw()
def main(lamb,i):
    # define all time related constants
    TIME_G_1 = 20 # seconds
    TIME_R_1 = 20 # seconds
#    TIME_G_2 = TIME_R_1 # seconds
#    TIME_R_2 = TIME_G_1 # seconds
    T = TIME_G_1 + TIME_R_1 # seconds
    dt = .01    #time step in cumsum method

    # define arrival constraints
    LAMBDA_1 = lamb[0]
    LAMBDA_2 = lamb[1]
    # define departure rate
    RHO_1 = 2.0
    RHO_2 = 3.0

    # define initial conditions
    q0, t0 = [7, 20], 0

    # arrivals dependent on poisson process
 #   ARRIVAL_1 = np.random.poisson(lam=LAMBDA_1)
 #   ARRIVAL_2 = np.random.poisson(lam=LAMBDA_2)

    # define indicator functions
    def I1(t): return 1.0 if np.mod(t,T) <= TIME_G_1 else 0.0
    def I2(t): return 1.0 if np.mod(t,T) >= TIME_G_1 else 0.0

    # define our right hand side
    def f(lam,rho,ind): return lam - rho*ind

    def RHS(t): return [f(LAMBDA_1,RHO_1,I1(t)), f(LAMBDA_2,RHO_2,I2(t))]

    def Solution(time,initial):
        queue = []
        for t in time:
            queue.append(RHS(t))
        fcn = np.reshape(queue,[len(time),2])
        sol = np.asarray(np.cumsum(fcn,axis=0)*dt + initial)
        sol[sol<0] = 0
        return sol
    # OBSOLETE : solution using numpy's cumsum
    # First part of the solution: time interval (t0,TIME_G_1)
    time = np.asarray(np.arange(t0,TIME_G_1,dt))
    Slope = RHS(time[1])
    sol = Solution(time,q0)
    # Lets try two cycles:
    numcycles = 3
    initial = sol[-1,]
    for j in range(2*numcycles-1):
        index = j+1
        start = np.mod(index,2)*TIME_G_1 + np.floor(index/2)*T
        end = np.mod(index+1,2)*TIME_G_1 + np.floor((index+1)/2)*T
        time_temp =  np.asarray(np.arange(start,end,dt))
        Slope.append(RHS(time_temp[1]))
        sol_temp = Solution(time_temp,initial)
        initial = sol_temp[-1,]
        time = np.concatenate((time,time_temp))
        sol = np.concatenate((sol,sol_temp))

    queues = np.squeeze(sol)
    print(Slope)
#    # set up scipy ode integrator
#    q=spi.ode(RHS).set_integrator("vode", method="bdf")
#    q.set_initial_value(q0, t0)
#
#    # iterate to get results
#    time = []
#    queues = []
#    while q.successful() and q.t < T:
#        step = q.t+dt
#        resp = q.integrate(q.t+dt)
#        resp[resp<0]=0
##        resp = max([resp,0])
#        time.append(step)
#        queues.append(resp)
#    #    print(step, resp)

    # generate pretty plots
    fig = plt.plot(time,queues[:,0], 'k-', label="Street 1", alpha=0.7)
    plt.plot(time, queues[:,1], 'k-', label="Street 2", alpha=0.7)
    ax = plt.gca()
    #fig = plt.plot(time, np.zeros(len(time)), 'w')
    #ax = plt.gca()
    ax.set_title("Queue Size vs. Time")
    ax.set_xlabel("Time (s)")
    ax.set_ylabel("Queue Size (# Cars)")
    # ax.legend(loc='best')
    # plt.axvspan(0, TIME_G_1, facecolor='r', alpha=0.2)
    # plt.axvspan(TIME_G_1, T, facecolor='g', alpha=0.2)
    # plt.axvline(x=TIME_G_1, color='g')

    #fig = plt.figure()
    #ax = fig.add_subplot(111)
    ax.set_title("Queue Size vs. Time")
    ax.set_xlabel("Time (s)")
    ax.set_ylabel("Queue Size (# Cars)")

    points1 = np.array([time, queues[:,0]]).T.reshape(-1,1,2)
    segments1 = np.concatenate([points1[:-1], points1[1:]], axis=1)
    lc1 = LineCollection(segments1, cmap=ListedColormap(['g','r']))
    lc1.set_array(time)
    lc1.set_linewidth(2)
    lc1.set_linestyle('-')
    ax.add_collection(lc1)

    points2 = np.array([time, queues[:,1]]).T.reshape(-1,1,2)
    segments2 = np.concatenate([points2[:-1], points2[1:]], axis=1)
    lc2 = LineCollection(segments2, cmap=ListedColormap(['r','g']))
    lc2.set_array(time)
    lc2.set_linewidth(2)
    lc2.set_linestyle('--')
    ax.add_collection(lc2)

    plt.xlim(time.min(), time.max())
    ax.grid()
    plt.savefig(str(i)+".png")
    plt.close()
Esempio n. 17
0
def show_frac_charge(filename=None,bias=False,usevec=False,theta=0,dmu=0.01,target_block=(0,0),append=False,**kwargs):
    '''
    Show the fractional charge wave functions.
    '''
    model,expander=get_solving_system(evolutor_type='masked',periodic=False,**kwargs)
    if filename is None:
        filename='data/frac_W1%s_W2%s_U%s_N%s'%(kwargs.get('K1'),kwargs.get('K2'),kwargs.get('U'),kwargs.get('nsite'))
    if not bias:
        ket_even=MPS.load(filename+'-even.dat')
        ket_odd=MPS.load(filename+'-odd.dat')
        #ket_odd=ket_odd-(ket_even.tobra(labels=ket_even.labels)*ket_odd).item()*ket_even
        #combine to left-right edge states.
        if usevec:
            ket_odd,ket_even=ket_odd.state,ket_even.state
        #else:
            #ket_odd.recanonicalize(tol=1e-8)
        ket_left=ket_even#(ket_even+exp(1j*theta)*ket_odd)/sqrt(2.)
        ket_right=ket_odd#(ket_even-exp(1j*theta)*ket_odd)/sqrt(2.)
        if not usevec:
            ket_left.recanonicalize(tol=1e-8)   #we must recanonicalize it, for it is not canonical!!!
            ket_right.recanonicalize(tol=1e-8)
            print ket_left
            print ket_right
            pls=[dos4mps(spaceconfig=expander.spaceconfig,ket=ket) for ket in [ket_left,ket_right]]
        else:
            pls=[dos4vec(spaceconfig=model.hgen.spaceconfig,ket=ket) for ket in [ket_left,ket_right]]
    else:
        suffix='W1%s_W2%s_U%s_N%s_dmu%s_%s.dat'%(kwargs.get('K1'),kwargs.get('K2'),kwargs.get('U'),kwargs.get('nsite'),dmu,target_block)
        filename_mps='data/mps_'+suffix
        print filename_mps
        fname='data/fracdos_'+suffix
        #suffix2='W1%s_W2%s_U%s_N%s_dmu%s_%s.dat'%(kwargs.get('K1'),kwargs.get('K2'),kwargs.get('U'),kwargs.get('nsite'),dmu,(0,-1))
        #filename_mps2='data/mps_'+suffix2
        if append:
            pls=loadtxt(fname)[newaxis,:,:]
        else:
            ket_bias=MPS.load(filename_mps)
            #ket_bias=1./sqrt(2)*(MPS.load(filename_mps2)-1j*ket_bias)
            #ket_bias.compress()
            pls=[dos4mps(spaceconfig=expander.spaceconfig,ket=ket) for ket in [ket_bias]]
            savetxt(fname,pls[0].real)

    #pls=sum(pls,axis=1)
    pls=array(pls)-0.5
    nsite=pls.shape[-1]
    pls_left=pls[:,:,:nsite/2]
    pls_right=pls[:,:,nsite/2:]
    print 'occupation in left block -> %s, right block -> %s.'%(sum(pls_left,axis=(-1,-2)),sum(pls_right,axis=(-1,-2)))
    if ONSV: return pls
    ion()
    lw=2
    lc='r'
    for n in xrange(len(pls)):
        pln=pls[n]
        ax=subplot(101+n+10*len(pls))
        for s in xrange(2):
            color='b' if s==0 else 'r'
            lc=LineCollection([[(i,0),(i,pln[s,i].real.item())] for i in xrange(model.nsite)])
            lc.set_linewidth(lw)
            lc.set_color(color)
            lc.set_linestyle('--' if s==1 else '-')
            ax.add_collection(lc)

        ax.autoscale()
        ax.margins(0.1)
        xlabel('N')
        ylabel(r'$\rho-\bar{\rho}$')
    pdb.set_trace()
Esempio n. 18
0
def plot2d(x: Union[core.NeuronObject, core.Volume, np.ndarray,
                    List[Union[core.NeuronObject, np.ndarray, core.Volume]]],
           method: Union[Literal['2d'], Literal['3d'],
                         Literal['3d_complex']] = '2d',
           **kwargs) -> Tuple[mpl.figure.Figure, mpl.axes.Axes]:
    """ Generate 2D plots of neurons and neuropils.

    The main advantage of this is that you can save plot as vector graphics.

    Important
    ---------
    This function uses matplotlib which "fakes" 3D as it has only very limited
    control over layers. Therefore neurites aren't necessarily plotted in the
    right Z order which becomes especially troublesome when plotting a complex
    scene with lots of neurons criss-crossing. See the ``method`` parameter
    for details. All methods use orthogonal projection.

    Parameters
    ----------
    x :               skeleton IDs | TreeNeuron | NeuronList | Volume | Dotprops | np.ndarray
                      Objects to plot::

                        - int is intepreted as skeleton ID(s)
                        - str is intepreted as volume name(s)
                        - multiple objects can be passed as list (see examples)
                        - numpy array of shape (n,3) is intepreted as scatter
    method :          '2d' | '3d' | '3d_complex'
                      Method used to generate plot. Comes in three flavours:
                        1. '2d' uses normal matplotlib. Neurons are plotted in
                           the order their are provided. Well behaved when
                           plotting neuropils and connectors. Always gives
                           frontal view.
                        2. '3d' uses matplotlib's 3D axis. Here, matplotlib
                           decide the order of plotting. Can chance perspective
                           either interacively or by code (see examples).
                        3. '3d_complex' same as 3d but each neuron segment is
                           added individually. This allows for more complex
                           crossing patterns to be rendered correctly. Slows
                           down rendering though.

    **kwargs
                      See Notes for permissible keyword arguments.

    Examples
    --------
    >>> import navis
    >>> import matplotlib.pyplot as plt

    Plot list of neurons as simple 2d
    >>> nl = navis.example_neurons()
    >>> fig, ax = navis.plot2d(nl)
    >>> plt.show()

    Add a volume
    >>> v = navis.example_volume('LH')
    >>> fig, ax = navis.plot2d([nl, vol])
    >>> plt.show()

    Change neuron colors
    >>> fig, ax = navis.plot2d(nl, color=['r', 'g', 'b', 'm', 'c', 'y'])
    >>> plt.show()

    Plot in "fake" 3D
    >>> fig, ax = navis.plot2d(nl, method='3d')
    >>> plt.show()
    >>> # Try dragging the window

    Plot in "fake" 3D and change perspective
    >>> fig, ax = navis.plot2d(nl, method='3d')
    >>> # Change view to lateral
    >>> ax.azim = 0
    >>> ax.elev = 0
    >>> # Change view to top
    >>> ax.azim = -90
    >>> ax.elev = 90
    >>> # Tilted top view
    >>> ax.azim = -135
    >>> ax.elev = 45
    >>> # Move camera closer (will make image bigger)
    >>> ax.dist = 5
    >>> plt.show()

    Plot using depth-coloring
    >>> fig, ax = navis.plot2d(nl, method='3d', depth_coloring=True)
    >>> plt.show()


    Returns
    --------
    fig, ax :      matplotlib figure and axis object

    Notes
    -----

    Optional keyword arguments:

    ``soma`` (bool, default = True)
       Plot soma if one exists.

    ``connectors`` (boolean, default = True)
       Plot connectors (synapses, gap junctions, abutting)

    ``connectors_only`` (boolean, default = False)
       Plot only connectors, not the neuron.

    ``cn_size`` (int | float, default = 1)
      Size of connectors.

    ``linewidth``/``lw`` (int | float, default = .5)
      Width of neurites.

    ``linestyle``/``ls`` (str, default = '-')
      Line style of neurites.

    ``autoscale`` (bool, default=True)
       If True, will scale the axes to fit the data.

    ``scalebar`` (int | float, default=False)
       Adds scale bar. Provide integer/float to set size of scalebar.
       For methods '3d' and '3d_complex', this will create an axis object.

    ``ax`` (matplotlib ax, default=None)
       Pass an ax object if you want to plot on an existing canvas.

    ``figsize`` (tuple, default = (8, 8))
      Size of figure.

    ``color`` (tuple | list | str | dict)
      Tuples/lists (r,g,b) and str (color name) are interpreted as a single
      colors that will be applied to all neurons. Dicts will be mapped onto
      neurons by skeleton ID.

    ``alpha`` (float [0-1], default = .9)
      Alpha value for neurons. Overriden if alpha is provided as fourth value
      in ``color``.

    ``use_neuron_color`` (bool, default = False)
      If True, will attempt to use ``.color`` attribute of neurons.

    ``depth_coloring`` (bool, default = False)
      If True, will color encode depth (Z). Overrides ``color``. Does not work
      with ``method = '3d_complex'``.

    ``depth_scale`` (bool, default = True)
      If True and ``depth_coloring=True`` will plot a scale.

    ``cn_mesh_colors`` (bool, default = False)
      If True, will use the neuron's color for its connectors too.

    ``group_neurons`` (bool, default = False)
      If True, neurons will be grouped. Works with SVG export (not PDF).
      Does NOT work with ``method='3d_complex'``.

    ``scatter_kws`` (dict, default = {})
      Parameters to be used when plotting points. Accepted keywords are:
      ``size`` and ``color``.

    ``view`` (tuple, default = ("x", "y"))
      Sets view for ``method='2d'``.


    See Also
    --------
    :func:`navis.plot3d`
            Use this if you want interactive, perspectively correct renders
            and if you don't need vector graphics as outputs.
    :func:`navis.plot1d`
            A nifty way to visualise neurons in a single dimension.

    """

    # Filter kwargs
    _ACCEPTED_KWARGS = [
        'soma', 'connectors', 'connectors_only', 'ax', 'color', 'colors', 'c',
        'view', 'scalebar', 'cn_mesh_colors', 'linewidth', 'cn_size',
        'group_neurons', 'scatter_kws', 'figsize', 'linestyle', 'alpha',
        'depth_coloring', 'autoscale', 'depth_scale', 'use_neuron_color', 'ls',
        'lw'
    ]
    wrong_kwargs = [a for a in kwargs if a not in _ACCEPTED_KWARGS]
    if wrong_kwargs:
        raise KeyError(f'Unknown kwarg(s): {",".join(wrong_kwargs)}. '
                       f'Currently accepted: {",".join(_ACCEPTED_KWARGS)}')

    _METHOD_OPTIONS = ['2d', '3d', '3d_complex']
    if method not in _METHOD_OPTIONS:
        raise ValueError(f'Unknown method "{method}". Please use either: '
                         f'{",".join(_METHOD_OPTIONS)}')

    # Set axis to plot for method '2d'
    axis1, axis2 = kwargs.get('view', ('x', 'y'))

    plot_soma = kwargs.get('soma', True)

    connectors = kwargs.get('connectors', False)
    connectors_only = kwargs.get('connectors_only', False)
    cn_mesh_colors = kwargs.get('cn_mesh_colors', False)
    use_neuron_color = kwargs.get('use_neuron_color', False)
    ax = kwargs.get('ax', None)
    color = kwargs.get('color', kwargs.get('c', kwargs.get('colors', None)))
    scalebar = kwargs.get('scalebar', None)
    group_neurons = kwargs.get('group_neurons', False)

    # This is overwritten if color specifies alphas
    alpha = kwargs.get('alpha', .9)

    # Depth coloring
    depth_coloring = kwargs.get('depth_coloring', False)
    depth_scale = kwargs.get('depth_scale', True)

    scatter_kws = kwargs.get('scatter_kws', {})

    linewidth = kwargs.get('linewidth', kwargs.get('lw', .5))
    cn_size = kwargs.get('cn_size', 1)
    linestyle = kwargs.get('linestyle', kwargs.get('ls', '-'))
    autoscale = kwargs.get('autoscale', True)

    # Keep track of limits if necessary
    lim = []

    # Parse objects
    skdata, dotprops, volumes, points, visuals = utils.parse_objects(x)

    # Generate the colormaps
    (neuron_cmap, dotprop_cmap,
     volumes_cmap) = prepare_colormap(color,
                                      skdata,
                                      dotprops,
                                      volumes,
                                      use_neuron_color=use_neuron_color,
                                      color_range=1)

    # Make sure axes are projected orthogonally
    if method in ['3d', '3d_complex']:
        proj3d.persp_transformation = _orthogonal_proj

    # Generate axes
    if not ax:
        if method == '2d':
            fig, ax = plt.subplots(figsize=kwargs.get('figsize', (8, 8)))
            ax.set_aspect('equal')
        elif method in ['3d', '3d_complex']:
            fig = plt.figure(figsize=kwargs.get('figsize',
                                                plt.figaspect(1) * 1.5))
            ax = fig.gca(projection='3d')

            # This sets front view
            ax.azim = -90
            ax.elev = 0
            ax.dist = 7
            # Disallowed for 3D in matplotlib 3.1.0
            # ax.set_aspect('equal')
    # Check if correct axis were provided
    else:
        if not isinstance(ax, mpl.axes.Axes):
            raise TypeError('Ax must be of type "mpl.axes.Axes", '
                            f'not "{type(ax)}"')
        fig = ax.get_figure()
        if method in ['3d', '3d_complex']:
            if ax.name != '3d':
                raise TypeError('Axis must be 3d.')

            # Add existing limits to ax
            lim += np.array((ax.get_xlim3d(), ax.get_zlim3d(),
                             ax.get_ylim3d())).T.tolist()
        elif method == '2d':
            if ax.name == '3d':
                raise TypeError('Axis must be 2d.')

    # Prepare some stuff for depth coloring
    if depth_coloring and method == '3d_complex':
        raise Exception(f'Depth coloring unavailable for method "{method}"')
    elif depth_coloring and method == '2d':
        all_co = skdata.nodes[['x', 'y', 'z']]
        norm = plt.Normalize(vmin=all_co.z.min(), vmax=all_co.z.max())

    # Plot volumes first
    if volumes:
        for i, v in enumerate(volumes):
            c = volumes_cmap[i]

            if method == '2d':
                vpatch = mpatches.Polygon(v.to_2d(view=f'{axis1}{axis2}',
                                                  invert_y=True),
                                          closed=True,
                                          lw=0,
                                          fill=True,
                                          fc=c,
                                          alpha=c[3] if len(c) == 4 else 1)
                ax.add_patch(vpatch)
            elif method in ['3d', '3d_complex']:
                verts = np.vstack(v.vertices)

                # Invert y-axis
                verts[:, 1] *= -1

                # Add alpha
                if len(c) == 3:
                    c = (c[0], c[1], c[2], .1)

                ts = ax.plot_trisurf(verts[:, 0],
                                     verts[:, 2],
                                     v.faces,
                                     verts[:, 1],
                                     label=v.name,
                                     color=c)
                ts.set_gid(v.name)

                # Keep track of limits
                lim.append(verts.max(axis=0))
                lim.append(verts.min(axis=0))

    # Create lines from segments
    line3D_collections = []
    surf3D_collections = []
    for i, neuron in enumerate(
            config.tqdm(skdata.itertuples(),
                        desc='Plot neurons',
                        total=skdata.shape[0],
                        leave=False,
                        disable=config.pbar_hide | len(dotprops) == 0)):
        this_color = neuron_cmap[i]

        if neuron.nodes.empty:
            logger.warning(f'Skipping neuron w/o nodes: {neuron.uuid}')
            continue

        if not connectors_only:
            # Now make traces (invert y axis)
            coords = segments_to_coords(neuron,
                                        neuron.segments,
                                        modifier=(1, -1, 1))

            if method == '2d':
                if not depth_coloring:
                    # We have to add (None, None, None) to the end of each
                    # slab to make that line discontinuous there
                    coords = np.vstack(
                        [np.append(t, [[None] * 3], axis=0) for t in coords])

                    this_line = mlines.Line2D(
                        coords[:, 0],
                        coords[:, 1],
                        lw=linewidth,
                        ls=linestyle,
                        alpha=alpha,
                        color=this_color,
                        label=
                        f'{getattr(neuron, "name", "NA")} - #{neuron.uuid}')
                    ax.add_line(this_line)
                else:
                    coords = tn_pairs_to_coords(neuron, modifier=(1, -1, 1))
                    lc = LineCollection(coords[:, :, [0, 1]],
                                        cmap='jet',
                                        norm=norm)
                    lc.set_array(neuron.nodes.loc[neuron.nodes.parent_id >= 0,
                                                  'z'].values)
                    lc.set_linewidth(linewidth)
                    lc.set_alpha(alpha)
                    lc.set_linestyle(linestyle)
                    lc.set_label(
                        f'{getattr(neuron, "name", "NA")} - #{neuron.uuid}')
                    line = ax.add_collection(lc)

                if plot_soma and not isinstance(neuron.soma, type(None)):
                    soma = utils.make_iterable(neuron.soma)
                    for s in soma:
                        n = neuron.nodes.set_index('node_id').loc[s]
                        r = getattr(n, neuron.soma_radius) if isinstance(
                            neuron.soma_radius, str) else neuron.soma_radius

                        if depth_coloring:
                            this_color = mpl.cm.jet(norm(n.z))

                        s = mpatches.Circle((int(n.x), int(-n.y)),
                                            radius=r,
                                            alpha=alpha,
                                            fill=True,
                                            fc=this_color,
                                            zorder=4,
                                            edgecolor='none')
                        ax.add_patch(s)

            elif method in ['3d', '3d_complex']:
                cmap = mpl.cm.jet if depth_coloring else None

                # For simple scenes, add whole neurons at a time -> will speed
                # up rendering
                if method == '3d':
                    if depth_coloring:
                        this_coords = tn_pairs_to_coords(
                            neuron, modifier=(1, -1, 1))[:, :, [0, 2, 1]]
                    else:
                        this_coords = [c[:, [0, 2, 1]] for c in coords]

                    lc = Line3DCollection(this_coords,
                                          color=this_color,
                                          label=neuron.uuid,
                                          alpha=alpha,
                                          cmap=cmap,
                                          lw=linewidth,
                                          linestyle=linestyle)
                    if group_neurons:
                        lc.set_gid(neuron.uuid)
                    ax.add_collection3d(lc)
                    line3D_collections.append(lc)

                # For complex scenes, add each segment as a single collection
                # -> help preventing Z-order errors
                elif method == '3d_complex':
                    for c in coords:
                        lc = Line3DCollection([c[:, [0, 2, 1]]],
                                              color=this_color,
                                              lw=linewidth,
                                              alpha=alpha,
                                              linestyle=linestyle)
                        if group_neurons:
                            lc.set_gid(neuron.uuid)
                        ax.add_collection3d(lc)

                coords = np.vstack(coords)
                lim.append(coords.max(axis=0))
                lim.append(coords.min(axis=0))

                surf3D_collections.append([])

                if plot_soma and not isinstance(neuron.soma, type(None)):
                    soma = utils.make_iterable(neuron.soma)
                    for s in soma:
                        n = neuron.nodes.set_index('node_id').loc[s]
                        r = getattr(n, neuron.soma_radius) if isinstance(
                            neuron.soma_radius, str) else neuron.soma_radius

                        resolution = 20
                        u = np.linspace(0, 2 * np.pi, resolution)
                        v = np.linspace(0, np.pi, resolution)
                        x = r * np.outer(np.cos(u), np.sin(v)) + n.x
                        y = r * np.outer(np.sin(u), np.sin(v)) - n.y
                        z = r * np.outer(np.ones(np.size(u)), np.cos(v)) + n.z
                        surf = ax.plot_surface(x,
                                               z,
                                               y,
                                               color=this_color,
                                               shade=False,
                                               alpha=alpha)
                        if group_neurons:
                            surf.set_gid(neuron.uuid)

                        surf3D_collections[-1].append(surf)

        if (connectors or connectors_only) and neuron.has_connectors:
            if not cn_mesh_colors:
                cn_types = {0: 'red', 1: 'blue', 2: 'green', 3: 'magenta'}
            else:
                cn_types = {
                    0: this_color,
                    1: this_color,
                    2: this_color,
                    3: this_color
                }
            if method == '2d':
                for c in cn_types:
                    this_cn = neuron.connectors[neuron.connectors.relation ==
                                                c]
                    ax.scatter(this_cn.x.values, (-this_cn.y).values,
                               c=cn_types[c],
                               alpha=alpha,
                               zorder=4,
                               edgecolor='none',
                               s=cn_size)
                    ax.get_children()[-1].set_gid(f'CN_{neuron.uuid}')
            elif method in ['3d', '3d_complex']:
                all_cn = neuron.connectors
                c = [cn_types[i] for i in all_cn.relation.values]
                ax.scatter(all_cn.x.values,
                           all_cn.z.values,
                           -all_cn.y.values,
                           c=c,
                           s=cn_size,
                           depthshade=False,
                           edgecolor='none',
                           alpha=alpha)
                ax.get_children()[-1].set_gid(f'CN_{neuron.uuid}')

            coords = neuron.connectors[['x', 'y', 'z']].values
            coords[:, 1] *= -1
            lim.append(coords.max(axis=0))
            lim.append(coords.min(axis=0))

    for i, neuron in enumerate(
            config.tqdm(dotprops.itertuples(),
                        desc='Plt dotprops',
                        total=dotprops.shape[0],
                        leave=False,
                        disable=config.pbar_hide | len(dotprops) == 0)):
        # Prepare lines - this is based on nat:::plot3d.dotprops
        halfvect = neuron.points[['x_vec', 'y_vec', 'z_vec']] / 2

        starts = neuron.points[['x', 'y', 'z']].values - halfvect.values
        ends = neuron.points[['x', 'y', 'z']].values + halfvect.values

        try:
            this_color = dotprop_cmap[i]
        except BaseException:
            this_color = (.1, .1, .1)

        if method == '2d':
            # Add None between segments
            x_coords = [
                n for sublist in zip(starts[:, 0], ends[:, 0], [None] *
                                     starts.shape[0]) for n in sublist
            ]
            y_coords = [
                n for sublist in zip(starts[:, 1] * -1, ends[:, 1] *
                                     -1, [None] * starts.shape[0])
                for n in sublist
            ]

            this_line = mlines.Line2D(x_coords,
                                      y_coords,
                                      lw=linewidth,
                                      ls=linestyle,
                                      alpha=alpha,
                                      color=this_color,
                                      label='%s' % (neuron.gene_name))

            ax.add_line(this_line)

            # Add soma
            if plot_soma:
                s = mpatches.Circle((neuron.X, -neuron.Y),
                                    radius=2,
                                    alpha=alpha,
                                    fill=True,
                                    fc=this_color,
                                    zorder=4,
                                    edgecolor='none')
                ax.add_patch(s)
        elif method in ['3d', '3d_complex']:
            # Combine coords by weaving starts and ends together
            coords = np.empty((starts.shape[0] * 2, 3), dtype=starts.dtype)
            coords[0::2] = starts
            coords[1::2] = ends

            # Invert y-axis
            coords[:, 1] *= -1

            # For simple scenes, add whole neurons at a time
            # -> will speed up rendering
            if method == '3d':
                lc = Line3DCollection(np.split(coords[:, [0, 2, 1]],
                                               starts.shape[0]),
                                      color=this_color,
                                      label=neuron.gene_name,
                                      lw=linewidth,
                                      alpha=alpha,
                                      linestyle=linestyle)
                if group_neurons:
                    lc.set_gid(neuron.gene_name)
                ax.add_collection3d(lc)

            # For complex scenes, add each segment as a single collection
            # -> help preventing Z-order errors
            elif method == '3d_complex':
                for c in np.split(coords[:, [0, 2, 1]], starts.shape[0]):
                    lc = Line3DCollection([c],
                                          color=this_color,
                                          lw=linewidth,
                                          alpha=alpha,
                                          linestyle=linestyle)
                    if group_neurons:
                        lc.set_gid(neuron.gene_name)
                    ax.add_collection3d(lc)

            lim.append(coords.max(axis=0))
            lim.append(coords.min(axis=0))

            resolution = 20
            u = np.linspace(0, 2 * np.pi, resolution)
            v = np.linspace(0, np.pi, resolution)
            x = 2 * np.outer(np.cos(u), np.sin(v)) + neuron.X
            y = 2 * np.outer(np.sin(u), np.sin(v)) - neuron.Y
            z = 2 * np.outer(np.ones(np.size(u)), np.cos(v)) + neuron.Z
            surf = ax.plot_surface(x,
                                   z,
                                   y,
                                   color=this_color,
                                   shade=False,
                                   alpha=alpha)
            if group_neurons:
                surf.set_gid(neuron.gene_name)

    if points:
        for p in points:
            if method == '2d':
                default_settings = dict(c='black',
                                        zorder=4,
                                        edgecolor='none',
                                        s=1)
                default_settings.update(scatter_kws)
                default_settings = _fix_default_dict(default_settings)

                ax.scatter(p[:, 0], p[:, 1] * -1, **default_settings)
            elif method in ['3d', '3d_complex']:
                default_settings = dict(c='black',
                                        s=1,
                                        depthshade=False,
                                        edgecolor='none')
                default_settings.update(scatter_kws)
                default_settings = _fix_default_dict(default_settings)

                ax.scatter(p[:, 0], p[:, 2], p[:, 1] * -1, **default_settings)

            coords = p
            coords[:, 1] *= -1
            lim.append(coords.max(axis=0))
            lim.append(coords.min(axis=0))

    if autoscale:
        if method == '2d':
            ax.autoscale()
        elif method in ['3d', '3d_complex']:
            lim = np.vstack(lim)
            lim_min = lim.min(axis=0)
            lim_max = lim.max(axis=0)

            center = lim_min + (lim_max - lim_min) / 2
            max_dim = (lim_max - lim_min).max()

            new_min = center - max_dim / 2
            new_max = center + max_dim / 2

            ax.set_xlim(new_min[0], new_max[0])
            ax.set_ylim(new_min[2], new_max[2])
            ax.set_zlim(new_min[1], new_max[1])

    if scalebar is not None:
        # Convert sc size to nm
        sc_size = scalebar * 1000

        # Hard-coded offset from figure boundaries
        ax_offset = 1000

        if method == '2d':
            xlim = ax.get_xlim()
            ylim = ax.get_ylim()

            coords = np.array(
                [[xlim[0] + ax_offset, ylim[0] + ax_offset],
                 [xlim[0] + ax_offset + sc_size, ylim[0] + ax_offset]])

            sbar = mlines.Line2D(coords[:, 0],
                                 coords[:, 1],
                                 lw=3,
                                 alpha=.9,
                                 color='black')
            sbar.set_gid(f'{scalebar}_um')

            ax.add_line(sbar)
        elif method in ['3d', '3d_complex']:
            left = lim_min[0] + ax_offset
            bottom = lim_min[1] + ax_offset
            front = lim_min[2] + ax_offset

            sbar = [
                np.array([[left, front, bottom], [left, front, bottom]]),
                np.array([[left, front, bottom], [left, front, bottom]]),
                np.array([[left, front, bottom], [left, front, bottom]])
            ]
            sbar[0][1][0] += sc_size
            sbar[1][1][1] += sc_size
            sbar[2][1][2] += sc_size

            lc = Line3DCollection(sbar, color='black', lw=1)
            lc.set_gid(f'{scalebar}_um')
            ax.add_collection3d(lc)

    def set_depth():
        """Sets depth information for neurons according to camera position."""

        # Modifier for soma coordinates
        modifier = np.array([1, 1, -1])

        # Get all coordinates
        all_co = np.concatenate(
            [lc._segments3d[:, 0, :] for lc in line3D_collections], axis=0)

        # Get projected coordinates
        proj_co = mpl_toolkits.mplot3d.proj3d.proj_points(
            all_co, ax.get_proj())

        # Get min and max of z coordinates
        z_min, z_max = min(proj_co[:, 2]), max(proj_co[:, 2])

        # Generate a new normaliser
        norm = plt.Normalize(vmin=z_min, vmax=z_max)

        # Go over all neurons and update Z information
        for neuron, lc, surf in zip(skdata, line3D_collections,
                                    surf3D_collections):
            # Get this neurons coordinates
            this_co = lc._segments3d[:, 0, :]

            # Get projected coordinates
            this_proj = mpl_toolkits.mplot3d.proj3d.proj_points(
                this_co, ax.get_proj())

            # Normalise z coordinates
            ns = norm(this_proj[:, 2]).data

            # Set array
            lc.set_array(ns)

            # No need for normaliser - already happened
            lc.set_norm(None)

            if not isinstance(neuron.soma, type(None)):
                # Get depth of soma(s)
                soma = utils.make_iterable(neuron.soma)
                soma_co = neuron.nodes.set_index('node_id').loc[soma][[
                    'x', 'z', 'y'
                ]].values
                soma_proj = mpl_toolkits.mplot3d.proj3d.proj_points(
                    soma_co * modifier, ax.get_proj())
                soma_cs = norm(soma_proj[:, 2]).data

                # Set soma color
                for cs, s in zip(soma_cs, surf):
                    s.set_color(cmap(cs))

    def Update(event):
        set_depth()

    if depth_coloring:
        if method == '2d' and depth_scale:
            fig.colorbar(line, ax=ax, fraction=.075, shrink=.5, label='Depth')
        elif method == '3d':
            fig.canvas.mpl_connect('draw_event', Update)
            set_depth()

    plt.axis('off')

    logger.debug('Done. Use matplotlib.pyplot.show() to show plot.')

    return fig, ax
def plot_tree(tree, figure_name, color_by_trait, initial_branch_width,
              tip_size, start_date, end_date, include_color_bar):
    """Plot a BioPython Phylo tree in the BALTIC-style.
    """
    # Plot H3N2 tree in BALTIC style from Bio.Phylo tree.
    mpl.rcParams['savefig.dpi'] = 120
    mpl.rcParams['figure.dpi'] = 100

    mpl.rcParams['font.weight'] = 300
    mpl.rcParams['axes.labelweight'] = 300
    mpl.rcParams['font.size'] = 14

    yvalues = [node.yvalue for node in tree.find_clades()]
    y_span = max(yvalues)
    y_unit = y_span / float(len(yvalues))

    # Setup colors.
    trait_name = color_by_trait
    traits = [k.attr[trait_name] for k in tree.find_clades()]
    norm = mpl.colors.Normalize(min(traits), max(traits))
    cmap = mpl.cm.viridis

    #
    # Setup the figure grid.
    #

    if include_color_bar:
        fig = plt.figure(figsize=(8, 6), facecolor='w')
        gs = gridspec.GridSpec(2,
                               1,
                               height_ratios=[14, 1],
                               width_ratios=[1],
                               hspace=0.1,
                               wspace=0.1)
        ax = fig.add_subplot(gs[0])
        colorbar_ax = fig.add_subplot(gs[1])
    else:
        fig = plt.figure(figsize=(8, 4), facecolor='w')
        gs = gridspec.GridSpec(1, 1)
        ax = fig.add_subplot(gs[0])

    L = len([k for k in tree.find_clades() if k.is_terminal()])

    # Setup arrays for tip and internal node coordinates.
    tip_circles_x = []
    tip_circles_y = []
    tip_circles_color = []
    tip_circle_sizes = []
    node_circles_x = []
    node_circles_y = []
    node_circles_color = []
    node_line_widths = []
    node_line_segments = []
    node_line_colors = []
    branch_line_segments = []
    branch_line_widths = []
    branch_line_colors = []
    branch_line_labels = []

    for k in tree.find_clades():  ## iterate over objects in tree
        x = k.attr["num_date"]  ## or from x position determined earlier
        y = k.yvalue  ## get y position from .drawTree that was run earlier, but could be anything else

        if k.parent is None:
            xp = None
        else:
            xp = k.parent.attr[
                "num_date"]  ## get x position of current object's parent

        if x == None:  ## matplotlib won't plot Nones, like root
            x = 0.0
        if xp == None:
            xp = x

        c = 'k'
        if trait_name in k.attr:
            c = cmap(norm(k.attr[trait_name]))

        branchWidth = 2
        if k.is_terminal():  ## if leaf...
            s = tip_size  ## tip size can be fixed

            tip_circle_sizes.append(s)
            tip_circles_x.append(x)
            tip_circles_y.append(y)
            tip_circles_color.append(c)
        else:  ## if node...
            k_leaves = [
                child for child in k.find_clades() if child.is_terminal()
            ]

            # Scale branch widths by the number of tips.
            branchWidth += initial_branch_width * len(k_leaves) / float(L)

            if len(k.clades) == 1:
                node_circles_x.append(x)
                node_circles_y.append(y)
                node_circles_color.append(c)

            ax.plot([x, x], [k.clades[-1].yvalue, k.clades[0].yvalue],
                    lw=branchWidth,
                    color=c,
                    ls='-',
                    zorder=9,
                    solid_capstyle='round')

        branch_line_segments.append([(xp, y), (x, y)])
        branch_line_widths.append(branchWidth)
        branch_line_colors.append(c)

    branch_lc = LineCollection(branch_line_segments, zorder=9)
    branch_lc.set_color(branch_line_colors)
    branch_lc.set_linewidth(branch_line_widths)
    branch_lc.set_label(branch_line_labels)
    branch_lc.set_linestyle("-")
    ax.add_collection(branch_lc)

    # Add circles for tips and internal nodes.
    tip_circle_sizes = np.array(tip_circle_sizes)
    ax.scatter(tip_circles_x,
               tip_circles_y,
               s=tip_circle_sizes,
               facecolor=tip_circles_color,
               edgecolor='none',
               zorder=11)  ## plot circle for every tip
    ax.scatter(tip_circles_x,
               tip_circles_y,
               s=tip_circle_sizes * 2,
               facecolor='k',
               edgecolor='none',
               zorder=10)  ## plot black circle underneath
    ax.scatter(
        node_circles_x,
        node_circles_y,
        facecolor=node_circles_color,
        s=50,
        edgecolor='none',
        zorder=10,
        lw=2,
        marker='|'
    )  ## mark every node in the tree to highlight that it's a multitype tree

    #ax.set_ylim(-10, y_span - 300)

    ax.spines['top'].set_visible(False)  ## no axes
    ax.spines['right'].set_visible(False)
    ax.spines['left'].set_visible(False)

    ax.grid(axis='x', ls='-', color='grey')
    ax.tick_params(axis='y', size=0)
    ax.set_yticklabels([])

    if start_date:
        # Always add a buffer to the left edge of the plot so data up to the
        # given end date can be clearly seen.
        ax.set_xlim(left=timestamp_to_float(pd.to_datetime(start_date)) - 2.0)

    if end_date:
        # Always add a buffer of 3 months to the right edge of the plot so data
        # up to the given end date can be clearly seen.
        ax.set_xlim(right=timestamp_to_float(pd.to_datetime(end_date)) + 0.25)

    if include_color_bar:
        cb1 = mpl.colorbar.ColorbarBase(colorbar_ax,
                                        cmap=cmap,
                                        norm=norm,
                                        orientation='horizontal')
        cb1.set_label(color_by_trait)

    gs.tight_layout(fig)
    plt.savefig(figure_name)
Esempio n. 20
0
    def plot_parameteric(
        self,
        spins=None,
        vmin=None,
        vmax=None,
        width_mask=None,
        color_mask=None,
        width_weights=None,
        color_weights=None,
    ):
        if width_weights is None:
            width_weights = np.ones_like(self.ebs.bands)
            linewidth = settings.ebs.linewidth
        else:
            linewidth = [l*5 for l in settings.ebs.linewidth]

        if spins is None:
            spins = range(self.ebs.nspins)
        if self.ebs.is_non_collinear:
            spins = [0]
        

        if width_mask is not None or color_mask is not None:
            if width_mask is not None:
                mbands = np.ma.masked_array(
                    self.ebs.bands, np.abs(width_weights) < width_mask)
            if color_mask is not None:
                mbands = np.ma.masked_array(
                    self.ebs.bands, np.abs(color_weights) < color_mask)
        else:
            # Faking a mask, all elemtnet are included
            mbands = np.ma.masked_array(self.ebs.bands, False)

        if color_weights is not None:

            if vmin is None:
                vmin = color_weights.min()
            if vmax is None:
                vmax = color_weights.max()
            print("normalizing to : ", (vmin, vmax))
            norm = matplotlib.colors.Normalize(vmin, vmax)

        for ispin in spins:
            for iband in range(self.ebs.nbands):
                points = np.array(
                    [self.x, mbands[:, iband, ispin]]).T.reshape(-1, 1, 2)
                segments = np.concatenate([points[:-1], points[1:]], axis=1)
                # this is to delete the segments on the high sym points
                x = self.x
                # segments = np.delete(
                #     segments, np.where(x[1:] == x[:-1])[0], axis=0)
                if color_weights is None:
                    lc = LineCollection(
                        segments, colors=settings.ebs.color[ispin], linestyle=settings.ebs.linestyle[ispin])
                else:
                    lc = LineCollection(
                        segments, cmap=plt.get_cmap(settings.ebs.color_map), norm=norm)
                    lc.set_array(color_weights[:, iband, ispin])
                lc.set_linewidth(
                    width_weights[:, iband, ispin]*linewidth[ispin])
                lc.set_linestyle(settings.ebs.linestyle[ispin])
                handle = self.ax.add_collection(lc)
            # if color_weights is not None:
            #     handle.set_color(color_map[iweight][:-1].lower())
            handle.set_linewidth(linewidth)
            self.handles.append(handle)

        if settings.ebs.plot_color_bar and color_weights is not None:
            cb = self.fig.colorbar(lc, ax=self.ax)
            cb.ax.tick_params(labelsize=20)
Esempio n. 21
0
def QuickPlot(conf=None,
              bodies=None,
              xaxis=None,
              yaxis=None,
              aaxis=None,
              interactive=True,
              nolog=False):
    '''

    '''

    # Assign defaults
    if conf is None:
        conf = GetConf()
    if bodies is None:
        bodies = conf.bodies
    if xaxis is None:
        xaxis = conf.xaxis
    if yaxis is None:
        yaxis = conf.yaxis
    if aaxis is None:
        aaxis = conf.aaxis
    if nolog:
        conf.xlog = False
        conf.ylog = False

    # Output object
    output = GetArrays(bodies=bodies)

    # Names of all available params
    param_names = list(
        set([param.name for body in output.bodies for param in body.params]))

    if len(param_names) == 0:
        raise Exception("There don't seem to be any parameters to be plotted.")

    # The x-axis parameter
    x = param_names[np.argmax(
        np.array(
            [name.lower().startswith(xaxis.lower()) for name in param_names]))]
    if not x.lower().startswith(xaxis.lower()):
        raise Exception('Parameter not understood: %s.' % xaxis)

    # The array of y-axis parameters
    # Ensure it's a list
    if type(yaxis) is str:
        yaxis = [yaxis]

    if len(yaxis) == 0:
        # User didn't specify any; let's plot all of them
        yarr = list(sorted(set(param_names) - set([x])))
    else:
        yarr = []
        for yn in yaxis:
            y = param_names[np.argmax(
                np.array([
                    name.lower().startswith(yn.lower()) for name in param_names
                ]))]
            if not y.lower().startswith(yn.lower()):
                raise Exception('Parameter not found: %s.' % yn)
            yarr.append(y)

    # The alpha parameter
    if aaxis is not None and aaxis != 'None':
        a = param_names[np.argmax(
            np.array([
                name.lower().startswith(aaxis.lower()) for name in param_names
            ]))]
        if not a.lower().startswith(aaxis.lower()):
            raise Exception('Parameter not found: %s.' % aaxis)

    # We will only plot up to a maximum of ``conf.maxrows`` if columns are off
    if (not conf.columns) and len(yarr) > conf.maxrows:
        yarr = yarr[:conf.maxrows]
        rows = conf.maxrows
    elif conf.columns and len(yarr) > conf.maxrows:
        columns = int(np.ceil(float(len(yarr)) / conf.maxrows))
        rows = conf.maxrows
    else:
        columns = 1
        rows = len(yarr)

    # Correct for border cases
    if len(yarr) <= (columns * (rows - 1)):
        rows -= 1
    elif len(yarr) <= ((columns - 1) * rows):
        columns -= 1

    # Set up the plot
    # See http://stackoverflow.com/a/19627237
    mpl.rcParams['figure.autolayout'] = False
    fig = pl.figure(1, figsize=(conf.figwidth, conf.figheight))
    gs = gridspec.GridSpec(rows, columns)
    for i, ss in enumerate(gs):
        if i == 0:
            ax = [fig.add_subplot(gs[0])]
        else:
            ax.append(fig.add_subplot(ss, sharex=ax[0]))

    # Hide empty subplots
    empty = range(len(yarr), rows * columns)
    for i in empty:
        ax[i].set_visible(False)

    # Loop over all parameters (one subplot per each)
    for i, y in enumerate(yarr):

        # Axes limits
        ymin = np.inf
        ymax = -np.inf
        xmin = np.inf
        xmax = -np.inf

        # Loop over all bodies
        for b, body in enumerate(output.bodies):

            # Get indices of the parameters
            if len(body.params):
                xi = np.where(
                    np.array([param.name for param in body.params]) == x)[0]
                yi = np.where(
                    np.array([param.name for param in body.params]) == y)[0]
            else:
                xi = np.array([], dtype=int)
                yi = np.array([], dtype=int)

            if aaxis is not None and aaxis != 'None':
                ai = np.where(
                    a == np.array([param.name for param in body.params]))[0]
            else:
                ai = []

            # Are both x and y arrays preset for this body?
            if len(xi) and len(yi):
                xi = xi[0]
                yi = yi[0]
            else:
                continue

            if len(ai):
                ai = ai[0]
            else:
                ai = None

            # Get the arrays
            xpts = body.params[xi].array
            ypts = body.params[yi].array

            # Decide whether to plot individual legends
            if conf.legend_all:
                label = body.name
            else:
                label = None

            # Should we plot the first point if x = 0?
            if xpts[0] == 0. and conf.xlog and conf.skip_xzero_log:
                xpts = xpts[1:]
                ypts = ypts[1:]

            # Plot the curve
            if ai is None:

                # A simple solid color line
                ax[i].plot(xpts,
                           ypts,
                           conf.line_styles[b],
                           label=label,
                           lw=conf.linewidth)
            else:

                # Let's get fancy: make the curve opacity proportional
                # to the `aaxis` parameter
                apts = body.params[ai].array

                # Make logarithmic if necessary
                if conf.alog:
                    if apts[0] == 0.:
                        apts = apts[1:]
                    apts = np.log10(apts)

                points = np.array([xpts, ypts]).T.reshape(-1, 1, 2)
                segments = np.concatenate([points[:-1], points[1:]], axis=1)
                lc = LineCollection(
                    segments,
                    cmap=AlphaMap(
                        *ColorConverter().to_rgb(conf.line_styles[b][0])),
                    norm=pl.Normalize(np.nanmin(apts), np.nanmax(apts)))
                lc.set_array(apts)
                lc.set_linestyle(conf.line_styles[b][1:])
                lc.set_linewidth(conf.linewidth)
                lc.set_label(label)
                ax[i].add_collection(lc)

            # Limits
            if np.nanmin(xpts) < xmin:
                xmin = np.nanmin(xpts)
            if np.nanmin(ypts) < ymin:
                ymin = np.nanmin(ypts)
            if np.nanmax(xpts) > xmax:
                xmax = np.nanmax(xpts)
            if np.nanmax(ypts) > ymax:
                ymax = np.nanmax(ypts)

            # Labels
            ax[i].set_xlabel(body.params[xi].label(conf.short_labels),
                             fontsize=conf.xlabel_fontsize)
            ax[i].set_ylabel(body.params[yi].label(conf.short_labels,
                                                   conf.maxylabelsize),
                             fontsize=conf.ylabel_fontsize)

            # Tick sizes
            for tick in ax[i].xaxis.get_major_ticks():
                tick.label.set_fontsize(conf.xticklabel_fontsize)
            for tick in ax[i].yaxis.get_major_ticks():
                tick.label.set_fontsize(conf.yticklabel_fontsize)

        # Log scale?
        if conf.xlog:
            if np.log(xmax) - np.log(xmin) > conf.xlog:
                if xmin > 0:
                    ax[i].set_xscale('log')
        if conf.ylog:
            if np.log(ymax) - np.log(ymin) > conf.ylog:
                if ymin > 0:
                    ax[i].set_yscale('log')

        # Tighten things up a bit
        if i < len(yarr) - columns:
            if conf.tight_layout:
                ax[i].set_xticklabels([])
            ax[i].set_xlabel('')

        # Add y-axis margins (doesn't work well with log)
        ax[i].margins(0., conf.ymargin)

        # Add a legend
        if conf.legend_all:
            ax[i].legend(loc=conf.legend_loc, fontsize=conf.legend_fontsize)
        elif i == 0:
            xlim = ax[i].get_xlim()
            ylim = ax[i].get_ylim()
            for b, body in enumerate(output.bodies):
                # HACK: Plot a line of length zero in the center
                # of the plot so that it will show up on the legend
                foo = ax[i].plot([(xlim[0] + xlim[1]) / 2.],
                                 [(ylim[0] + ylim[1]) / 2.],
                                 conf.line_styles[b],
                                 label=body.name)
            ax[i].legend(loc=conf.legend_loc, fontsize=conf.legend_fontsize)

    # Add title
    if conf.title:
        if len(yarr) == 1:
            pl.title('VPLANET: %s' % output.sysname, fontsize=24)
        else:
            pl.suptitle('VPLANET: %s' % output.sysname, fontsize=24)

    try:
        gs.tight_layout(fig, rect=[0, 0.03, 1, 0.95])
    except:
        # No biggie
        pass

    # Show or save?
    if interactive and conf.interactive:
        pl.show()
    else:
        fig.savefig(conf.figname, bbox_inches='tight')

    return fig, ax
Esempio n. 22
0
    def animate(self,
                max_turns: int = 1000,
                max_laps: int = 5,
                as_gif=False,
                filename='/tmp/pods',
                reset: bool = True,
                trail_len: int = 20,
                highlight_checks: bool = False,
                show_vel: bool = False,
                fps: int = 10):
        """
        Generate an animated GIF of the players running through the game
        :param show_vel Whether to draw a vector showing each Pod's velocity
        :param highlight_checks If true, a pod's next check will change to the pod's color
        :param trail_len Number of turns behind the pod to show its path
        :param as_gif If True, generate a GIF, otherwise an HTML animation
        :param max_turns Max number of turns to play
        :param max_laps Max number of laps for any player
        :param filename Where to store the generated file
        :param reset Whether to reset the state of each Player first
        :param fps Frames per second
        """
        if len(self.hist) < 1: self.record(max_turns, max_laps, reset)

        _prepare_size()
        self.__prepare_for_world()

        #########################################
        # Create the objects for display
        #########################################

        art = {
            'check': [],
            'pod': [],
            'color': [],
            'trails': [],
            'vel': [],
            'count':
            0,
            'log':
            JupyterLog(),
            'turnCounter':
            self.ax.text(-PADDING,
                         Constants.world_y() + PADDING,
                         'Turn 0',
                         fontsize=14)
        }

        fa = _get_field_artist()
        self.ax.add_artist(fa)

        for (idx, check) in enumerate(self.board.checkpoints):
            ca = self.__draw_check(check, idx)
            self.ax.add_artist(ca)
            art['check'].append(ca)

        for (idx, p) in enumerate(self.players):
            color = _gen_color(idx)
            pa = _get_pod_artist(p.pod, color)
            self.ax.add_artist(pa)
            art['pod'].append(pa)
            art['color'].append(color)
        plt.legend(art['pod'], self.labels, loc='lower right')

        if trail_len > 0:
            for i in range(len(self.players)):
                lc = LineCollection([], colors=art['color'][i])
                lc.set_segments([])
                lc.set_linestyle(':')
                self.ax.add_collection(lc)
                art['trails'].append(lc)

        if show_vel:
            for p in self.players:
                xy = _vel_coords(p.pod)
                line = self.ax.plot(xy[0], xy[1])[0]
                art['vel'].append(line)

        all_updates = [
            fa, *art['check'], *art['pod'], *art['trails'], *art['vel'],
            art['turnCounter']
        ]

        #########################################
        # Define the animation function
        #########################################

        def do_animate(frame_idx: int):
            art['log'].replace("Drawing frame {}".format(art['count']))
            art['count'] += 1

            check_colors = [
                'royalblue' for _ in range(len(self.board.checkpoints))
            ]
            frame_data = self.hist[frame_idx]

            # Update the pods
            for (p_idx, player_log) in enumerate(frame_data):
                pod = player_log['pod']
                theta1, theta2, center = _pod_wedge_info(pod)
                art['pod'][p_idx].set_center((center.x, center.y))
                art['pod'][p_idx].set_theta1(theta1)
                art['pod'][p_idx].set_theta2(theta2)
                art['pod'][p_idx]._recompute_path()  # pylint: disable=protected-access

                check_colors[pod.nextCheckId] = art['color'][p_idx]

                # Update the velocities
                if show_vel:
                    xy = _vel_coords(pod)
                    art['vel'][p_idx].set_xdata(xy[0])
                    art['vel'][p_idx].set_ydata(xy[1])

            # Update the trails
            if frame_idx > 0 and trail_len > 0:
                for p_idx in range(len(self.players)):
                    line = _to_line(self.hist[frame_idx - 1][p_idx]['pod'].pos,
                                    frame_data[p_idx]['pod'].pos)
                    segs = art['trails'][p_idx].get_segments() + [line]
                    art['trails'][p_idx].set_segments(segs[-trail_len:])

            # Update the check colors
            if highlight_checks:
                for col, check_art in zip(check_colors, art['check']):
                    check_art.set_color(col)

            # Update the turn counter
            art['turnCounter'].set_text('Turn ' + str(frame_idx))

            return all_updates

        #########################################
        # Create the animation
        #########################################

        anim = FuncAnimation(
            plt.gcf(),
            do_animate,
            frames=len(self.hist),
        )
        plt.close(self.fig)

        if as_gif:
            if not filename.endswith(".gif"): filename = filename + ".gif"
            anim.save(filename, writer=PillowWriter(fps=fps))
            return Image(filename=filename)
        else:
            if not filename.endswith(".html"): filename = filename + ".html"
            anim.save(filename,
                      writer=HTMLWriter(fps=fps,
                                        embed_frames=True,
                                        default_mode='loop'))
            path = Path(filename)
            return HTML(path.read_text())
Esempio n. 23
0
    def readshapefileext(self,
                         shapefile,
                         name,
                         drawbounds=True,
                         zorder=None,
                         linewidth=0.5,
                         color='k',
                         antialiased=1,
                         ax=None,
                         default_encoding='utf-8',
                         linestyle='-'):
        """
        Read in shape file, optionally draw boundaries on map.

        .. note::
          - Assumes shapes are 2D
          - only works for Point, MultiPoint, Polyline and Polygon shapes.
          - vertices/points must be in geographic (lat/lon) coordinates.

        Mandatory Arguments:

        .. tabularcolumns:: |l|L|

        ==============   ====================================================
        Argument         Description
        ==============   ====================================================
        shapefile        path to shapefile components.  Example:
                         shapefile='/home/jeff/esri/world_borders' assumes
                         that world_borders.shp, world_borders.shx and
                         world_borders.dbf live in /home/jeff/esri.
        name             name for Basemap attribute to hold the shapefile
                         vertices or points in map projection
                         coordinates. Class attribute name+'_info' is a list
                         of dictionaries, one for each shape, containing
                         attributes of each shape from dbf file, For
                         example, if name='counties', self.counties
                         will be a list of x,y vertices for each shape in
                         map projection  coordinates and self.counties_info
                         will be a list of dictionaries with shape
                         attributes.  Rings in individual Polygon
                         shapes are split out into separate polygons, and
                         additional keys 'RINGNUM' and 'SHAPENUM' are added
                         to the shape attribute dictionary.
        ==============   ====================================================

        The following optional keyword arguments are only relevant for Polyline
        and Polygon shape types, for Point and MultiPoint shapes they are
        ignored.

        .. tabularcolumns:: |l|L|

        ==============   ====================================================
        Keyword          Description
        ==============   ====================================================
        drawbounds       draw boundaries of shapes (default True).
        zorder           shape boundary zorder (if not specified,
                         default for mathplotlib.lines.LineCollection
                         is used).
        linewidth        shape boundary line width (default 0.5)
        color            shape boundary line color (default black)
        antialiased      antialiasing switch for shape boundaries
                         (default True).
        ax               axes instance (overrides default axes instance)
        ==============   ====================================================

        A tuple (num_shapes, type, min, max) containing shape file info
        is returned.
        num_shapes is the number of shapes, type is the type code (one of
        the SHPT* constants defined in the shapelib module, see
        http://shapelib.maptools.org/shp_api.html) and min and
        max are 4-element lists with the minimum and maximum values of the
        vertices. If ``drawbounds=True`` a
        matplotlib.patches.LineCollection object is appended to the tuple.
        """
        import shapefile as shp
        from shapefile import Reader
        shp.default_encoding = default_encoding
        if not os.path.exists('%s.shp' % shapefile):
            raise IOError('cannot locate %s.shp' % shapefile)
        if not os.path.exists('%s.shx' % shapefile):
            raise IOError('cannot locate %s.shx' % shapefile)
        if not os.path.exists('%s.dbf' % shapefile):
            raise IOError('cannot locate %s.dbf' % shapefile)
        # open shapefile, read vertices for each object, convert
        # to map projection coordinates (only works for 2D shape types).
        try:
            shf = Reader(shapefile)
        except:
            raise IOError('error reading shapefile %s.shp' % shapefile)
        fields = shf.fields
        coords = []
        attributes = []
        msg = dedent("""
        shapefile must have lat/lon vertices  - it looks like this one has vertices
        in map projection coordinates. You can convert the shapefile to geographic
        coordinates using the shpproj utility from the shapelib tools
        (http://shapelib.maptools.org/shapelib-tools.html)""")
        shptype = shf.shapes()[0].shapeType
        bbox = shf.bbox.tolist()
        info = (shf.numRecords, shptype, bbox[0:2] + [0., 0.],
                bbox[2:] + [0., 0.])
        npoly = 0
        for shprec in shf.shapeRecords():
            shp = shprec.shape
            rec = shprec.record
            npoly = npoly + 1
            if shptype != shp.shapeType:
                raise ValueError(
                    'readshapefile can only handle a single shape type per file'
                )
            if shptype not in [1, 3, 5, 8]:
                raise ValueError(
                    'readshapefile can only handle 2D shape types')
            verts = shp.points
            if shptype in [1, 8]:  # a Point or MultiPoint shape.
                lons, lats = list(zip(*verts))
                if max(lons) > 721. or min(lons) < -721. or max(
                        lats) > 90.01 or min(lats) < -90.01:
                    raise ValueError(msg)
                # if latitude is slightly greater than 90, truncate to 90
                lats = [max(min(lat, 90.0), -90.0) for lat in lats]
                if len(verts) > 1:  # MultiPoint
                    x, y = self(lons, lats)
                    coords.append(list(zip(x, y)))
                else:  # single Point
                    x, y = self(lons[0], lats[0])
                    coords.append((x, y))
                attdict = {}
                for r, key in zip(rec, fields[1:]):
                    attdict[key[0]] = r
                attributes.append(attdict)
            else:  # a Polyline or Polygon shape.
                parts = shp.parts.tolist()
                ringnum = 0
                for indx1, indx2 in zip(parts, parts[1:] + [len(verts)]):
                    ringnum = ringnum + 1
                    lons, lats = list(zip(*verts[indx1:indx2]))
                    if max(lons) > 721. or min(lons) < -721. or max(
                            lats) > 90.01 or min(lats) < -90.01:
                        raise ValueError(msg)
                    # if latitude is slightly greater than 90, truncate to 90
                    lats = [max(min(lat, 90.0), -90.0) for lat in lats]
                    x, y = self(lons, lats)
                    coords.append(list(zip(x, y)))
                    attdict = {}
                    for r, key in zip(rec, fields[1:]):
                        attdict[key[0]] = r
                    # add information about ring number to dictionary.
                    attdict['RINGNUM'] = ringnum
                    attdict['SHAPENUM'] = npoly
                    attributes.append(attdict)
        # draw shape boundaries for polylines, polygons  using LineCollection.
        if shptype not in [1, 8] and drawbounds:
            # get current axes instance (if none specified).
            ax = ax or self._check_ax()
            # make LineCollections for each polygon.
            lines = LineCollection(coords, antialiaseds=(1, ))
            lines.set_color(color)
            lines.set_linewidth(linewidth)
            lines.set_linestyle(linestyle)
            lines.set_label('_nolabel_')
            if zorder is not None:
                lines.set_zorder(zorder)
            ax.add_collection(lines)
            # set axes limits to fit map region.
            self.set_axes_limits(ax=ax)
            # clip boundaries to map limbs
            lines, c = self._cliplimb(ax, lines)
            info = info + (lines, )
        self.__dict__[name] = coords
        self.__dict__[name + '_info'] = attributes
        return info
Esempio n. 24
0
class ScatterLayerArtist(MatplotlibLayerArtist):

    _layer_state_cls = ScatterLayerState

    def __init__(self, axes, viewer_state, layer_state=None, layer=None):

        super(ScatterLayerArtist, self).__init__(axes,
                                                 viewer_state,
                                                 layer_state=layer_state,
                                                 layer=layer)

        # Watch for changes in the viewer state which would require the
        # layers to be redrawn
        self._viewer_state.add_global_callback(self._update_scatter)
        self.state.add_global_callback(self._update_scatter)

        # Scatter
        self.scatter_artist = self.axes.scatter([], [])
        self.plot_artist = self.axes.plot([], [], 'o', mec='none')[0]
        self.errorbar_artist = self.axes.errorbar([], [], fmt='none')
        self.vector_artist = None
        self.line_collection = LineCollection(np.zeros((0, 2, 2)))
        self.axes.add_collection(self.line_collection)

        # Scatter density
        self.density_auto_limits = DensityMapLimits()
        self.density_artist = ScatterDensityArtist(
            self.axes, [], [],
            color='white',
            vmin=self.density_auto_limits.min,
            vmax=self.density_auto_limits.max)
        self.axes.add_artist(self.density_artist)

        self.mpl_artists = [
            self.scatter_artist, self.plot_artist, self.errorbar_artist,
            self.vector_artist, self.line_collection, self.density_artist
        ]
        self.errorbar_index = 2
        self.vector_index = 3

        self.reset_cache()

    def reset_cache(self):
        self._last_viewer_state = {}
        self._last_layer_state = {}

    @defer_draw
    def _update_data(self, changed):

        # Layer artist has been cleared already
        if len(self.mpl_artists) == 0:
            return

        try:
            x = self.layer[self._viewer_state.x_att].ravel()
        except (IncompatibleAttribute, IndexError):
            # The following includes a call to self.clear()
            self.disable_invalid_attributes(self._viewer_state.x_att)
            return
        else:
            self.enable()

        try:
            y = self.layer[self._viewer_state.y_att].ravel()
        except (IncompatibleAttribute, IndexError):
            # The following includes a call to self.clear()
            self.disable_invalid_attributes(self._viewer_state.y_att)
            return
        else:
            self.enable()

        if self.state.markers_visible:
            if self.state.density_map:
                self.density_artist.set_xy(x, y)
                self.plot_artist.set_data([], [])
                self.scatter_artist.set_offsets(np.zeros((0, 2)))
            else:
                if self.state.cmap_mode == 'Fixed' and self.state.size_mode == 'Fixed':
                    # In this case we use Matplotlib's plot function because it has much
                    # better performance than scatter.
                    self.plot_artist.set_data(x, y)
                    self.scatter_artist.set_offsets(np.zeros((0, 2)))
                    self.density_artist.set_xy([], [])
                else:
                    self.plot_artist.set_data([], [])
                    offsets = np.vstack((x, y)).transpose()
                    self.scatter_artist.set_offsets(offsets)
                    self.density_artist.set_xy([], [])
        else:
            self.plot_artist.set_data([], [])
            self.scatter_artist.set_offsets(np.zeros((0, 2)))
            self.density_artist.set_xy([], [])

        if self.state.line_visible:
            if self.state.cmap_mode == 'Fixed':
                points = np.array([x, y]).transpose()
                self.line_collection.set_segments([points])
            else:
                # In the case where we want to color the line, we need to over
                # sample the line by a factor of two so that we can assign the
                # correct colors to segments - if we didn't do this, then
                # segments on one side of a point would be a different color
                # from the other side. With oversampling, we can have half a
                # segment on either side of a point be the same color as a
                # point
                x_fine = np.zeros(len(x) * 2 - 1, dtype=float)
                y_fine = np.zeros(len(y) * 2 - 1, dtype=float)
                x_fine[::2] = x
                x_fine[1::2] = 0.5 * (x[1:] + x[:-1])
                y_fine[::2] = y
                y_fine[1::2] = 0.5 * (y[1:] + y[:-1])
                points = np.array([x_fine,
                                   y_fine]).transpose().reshape(-1, 1, 2)
                segments = np.concatenate([points[:-1], points[1:]], axis=1)
                self.line_collection.set_segments(segments)
        else:
            self.line_collection.set_segments(np.zeros((0, 2, 2)))

        for eartist in list(self.errorbar_artist[2]):
            if eartist is not None:
                try:
                    eartist.remove()
                except ValueError:
                    pass
                except AttributeError:  # Matplotlib < 1.5
                    pass

        if self.vector_artist is not None:
            self.vector_artist.remove()
            self.vector_artist = None

        if self.state.vector_visible:

            if self.state.vx_att is not None and self.state.vy_att is not None:

                vx = self.layer[self.state.vx_att].ravel()
                vy = self.layer[self.state.vy_att].ravel()

                if self.state.vector_mode == 'Polar':
                    ang = vx
                    length = vy
                    # assume ang is anti clockwise from the x axis
                    vx = length * np.cos(np.radians(ang))
                    vy = length * np.sin(np.radians(ang))

            else:
                vx = None
                vy = None

            if self.state.vector_arrowhead:
                hw = 3
                hl = 5
            else:
                hw = 1
                hl = 0

            v = np.hypot(vx, vy)
            vmax = np.nanmax(v)
            vx = vx / vmax
            vy = vy / vmax

            self.vector_artist = self.axes.quiver(
                x,
                y,
                vx,
                vy,
                units='width',
                pivot=self.state.vector_origin,
                headwidth=hw,
                headlength=hl,
                scale_units='width',
                scale=10 / self.state.vector_scaling)
            self.mpl_artists[self.vector_index] = self.vector_artist

        if self.state.xerr_visible or self.state.yerr_visible:

            if self.state.xerr_visible and self.state.xerr_att is not None:
                xerr = self.layer[self.state.xerr_att].ravel()
            else:
                xerr = None

            if self.state.yerr_visible and self.state.yerr_att is not None:
                yerr = self.layer[self.state.yerr_att].ravel()
            else:
                yerr = None

            self.errorbar_artist = self.axes.errorbar(x,
                                                      y,
                                                      fmt='none',
                                                      xerr=xerr,
                                                      yerr=yerr)
            self.mpl_artists[self.errorbar_index] = self.errorbar_artist

    @defer_draw
    def _update_visual_attributes(self, changed, force=False):

        if not self.enabled:
            return

        if self.state.markers_visible:

            if self.state.density_map:

                if self.state.cmap_mode == 'Fixed':
                    if force or 'color' in changed or 'cmap_mode' in changed:
                        self.density_artist.set_color(self.state.color)
                        self.density_artist.set_c(None)
                        self.density_artist.set_clim(
                            self.density_auto_limits.min,
                            self.density_auto_limits.max)
                elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                    c = self.layer[self.state.cmap_att].ravel()
                    set_mpl_artist_cmap(self.density_artist, c, self.state)

                if force or 'stretch' in changed:
                    self.density_artist.set_norm(
                        ImageNormalize(
                            stretch=STRETCHES[self.state.stretch]()))

                if force or 'dpi' in changed:
                    self.density_artist.set_dpi(self._viewer_state.dpi)

                if force or 'density_contrast' in changed:
                    self.density_auto_limits.contrast = self.state.density_contrast
                    self.density_artist.stale = True

            else:

                if self.state.cmap_mode == 'Fixed' and self.state.size_mode == 'Fixed':

                    if force or 'color' in changed:
                        self.plot_artist.set_color(self.state.color)

                    if force or 'size' in changed or 'size_scaling' in changed:
                        self.plot_artist.set_markersize(
                            self.state.size * self.state.size_scaling)

                else:

                    # TEMPORARY: Matplotlib has a bug that causes set_alpha to
                    # change the colors back: https://github.com/matplotlib/matplotlib/issues/8953
                    if 'alpha' in changed:
                        force = True

                    if self.state.cmap_mode == 'Fixed':
                        if force or 'color' in changed or 'cmap_mode' in changed:
                            self.scatter_artist.set_facecolors(
                                self.state.color)
                            self.scatter_artist.set_edgecolor('none')
                    elif force or any(prop in changed
                                      for prop in CMAP_PROPERTIES):
                        c = self.layer[self.state.cmap_att].ravel()
                        set_mpl_artist_cmap(self.scatter_artist, c, self.state)
                        self.scatter_artist.set_edgecolor('none')

                    if force or any(prop in changed
                                    for prop in MARKER_PROPERTIES):

                        if self.state.size_mode == 'Fixed':
                            s = self.state.size * self.state.size_scaling
                            s = broadcast_to(
                                s,
                                self.scatter_artist.get_sizes().shape)
                        else:
                            s = self.layer[self.state.size_att].ravel()
                            s = ((s - self.state.size_vmin) /
                                 (self.state.size_vmax -
                                  self.state.size_vmin)) * 30
                            s *= self.state.size_scaling

                        # Note, we need to square here because for scatter, s is actually
                        # proportional to the marker area, not radius.
                        self.scatter_artist.set_sizes(s**2)

        if self.state.line_visible:

            if self.state.cmap_mode == 'Fixed':
                if force or 'color' in changed or 'cmap_mode' in changed:
                    self.line_collection.set_array(None)
                    self.line_collection.set_color(self.state.color)
            elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                # Higher up we oversampled the points in the line so that
                # half a segment on either side of each point has the right
                # color, so we need to also oversample the color here.
                c = self.layer[self.state.cmap_att].ravel()
                cnew = np.zeros((len(c) - 1) * 2)
                cnew[::2] = c[:-1]
                cnew[1::2] = c[1:]
                set_mpl_artist_cmap(self.line_collection, cnew, self.state)

            if force or 'linewidth' in changed:
                self.line_collection.set_linewidth(self.state.linewidth)

            if force or 'linestyle' in changed:
                self.line_collection.set_linestyle(self.state.linestyle)

        if self.state.vector_visible and self.vector_artist is not None:

            if self.state.cmap_mode == 'Fixed':
                if force or 'color' in changed or 'cmap_mode' in changed:
                    self.vector_artist.set_array(None)
                    self.vector_artist.set_color(self.state.color)
            elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                c = self.layer[self.state.cmap_att].ravel()
                set_mpl_artist_cmap(self.vector_artist, c, self.state)

        if self.state.xerr_visible or self.state.yerr_visible:

            for eartist in list(self.errorbar_artist[2]):

                if eartist is None:
                    continue

                if self.state.cmap_mode == 'Fixed':
                    if force or 'color' in changed or 'cmap_mode' in changed:
                        eartist.set_color(self.state.color)
                elif force or any(prop in changed for prop in CMAP_PROPERTIES):
                    c = self.layer[self.state.cmap_att].ravel()
                    set_mpl_artist_cmap(eartist, c, self.state)

                if force or 'alpha' in changed:
                    eartist.set_alpha(self.state.alpha)

                if force or 'visible' in changed:
                    eartist.set_visible(self.state.visible)

                if force or 'zorder' in changed:
                    eartist.set_zorder(self.state.zorder)

        for artist in [
                self.scatter_artist, self.plot_artist, self.vector_artist,
                self.line_collection, self.density_artist
        ]:

            if artist is None:
                continue

            if force or 'alpha' in changed:
                artist.set_alpha(self.state.alpha)

            if force or 'zorder' in changed:
                artist.set_zorder(self.state.zorder)

            if force or 'visible' in changed:
                artist.set_visible(self.state.visible)

        self.redraw()

    @defer_draw
    def _update_scatter(self, force=False, **kwargs):

        if (self._viewer_state.x_att is None
                or self._viewer_state.y_att is None
                or self.state.layer is None):
            return

        # Figure out which attributes are different from before. Ideally we shouldn't
        # need this but currently this method is called multiple times if an
        # attribute is changed due to x_att changing then hist_x_min, hist_x_max, etc.
        # If we can solve this so that _update_histogram is really only called once
        # then we could consider simplifying this. Until then, we manually keep track
        # of which properties have changed.

        changed = set()

        if not force:

            for key, value in self._viewer_state.as_dict().items():
                if value != self._last_viewer_state.get(key, None):
                    changed.add(key)

            for key, value in self.state.as_dict().items():
                if value != self._last_layer_state.get(key, None):
                    changed.add(key)

        self._last_viewer_state.update(self._viewer_state.as_dict())
        self._last_layer_state.update(self.state.as_dict())

        if force or len(changed & DATA_PROPERTIES) > 0:
            self._update_data(changed)
            force = True

        if force or len(changed & VISUAL_PROPERTIES) > 0:
            self._update_visual_attributes(changed, force=force)

    def get_layer_color(self):
        if self.state.cmap_mode == 'Fixed':
            return self.state.color
        else:
            return self.state.cmap

    @defer_draw
    def update(self):
        self._update_scatter(force=True)
        self.redraw()
Esempio n. 25
0
def _plot_skeleton(neuron, color, method, ax, **kwargs):
    """Plot skeleton."""
    depth_coloring = kwargs.get('depth_coloring', False)
    linewidth = kwargs.get('linewidth', kwargs.get('lw', .5))
    linestyle = kwargs.get('linestyle', kwargs.get('ls', '-'))
    alpha = kwargs.get('alpha', .9)
    norm = kwargs.get('norm')
    plot_soma = kwargs.get('soma', True)
    group_neurons = kwargs.get('group_neurons', False)
    view = kwargs.get('view', ('x', 'y'))

    if method == '2d':
        if not depth_coloring and not (isinstance(color, np.ndarray)
                                       and color.ndim == 2):
            # Generate by-segment coordinates
            coords = segments_to_coords(neuron,
                                        neuron.segments,
                                        modifier=(1, 1, 1))

            # We have to add (None, None, None) to the end of each
            # slab to make that line discontinuous there
            coords = np.vstack(
                [np.append(t, [[None] * 3], axis=0) for t in coords])

            x, y = _parse_view2d(coords, view)
            this_line = mlines.Line2D(
                x,
                y,
                lw=linewidth,
                ls=linestyle,
                alpha=alpha,
                color=color,
                label=f'{getattr(neuron, "name", "NA")} - #{neuron.id}')
            ax.add_line(this_line)
        else:
            coords = tn_pairs_to_coords(neuron, modifier=(1, 1, 1))

            xy = _parse_view2d(coords, view)
            lc = LineCollection(xy,
                                cmap='jet' if depth_coloring else None,
                                norm=norm if depth_coloring else None,
                                joinstyle='round')

            lc.set_linewidth(linewidth)
            lc.set_linestyle(linestyle)
            lc.set_label(f'{getattr(neuron, "name", "NA")} - #{neuron.id}')

            if depth_coloring:
                lc.set_alpha(alpha)
                lc.set_array(neuron.nodes.loc[neuron.nodes.parent_id >= 0,
                                              'z'].values)
            elif (isinstance(color, np.ndarray) and color.ndim == 2):
                # If we have a color for each node, we need to drop the roots
                if color.shape[1] != coords.shape[0]:
                    lc.set_color(color[neuron.nodes.parent_id.values >= 0])
                else:
                    lc.set_color(color)

            ax.add_collection(lc)

        if plot_soma and np.any(neuron.soma):
            soma = utils.make_iterable(neuron.soma)
            # If soma detection is messed up we might end up producing
            # dozens of soma which will freeze the kernel
            if len(soma) >= 10:
                logger.warning(f'{neuron.id} - {len(soma)} somas found.')
            for s in soma:
                if isinstance(color, np.ndarray) and color.ndim > 1:
                    s_ix = np.where(neuron.nodes.node_id == s)[0][0]
                    soma_color = color[s_ix]
                else:
                    soma_color = color

                n = neuron.nodes.set_index('node_id').loc[s]
                r = getattr(n, neuron.soma_radius) if isinstance(
                    neuron.soma_radius, str) else neuron.soma_radius

                if depth_coloring:
                    d = [n.x, n.y, n.z][_get_depth_axis(view)]
                    soma_color = mpl.cm.jet(norm(d))

                sx, sy = _parse_view2d(np.array([[n.x, n.y, n.z]]), view)
                c = mpatches.Circle((sx[0], sy[0]),
                                    radius=r,
                                    alpha=alpha,
                                    fill=True,
                                    fc=soma_color,
                                    zorder=4,
                                    edgecolor='none')
                ax.add_patch(c)
        return None, None

    elif method in ['3d', '3d_complex']:
        # For simple scenes, add whole neurons at a time to speed up rendering
        if method == '3d':
            if (isinstance(color, np.ndarray)
                    and color.ndim == 2) or depth_coloring:
                coords = tn_pairs_to_coords(neuron, modifier=(1, 1, 1))
                # If we have a color for each node, we need to drop the roots
                if isinstance(
                        color,
                        np.ndarray) and color.shape[1] != coords.shape[0]:
                    line_color = color[neuron.nodes.parent_id.values >= 0]
                else:
                    line_color = color
            else:
                # Generate by-segment coordinates
                coords = segments_to_coords(neuron,
                                            neuron.segments,
                                            modifier=(1, 1, 1))
                line_color = color

            lc = Line3DCollection(
                coords,
                color=line_color,
                label=neuron.id,
                alpha=alpha if not kwargs.get('shade_by', False) else None,
                cmap=mpl.cm.jet if depth_coloring else None,
                lw=linewidth,
                joinstyle='round',
                linestyle=linestyle)
            if group_neurons:
                lc.set_gid(neuron.id)
            # Need to get this before adding data
            line3D_collection = lc
            ax.add_collection3d(lc)

        # For complex scenes, add each segment as a single collection
        # -> helps reducing Z-order errors
        elif method == '3d_complex':
            # Generate by-segment coordinates
            coords = segments_to_coords(neuron,
                                        neuron.segments,
                                        modifier=(1, 1, 1))
            for c in coords:
                lc = Line3DCollection([c],
                                      color=color,
                                      lw=linewidth,
                                      alpha=alpha,
                                      linestyle=linestyle)
                if group_neurons:
                    lc.set_gid(neuron.id)
                ax.add_collection3d(lc)
            line3D_collection = None

        surf3D_collections = []
        if plot_soma and not isinstance(getattr(neuron, 'soma', None),
                                        type(None)):
            soma = utils.make_iterable(neuron.soma)
            # If soma detection is messed up we might end up producing
            # dozens of soma which will freeze the kernel
            if len(soma) >= 5:
                logger.warning(
                    f'Neuron {neuron.id} appears to have {len(soma)}'
                    ' somas. Skipping plotting its somas.')
            else:
                for s in soma:
                    if isinstance(color, np.ndarray) and color.ndim > 1:
                        s_ix = np.where(neuron.nodes.node_id == s)[0][0]
                        soma_color = color[s_ix]
                    else:
                        soma_color = color

                    n = neuron.nodes.set_index('node_id').loc[s]
                    r = getattr(n, neuron.soma_radius) if isinstance(
                        neuron.soma_radius, str) else neuron.soma_radius

                    resolution = 20
                    u = np.linspace(0, 2 * np.pi, resolution)
                    v = np.linspace(0, np.pi, resolution)
                    x = r * np.outer(np.cos(u), np.sin(v)) + n.x
                    y = r * np.outer(np.sin(u), np.sin(v)) + n.y
                    z = r * np.outer(np.ones(np.size(u)), np.cos(v)) + n.z
                    surf = ax.plot_surface(x,
                                           y,
                                           z,
                                           color=soma_color,
                                           shade=False,
                                           alpha=alpha)
                    if group_neurons:
                        surf.set_gid(neuron.id)

                    surf3D_collections.append(surf)

        return line3D_collection, surf3D_collections
Esempio n. 26
0
def plot_volume(sim,
                vol=None,
                center=None,
                size=None,
                options=None,
                plot3D=False,
                label=None):

    options = options if options else def_plot_options

    fig = plt.gcf()
    ax = fig.gca(projection='3d') if plot3D else fig.gca()

    if vol:
        center, size = vol.center, vol.size
    v0 = np.array([center.x, center.y])
    dx, dy = np.array([0.5 * size.x, 0.0]), np.array([0.0, 0.5 * size.y])
    if plot3D:
        zmin, zmax = ax.get_zlim3d()
        z0 = zmin + options['zrel'] * (zmax - zmin)

    ##################################################
    # add polygon(s) to the plot to represent the volume
    ##################################################
    def add_to_plot(c):
        ax.add_collection3d(c, zs=z0,
                            zdir='z') if plot3D else ax.add_collection(c)

    if size.x == 0.0 or size.y == 0.0:  # zero thickness, plot as line
        polygon = [v0 + dx + dy, v0 - dx - dy]
        add_to_plot(
            LineCollection([polygon],
                           colors=options['line_color'],
                           linewidths=options['line_width'],
                           linestyles=options['line_style']))
    else:
        if options['fill_color'] != 'none':  # first copy: faces, no edges
            polygon = np.array(
                [v0 + dx + dy, v0 - dx + dy, v0 - dx - dy, v0 + dx - dy])
            pc = PolyCollection([polygon], linewidths=0.0)
            pc.set_color(options['fill_color'])
            pc.set_alpha(options['alpha'])
            add_to_plot(pc)
        if options['boundary_width'] > 0.0:  # second copy: edges, no faces
            closed_polygon = np.array([
                v0 + dx + dy, v0 - dx + dy, v0 - dx - dy, v0 + dx - dy,
                v0 + dx + dy
            ])
            lc = LineCollection([closed_polygon])
            lc.set_linestyle(options['boundary_style'])
            lc.set_linewidth(options['boundary_width'])
            lc.set_edgecolor(options['boundary_color'])
            add_to_plot(lc)

    ######################################################################
    # attempt to autodetermine text rotation and alignment
    ######################################################################
    if label:
        x0, y0, r, h, v = np.mean(ax.get_xlim()), np.mean(
            ax.get_ylim()), 0, 'center', 'center'
        if size.y == 0.0:
            v = 'bottom' if center.y > y0 else 'top'
        elif size.x == 0.0:
            r, h = (270, 'left') if center.x > x0 else (90, 'right')
        if plot3D:
            ax.text(center.x,
                    center.y,
                    z0,
                    label,
                    rotation=r,
                    fontsize=options['fontsize'],
                    color=options['line_color'],
                    horizontalalignment=h,
                    verticalalignment=v)
        else:
            ax.text(center.x,
                    center.y,
                    label,
                    rotation=r,
                    fontsize=options['fontsize'],
                    color=options['line_color'],
                    horizontalalignment=h,
                    verticalalignment=v)