示例#1
0
 def test_pipe_stream(self):
     stream = Pipe(data=self.df)
     plot = self.df.hvplot('x', 'y', stream=stream)
     pd.testing.assert_frame_equal(plot[()].data, self.df)
     new_df = pd.DataFrame([[7, 8], [9, 10]], columns=['x', 'y'])
     stream.send(new_df)
     pd.testing.assert_frame_equal(plot[()].data, new_df)
class SubwayMap(Stream):
    '''subway map (holoviews dynamic map) including pyviz.param-based control interface.
    inherited from a holoviews stream object.'''

    #class variables
    direction_list = ['North', 'South']
    lines_list = [
        'All', '1', '2', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F',
        'G', 'H', 'J', 'L', 'M', 'N', 'Q', 'R', 'SI', 'W'
    ]
    display_list = ['Time since last train', 'Probability of train delay']

    #Selector class variables (parameters) for holoviews panel
    direction = param.ObjectSelector(default='North', objects=direction_list)
    line = param.ObjectSelector(default='All', objects=lines_list)
    display = param.ObjectSelector(default='Probability of train delay',
                                   objects=display_list)

    def callback(self, data):
        if (self.display == 'Probability of train delay'):
            layout = gv.Points(data,
                               vdims=[
                                   'color', 'displaysize', 'name',
                                   'waittime_str', 'delay_prob', 'MTAdelay',
                                   'inboundtrain', 'inbound_from'
                               ]).opts(tools=[SubwayMap.hover_delays],
                                       size='displaysize',
                                       color='color')
        #elif(self.display == 'Time since last train'):
        else:
            layout = gv.Points(data,
                               vdims=[
                                   'waittimecolor', 'waittimedisplaysize',
                                   'name', 'waittime_str', 'delay_prob',
                                   'MTAdelay'
                               ]).opts(tools=[SubwayMap.hover_waittime],
                                       size='waittimedisplaysize',
                                       color='waittimecolor')
        return layout

    def __init__(self, mapdata):
        '''initialize a SubwayMap object
        Args:
            mapdata (SubwayMapData): container-class for stations and lines dataframes with implemented observer pattern.
                                    This is necessary for data binding of the view to the viewmodel.
        '''
        Stream.__init__(self)

        #create an initial map
        stations, lines = mapdata.stationsdf, mapdata.linesdf
        self.pipe = Pipe(data=[])
        self.subway_map = gv.Path(lines, vdims=['color']).opts(
            projection=crs.LambertConformal(),
            height=800,
            width=800,
            color='color') * gv.DynamicMap(self.callback, streams=[self.pipe])
        self.pipe.send(stations)

        #bind changes in the stationsdf to pipe.send
        mapdata.bind_to_stationsdf(self.pipe.send)
        self.mapdata = mapdata

    hover_delays = HoverTool(
        tooltips=[("station", "@name"), (
            "incoming train",
            "@inboundtrain"), ("from station", "@inbound_from"),
                  ("probability that incoming train is delayed",
                   "@delay_prob"), ("MTA reports delay?", "@MTAdelay")])
    hover_waittime = HoverTool(
        tooltips=[("station",
                   "@name"), ("time since last train", "@waittime_str")])

    def view(self):
        return self.subway_map

    #https://panel.pyviz.org/user_guide/Param.html
    @param.depends('direction', 'line', watch=True)
    def update(self):
        self.mapdata.selected_dir = self.direction
        self.mapdata.selected_line = self.line
