Esempio n. 1
0
class SimpleWatchExample(param.Parameterized):
    a = param.Parameter(default=0)
    b = param.Parameter(default=0)
    c = param.Parameter(default=0)
    d = param.Integer(default=0)
    e = param.Event()
    f = param.Event()

    def method(self, event):
        self.b = self.a * 2
Esempio n. 2
0
class Transform(param.Parameterized):
    """Gets data and applies transform"""

    _type = "base"

    widgets = param.Dict(default={})

    updated = param.Event()

    redrawn = param.Event(
        doc="event gets triggered when widgets are changed and the controller needs to redraw them"
    )

    _hash = param.Integer(doc="Hash of current transform state")

    _cache = param.ClassSelector(default=Cache(), class_=Cache)

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

    # perhaps htey should all be private to prevent namespace collision with filter options
    @property
    def source_hash(self):
        return self.source.hash

    @property
    def hash_key(self):
        """hashable key describing the transform"""
        excluded = ["updated", "source", "widgets"]
        return tuple(
            (item, make_tuple(val))
            for item, val in self.param.get_param_values()
            if not (item.startswith("_") or item in excluded)
        )

    @property
    def hash(self):
        tup = (*self.hash_key, self.source_hash)

        return hash(tup)

    def update_hash(self):
        if self.hash == self._hash:
            return False
        else:
            self._hash = self.hash
            return True

    def update(self):
        if self.update_hash():
            self._update_options()  # todo this shouldnt be here
            self.updated = True
Esempio n. 3
0
class Button(_ClickButton):

    clicks = param.Integer(default=0)

    value = param.Event()

    _rename = {'clicks': None, 'name': 'label', 'value': None}

    _widget_type = _BkButton

    def _server_click(self, doc, ref, event):
        processing = bool(self._events)
        self._events.update({"clicks": self.clicks + 1})
        self.param.trigger('value')
        if not processing:
            if doc.session_context:
                doc.add_timeout_callback(partial(self._change_coroutine, doc),
                                         self._debounce)
            else:
                self._change_event(doc)

    def _process_property_change(self, msg):
        msg = super()._process_property_change(msg)
        if 'clicks' in msg:
            msg['clicks'] = self.clicks + 1
        return msg

    def on_click(self, callback):
        self.param.watch(callback, 'clicks', onlychanged=False)
Esempio n. 4
0
class WebAppTransform(param.Parameterized):  #todo subclass from Transform?

    updated = param.Event()

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

    @property
    def panel(self):
        return pn.Column(*self.widgets.values())
        # widget = self.widget.clone()
        # self.widget.link(widget, value='value', bidirectional=True)
        # return widget

    def generate_widgets(self, **kwargs):
        """returns a dict with keys parameter names and values default mapped widgets"""

        names = [
            p for p in self.param
            if self.param[p].precedence is None or self.param[p].precedence > 1
        ]
        widgets = pn.Param(self.param,
                           show_name=False,
                           show_labels=True,
                           widgets=kwargs)

        return {k: v for k, v in zip(names[1:], widgets)}
Esempio n. 5
0
class Source(param.Parameterized):
    """Base class for sources"""

    _type = "base"

    updated = param.Event()

    def get(self):
        raise NotImplementedError()
Esempio n. 6
0
class Button(_ClickButton):

    clicks = param.Integer(default=0)

    value = param.Event()

    _rename = {'clicks': None, 'name': 'label', 'value': None}

    _target_transforms = {'event:button_click': None, 'value': None}

    _widget_type = _BkButton

    @property
    def _linkable_params(self):
        return super()._linkable_params + ['value']

    def jslink(self,
               target,
               code=None,
               args=None,
               bidirectional=False,
               **links):
        links = {
            'event:' + self._event if p == 'value' else p: v
            for p, v in links.items()
        }
        super().jslink(target, code, args, bidirectional, **links)

    jslink.__doc__ = Widget.jslink.__doc__

    def _server_click(self, doc, ref, event):
        processing = bool(self._events)
        self._events.update({"clicks": self.clicks + 1})
        self.param.trigger('value')
        if not processing:
            if doc.session_context:
                doc.add_timeout_callback(partial(self._change_coroutine, doc),
                                         self._debounce)
            else:
                self._change_event(doc)

    def _process_property_change(self, msg):
        msg = super()._process_property_change(msg)
        if 'clicks' in msg:
            msg['clicks'] = self.clicks + 1
        return msg

    def on_click(self, callback):
        self.param.watch(callback, 'clicks', onlychanged=False)
