Exemplo n.º 1
0
 def build_gui(self) -> None:
     val_min = min(self.data)
     val_max = max(self.data)
     # subtract and add a bit to the min and max value to ensure the whole range is captured
     dist = val_max - val_min if val_max != val_min else 1
     val_min = val_min - 0.01 * dist
     val_max = val_max + 0.01 * dist
     self.slider = pnw.RangeSlider(name=self.name,
                                   start=val_min,
                                   end=val_max,
                                   step=round(
                                       ((val_max - val_min) / self.steps),
                                       1),
                                   width=int(0.97 * self.width))
     self.slider.param.watch(self.update_self, "value_throttled")
     if self.with_hist:
         self.hist = histogram(self.data,
                               bins=self.bins,
                               range=(self.data.min(), self.data.max()),
                               height=100,
                               width=self.width,
                               remove_tools=True)
     else:
         self.hist = None
     self.gui = pn.Column(self.slider, self.hist)
Exemplo n.º 2
0
    def __init__(
        self,
        df,
        *,
        feature_aliases=None,
        describe=True,
        x_label="timestamp",
        port=5006,
        websocket_origin=49179,
        sample_rate=1.0,
        plot_width=600,
        plot_height=400,
        **params,
    ):

        BasePanel.__init__(
            self,
            df,
            feature_aliases=feature_aliases,
            port=port,
            websocket_origin=websocket_origin,
            sample_rate=sample_rate,
        )
        self.plot_width = plot_width
        self.plot_height = plot_height
        self.describe = describe
        self.x_label = x_label

        tags = sorted(list(df.columns))
        tag = tags[0]
        bounds = self.tag_bounds[tag]

        # widget objects
        self.feature = pnw.Select(value=tag, options=tags, name="Ticker")
        self.description = pnw.Select(
            value=self.feature_aliases[tag],
            options=sorted(list(self.feature_aliases.values())),
            name="Company",
        )
        self.tag_range = pnw.RangeSlider(start=bounds[0],
                                         end=bounds[1],
                                         value=bounds,
                                         name="Feature Range")
        self.log_scale = pnw.Checkbox(
            name="Log scale",
            value=False,
        )

        pm.Parameterized.__init__(self, **params)