示例#3
0
class hvRectangleAppView(View):

    opts = param.Dict(default={}, doc="HoloViews option to apply on the plot.")

    view_type = 'rectangles'

    streaming = param.Boolean(default=False,
                              doc="""
        Whether to stream new data to the plot or rerender the plot.""")

    def __init__(self, **params):
        # import hvplot.pandas # noqa
        # if 'dask' in sys.modules:
        #     try:
        #         import hvplot.dask # noqa
        #     except Exception:
        #         pass
        self._stream = None
        self._linked_objs = []
        super().__init__(**params)

    def get_panel(self):
        kwargs = self._get_params()
        #interactive? https://github.com/holoviz/panel/issues/1824
        return pn.pane.HoloViews(**kwargs)

    def get_plot(self, df):
        """
        Dataframe df must have columns x0, y0, x1, y1 (in this order) for coordinates
        bottom-left (x0, y0) and top right (x1, y1). Optionally a fifth value-column can be provided for colors

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

        Returns
        -------

        """
        # processed = {}
        # for k, v in self.kwargs.items():
        #     if k.endswith('formatter') and isinstance(v, str) and '%' not in v:
        #         v = NumeralTickFormatter(format=v)
        #     processed[k] = v
        # if self.streaming:
        #     processed['stream'] = self._stream

        #hvplots stream? https://holoviews.org/user_guide/Streaming_Data.html

        #        plot = hv.Rectangles([(0, 0, 1, 1), (2, 3, 4, 6), (0.5, 2, 1.5, 4), (2, 1, 3.5, 2.5)])

        processed = {}
        for k, v in self.kwargs.items():
            if k.endswith('formatter') and isinstance(v, str) and '%' not in v:
                v = NumeralTickFormatter(format=v)
            processed[k] = v
        if self.streaming:
            #processed['stream'] = self._stream

            plot = hv.DynamicMap(hv.Rectangles, streams=[self._stream])
            plot = plot.apply.opts(**self.opts) if self.opts else plot
        else:
            plot = hv.Rectangles(df)
            plot.opts(**self.opts) if self.opts else plot

        if self.selection_group or 'selection_expr' in self._param_watchers:
            plot = self._link_plot(plot)

        return plot

    def _get_params(self):
        df = self.get_data()

        if self.streaming:
            from holoviews.streams import Pipe
            self._stream = Pipe(data=df)
        return dict(object=self.get_plot(df),
                    sizing_mode='stretch_both')  # todo update sizing mode

    def get_data(self):
        #todo uniformify this method for all views
        try:
            return super().get_data()
        except (KeyError, ValueError) as e:
            print(f'Empty data in {self.__class__}: {e}')
            return self.empty_df

    def update(self, *events, invalidate_cache=True):
        """
        Triggers an update in the View.

        Parameters
        ----------
        events: tuple
            param events that may trigger an update.
        invalidate_cache : bool
            Whether to clear the View's cache.

        Returns
        -------
        stale : bool
            Whether the panel on the View is stale and needs to be
            rerendered.
        """
        # Skip events triggered by a parameter change on this View
        own_parameters = [self.param[p] for p in self.param]
        own_events = events and all(
            isinstance(e.obj, ParamFilter) and
            (e.obj.parameter in own_parameters
             or e.new is self._ls.selection_expr) for e in events)
        if own_events:
            return False
        if invalidate_cache:
            self._cache = None
        if not self.streaming or self._stream is None:
            upd = self._update_panel()
            return upd
        self._stream.send(self.get_data())
        return False

    @property
    def empty_df(self):
        return pd.DataFrame([[0] * 5],
                            columns=['x0', 'x1', 'y0', 'y1', 'value'])