class TestButton(param.Parameterized):

    action = param.Action(lambda x: x._print_something())
    event = param.Event()

    updating = param.Boolean()
    view = param.Parameter(precedence=-1)

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

        self.view = self._create_view()

    @param.depends("event", watch=True)
    def _print_something(self):
        if self.updating:
            return

        self.updating = True
        print(f"event: {self.event}, action: {self.action}")
        time.sleep(1)
        self.updating = False

    @param.depends("updating", watch=True)
    def toggle_loading(self):
        self._action_button.loading = self.updating
        self._event_button.loading = self.updating

    def _create_view(self):
        widgets = pn.Param(
            self,
            parameters=["action", "event", "updating"],
            widgets={
                "action": {
                    "button_type": "primary"
                },
                "event": {
                    "button_type": "success"
                },
                "updating": {
                    "disabled": True
                },
            },
        )
        self._action_button = widgets[1]
        self._event_button = widgets[2]
        self._updating_checkbox = widgets[3]
        return widgets
class TestButton(param.Parameterized):

    action = param.Action(lambda x: x._print_something())
    event = param.Event()

    updating = param.Boolean()

    @param.depends("event", watch=True)
    def _print_something(self):
        if self.updating:
            return

        self.updating = True
        print(f"event: {self.event}, action: {self.action}")
        time.sleep(1)
        self.updating = False
Esempio n. 9
0
class OptsBase(param.Parameterized):

    _type = None

    updated = param.Event()

    def __init__(self, **params):
        super().__init__(**params)
        self._excluded_from_opts = ["name"
                                    ]  # todo remove this and opts property

        self.widgets = self.generate_widgets()

    @property
    def panel(self):
        return pn.Column(*self.widgets.values())

    @property
    def opts(self):
        opts = {
            name: self.param[name]
            for name in self.param if name not in self._excluded_from_opts
        }
        return opts

    def generate_widgets(self, **kwargs):
        """returns a dict with keys parameter names and values default mapped widgets"""
        # todo base class?

        names = [
            p for p in self.param
            if self.param[p].precedence is None or self.param[p].precedence > 1
        ]
        widgets = pn.Param(self.param,
                           show_name=False,
                           show_labels=True,
                           widgets=kwargs)

        return {k: v for k, v in zip(names[1:], widgets)}
Esempio n. 10
0
class WebAppFilter(Filter):
    """

    """

    source = param.ClassSelector(Source)

    # maybe instead of making filters co-dependent the second filter should have a DerivedSource
    # but we'll deal with this later
    filters = param.List()

    updated = param.Event()

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

        if self.source:
            self.source.param.watch(self.update, 'updated')

        for filt in self.filters:
            filt.param.watch(self.update, 'updated')

    def get_data(self):
        """Equivalent to view's get_data method"""

        query = {
            filt.field: filt.query
            for filt in self.filters if filt.query is not None and (
                filt.table is None or filt.table == self.table)
        }

        data = self.source.get(self.table, **query)
        return data

    @param.depends('value', watch=True)
    def update(self, *events):
        """gets called when the source event triggers"""
        self.updated = True
