<commit_before>import copy
from itertools import groupby

import numpy as np

from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection

import param

from .. import SheetStack, Points, View, SheetView, SheetOverlay, \
    CoordinateGrid, NdMapping, Contours, VectorField
from .dataplots import MatrixPlot
from .viewplots import OverlayPlot, Plot



class PointPlot(Plot):
    """
    Note that the 'cmap', 'vmin' and 'vmax' style arguments control
    how point magnitudes are rendered.
    """

    style_opts = param.List(default=['alpha', 'color', 'edgecolors', 'facecolors',
                                     'linewidth', 'marker', 's', 'visible',
                                     'cmap', 'vmin', 'vmax'],
                            constant=True, doc="""
     The style options for PointPlot match those of matplotlib's
     scatter plot command.""")

    _stack_type = SheetStack
    _view_type = Points

    def __call__(self, axis=None, cyclic_index=0, lbrt=None):
        points = self._stack.last
        title = None if self.zorder > 0 else self._format_title(-1)
        ax = self._axis(axis, title, 'x', 'y', self._stack.bounds.lbrt())

        xs = points.data[:, 0] if len(points.data) else []
        ys = points.data[:, 1] if len(points.data) else []
        cs = points.data[:, 2] if points.data.shape[1]>=3 else None

        kwargs = View.options.style(points)[cyclic_index]
        scatterplot = ax.scatter(xs, ys, zorder=self.zorder,
                                 **({k:v for k,v in dict(kwargs, c=cs).items() if k!='color'}
                                    if cs is not None else kwargs))

        ax.add_collection(scatterplot)
        self.handles['scatter'] = scatterplot
        if axis is None: plt.close(self.handles['fig'])
        return ax if axis else self.handles['fig']


    def update_frame(self, n):
        n = n if n < len(self) else len(self) - 1
        points = list(self._stack.values())[n]
        self.handles['scatter'].set_offsets(points.data[:,0:2])
        if points.data.shape[1]==3:
            self.handles['scatter'].set_array(points.data[:,2])
        self._update_title(n)
        plt.draw()


class VectorFieldPlot(Plot):
    """
    Renders 2D, 3D or 4D vector field. The 3rd and 4th dimension may
    be either the arrow color or the relative arrow length. For 2D
    vector fields, all arrows have a relative length of 1.0.

    Note that the 'cmap', 'clim' style arguments control the colors of
    the vectors for 3D vector fields.
    """

    style_opts = param.List(default=['alpha', 'color', 'edgecolors', 'facecolors',
                                     'linewidth', 'marker', 's', 'visible',
                                     'cmap', 'clim', 'scale'],
                            constant=True, doc="""
     The style options for PointPlot match those of matplotlib's<commit_msg>Added control for color limits in PointPlot via normalize_individually<commit_after>import copy
from itertools import groupby

import numpy as np

from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection

import param

from .. import SheetStack, Points, View, SheetView, SheetOverlay, \
    CoordinateGrid, NdMapping, Contours, VectorField
from .dataplots import MatrixPlot
from .viewplots import OverlayPlot, Plot



class PointPlot(Plot):
    """
    Note that the 'cmap', 'vmin' and 'vmax' style arguments control
    how point magnitudes are rendered.
    """

    normalize_individually = param.Boolean(default=False, doc="""
      Whether to normalize the colors used to represent magnitude for
      each frame or across the stack (when color is applicable).""")

    style_opts = param.List(default=['alpha', 'color', 'edgecolors', 'facecolors',
                                     'linewidth', 'marker', 's', 'visible',
                                     'cmap', 'vmin', 'vmax'],
                            constant=True, doc="""
     The style options for PointPlot match those of matplotlib's
     scatter plot command.""")

    _stack_type = SheetStack
    _view_type = Points

    def __call__(self, axis=None, cyclic_index=0, lbrt=None):
        points = self._stack.last
        title = None if self.zorder > 0 else self._format_title(-1)
        ax = self._axis(axis, title, 'x', 'y', self._stack.bounds.lbrt())

        xs = points.data[:, 0] if len(points.data) else []
        ys = points.data[:, 1] if len(points.data) else []
        cs = points.data[:, 2] if points.data.shape[1]>=3 else None

        kwargs = View.options.style(points)[cyclic_index]
        scatterplot = ax.scatter(xs, ys, zorder=self.zorder,
                                 **({k:v for k,v in dict(kwargs, c=cs).items() if k!='color'}
                                    if cs is not None else kwargs))

        ax.add_collection(scatterplot)
        self.handles['scatter'] = scatterplot

        if cs is not None:
            clims = points.range if self.normalize_individually else self._stack.range
            scatterplot.set_clim(clims)

        if axis is None: plt.close(self.handles['fig'])
        return ax if axis else self.handles['fig']


    def update_frame(self, n):
        n = n if n < len(self) else len(self) - 1
        points = list(self._stack.values())[n]

        scatter = self.handles['scatter']
        scatter.set_offsets(points.data[:,0:2])
        if points.data.shape[1]==3:
            scatter.set_array(points.data[:,2])

        if self.normalize_individually:
            scatter.set_clim(points.range)
        self._update_title(n)
        plt.draw()


class VectorFieldPlot(Plot):
    """
    Renders 2D, 3D or 4D vector field. The 3rd and 4th dimension may
    be either the arrow color or the relative arrow length. For 2D
    vector fields, all arrows have a relative length of 1.0.

    Note that the 'cmap', 'clim' style arguments control the colors of
    the vectors for 3D vector fields.
    """

    style_opts = param.List(default=['alpha', 'color', 'edgecolors', 'facecolors',
                                     'linewidth', 'marker', 's', 'visible',
                                     'cmap', 'clim', 'scale'],
                            constant=True, doc="""
     The style options for PointPlot match those of matplotlib's
{'fraction_non_alphanumeric': 0.11306692039327625, 'fraction_numerical': 0.007294640025372661, 'mean_word_length': 2.340572033898305, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4916360', 'n_tokens_mistral': 1901, 'n_tokens_neox': 1811, 'n_words': 565}