示例#4
0
class hvPlotView(View):
    """
    The hvPlotView renders the queried data as a bokeh plot generated
    with hvPlot. hvPlot allows for a concise declaration of a plot via
    its simple API.
    """

    kind = param.String(doc="The kind of plot, e.g. 'scatter' or 'line'.")

    x = param.Selector(doc="The column to render on the x-axis.")

    y = param.Selector(doc="The column to render on the y-axis.")

    by = param.ListSelector(doc="The column(s) to facet the plot by.")

    groupby = param.ListSelector(doc="The column(s) to group by.")

    opts = param.Dict(default={},
                      doc="HoloViews options to apply on the plot.")

    streaming = param.Boolean(default=False,
                              doc="""
        Whether to stream new data to the plot or rerender the plot.""")

    selection_expr = param.Parameter(doc="""
        A selection expression caputirng the current selection applied
        on the plot.""")

    view_type = 'hvplot'

    _field_params = ['x', 'y', 'by', 'groupby']

    _supports_selections = True

    def __init__(self, **params):
        import hvplot.pandas  # noqa
        if 'dask' in sys.modules:
            try:
                import hvplot.dask  # noqa
            except Exception:
                pass
        if 'by' in params and isinstance(params['by'], str):
            params['by'] = [params['by']]
        if 'groupby' in params and isinstance(params['groupby'], str):
            params['groupby'] = [params['groupby']]
        self._stream = None
        self._linked_objs = []
        super().__init__(**params)

    def get_plot(self, df):
        processed = {}
        for k, v in self.kwargs.items():
            if k.endswith('formatter') and isinstance(v, str) and '%' not in v:
                v = NumeralTickFormatter(format=v)
            processed[k] = v
        if self.streaming:
            processed['stream'] = self._stream
        plot = df.hvplot(kind=self.kind, x=self.x, y=self.y, **processed)
        plot = plot.opts(**self.opts) if self.opts else plot
        if self.selection_group or 'selection_expr' in self._param_watchers:
            plot = self._link_plot(plot)
        return plot

    def _link_plot(self, plot):
        self._init_link_selections()
        linked_objs = list(self._ls._plot_reset_streams)
        plot = self._ls(plot)
        self._linked_objs += [
            o for o in self._ls._plot_reset_streams if o not in linked_objs
        ]
        return plot

    def _cleanup(self):
        if self._ls is None:
            return
        for obj in self._linked_objs:
            reset = self._ls._plot_reset_streams.pop(obj)
            sel_expr = self._ls._selection_expr_streams.pop(obj)
            self._ls._cross_filter_stream.input_streams.remove(sel_expr)
            sel_expr.clear()
            sel_expr.source = None
            reset.clear()
            reset.source = None
        self._linked_objs = []

    def get_panel(self):
        return pn.pane.HoloViews(**self._get_params())

    def _get_params(self):
        df = self.get_data()
        if self.streaming:
            from holoviews.streams import Pipe
            self._stream = Pipe(data=df)
        return dict(object=self.get_plot(df))

    def update(self, *events, invalidate_cache=True):
        """
        Triggers an update in the View.

        Parameters
        ----------
        events: tuple
            param events that may trigger an update.
        invalidate_cache : bool
            Whether to clear the View's cache.

        Returns
        -------
        stale : bool
            Whether the panel on the View is stale and needs to be
            rerendered.
        """
        # Skip events triggered by a parameter change on this View
        own_parameters = [self.param[p] for p in self.param]
        own_events = events and all(
            isinstance(e.obj, ParamFilter) and
            (e.obj.parameter in own_parameters
             or e.new is self._ls.selection_expr) for e in events)
        if own_events:
            return False
        if invalidate_cache:
            self._cache = None
        if not self.streaming or self._stream is None:
            return self._update_panel()
        self._stream.send(self.get_data())
        return False
示例#5
0
class Animator:
    """
    Creates animated plots with holoviews.

    Constructor Args:
        dynamic_range: bool = if set to True, auto-scale the chart each time it is drawn

    # ------------ Simple Example -------------------
    # Define a function to make your plots.
    # Data will be whatever object is passed to animator.send()
    def myplot(data):
        return hv.Curve(data)

    # Pass your plotting function to the animator constructor
    animator = Animator(myplot)

    # Simply send the animator updated versions of your data
    # to update the plot
    t0 = np.linspace(0, 6., 100)
    for delta in np.linspace(0, 3, 30):
        t = t0 - delta
        y = 2 + np.sin(t)
        animator.send((t, y))

    # ------------ Advanced Example -------------------
    def myplot(data):
        # First two elements of data are to be ploted
        # Third element of data is going to update a label
        c = hv.Curve(data[:2], 'a', 'b', label=f'hello {data[-1]}').options(color=ezr.cc.c, logy=True)
        c *= hv.Scatter((data[0], 2 * data[1])).options(color=ezr.cc.d)
        return c


    # Send data for animation
    for ind, delta in enumerate(np.linspace(0, 3, 300)):
        t = t0 - delta
        y = 2 + np.sin(t)
        # Can control when animations are drawn with this
        if ind % 1 == 0:
            animator.send((t, y))
    """
    def __init__(self, plot_func, dynamic_range=True, plot_every=1):
        import holoviews as hv
        from holoviews.streams import Pipe
        # Store the user-defined plot function
        self.plot_func = plot_func
        self.dynamic_range = dynamic_range
        self.pipe = Pipe(data=[])
        self.data_has_been_sent = False
        self.dmap = hv.DynamicMap(self.plot_wrapper, streams=[self.pipe])
        self.plot_every = plot_every
        self.plot_count = 0

    def plot_wrapper(self, *args, **kwargs):
        data = kwargs.get('data', ([0], [0]))
        hv_obj = self.plot_func(data)
        if self.dynamic_range:
            hv_obj = hv_obj.opts(norm=dict(framewise=True))
        return hv_obj

    def send(self, data):
        from IPython.display import display
        if self.plot_count % self.plot_every == 0:
            self.pipe.send(data)
            if not self.data_has_been_sent:
                display(self.dmap)
                self.data_has_been_sent = True
        self.plot_count += 1