Esempio n. 11
0
class SpeechToText(Widget):
    """
    The SpeechToText widget controls the speech recognition service of
    the browser.

    It wraps the HTML5 SpeechRecognition API.  See
    https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition

    This functionality is **experimental** and only supported by
    Chrome and a few other browsers.  Checkout
    https://caniuse.com/speech-recognition for a up to date list of
    browsers supporting the SpeechRecognition Api. Or alternatively
    https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition#Browser_compatibility

    On some browsers, like Chrome, using Speech Recognition on a web
    page involves a server-based recognition engine. Your audio is
    sent to a web service for recognition processing, so it won't work
    offline. Whether this is secure and confidential enough for your
    use case is up to you to evaluate.
    """

    abort = param.Event(doc="""
        Stops the speech recognition service from listening to
        incoming audio, and doesn't attempt to return a
        RecognitionResult.""")

    start = param.Event(doc="""
        Starts the speech recognition service listening to incoming
        audio with intent to recognize grammars associated with the
        current SpeechRecognition.""")

    stop = param.Event(doc="""
        Stops the speech recognition service from listening to
        incoming audio, and attempts to return a RecognitionResult
        using the audio captured so far.""")

    lang = param.ObjectSelector(default="",
                                objects=[""] + LANGUAGE_CODES,
                                allow_None=True,
                                label="Language",
                                doc="""
        The language of the current SpeechRecognition in BCP 47
        format. For example 'en-US'. If not specified, this defaults
        to the HTML lang attribute value, or the user agent's language
        setting if that isn't set either.  """)

    continuous = param.Boolean(default=False,
                               doc="""
        Controls whether continuous results are returned for each
        recognition, or only a single result. Defaults to False""")

    interim_results = param.Boolean(default=False,
                                    doc="""
        Controls whether interim results should be returned (True) or
        not (False.) Interim results are results that are not yet
        final (e.g. the RecognitionResult.is_final property is
        False).""")

    max_alternatives = param.Integer(default=1,
                                     bounds=(1, 5),
                                     doc="""
        Sets the maximum number of RecognitionAlternatives provided
        per result.  A number between 1 and 5. The default value is
        1.""")

    service_uri = param.String(doc="""
        Specifies the location of the speech recognition service used
        by the current SpeechRecognition to handle the actual
        recognition. The default is the user agent's default speech
        service.""")

    grammars = param.ClassSelector(class_=GrammarList,
                                   doc="""
        A GrammarList object that represents the grammars that will be
        understood by the current SpeechRecognition service""")

    button_hide = param.Boolean(default=False,
                                label="Hide the Button",
                                doc="""
        If True no button is shown. If False a toggle Start/ Stop button is shown."""
                                )

    button_type = param.ObjectSelector(default="light",
                                       objects=BUTTON_TYPES,
                                       doc="""
        The button styling.""")

    button_not_started = param.String(label="Button Text when not started",
                                      doc="""
        The text to show on the button when the SpeechRecognition
        service is NOT started.  If '' a *muted microphone* icon is
        shown.""")

    button_started = param.String(label="Button Text when started",
                                  doc="""
        The text to show on the button when the SpeechRecognition
        service is started. If '' a *muted microphone* icon is
        shown.""")

    started = param.Boolean(constant=True,
                            doc="""
        Returns True if the Speech Recognition Service is started and
        False otherwise.""")

    audio_started = param.Boolean(constant=True,
                                  doc="""
        Returns True if the Audio is started and False otherwise.""")

    sound_started = param.Boolean(constant=True,
                                  doc="""
        Returns True if the Sound is started and False otherwise.""")

    speech_started = param.Boolean(constant=True,
                                   doc="""
        Returns True if the the User has started speaking and False otherwise."""
                                   )

    results = param.List(constant=True,
                         doc="""
        The `results` as a list of Dictionaries.""")

    value = param.String(constant=True,
                         label="Last Result",
                         doc="""
        The transcipt of the highest confidence RecognitionAlternative
        of the last RecognitionResult. Please note we strip the
        transcript for leading spaces.""")

    _grammars = param.List(constant=True,
                           doc="""
        List used to transfer the serialized grammars from server to
        browser.""")

    _widget_type = _BkSpeechToText

    _rename = {
        "value": None,
        "grammars": None,
        "_grammars": "grammars",
    }

    def __init__(self, **params):
        super().__init__(**params)
        if self.grammars:
            self._update_grammars()

    def __repr__(self, depth=None):
        # Custom repr needed to avoid infinite recursion because this Parameterized class has
        # multiple actions
        return f"SpeechToText(name='{self.name}')"

    @param.depends("grammars", watch=True)
    def _update_grammars(self):
        with param.edit_constant(self):
            if self.grammars:
                self._grammars = self.grammars.serialize()  # pylint: disable=no-member
            else:
                self._grammars = []

    @param.depends("results", watch=True)
    def _update_results(self):
        # pylint: disable=unsubscriptable-object
        with param.edit_constant(self):
            if self.results and "alternatives" in self.results[-1]:
                self.value = (self.results[-1]["alternatives"][0]["transcript"]
                              ).lstrip()
            else:
                self.value = ""

    @property
    def results_deserialized(self):
        """
        Returns the results as a List of RecognitionResults
        """
        return RecognitionResult.create_from_list(self.results)

    @property
    def results_as_html(self) -> str:
        """
        Returns the `results` formatted as html

        Convenience method for ease of use
        """
        if not self.results:
            return "No results"
        html = "<div class='pn-speech-recognition-result'>"
        total = len(self.results) - 1
        for index, result in enumerate(reversed(self.results_deserialized)):
            if len(self.results) > 1:
                html += f"<h3>Result {total-index}</h3>"
            html += f"<span>Is Final: {result.is_final}</span><br/>"
            for index2, alternative in enumerate(result.alternatives):
                if len(result.alternatives) > 1:
                    html += f"<h4>Alternative {index2}</h4>"
                html += f"""
                <span>Confidence: {alternative.confidence:.2f}</span>
                </br>
                <p>
                  <strong>{alternative.transcript}</strong>
                </p>
                """
        html += "</div>"
        return html