Exemplo n.º 3
0
def categorical_2d_histogram_with_gui(data: pd.DataFrame, category_cols=None, hist_cols=None, width=500, height=500):
    """Creates a categorical_2d_histogram for a dataframe, where each option (except width, height and color_mapper) of the categorical_2d_histogram can be set with gui elements.
    If the input is a list all dataframes need to have the same cols as the first dataframe in the list"""
    if category_cols is None and isinstance(data, pd.DataFrame):
        category_cols = data.columns.tolist()
    elif category_cols is None and isinstance(data, list):
        category_cols = data[0].columns.tolist()
    if hist_cols is None and isinstance(data, pd.DataFrame):
        hist_cols = [col_name for col_name in data.columns if is_numeric_dtype(data[col_name])]
    elif hist_cols is None and isinstance(data, list):
        hist_cols = [col_name for col_name in data[0].columns if is_numeric_dtype(data[0][col_name])]
    x_select = pnw.Select(name="X-Axis", options=hist_cols)
    y_select = pnw.Select(name="Y-Axis", options=category_cols)

    axis_selector = pn.Row(x_select, y_select, width=width)

    x_is_categorical = pnw.Checkbox(name="X is categorical", value=False)
    x_bins = pnw.IntInput(name="Bins", start=1, end=500, value=10, disabled=False)
    if isinstance(data, pd.DataFrame):
        x_range_start=data[x_select.value].min()
        x_range_end=data[x_select.value].max()
        x_range_end=x_range_end if x_range_end > x_range_start else x_range_end*1.1
        x_range_step=(x_range_end - x_range_start) / 50
    elif isinstance(data, list):
        x_range_start=min(df[x_select.value].min() for df in data)
        x_range_end=max(df[x_select.value].max() for df in data)
        x_range_end=x_range_end if x_range_end > x_range_start else x_range_end*1.1
        x_range_step=(x_range_end - x_range_start) / 50
    x_range = pnw.RangeSlider(name="X-Axis Range", start=x_range_start, end=x_range_end, step=x_range_step, disabled=False)

    x_axis_configuration = pn.Row(x_range, x_bins, width=width)

    normalize_rows = pnw.Checkbox(name="Normalize rows", value=False)
    x_precision = pnw.IntInput(name="Precision", start=0, end=10, value=2, disabled=False)

    additional_parameters = pn.Row(x_is_categorical, normalize_rows, x_precision, width=width)

    config_gui = pn.Column(axis_selector, additional_parameters, x_axis_configuration, align="center")

    @pn.depends(y_select.param.value, x_select.param.value, x_bins.param.value_throttled, x_range.param.value_throttled, x_is_categorical.param.value, normalize_rows.param.value, x_precision.param.value)
    def _plot(category_col, hist_col, bins, range, x_is_categorical, normalize_rows, precision):
        if x_is_categorical:
            x_range.disabled = True
            x_precision.disabled = True
            x_bins.disabled = True
        else:
            x_range.disabled = False
            x_precision.disabled = False
            x_bins.disabled = False

        if isinstance(data, pd.DataFrame):
            if data[hist_col].min() != x_range.start or data[hist_col].max() != x_range.end:
                x_range.start = data[hist_col].min()
                x_range.end = data[hist_col].max() if data[hist_col].max() > x_range.start else data[hist_col].max()*1.1
                x_range.value = (x_range.start, x_range.end)
                x_range.step = (x_range.end-x_range.start)/50
        elif isinstance(data, list):
            if min(df[hist_col].min() for df in data) != x_range.start or max(df[hist_col].max() for df in data) != x_range.end:
                x_range.start = min(df[hist_col].min() for df in data)
                x_range.end = max(df[hist_col].max() for df in data) if max(df[hist_col].max() for df in data) > x_range.start else max(df[hist_col].max() for df in data)*1.1
                x_range.value = (x_range.start, x_range.end)
                x_range.step = (x_range.end-x_range.start)/50
        range = x_range.value

        if isinstance(data, list):
            plot = pn.Row(*categorical_2d_histogram(data, category_col, hist_col, bins, range, normalize_rows, precision, color_mapper=None, hist_col_is_categorical=x_is_categorical, width=width, height=height))
        elif isinstance(data, pd.DataFrame):
            plot = pn.Row(categorical_2d_histogram(data, category_col, hist_col, bins, range, normalize_rows, precision, color_mapper=None, hist_col_is_categorical=x_is_categorical, width=width, height=height))
        return plot

    return pn.Column(config_gui, _plot)
