<commit_before>import numpy as np
import bokeh.plotting
from bokeh.models import HoverTool
from bokeh.models.tickers import Ticker, FixedTicker
from bokeh.models.widgets import Panel, Tabs

try:
    from bokeh import mpl
except ImportError:
    mpl = None
import param

from ...core import Store, HoloMap, Overlay
from ...core import util
from ..plot import GenericElementPlot, GenericOverlayPlot
from .plot import BokehPlot
from .util import mpl_to_bokeh


# Define shared style properties for bokeh plots
line_properties = ['line_width', 'line_color', 'line_alpha',
                   'line_join', 'line_cap', 'line_dash']

fill_properties = ['fill_color', 'fill_alpha']

text_properties = ['text_font', 'text_font_size', 'text_font_style', 'text_color',
                   'text_alpha', 'text_align', 'text_baseline']

legend_dimensions = ['label_standoff', 'label_width', 'label_height', 'glyph_width',
                     'glyph_height', 'legend_padding', 'legend_spacing']



class ElementPlot(BokehPlot, GenericElementPlot):

    bgcolor = param.Parameter(default='white', doc="""
        Background color of the plot.""")

    border = param.Number(default=2, doc="""
        Minimum border around plot.""")

    fontsize = param.Parameter(default={'title': '12pt'}, allow_None=True,  doc="""
       Specifies various fontsizes of the displayed text.

       Finer control is available by supplying a dictionary where any
       unmentioned keys reverts to the default sizes, e.g:

          {'ticks': '20pt', 'title': '15pt', 'ylabel': '5px', 'xlabel': '5px'}""")

    invert_xaxis = param.Boolean(default=False, doc="""
        Whether to invert the plot x-axis.""")

    invert_yaxis = param.Boolean(default=False, doc="""
        Whether to invert the plot y-axis.""")

    lod = param.Dict(default={'factor': 10, 'interval': 300,
                              'threshold': 2000, 'timeout': 500}, doc="""
        Bokeh plots offer "Level of Detail" (LOD) capability to
        accomodate large (but not huge) amounts of data. The available
        options are:

          * factor    - Decimation factor to use when applying
                        decimation.
          * interval  - Interval (in ms) downsampling will be enabled
                        after an interactive event.
          * threshold - Number of samples before downsampling is enabled.
          * timeout   - Timeout (in ms) for checking whether interactive
                        tool events are still occurring.""")

    show_legend = param.Boolean(default=False, doc="""
        Whether to show legend for the plot.""")

    shared_axes = param.Boolean(default=True, doc="""
        Whether to invert the share axes across plots
        for linked panning and zooming.""")

    default_tools = param.List(default=['save', 'pan', 'wheel_zoom',
                                        'box_zoom', 'resize', 'reset'],
        doc="A list of plugin tools to use on the plot.")

    tools = param.List(default=[], doc="""
        A list of plugin tools to use on the plot.""")

    xaxis = param.ObjectSelector(default='left',
                                 objects=['left', 'right', 'bare',
                                          'left-bare', 'right-bare',
                                          None], doc="""
        Whether and where to display the xaxis, bare options allow
        suppressing all axis labels including ticks and xlabel.""")

    xlog = param.Boolean(default=False, doc="""
        Whether the x-axis of the plot will be a log axis.""")

    xrotation = param.Integer(default=None, bounds=(0, 360), doc="""
        Rotation angle of the xticks.""")

    xticks = param.Parameter(default=None, doc="""
        Ticks along x-axis specified as an integer, explicit list of
        tick locations or bokeh Ticker object. If set to None default
        bokeh ticking behavior is applied.""")

    yaxis = param.ObjectSelector(default='bottom',
                                 objects=['top', 'bottom',
                                          'bare', 'top-bare',
                                          'bottom-bare', None],
                                 doc="""
        Whether and where to display the yaxis, bare options allow
        suppressing all axis labels including ticks and ylabel.""")

    ylog = param.Boolean(default=False, doc="""
        Whether the x-axis of the plot will be a log axis.""")

    yrotation = param.Integer(default=None, bounds=(0, 360), doc="""
        Rotation angle of the xticks.""")

    yticks = param.Parameter(default=None, doc="""
        Ticks along y-axis specified as an integer, explicit list of
        tick locations or bokeh Ticker object. If set to None
        default bokeh ticking behavior is applied.""")

    # A string corresponding to the glyph being drawn by the
    # ElementPlot
    _plot_method = None

    def __init__(self, element, plot=None, **params):
        super(ElementPlot, self).__init__(element, **params)
        self.handles = {} if plot is None else self.handles['plot']


    def _init_tools(self, element):
        """
        Processes the list of tools to be supplied to the plot.
        """
        tools = self.default_tools + self.tools
        if 'hover' in tools:
            tooltips = [(d, '@'+d) for d in element.dimensions(label=True)]
            tools[tools.index('hover')] = HoverTool(tooltips=tooltips)
        return tools


    def _init_axes(self, plots, element, ranges):
        xlabel, ylabel, zlabel = self._axis_labels(element, plots)
        plot_ranges = {}
        # Try finding shared ranges in other plots in the same Layout
        if plots and self.shared_axes:
            for plot in plots:
                if plot is None or not hasattr(plot, 'xaxis'): continue
                if plot.xaxis[0].axis_label == xlabel:
                    plot_ranges['x_range'] = plot.x_range
                if plot.xaxis[0].axis_label == ylabel:
                    plot_ranges['y_range'] = plot.x_range
                if plot.yaxis[0].axis_label == ylabel:
                    plot_ranges['y_range'] = plot.y_range
                if plot.yaxis[0].axis_label == xlabel:
                    plot_ranges['x_range'] = plot.y_range

        if not 'x_range' in plot_ranges:
            if 'x_range' in ranges:
                plot_ranges['x_range'] = ranges['x_range']
            else:
                l, _, r, _ = self.get_extents(element, ranges)
                if all(x is not None for x in (l, r)):
                    plot_ranges['x_range'] = [l, r]

        if self.invert_xaxis:
            plot_ranges['x_ranges'] = plot_ranges['x_ranges'][::-1]

        if not 'y_range' in plot_ranges:
            if 'y_range' in ranges:
                plot_ranges['y_range'] = ranges['y_range']
            else:
                _, b, _, t = self.get_extents(element, ranges)
                if all(y is not None for y in (b, t)):
                    plot_ranges['y_range'] = [b, t]
        if self.invert_yaxis:
            plot_ranges['y_range'] = plot_ranges['y_range'][::-1]
        x_axis_type = 'log' if self.xlog else 'auto'
        y_axis_type = 'log' if self.ylog else 'auto'
        return (x_axis_type, y_axis_type), (xlabel, ylabel, zlabel), plot_ranges


    def _init_plot(self, key, plots, ranges=None):
        """<commit_msg>Correctly handling range inversions in Bokeh<commit_after>import numpy as np
import bokeh.plotting
from bokeh.models import Range, HoverTool
from bokeh.models.tickers import Ticker, FixedTicker
from bokeh.models.widgets import Panel, Tabs

try:
    from bokeh import mpl
except ImportError:
    mpl = None
import param

from ...core import Store, HoloMap, Overlay
from ...core import util
from ..plot import GenericElementPlot, GenericOverlayPlot
from .plot import BokehPlot
from .util import mpl_to_bokeh


# Define shared style properties for bokeh plots
line_properties = ['line_width', 'line_color', 'line_alpha',
                   'line_join', 'line_cap', 'line_dash']

fill_properties = ['fill_color', 'fill_alpha']

text_properties = ['text_font', 'text_font_size', 'text_font_style', 'text_color',
                   'text_alpha', 'text_align', 'text_baseline']

legend_dimensions = ['label_standoff', 'label_width', 'label_height', 'glyph_width',
                     'glyph_height', 'legend_padding', 'legend_spacing']



class ElementPlot(BokehPlot, GenericElementPlot):

    bgcolor = param.Parameter(default='white', doc="""
        Background color of the plot.""")

    border = param.Number(default=2, doc="""
        Minimum border around plot.""")

    fontsize = param.Parameter(default={'title': '12pt'}, allow_None=True,  doc="""
       Specifies various fontsizes of the displayed text.

       Finer control is available by supplying a dictionary where any
       unmentioned keys reverts to the default sizes, e.g:

          {'ticks': '20pt', 'title': '15pt', 'ylabel': '5px', 'xlabel': '5px'}""")

    invert_xaxis = param.Boolean(default=False, doc="""
        Whether to invert the plot x-axis.""")

    invert_yaxis = param.Boolean(default=False, doc="""
        Whether to invert the plot y-axis.""")

    lod = param.Dict(default={'factor': 10, 'interval': 300,
                              'threshold': 2000, 'timeout': 500}, doc="""
        Bokeh plots offer "Level of Detail" (LOD) capability to
        accomodate large (but not huge) amounts of data. The available
        options are:

          * factor    - Decimation factor to use when applying
                        decimation.
          * interval  - Interval (in ms) downsampling will be enabled
                        after an interactive event.
          * threshold - Number of samples before downsampling is enabled.
          * timeout   - Timeout (in ms) for checking whether interactive
                        tool events are still occurring.""")

    show_legend = param.Boolean(default=False, doc="""
        Whether to show legend for the plot.""")

    shared_axes = param.Boolean(default=True, doc="""
        Whether to invert the share axes across plots
        for linked panning and zooming.""")

    default_tools = param.List(default=['save', 'pan', 'wheel_zoom',
                                        'box_zoom', 'resize', 'reset'],
        doc="A list of plugin tools to use on the plot.")

    tools = param.List(default=[], doc="""
        A list of plugin tools to use on the plot.""")

    xaxis = param.ObjectSelector(default='left',
                                 objects=['left', 'right', 'bare',
                                          'left-bare', 'right-bare',
                                          None], doc="""
        Whether and where to display the xaxis, bare options allow
        suppressing all axis labels including ticks and xlabel.""")

    xlog = param.Boolean(default=False, doc="""
        Whether the x-axis of the plot will be a log axis.""")

    xrotation = param.Integer(default=None, bounds=(0, 360), doc="""
        Rotation angle of the xticks.""")

    xticks = param.Parameter(default=None, doc="""
        Ticks along x-axis specified as an integer, explicit list of
        tick locations or bokeh Ticker object. If set to None default
        bokeh ticking behavior is applied.""")

    yaxis = param.ObjectSelector(default='bottom',
                                 objects=['top', 'bottom',
                                          'bare', 'top-bare',
                                          'bottom-bare', None],
                                 doc="""
        Whether and where to display the yaxis, bare options allow
        suppressing all axis labels including ticks and ylabel.""")

    ylog = param.Boolean(default=False, doc="""
        Whether the x-axis of the plot will be a log axis.""")

    yrotation = param.Integer(default=None, bounds=(0, 360), doc="""
        Rotation angle of the xticks.""")

    yticks = param.Parameter(default=None, doc="""
        Ticks along y-axis specified as an integer, explicit list of
        tick locations or bokeh Ticker object. If set to None
        default bokeh ticking behavior is applied.""")

    # A string corresponding to the glyph being drawn by the
    # ElementPlot
    _plot_method = None

    def __init__(self, element, plot=None, **params):
        super(ElementPlot, self).__init__(element, **params)
        self.handles = {} if plot is None else self.handles['plot']


    def _init_tools(self, element):
        """
        Processes the list of tools to be supplied to the plot.
        """
        tools = self.default_tools + self.tools
        if 'hover' in tools:
            tooltips = [(d, '@'+d) for d in element.dimensions(label=True)]
            tools[tools.index('hover')] = HoverTool(tooltips=tooltips)
        return tools


    def _init_axes(self, plots, element, ranges):
        xlabel, ylabel, zlabel = self._axis_labels(element, plots)
        plot_ranges = {}
        # Try finding shared ranges in other plots in the same Layout
        if plots and self.shared_axes:
            for plot in plots:
                if plot is None or not hasattr(plot, 'xaxis'): continue
                if plot.xaxis[0].axis_label == xlabel:
                    plot_ranges['x_range'] = plot.x_range
                if plot.xaxis[0].axis_label == ylabel:
                    plot_ranges['y_range'] = plot.x_range
                if plot.yaxis[0].axis_label == ylabel:
                    plot_ranges['y_range'] = plot.y_range
                if plot.yaxis[0].axis_label == xlabel:
                    plot_ranges['x_range'] = plot.y_range

        if not 'x_range' in plot_ranges:
            if 'x_range' in ranges:
                plot_ranges['x_range'] = ranges['x_range']
            else:
                l, _, r, _ = self.get_extents(element, ranges)
                if all(x is not None for x in (l, r)):
                    plot_ranges['x_range'] = [l, r]

        if self.invert_xaxis:
            plot_ranges['x_ranges'] = plot_ranges['x_ranges'][::-1]

        if not 'y_range' in plot_ranges:
            if 'y_range' in ranges:
                plot_ranges['y_range'] = ranges['y_range']
            else:
                _, b, _, t = self.get_extents(element, ranges)
                if all(y is not None for y in (b, t)):
                    plot_ranges['y_range'] = [b, t]
        if self.invert_yaxis:
            yrange = plot_ranges['y_range']
            if isinstance(yrange, Range):
                plot_ranges['y_range'] = yrange.__class__(start=yrange.end,
                                                          end=yrange.start)
            else:
                plot_ranges['y_range'] = yrange[::-1]
        x_axis_type = 'log' if self.xlog else 'auto'
        y_axis_type = 'log' if self.ylog else 'auto'
        return (x_axis_type, y_axis_type), (xlabel, ylabel, zlabel), plot_ranges


    def _init_plot(self, key, plots, ranges=None):
        """
{'fraction_non_alphanumeric': 0.10971703150026695, 'fraction_numerical': 0.004671649759743727, 'mean_word_length': 2.167406467977172, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5545675', 'n_tokens_mistral': 4403, 'n_tokens_neox': 4108, 'n_words': 1331}