Esempio n. 12
0
class GridEditor(param.Parameterized):
    """
    Interactive boundary editor for previewing and generating pygridgen grids.

    Core features:
       * Add, drag and delete nodes interactively with the PointsDraw tool
       * Toggle their polarity (beta) value with the Tap Tool
       * Insert nodes into selected edges after selecting them with the Tap Tool.
       * Set a focus function and update the grid
       * Pythonic access to the geopandas boundary DataFrame.
       * Serializable state to capture editor state between sessions
       * Customizable background tile sources or background tile elements.

    For more information please visit https://github.com/pygridgen/hologridgen
    """

    # Algorithmic parameters hidden from the GUI

    max_nodes = param.Integer(default=1000, precedence=-1,
                              doc = "Maximum number of nodes in a boundary")

    ul_idx=param.Integer(default=0, precedence=-1,
                         doc='Upper left index: parameter of grid generation')

    polarity_value = param.Dict(default={'+':1, '0':0, '-':-1}, precedence=-1, doc="""
      Beta values to associate with the three node polarities (positive
      '+', neutral '0' and negative '-'). Setting '+':4/3 for instance
      enables grid generation with only three positive nodes.""")

    # Parameters not in the GUI for Pythonic data access

    focus = param.ClassSelector(default=None, class_=pgg.Focus,
                                allow_None=True, precedence=-1, doc="""
      Parameter that can be set to a pygridgen Focus object (or None).
      When set, mesh generation will apply the specified Focus
      function.""")

    grid = param.ClassSelector(default=None, class_=pgg.grid.Gridgen,
                               allow_None=True, precedence=-1, doc="""
      Parameter that exposes the pygridgen Gridgen object that will be
      set after mesh generation """)

    ready = param.Boolean(default=False, precedence=-1, doc="""
      Boolean predicate indicating readiness for mesh generation: mesh generation
      can be executed when the sum of the polarity in the boundary is 4.""")

    # User settings hidden from the GUI, settable in the constructor (precedence= -1)

    width = param.Integer(default=600, precedence=-1, bounds=(200, 1000),
        doc="Width of the HoloViews object corresponding to the editor view area")

    height = param.Integer(default=600, precedence=-1, bounds=(200, 1000),
        doc="Height of the HoloViews object corresponding to the editor view area")

    custom_background = param.Parameter(default=None, precedence=-1, doc="""
      Custom HoloViews element to use as the background when the
      background parameter is set to 'Custom'.""")

    background = param.ObjectSelector('None', objects=TILE_SOURCES.keys(), doc="""
      Selector of available default tile sources which can also be set
      to 'None' for no background or 'Custom' in which case the
      HoloViews/GeoViews element set in the custom_background parameter
      (if any) is used as the background.""")

    # Customizable HoloViews styles (hidden from the GUI, settable in the constructor)

    node_style = param.Dict(dict(cmap={'+': 'red', '-': 'blue', '0':'black'}),
                            precedence=-1, doc="""
      Style options for nodes. Note that the size is overidden by the
      node_size param controllable in the GUI and the polarity colors
      can be changed by setting the cmap dictionary.""")

    mesh_style = param.Dict(dict(line_width=2, line_alpha=1, line_color='blue'),
                            precedence=-1, doc="Style options for displayed mesh.")


    edge_style = param.Dict(dict(line_width=2, line_alpha=1, line_color='green',
                                nonselection_color='green', nonselection_alpha=0.5),
                            precedence=-1, doc="""
      Style options for displayed boundary edges. The nonselection_*
      options set how deselected edges appear when the Tap tool is used
      to insert new nodes into edges""")

    start_indicator_style = param.Dict(
        dict(marker='triangle', angle=30, fill_alpha=0, size=30, color='black'),
        precedence=-1, doc="""
      Style of the start marker indicating the first boundary
      point. Default is a triangle that can be rotated by setting the
      'angle' keyword.""")

    # GUI controllable parameters

    node_size = param.Integer(default=10, bounds=(1,200),
                              doc="Size of nodes used to mark the boundary.")

    edge_width = param.Integer(default=2, bounds=(1,50), doc="Width of the boundary edges")

    xres = param.Integer(default=50,  bounds=(2, None), doc="""
       X resolution of the generated grid""")

    yres = param.Integer(default=50,  bounds=(2, None), doc="""
       Y resolution of the generated grid""")

    generate_mesh = param.Event(doc='Event that runs mesh generation')

    hide_mesh = param.Event(doc='Event that clears displayed mesh')

    insert_points = param.Event(
        doc='Event that inserts a new node into an edge selected with the Tap tool')

    _columns = ['color', 'polarity', 'x', 'y']


    def __init__(self, data=None, **params):
        data_params = {} if data is None else {k:v for k,v in data.items()
                                               if k not in self._columns}
        params = dict(data_params, **params)
        data = {k:[] for k in self._columns} if (data is None) else data
        super().__init__(**params)

        def install_handle(plot, element):
            "Handle needed to make the draw_tool available in the JS callback"
            plot.handles['draw_tool'] = plot.state.tools[-1]

        node_style = dict(self.node_style,
                           tools=['tap'],
                           color=hv.dim('polarity'),
                           fill_alpha=hv.dim('polarity').categorize({'0':0, '+':1, '-':1 }),
                           show_legend=False, hooks=[install_handle])

        # PointDraw Stream that enables the PointDraw Bokeh tool
        self._node_stream = hv.streams.PointDraw(data=data,
                                                 num_objects=self.max_nodes,
                                                 empty_value = '+')

        # Nodes is a DynamicMap returning hv.Points along the boundary
        self.nodes = hv.DynamicMap(self.points,
                                  streams=[self._node_stream,
                                           self.param.insert_points,
                                           self.param.node_size]).opts(**node_style)
        # DynamicMap drawing the boundary as a hv.Path element
        self.boundary_dmap = hv.DynamicMap(self._boundary,
                                         streams=[self._node_stream,
                                                  hv.streams.Selection1D()])
        # DynamicMap placing the start indicator
        self.start_marker = hv.DynamicMap(self._start_marker,
                                          streams=[self._node_stream]
                                          ).opts(**self.start_indicator_style)

        # Initial, empty mesh
        self.qmesh = hv.QuadMesh((np.zeros((2,2)), np.zeros((2,2)), np.zeros((2,2))))

        self._selected_edge_index = None

    @classmethod
    def from_geopandas(cls, df):
        """
        Classmethod that allows a GridEditor to be initialized from a
        boundary geopandas DataFrame (such as the one available from the
        .boundary property).
        """
        if len(df) == 0:
            return GridEditor()
        allowed = [el for el in cls._columns if el != 'geometry']
        color_vals = {v:k for k,v in cls.polarity_value.items()}
        data = {k:list(v) for k,v in df.to_dict(orient='list').items() if k in allowed}
        data['color'] = [color_vals[p] for p in data['polarity']]
        data['polarity'] = data['color']
        return GridEditor(data)

    @property
    def boundary(self):
        "Property returning the boundary GeoDataFrame"
        exclude = ['color', 'fill_alpha']
        data = self._node_stream.data
        polarity = [self.polarity_value[c] for c in data['color']]
        df_data = {c:[el for el in v] for c,v in data.items() if c not in exclude}
        df_data['polarity'] = polarity
        df = pd.DataFrame(df_data)
        return geopandas.GeoDataFrame(df, geometry=geopandas.points_from_xy(df.x, df.y))


    @property
    def data(self, exclude=['name', 'fill_alpha', 'grid']):
        """
        Propery exposing serializable state of the editor that can be
        passed into the GridEditor constructor to restore that state
        """
        data = {k:[el for el in v] for k,v in self._node_stream.data.items()}
        param_data = {p:getattr(self, p) for p in self.param}
        data.update(param_data)
        return {k:v for k,v in data.items() if k not in exclude}

    def _ready(self):
        "Predicate method indicating current readiness for mesh generation"
        data = self._node_stream.data

        if len(data['x']) > 3:
            summed = sum(self.polarity_value[el] for el in data['color'])
            return (summed == 4)
        else:
            return False


    @pn.depends('ready', watch=True)
    def _check_readiness(self):
        "Callback used to disable generate mesh button till ready"
        for widget in self.widgets:
            if isinstance(widget, pn.widgets.button.Button) and (widget.name == 'Generate mesh'):
                button = widget
                break
        button.disabled = not self.ready


    @pn.depends('_node_stream.data')
    def _geojson(self):
        "Callback to generate GeoJSON file when download button is clicked"
        boundary = self.boundary
        bio = BytesIO()
        if len(boundary) != 0:
            boundary.to_file(bio, driver='GeoJSON')
        bio.seek(0)
        return bio

    # DynamicMap callbacks

    def points(self, data, insert_points, node_size):
        "DynamicMap callback returns Points representing boundary nodes"
        new_data = {'x': data['x'], 'y': data['y'],
                    'polarity' : np.array(data['color'], dtype='U1')}
        if insert_points and len(self._selected_edge_index)==1:
            point_index = self._selected_edge_index[0] + 1
            sx, ex = new_data['x'][point_index-1], new_data['x'][point_index]
            sy, ey = new_data['y'][point_index-1], new_data['y'][point_index]

            new_data['x'] = np.insert(new_data['x'], point_index, (sx+ex) / 2.)
            new_data['y'] = np.insert(new_data['y'], point_index, (sy+ey) / 2.)
            new_data['polarity'] = np.insert(new_data['polarity'], point_index, '+')
        return hv.Points(new_data, vdims=['polarity']).opts(size=node_size)


    def _generate_mesh(self, generate_mesh=False, hide_mesh=False):
        "Callback returning generated QuadMesh element"
        if not self.ready:
            return self.qmesh.opts(fill_alpha=0, line_alpha=0)

        elif hide_mesh or (not generate_mesh):
            return self.qmesh.opts(fill_alpha=0, line_alpha=0)

        if self.ready:
            gdf = self.boundary
            kwargs = dict(shape=(self.xres, self.yres), ul_idx=self.ul_idx)
            if self.focus is not None:
                kwargs['focus'] = self.focus
            self.grid = pgg.Gridgen(gdf.geometry.x, gdf.geometry.y, gdf.polarity, **kwargs)
            xdim, ydim = self.grid.x.shape
            zs = np.ones((xdim-1, ydim-1))
            self.qmesh = hv.QuadMesh((np.array(self.grid.x), np.array(self.grid.y), zs))
            return self.qmesh.opts(**self.mesh_style, fill_alpha=0)


    def _boundary(self, data,  index):
        "Callback drawing Path element defining boundary"
        self._selected_edge_index = index
        xs, ys = data['x'], data['y']
        lines = []
        for i in range(len(xs)-1):
            s, e = i, (i+1)
            lines.append([(xs[s], ys[s]), (xs[e], ys[e])])
        self.ready = self._ready()
        return hv.Path(lines).opts(**self.edge_style)

    def _start_marker(self, data):
        "Callback to draw the start marker"
        if len(data['x']) == 0:
            return hv.Points(None)
        return hv.Points((data['x'][0], data['y'][0]))


    def _background(self, background):
        """
        Callback that allows the background to be switched between tile
        sources, a custom background element or None for no
        background
        """
        elements = []
        if background != 'None':
            elements = [TILE_SOURCES[background].opts(global_extent=True, alpha=1)]
        elif background == 'None':
            if self.custom_background:
                elements = [self.custom_background]
            else:
                elements = [TILE_SOURCES[list(TILE_SOURCES.keys())[0]].opts(alpha=0)]
        return hv.Overlay(elements)


    def view(self):
        "Main entry point for using the GridEditor after construction"
        self.polarity_link =  PolaritySwap(self.nodes)
        param_stream = hv.streams.Params(self,
                                         ['generate_mesh', 'hide_mesh'],
                                         transient=True)

        elements = [hv.DynamicMap(self._background, streams=[self.param.background]),
                    self.boundary_dmap.apply.opts(line_width=self.param.edge_width),
                    self.start_marker,
                    self.nodes,
                    hv.DynamicMap(self._generate_mesh,
                    streams=[param_stream])]

        hvobj = hv.Overlay(elements).collate()
        self.widgets = pn.Param(self.param,
                                widgets={'edge_select_mode': pn.widgets.Toggle})
        obj = pn.Row(pn.Column(self.widgets,
                               pn.widgets.FileDownload(callback=self._geojson,
                                                       filename='boundary.geojson')),
                     hvobj.opts(width=self.width, height=self.height))
        self.param.trigger('ready')
        return obj