Exemplo n.º 4
0
class DdbFilePanel(AbipyParameterized):
    """
    A panel to analyze a |DdbFile|.
    Provides widgets to invoke anaddb and visualize the results.
    """
    verbose = param.Integer(0, bounds=(0, None), doc="Verbosity Level")
    mpi_procs = param.Integer(1,
                              bounds=(1, None),
                              doc="Number of MPI processes used in anaddb")

    nqsmall = param.Integer(
        10,
        bounds=(1, None),
        doc="Number of divisions for smallest vector to generate Q-mesh")
    ndivsm = param.Integer(
        2,
        bounds=(1, None),
        doc="Number of divisions for smallest segment in q-path")
    lo_to_splitting = param.ObjectSelector(default="automatic",
                                           objects=["automatic", True, False])
    chneut = param.ObjectSelector(default=1,
                                  objects=[0, 1, 2],
                                  doc="Abinit variable")
    dipdip = param.ObjectSelector(default=1,
                                  objects=[0, 1],
                                  doc="Abinit variable")
    asr = param.ObjectSelector(default=2,
                               objects=[0, 1, 2],
                               doc="Abinit variable")
    units = param.ObjectSelector(default="eV",
                                 objects=["eV", "meV", "Ha", "cm-1", "Thz"],
                                 doc="Energy units")

    dos_method = param.ObjectSelector(default="tetra",
                                      objects=["tetra", "gaussian"],
                                      doc="Integration method for DOS")
    temp_range = pnw.RangeSlider(name="T-range",
                                 start=0.0,
                                 end=1000,
                                 value=(0.0, 300.0),
                                 step=20)

    gamma_ev = param.Number(1e-4,
                            bounds=(1e-20, None),
                            doc="Phonon linewidth in eV")
    w_range = pnw.RangeSlider(name="Frequency range (eV)",
                              start=0.0,
                              end=1.0,
                              value=(0.0, 0.1),
                              step=0.001)

    get_epsinf_btn = pnw.Button(name="Compute", button_type='primary')
    plot_phbands_btn = pnw.Button(name="Plot Bands and DOS",
                                  button_type='primary')
    plot_eps0w_btn = pnw.Button(name="Plot eps0(omega)", button_type='primary')

    plot_vsound_btn = pnw.Button(name="Calculate speed of sound",
                                 button_type='primary')

    def __init__(self, ddb, **params):
        super().__init__(**params)
        self.ddb = ddb

    @param.depends('get_epsinf_btn.clicks')
    def get_epsinf(self):
        """Compute eps_infinity and Born effective charges from DDB."""
        if self.get_epsinf_btn.clicks == 0: return

        epsinf, becs = self.ddb.anaget_epsinf_and_becs(
            chneut=self.chneut, mpi_procs=self.mpi_procs, verbose=self.verbose)

        gen, inp = self.ddb.anaget_dielectric_tensor_generator(
            asr=self.asr,
            chneut=self.chneut,
            dipdip=self.dipdip,
            mpi_procs=self.mpi_procs,
            verbose=self.verbose,
            return_input=True)

        eps0 = gen.tensor_at_frequency(w=0, gamma_ev=self.gamma_ev)
        #eps0 = pnw.DataFrame(eps0.get_dataframe())
        return pn.Column(epsinf, eps0, becs, pn.pane.HTML(inp._repr_html_()))

    @param.depends('plot_eps0w_btn.clicks')
    def plot_eps0w(self):
        """Compute eps0(omega) from DDB and plot the results."""
        if self.plot_eps0w_btn.clicks == 0: return
        gen, inp = self.ddb.anaget_dielectric_tensor_generator(
            asr=self.asr,
            chneut=self.chneut,
            dipdip=self.dipdip,
            mpi_procs=self.mpi_procs,
            verbose=self.verbose,
            return_input=True)
        ws = self.w_range.value
        w_max = ws[1]
        if w_max == 1.0:
            w_max = None  # Will compute w_max in plot routine from ph freqs.

        def p(component, reim):
            return gen.plot(w_min=ws[0],
                            w_max=w_max,
                            gamma_ev=self.gamma_ev,
                            num=500,
                            component=component,
                            reim=reim,
                            units=self.units,
                            **self.fig_kwargs)

        # Build grid
        gspec = pn.GridSpec(sizing_mode='scale_width')
        gspec[0, 0] = p("diag", "re")
        gspec[0, 1] = p("diag", "im")
        gspec[1, 0] = p("offdiag", "re")
        gspec[1, 1] = p("offdiag", "im")
        gspec[2, :] = gen.get_oscillator_dataframe(reim="all", tol=1e-6)
        # Add HTML pane with input.
        gspec[3, 0] = pn.pane.HTML(inp._repr_html_())

        return gspec

    @param.depends('plot_phbands_btn.clicks')
    def plot_phbands_and_phdos(self, event=None):
        """Compute phonon bands and ph-DOSes from DDB and plot the results."""
        if self.plot_phbands_btn.clicks == 0: return
        #self.plot_phbands_btn.button_type = "warning"

        print("Computing phbands")
        with self.ddb.anaget_phbst_and_phdos_files(
                nqsmall=self.nqsmall,
                qppa=None,
                ndivsm=self.ndivsm,
                line_density=None,
                asr=self.asr,
                chneut=self.chneut,
                dipdip=self.dipdip,
                dos_method=self.dos_method,
                lo_to_splitting=self.lo_to_splitting,
                verbose=self.verbose,
                mpi_procs=self.mpi_procs,
                return_input=True) as g:

            phbst_file, phdos_file = g
            phbands, phdos = phbst_file.phbands, phdos_file.phdos
            print("Computing phbands completed")

            # Build grid
            gspec = pn.GridSpec(sizing_mode='scale_width')
            gspec[0, 0] = phbands.plot_with_phdos(phdos,
                                                  units=self.units,
                                                  **self.fig_kwargs)
            gspec[0, 1] = phdos_file.plot_pjdos_type(units=self.units,
                                                     exchange_xy=True,
                                                     **self.fig_kwargs)
            gspec[1, 0] = phdos_file.msqd_dos.plot(units=self.units,
                                                   **self.fig_kwargs)
            temps = self.temp_range.value
            gspec[1, 1] = phdos.plot_harmonic_thermo(tstart=temps[0],
                                                     tstop=temps[1],
                                                     num=50,
                                                     **self.fig_kwargs)
            #msqd_dos.plot_tensor(**self.fig_kwargs)
            #self.plot_phbands_btn.button_type = "primary"

            # Add HTML pane with input
            gspec[2, :] = pn.pane.HTML(g.input._repr_html_())

        return gspec

    @param.depends('plot_vsound_btn.clicks')
    def plot_vsound(self):
        """
        Compute the speed of sound by fitting phonon frequencies
        along selected directions by linear least-squares fit.
        """
        if self.plot_vsound_btn.clicks == 0: return
        from abipy.dfpt.vsound import SoundVelocity
        sv = SoundVelocity.from_ddb(self.ddb.filepath,
                                    num_points=20,
                                    qpt_norm=0.1,
                                    ignore_neg_freqs=True,
                                    asr=self.asr,
                                    chneut=self.chneut,
                                    dipdip=self.dipdip,
                                    verbose=self.verbose,
                                    mpi_procs=self.mpi_procs)

        # Insert results in grid.
        gspec = pn.GridSpec(sizing_mode='scale_width')
        gspec[0, :1] = sv.get_dataframe()
        gspec[1, :1] = sv.plot(**self.fig_kwargs)

        return gspec

    def get_panel(self):
        """Return tabs with widgets to interact with the DDB file."""
        tabs = pn.Tabs()
        app = tabs.append
        row = pn.Row(
            bkw.PreText(text=self.ddb.to_string(verbose=self.verbose),
                        sizing_mode="scale_both"))
        app(("Summary", row))
        app(("Ph-bands",
             pn.Row(
                 pn.Column(
                     "# PH-bands options", *[
                         self.param[k]
                         for k in ("nqsmall", "ndivsm", "asr", "chneut",
                                   "dipdip", "lo_to_splitting")
                     ], self.temp_range, self.plot_phbands_btn),
                 self.plot_phbands_and_phdos)))
        app(("BECs",
             pn.Row(
                 pn.Column(
                     "# Born effective charges options", *[
                         self.param[k]
                         for k in ("asr", "chneut", "dipdip", "gamma_ev")
                     ], self.get_epsinf_btn), self.get_epsinf)))
        app(("eps0",
             pn.Row(
                 pn.Column(
                     "# epsilon_0", *[
                         self.param[k]
                         for k in ("asr", "chneut", "dipdip", "gamma_ev")
                     ], self.w_range, self.plot_eps0w_btn), self.plot_eps0w)))
        app(("Speed of sound",
             pn.Row(
                 pn.Column(
                     "# Speed of sound options",
                     *[self.param[k] for k in ("asr", "chneut", "dipdip")],
                     self.plot_vsound_btn), self.plot_vsound)))
        app(("Global",
             pn.Column(
                 "# Global parameters",
                 *[self.param[k] for k in ("units", "mpi_procs", "verbose")])))

        return tabs