示例#6
0
class DistributedSwarm:
    def __init__(
        self,
        swarm: Callable,
        n_swarms: int,
        n_param_servers: int,
        max_iters_ray: int = 10,
        log_every: int = 100,
        n_comp_add: int = 5,
        minimize: bool = False,
        ps_maxlen: int = 100,
        init_reward: float = None,
        log_reward: bool = False,
    ):
        self.n_swarms = n_swarms
        self.minimize = minimize
        self.log = log_reward
        self.init_reward = (init_reward if init_reward is not None else
                            (np.inf if minimize else -np.inf))
        self.log_every = log_every
        self.param_servers = [
            ParamServer.remote(minimize=minimize, maxlen=ps_maxlen)
            for _ in range(n_param_servers)
        ]
        self.swarms = [
            RemoteSwarm.remote(copy.copy(swarm),
                               int(n_comp_add),
                               minimize=minimize) for _ in range(self.n_swarms)
        ]
        self.max_iters_ray = max_iters_ray
        self.frame_pipe: Pipe = None
        self.stream = None
        self.buffer_df = None
        self.score_dmap = None
        self.frame_dmap = None
        self.init_plot()
        self.n_iters = 0
        self.best = (None, None, None)

    def init_plot(self):
        self.frame_pipe = Pipe(data=[])
        self.frame_dmap = hv.DynamicMap(hv.RGB, streams=[self.frame_pipe])
        self.frame_dmap = self.frame_dmap.opts(xlim=(-0.5, 0.5),
                                               ylim=(-0.5, 0.5),
                                               xaxis=None,
                                               yaxis=None,
                                               title="Game screen")
        example = pd.DataFrame({"reward": []})
        self.stream = Stream()
        self.buffer_df = DataFrame(stream=self.stream, example=example)
        self.score_dmap = self.buffer_df.hvplot(y=["reward"]).opts(
            height=200, width=500, title="Game score")

    def plot(self):
        return self.frame_dmap + self.score_dmap

    def stream_progress(self, state, observation, reward):
        example = pd.DataFrame({"reward": [reward]},
                               index=[self.n_iters // self.n_swarms])
        self.stream.emit(example)
        obs = observation.reshape((210, 160, 3)).astype(np.uint8)
        self.frame_pipe.send(obs)

    def run_swarm(self):
        self.n_iters = 0
        best_ids = [s.reset.remote() for s in self.swarms]
        steps = {}
        param_servers = deque([])
        for worker, best in zip(self.swarms, best_ids):
            steps[worker.make_iteration.remote(best)] = worker

        bests = []
        for ps, walker in zip(self.param_servers,
                              list(steps.keys())[:len(self.param_servers)]):
            bests.append(ps.exchange_walker.remote(walker))
            param_servers.append(ps)
        ray.get(bests)

        for i in range(self.max_iters_ray * len(self.swarms)):
            self.n_iters += 1
            ready_bests, _ = ray.wait(list(steps))
            ready_best_id = ready_bests[0]
            worker = steps.pop(ready_best_id)
            ps = param_servers.popleft()

            new_best = ps.exchange_walker.remote(ready_best_id)
            param_servers.append(ps)
            steps[worker.make_iteration.remote(new_best)] = worker

            if i % (self.log_every * len(self.swarms)) == 0:
                id_, _ = ray.wait([param_servers[-1].get_best.remote()])
                (state, best_obs, best_reward) = ray.get(id_)[0]
                if state is not None:
                    self.best = (state, best_obs, float(best_reward))
                    if ((best_reward > self.init_reward) if self.minimize else
                        (best_reward < self.init_reward)):
                        best_reward = self.init_reward
                    best_reward = np.log(
                        best_reward) if self.log else best_reward
                    self.stream_progress(state, best_obs, best_reward)
                else:
                    print("skipping, not ready")