Esempio n. 13
0
class TextToSpeech(Utterance, Widget):
    """
    The `TextToSpeech` widget wraps the HTML5 SpeechSynthesis API

    See https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis

    Reference: https://panel.holoviz.org/reference/widgets/TextToSpeech.html

    :Example:

    >>> TextToSpeech(name="Speech Synthesis", value="Data apps are nice")
    """

    auto_speak = param.Boolean(default=True,
                               doc="""
        Whether or not to automatically speak when the value changes.""")

    cancel = param.Event(doc="""
        Removes all utterances from the utterance queue.""")

    pause = param.Event(doc="""
        Puts the TextToSpeak object into a paused state.""")

    resume = param.Event(doc="""
        Puts the TextToSpeak object into a non-paused state: resumes
        it if it was already paused.""")

    paused = param.Boolean(readonly=True,
                           doc="""
        A Boolean that returns true if the TextToSpeak object is in a
        paused state.""")

    pending = param.Boolean(readonly=True,
                            doc="""
        A Boolean that returns true if the utterance queue contains
        as-yet-unspoken utterances.""")

    speak = param.Event(doc="""
        Speak. I.e. send a new Utterance to the browser""")

    speaking = param.Boolean(readonly=True,
                             doc="""
        A Boolean that returns true if an utterance is currently in
        the process of being spoken — even if TextToSpeak is in a
        paused state.""")

    voices = param.List(readonly=True,
                        doc="""
        Returns a list of Voice objects representing all the available
        voices on the current device.""")

    _voices = param.List()

    _widget_type = _BkTextToSpeech

    _rename = {
        "auto_speak": None,
        "lang": None,
        "pitch": None,
        "rate": None,
        "speak": None,
        "value": None,
        "voice": None,
        "voices": None,
        "volume": None,
        "_voices": "voices",
    }

    def _process_param_change(self, msg):
        speak = msg.get('speak') or ('value' in msg and self.auto_speak)
        msg = super()._process_param_change(msg)
        if speak:
            msg['speak'] = self.to_dict()
        return msg

    @param.depends("_voices", watch=True)
    def _update_voices(self):
        voices = []
        for _voice in self._voices:  # pylint: disable=not-an-iterable
            voice = Voice(**_voice)
            voices.append(voice)
        self.voices = voices
        self.set_voices(self.voices)

    def __repr__(self, depth=None):
        # We need to do this because otherwise a error is raised when used in notebook
        # due to infinite recursion
        return f"TextToSpeech(name={self.name})"

    def __str__(self):
        return f"TextToSpeech(name={self.name})"