Exemplo n.º 5
0
import glob, os, sys
import pandas as pd
import numpy as np
import itertools
import panel as pn
import panel.widgets as pnw
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.models.glyphs import Line
from bokeh.palettes import Category10
pn.extension()

year_select = pnw.RangeSlider(name='year',
                              start=2000,
                              end=2015,
                              value=(2000, 2003))
plot = pn.pane.Bokeh()


def plot_extent(event):

    years = range(year_select.value[0], year_select.value[1])
    df = pd.read_csv('seaice_extent_cleaned.csv', index_col=0)
    df['day_of_year'] = pd.to_datetime(df.date).dt.dayofyear
    df = df[df.year.isin(years)]
    df['year'] = df.year.astype(str)
    data = pd.pivot_table(df,
                          index='day_of_year',
                          columns='year',
                          values='Extent').reset_index()
    source = ColumnDataSource(data)
Exemplo n.º 6
0
    def _update_widgets_panel(self):
        self._default_component[self.component_type] = self.component

        component = None
        controls = None
        if self.component is pn.pane.HoloViews:
            component = pn.pane.HoloViews(_create_hvplot())
        if self.component is pn.pane.ECharts:
            # Issue https://github.com/holoviz/panel/issues/1817
            component = pn.pane.ECharts(_create_echarts_plot(),
                                        min_height=400,
                                        min_width=200,
                                        sizing_mode="stretch_both")
        if self.component is pnw.Ace:
            py_code = inspect.getsource(_create_hvplot)
            component = pnw.Ace(
                value=py_code,
                sizing_mode="stretch_width",
                language="python",
                height=400,
                theme=self._ace_theme,
            )
        elif self.component is pnw.AutocompleteInput:
            component = pnw.AutocompleteInput(
                name="Autocomplete Input",
                options=["Biology", "Chemistry", "Physics"],
                placeholder="Write something here",
            )
        elif self.component is pnw.Button:
            component = pnw.Button(name="Click me", button_type="primary")
        elif self.component is pnw.CheckBoxGroup:
            component = pnw.CheckBoxGroup(
                name="Checkbox Group",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
                inline=True,
            )
        elif self.component is pnw.CheckButtonGroup:
            component = pnw.CheckButtonGroup(
                name="Check Button Group",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
                button_type="success",
            )
        elif self.component is pnw.Checkbox:
            component = pnw.Checkbox(name="Checkbox")
        elif self.component is pnw.ColorPicker:
            component = pnw.ColorPicker(name="Color Picker", value="#DF3874")
        elif self.component is pnw.CrossSelector:
            component = pnw.CrossSelector(
                name="Fruits",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
                height=300,
            )
        elif self.component is pnw.DataFrame:
            component = self.component(name="Hello")
            component.value = get_dataframe()
            component.formatters = get_default_formatters(component.value)
            controls = pn.Spacer()
        elif self.component is pnw.DatePicker:
            component = pnw.DatePicker(name="Date Picker")
            # Issue: https://github.com/holoviz/panel/issues/1810
            # component.start = date(2020, 1, 20)
            # component.end = date(2020, 2, 20)
            # component.value = date(2020, 2, 18)
        elif self.component is pnw.DateRangeSlider:
            component = self.component(name="Hello")
            component.start = date(2020, 1, 20)
            component.end = date(2020, 2, 20)
            component.value = (date(2020, 2, 18), date(2020, 2, 20))
        elif self.component is pnw.DateSlider:
            component = self.component(name="Hello")
            component.start = date(2020, 1, 20)
            component.end = date(2020, 2, 20)
            component.value = date(2020, 2, 18)
        elif self.component is pnw.DatetimeInput:
            component = self.component(name="Hello")
            component.value = datetime(2020, 2, 18, 1, 2, 3)
        elif self.component is pnw.DatetimeRangeInput:
            component = self.component(
                name="Hello",
                start=datetime(2020, 1, 20),
                end=datetime(2020, 2, 20),
                value=(datetime(2020, 2, 18), datetime(2020, 2, 20)),
            )
        elif self.component is pnw.DiscretePlayer:
            component = pnw.DiscretePlayer(
                name="Discrete Player",
                options=[2, 4, 8, 16, 32, 64, 128],
                value=32,
                loop_policy="loop",
            )
        elif self.component is pnw.DiscreteSlider:
            component = pnw.DiscreteSlider(name="Discrete Slider",
                                           options=[2, 4, 8, 16, 32, 64, 128],
                                           value=32)
        elif self.component is pnw.FileDownload:
            component = pnw.FileDownload(file="README.md",
                                         filename="README.md")
        elif self.component is pnw.FileInput:
            component = pnw.FileInput(accept=".csv,.json")
        elif self.component is pnw.FileSelector:
            component = pnw.FileSelector(name="Hello", max_height=400)
        elif self.component is pnw.FloatInput:
            component = pnw.FloatInput(name="FloatInput",
                                       value=5.0,
                                       step=1e-1,
                                       start=0,
                                       end=1000)
        elif self.component is pnw.FloatSlider:
            component = pnw.FloatSlider(name="Float Slider",
                                        start=0,
                                        end=3.141,
                                        step=0.01,
                                        value=1.57)
        elif self.component is pnw.IntInput:
            component = pnw.IntInput(name="IntInput",
                                     value=5,
                                     step=2,
                                     start=0,
                                     end=1000)
        elif self.component is pnw.IntRangeSlider:
            component = pnw.IntRangeSlider(name="Integer Range Slider",
                                           start=0,
                                           end=100,
                                           value=(8, 40),
                                           step=2)
        elif self.component is pnw.IntSlider:
            component = pnw.IntSlider(name="Integer Slider",
                                      start=0,
                                      end=20,
                                      step=2,
                                      value=4)
        elif self.component is pnw.LiteralInput:
            component = pnw.LiteralInput(name="Literal Input (dict)",
                                         value={"key": [1, 2, 3]},
                                         type=dict)
        elif self.component is pnw.MenuButton:
            menu_items = [
                ("Option A", "a"),
                ("Option B", "b"),
                ("Option C", "c"),
                None,
                ("Help", "help"),
            ]
            component = pnw.MenuButton(name="Dropdown",
                                       items=menu_items,
                                       button_type="primary")
        elif self.component is pnw.MultiChoice:
            component = pnw.MultiChoice(
                name="MultiSelect",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
            )
        elif self.component is pnw.MultiSelect:
            component = pnw.MultiSelect(
                name="MultiSelect",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
                size=8,
            )
        elif self.component is pnw.PasswordInput:
            component = pnw.PasswordInput(name="Password Input",
                                          placeholder="Enter a string here...")
        elif self.component is pnw.Player:
            component = pnw.Player(name="Player",
                                   start=0,
                                   end=100,
                                   value=32,
                                   loop_policy="loop")
        elif self.component is pnw.Progress:
            component = pnw.Progress(name="Progress", value=20, width=200)
        elif self.component is pnw.RadioBoxGroup:
            component = pnw.RadioBoxGroup(
                name="RadioBoxGroup",
                options=["Biology", "Chemistry", "Physics"],
                inline=True)
        elif self.component is pnw.RadioButtonGroup:
            component = pnw.RadioButtonGroup(
                name="Radio Button Group",
                options=["Biology", "Chemistry", "Physics"],
                button_type="success",
            )
        elif self.component is pnw.RangeSlider:
            component = pnw.RangeSlider(
                name="Range Slider",
                start=0,
                end=math.pi,
                value=(math.pi / 4.0, math.pi / 2.0),
                step=0.01,
            )
        elif self.component is pnw.Select:
            component = pnw.Select(name="Select",
                                   options=["Biology", "Chemistry", "Physics"])
        elif self.component is pnw.StaticText:
            component = pnw.StaticText(name="Static Text", value="A string")
        elif self.component is pnw.TextAreaInput:
            component = pnw.input.TextAreaInput(
                name="Text Area Input", placeholder="Enter a string here...")
        elif self.component is pnw.TextInput:
            component = pnw.TextInput(name="Text Input",
                                      placeholder="Enter a string here...")
        elif self.component == pnw.Toggle:
            component = pnw.Toggle(name="Toggle", button_type="success")
        elif self.component == pnw.VideoStream:
            component = pnw.VideoStream(name="Video Stream",
                                        sizing_mode="stretch_width",
                                        height=300)
        if not component:
            component = self.component(name="Hello")
        if not controls:
            controls = component.controls()
        controls.margin = 0
        self._component_panel[:] = [
            pn.pane.Markdown("## " + component.__class__.name + " " +
                             self.component_type),
            component,
            pn.layout.Divider(),
            pn.pane.Markdown("## Parameters"),
            controls,
        ]
Exemplo n.º 7
0
    ppp.object = rand_df()


rb.on_click(b)

w_tab = pn.Column(rb, ppp, css_classes=['panel-widget-box'], margin=0)

#Histogram and descriptive statistics

variable = pnw.Select(name='Select',
                      options=['rating', 'desc_length', 'price', 'vintage'],
                      width=75)
limits = pnw.RangeSlider(name='Limits',
                         start=80,
                         end=100,
                         value=(80, 100),
                         step=1,
                         orientation='horizontal')
bins = pnw.IntSlider(name='bins',
                     value=20,
                     start=10,
                     end=100,
                     orientation='vertical',
                     width=50)


def cb(event):
    if event.new == 'price':
        limits.value = (int(wine['price'].min()), int(wine['price'].max()))
        limits.start = int(wine['price'].min())
        limits.end = int(wine['price'].max())