Esempio n. 14
0
class DataFrameSource(Source):

    tables = param.Dict({}, doc="Dictionary of tables in this Source")

    updated = param.Event()

    dropna = param.Boolean(
        True,
        doc=
        'Remove rows of all NaN when adding / selecting / removing  dataframes'
    )

    # def __init__(self, **params):
    #     pass
    # super().__init__(**params)
    # if self.df.columns.nlevels == 1:
    #     self.tables = [self.name]
    #     self.multiindex = False
    # elif self.df.columns.nlevels == 2:
    #     self.multiindex = True
    #     self.tables = [] # todo populate tables for multiindex
    # else:
    #     raise ValueError("Currently column multiindex beyond two levels is not supported")

    def remove_df(self, table, name, level):
        raise NotImplementedError('Removing datafarmes not implemented')

        self.updated = True

    def add_df(self, df, table, names=None):
        """
        #Todo method for adding a table to multindex source

        Parameters
        ----------
        df

        Returns
        -------

        """

        # todo check if df already present, update?

        target_df = self.tables[table]
        df = df.copy()
        if target_df.columns.nlevels != df.columns.nlevels:
            if isinstance(names, str):
                names = [names]
            if len(names) != target_df.columns.nlevels - df.columns.nlevels:
                raise ValueError(
                    f"Insufficient names provided to match target dataframe multindex level {df.columns.nlevels}"
                )

            if df.columns.nlevels == 1:
                cols = ((column, ) for column in df.columns)
            else:
                cols = df.columns
            tuples = tuple((*names, *tup) for tup in cols)
            new_index = pd.MultiIndex.from_tuples(
                tuples, names=target_df.columns.names)
            df.columns = new_index

        new_df = pd.concat([target_df, df], axis=1)
        if self.dropna:
            new_df = new_df.dropna(how='all')

        self.tables[table] = new_df
        #todo check for row indices

        self.updated = True

    def get(self, table, **query):
        df = self.tables[table]

        # This means querying a field with the same name as higher-levels columns is not possible
        while df.columns.nlevels > 1:
            selected_col = query.pop(df.columns.names[0], False)
            if selected_col:
                df = df[selected_col]
                if self.dropna:
                    df = df.dropna(
                        how='all'
                    )  # These subsets will have padded NaN rows. Remove?
            else:
                break

        dask = query.pop('__dask', False)
        df = self._filter_dataframe(df, **query)

        return df

    @cached_schema
    def get_schema(self, table=None):
        schemas = {}
        for name in self.tables:
            if table is not None and name != table:
                continue
            df = self.get(name)
            schemas[name] = get_dataframe_schema(df)['items']['properties']
        return schemas if table is None else schemas[table]

    def get_unique(self, table=None, field=None, **query):
        """Get unique values for specified tables and fields"""
        print('deprecation candidate')
        unique_values = {}
        for name in self.tables:
            if table is not None and name != table:
                continue
            df = self.get(name, **query)
            if field is not None:
                unique_values[name] = df[field].unique()
            else:
                unique_values[name] = {
                    field_name: df[field_name].unique()
                    for field_name in df.columns
                }

            return unique_values if table is None else unique_values[table]
Esempio n. 15
0
class Button(_ClickButton):
    """
    The `Button` widget allows triggering events when the button is
    clicked.

    The Button provides a `value` parameter, which will toggle from
    `False` to `True` while the click event is being processed

    It also provides an additional `clicks` parameter, that can be
    watched to subscribe to click events.

    Reference: https://panel.holoviz.org/reference/widgets/Button.html#widgets-gallery-button

    :Example:

    >>> pn.widgets.Button(name='Click me', button_type='primary')
    """

    clicks = param.Integer(default=0,
                           doc="""
        Number of clicks (can be listened to)""")

    value = param.Event(doc="""
        Toggles from False to True while the event is being processed.""")

    _rename = {'clicks': None, 'name': 'label', 'value': None}

    _target_transforms = {'event:button_click': None, 'value': None}

    _widget_type = _BkButton

    @property
    def _linkable_params(self):
        return super()._linkable_params + ['value']

    def jslink(self,
               target,
               code=None,
               args=None,
               bidirectional=False,
               **links):
        links = {
            'event:' + self._event if p == 'value' else p: v
            for p, v in links.items()
        }
        super().jslink(target, code, args, bidirectional, **links)

    jslink.__doc__ = Widget.jslink.__doc__

    def _process_event(self, event):
        self.param.trigger('value')
        self.clicks += 1

    def on_click(self, callback):
        """
        Register a callback to be executed when the `Button` is clicked.

        The callback is given an `Event` argument declaring the number of clicks

        Arguments
        ---------
        callback: (callable)
            The function to run on click events. Must accept a positional `Event` argument
        """
        self.param.watch(callback, 'clicks', onlychanged=False)