예제 #1
0
class DynamicPlotHandler(Handler):
    def __init__(self, network):
        self._network = weakref.ref(network)
        self.sources = {}
        self._last_time_list = None
        self._update_complete = False
        self._recurring_update = RecurringTask(self.plan_update_data, delay=5)
        self._pcb = None  # Periodic callback
        self._ntcb = None  # Next Tick callback
        super().__init__()

    @property
    def network(self):
        return self._network()

    def organize_data(self):

        self._log.debug("Organize Data")

        self.s = {}
        for point in self.network.trends:
            self.s[point.history.name] = (point.history, point.history.units)
        self.lst_of_trends = [his[0] for name, his in self.s.items()]

    def build_data_sources(self):
        sources = {}
        self.organize_data()
        for each in self.lst_of_trends:
            df = pd.DataFrame(each)
            df = df.reset_index()
            df["name"] = each.name
            df["units"] = str(each.units)
            df["time_s"] = df["index"].apply(str)
            df.states = each.states
            try:
                df = (
                    df.fillna(method="ffill")
                    .fillna(method="bfill")
                    .replace(["inactive", "active"], [0, 1])
                )
            except TypeError:
                df = df.fillna(method="ffill").fillna(method="bfill")

            sources[each.name] = ColumnDataSource(
                data=dict(
                    x=df["index"],
                    y=df[each.name],
                    time=df["time_s"],
                    name=df["name"],
                    units=df["units"],
                )
            )
        return sources

    def build_plot(self):
        self._log.debug("Build Plot")

        self.stop_update_data()
        self.sources = self.build_data_sources()

        TOOLS = "pan,box_zoom,wheel_zoom,save,reset"
        self.p = Figure(
            x_axis_type="datetime",
            x_axis_label="Time",
            y_axis_label="Numeric Value",
            title="BAC0 Trends",
            tools=TOOLS,
            plot_width=800,
            plot_height=600,
            toolbar_location="above",
        )

        self.p.background_fill_color = "#f4f3ef"
        self.p.border_fill_color = "#f4f3ef"
        self.p.extra_y_ranges = {
            "bool": Range1d(start=0, end=1.1),
            "enum": Range1d(start=0, end=10),
        }
        self.p.add_layout(LinearAxis(y_range_name="bool", axis_label="Binary"), "left")
        self.p.add_layout(
            LinearAxis(y_range_name="enum", axis_label="Enumerated"), "right"
        )

        hover = HoverTool(
            tooltips=[
                ("name", "@name"),
                ("value", "@y"),
                ("units", "@units"),
                ("time", "@time"),
            ]
        )
        self.p.add_tools(hover)

        self.legends_list = []

        length = len(self.s.keys())
        if length <= 10:
            if length < 3:
                length = 3
            color_mapper = dict(zip(self.s.keys(), d3["Category10"][length]))
        else:
            # This would be a very loaded trend...
            color_mapper = dict(zip(self.s.keys(), Spectral6[:length]))

        for each in self.lst_of_trends:
            if each.states == "binary":
                self.p.circle(
                    "x",
                    "y",
                    source=self.sources[each.name],
                    name=each.name,
                    color=color_mapper[each.name],
                    legend=("{} | {} (OFF-ON)".format(each.name, each.description)),
                    y_range_name="bool",
                    size=10,
                )
                # self.legends_list.append(
                #    (("{} | {} (OFF-ON)".format(each.name, each.description)), [c])
                # )
            elif each.states == "multistates":
                self.p.diamond(
                    "x",
                    "y",
                    source=self.sources[each.name],
                    name=each.name,
                    color=color_mapper[each.name],
                    legend=(
                        "{} | {} ({})".format(each.name, each.description, each.units)
                    ),
                    y_range_name="enum",
                    size=20,
                )
            else:
                self.p.line(
                    "x",
                    "y",
                    source=self.sources[each.name],
                    name=each.name,
                    color=color_mapper[each.name],
                    legend=(
                        "{} | {} ({})".format(each.name, each.description, each.units)
                    ),
                    line_width=2,
                )

            self.p.legend.location = "top_left"
            # legend = Legend(items=self.legends_list, location=(0, -60))
            self.p.legend.click_policy = "hide"
            # self.p.add_layout(legend, "right")
            self.plots = [self.p]

    def update_data(self):
        self._log.debug("Update Data")
        doc = curdoc()
        # self.organize_data()
        if self._last_time_list:
            if self._last_time_list != self.s.keys():
                self._list_have_changed = True
                self.stop_update_data()
                # doc.add_next_tick_callback(self.modify_document)
                self.modify_document(doc)
            else:
                self._list_have_changed = False

        l = []
        for each in self.p.renderers:
            l.append(each.name)

            # for each in self.lst_of_trends:
            #    df = pd.DataFrame(each)
            #    df = df.reset_index()
            #    df['name'] = each.name
            #    df['units'] = str(each.units)
            #    df['time_s'] = df['index'].apply(str)

            #    try:
            #        df = df.fillna(method='ffill').fillna(
            #            method='bfill').replace(['inactive', 'active'], [0, 1])
            #    except TypeError:
            #        df = df.fillna(method='ffill').fillna(method='bfill')

            index = l.index(each.name)
        #    renderer = self.p.renderers[index]
        #    new_data = {}
        #    new_data['name'] = df['name']
        #    new_data['x'] = df['index']
        #    new_data['y'] = df[each.name]
        #    if each.states == 'binary':
        #        new_data['units'] = [each.units[int(x)] for x in df[each.name]]
        #    elif each.states == 'multistates':
        #        new_data['units'] = [
        #            each.units[int(math.fabs(x-1))] for x in df[each.name]]
        #    else:
        #        new_data['units'] = df['units']
        #    new_data['time'] = df['time_s']
        #    renderer.data_source.data = new_data
        try:
            new_data = self.build_data_sources()
            for each in self.lst_of_trends:
                self.sources[each.name].data = new_data[each.name].data

        except KeyError:
            self._log.warning(
                "Problem updating {} on chart, will try again next time.".format(
                    each.name
                )
            )

        else:
            self._last_time_list = self.s.keys()
            # self.start_update_data()
            self._update_complete = True

    def modify_document(self, doc):
        doc.clear()
        self.build_plot()
        layout = gridplot(self.plots, ncols=2)

        doc.add_root(layout)
        self._pcb = doc.add_periodic_callback(self.update_data, 10000)
        return doc

    def plan_update_data(self):
        doc = curdoc()
        if self._update_complete == True:
            self._update_complete = False
            self._ntcb = doc.add_next_tick_callback(self.update_data)

    def stop_update_data(self):
        doc = curdoc()
        try:
            doc.remove_periodic_callback(self._pcb)
        except:
            pass
        if self._recurring_update.is_running:
            self._recurring_update.stop()
            while self._recurring_update.is_running:
                pass
        try:
            doc.remove_next_tick_callback(self._ntcb)
        except (ValueError, RuntimeError):
            pass  # Already gone

    def start_update_data(self):
        if not self._recurring_update.is_running:
            try:
                self._recurring_update.start()
                while not self._recurring_update.is_running:
                    pass
            except RuntimeError:
                pass
예제 #2
0
class DynamicPlotHandler(Handler):
    def __init__(self, network):
        self._network = weakref.ref(network)
        self.sources = {}
        self._last_time_list = None
        self._update_complete = False
        self._recurring_update = RecurringTask(self.plan_update_data, delay=5)
        super().__init__()

    @property
    def network(self):
        return self._network()

    def organize_data(self):

        self._log.debug('Organize Data')

        self.s = {}
        for point in self.network.trends:
            self.s[point.history.name] = (point.history, point.history.units)
        self.lst_of_trends = [his[0] for name, his in self.s.items()]

    def build_plot(self):
        self._log.debug('Build Plot')

        self.stop_update_data()
        self.organize_data()
        for each in self.lst_of_trends:
            df = pd.DataFrame(each)
            df = df.reset_index()
            # print(df)
            df['name'] = each.name
            df['units'] = str(each.units)
            df['time_s'] = df['index'].apply(str)
            df.states = each.states
            try:
                df = df.fillna(method='ffill').fillna(method='bfill').replace(
                    ['inactive', 'active'], [0, 1])
            except TypeError:
                df = df.fillna(method='ffill').fillna(method='bfill')

            self.sources[each.name] = ColumnDataSource(
                data=dict(x=df['index'],
                          y=df[each.name],
                          time=df['time_s'],
                          name=df['name'],
                          units=df['units']))

        TOOLS = "pan,box_zoom,wheel_zoom,save,reset"
        self.p = Figure(x_axis_type="datetime",
                        x_axis_label="Time",
                        y_axis_label="Numeric Value",
                        title='BAC0 Trends',
                        tools=TOOLS,
                        plot_width=1300,
                        plot_height=600,
                        toolbar_location='above')

        self.p.background_fill_color = "#f4f3ef"
        self.p.border_fill_color = "#f4f3ef"
        self.p.extra_y_ranges = {
            "bool": Range1d(start=0, end=1.1),
            "enum": Range1d(start=0, end=10)
        }
        self.p.add_layout(LinearAxis(y_range_name="bool", axis_label="Binary"),
                          'left')
        self.p.add_layout(
            LinearAxis(y_range_name="enum", axis_label="Enumerated"), 'right')

        hover = HoverTool(tooltips=[
            ('name', '@name'),
            ('value', '@y'),
            ('units', '@units'),
            ('time', '@time'),
        ])
        self.p.add_tools(hover)

        length = len(self.s.keys())
        if length <= 10:
            if length < 3:
                length = 3
            color_mapper = dict(zip(self.s.keys(), d3['Category10'][length]))
        else:
            # This would be a very loaded trend...
            color_mapper = dict(zip(self.s.keys(), Spectral6[:length]))

        for each in self.lst_of_trends:
            if each.states == 'binary':
                self.p.circle('x',
                              'y',
                              source=self.sources[each.name],
                              name=each.name,
                              color=color_mapper[each.name],
                              legend=("%s | %s (OFF-ON)" %
                                      (each.name, each.description)),
                              y_range_name="bool",
                              size=10)
            elif each.states == 'multistates':
                self.p.diamond(
                    'x',
                    'y',
                    source=self.sources[each.name],
                    name=each.name,
                    color=color_mapper[each.name],
                    legend=("%s | %s (%s)" %
                            (each.name, each.description, each.units)),
                    y_range_name="enum",
                    size=20)
            else:
                self.p.line('x',
                            'y',
                            source=self.sources[each.name],
                            name=each.name,
                            color=color_mapper[each.name],
                            legend=("%s | %s (%s)" %
                                    (each.name, each.description, each.units)),
                            line_width=2)

            self.p.legend.location = 'bottom_left'
            self.p.legend.click_policy = "hide"

            self.plots = [
                self.p,
            ]

    #@gen.coroutine
    def update_data(self):
        self._log.debug('Update Data')
        doc = curdoc()
        self.organize_data()
        if self._last_time_list:
            if self._last_time_list != self.s.keys():
                self._list_have_changed = True
                self.stop_update_data()
                self.modify_document(doc)
            else:
                self._list_have_changed = False

        l = []
        for each in self.p.renderers:
            l.append(each.name)

        for each in self.lst_of_trends:
            df = pd.DataFrame(each)
            df = df.reset_index()
            df['name'] = each.name
            df['units'] = str(each.units)
            df['time_s'] = df['index'].apply(str)

            try:
                df = df.fillna(method='ffill').fillna(method='bfill').replace(
                    ['inactive', 'active'], [0, 1])
            except TypeError:
                df = df.fillna(method='ffill').fillna(method='bfill')

            index = l.index(each.name)
            renderer = self.p.renderers[index]
            new_data = {}
            new_data['name'] = df['name']
            new_data['x'] = df['index']
            new_data['y'] = df[each.name]
            if each.states == 'binary':
                new_data['units'] = [each.units[int(x)] for x in df[each.name]]
            elif each.states == 'multistates':
                new_data['units'] = [
                    each.units[int(math.fabs(x - 1))] for x in df[each.name]
                ]
            else:
                new_data['units'] = df['units']
            new_data['time'] = df['time_s']
            renderer.data_source.data = new_data
        self._last_time_list = self.s.keys()
        # self.start_update_data()
        self._update_complete = True

    def modify_document(self, doc):
        curdoc().clear()
        try:
            curdoc().remove_periodic_callback(self.update_data)
        except:
            pass
        doc.clear()
        self.build_plot()
        # column(widgetbox(self.div_header_doc),
        layout = gridplot(self.plots, ncols=2)
        # widgetbox(self.div_header_notes),
        # widgetbox(self.div_footer)

        doc.add_root(layout)
        doc.add_periodic_callback(self.update_data, 10000)
        return doc

    def plan_update_data(self):
        doc = curdoc()
        if self._update_complete == True:
            self._update_complete = False
            doc.add_next_tick_callback(self.update_data)

    def stop_update_data(self):
        doc = curdoc()
        if self._recurring_update.is_running:
            self._recurring_update.stop()
            while self._recurring_update.is_running:
                pass
            try:
                doc.remove_next_tick_callback(self.update_data)
            except (ValueError, RuntimeError):
                pass  # Already gone

    def start_update_data(self):
        if not self._recurring_update.is_running:
            try:
                self._recurring_update.start()
                while not self._recurring_update.is_running:
                    pass
            except RuntimeError:
                pass
예제 #3
0
class DynamicPlotHandler(Handler):
    def __init__(self, network):
        self._network = weakref.ref(network)
        self.sources = {}
        self._last_time_list = None
        self._update_complete = False
        self._recurring_update = RecurringTask(self.plan_update_data, delay=5)
        self._pcb = None  # Periodic callback
        self._ntcb = None  # Next Tick callback
        super().__init__()

    @property
    def network(self):
        return self._network()

    def organize_data(self):

        self._log.debug("Organize Data")

        self.s = {}
        for point in self.network.trends:
            self.s[point.history.name] = (point.history, point.history.units)
        self.lst_of_trends = [his[0] for name, his in self.s.items()]

    def build_data_sources(self):
        sources = {}
        self.organize_data()
        for each in self.lst_of_trends:
            df = pd.DataFrame(each)
            df = df.reset_index()
            df["name"] = each.name
            df["units"] = str(each.units)
            df["time_s"] = df["index"].apply(str)
            df.states = each.states
            try:
                df = (
                    df.fillna(method="ffill")
                    .fillna(method="bfill")
                    .replace(["inactive", "active"], [0, 1])
                )
            except TypeError:
                df = df.fillna(method="ffill").fillna(method="bfill")

            sources[each.name] = ColumnDataSource(
                data=dict(
                    x=df["index"],
                    y=df[each.name],
                    time=df["time_s"],
                    name=df["name"],
                    units=df["units"],
                )
            )
        return sources

    def build_plot(self):
        self._log.debug("Build Plot")

        self.stop_update_data()
        self.sources = self.build_data_sources()

        TOOLS = "pan,box_zoom,wheel_zoom,save,reset"
        self.p = Figure(
            x_axis_type="datetime",
            x_axis_label="Time",
            y_axis_label="Numeric Value",
            title="BAC0 Trends",
            tools=TOOLS,
            plot_width=800,
            plot_height=600,
            toolbar_location="above",
        )

        self.p.background_fill_color = "#f4f3ef"
        self.p.border_fill_color = "#f4f3ef"
        self.p.extra_y_ranges = {
            "bool": Range1d(start=0, end=1.1),
            "enum": Range1d(start=0, end=10),
        }
        self.p.add_layout(LinearAxis(y_range_name="bool", axis_label="Binary"), "left")
        self.p.add_layout(
            LinearAxis(y_range_name="enum", axis_label="Enumerated"), "right"
        )

        hover = HoverTool(
            tooltips=[
                ("name", "@name"),
                ("value", "@y"),
                ("units", "@units"),
                ("time", "@time"),
            ]
        )
        self.p.add_tools(hover)

        length = len(self.s.keys())
        if length <= 10:
            if length < 3:
                length = 3
            color_mapper = dict(zip(self.s.keys(), d3["Category10"][length]))
        else:
            # This would be a very loaded trend...
            color_mapper = dict(zip(self.s.keys(), Spectral6[:length]))

        for each in self.lst_of_trends:
            if each.states == "binary":
                self.p.circle(
                    "x",
                    "y",
                    source=self.sources[each.name],
                    name=each.name,
                    color=color_mapper[each.name],
                    legend=("%s | %s (OFF-ON)" % (each.name, each.description)),
                    y_range_name="bool",
                    size=10,
                )
            elif each.states == "multistates":
                self.p.diamond(
                    "x",
                    "y",
                    source=self.sources[each.name],
                    name=each.name,
                    color=color_mapper[each.name],
                    legend=("%s | %s (%s)" % (each.name, each.description, each.units)),
                    y_range_name="enum",
                    size=20,
                )
            else:
                self.p.line(
                    "x",
                    "y",
                    source=self.sources[each.name],
                    name=each.name,
                    color=color_mapper[each.name],
                    legend=("%s | %s (%s)" % (each.name, each.description, each.units)),
                    line_width=2,
                )

            self.p.legend.location = "bottom_right"
            self.p.legend.click_policy = "hide"

            self.plots = [self.p]

    def update_data(self):
        self._log.debug("Update Data")
        doc = curdoc()
        # self.organize_data()
        if self._last_time_list:
            if self._last_time_list != self.s.keys():
                self._list_have_changed = True
                self.stop_update_data()
                # doc.add_next_tick_callback(self.modify_document)
                self.modify_document(doc)
            else:
                self._list_have_changed = False

        l = []
        for each in self.p.renderers:
            l.append(each.name)

            # for each in self.lst_of_trends:
            #    df = pd.DataFrame(each)
            #    df = df.reset_index()
            #    df['name'] = each.name
            #    df['units'] = str(each.units)
            #    df['time_s'] = df['index'].apply(str)

            #    try:
            #        df = df.fillna(method='ffill').fillna(
            #            method='bfill').replace(['inactive', 'active'], [0, 1])
            #    except TypeError:
            #        df = df.fillna(method='ffill').fillna(method='bfill')

            index = l.index(each.name)
        #    renderer = self.p.renderers[index]
        #    new_data = {}
        #    new_data['name'] = df['name']
        #    new_data['x'] = df['index']
        #    new_data['y'] = df[each.name]
        #    if each.states == 'binary':
        #        new_data['units'] = [each.units[int(x)] for x in df[each.name]]
        #    elif each.states == 'multistates':
        #        new_data['units'] = [
        #            each.units[int(math.fabs(x-1))] for x in df[each.name]]
        #    else:
        #        new_data['units'] = df['units']
        #    new_data['time'] = df['time_s']
        #    renderer.data_source.data = new_data
        try:
            new_data = self.build_data_sources()
            for each in self.lst_of_trends:
                self.sources[each.name].data = new_data[each.name].data

        except KeyError:
            self._log.warning(
                "Problem updating {} on chart, will try again next time.".format(
                    each.name
                )
            )

        else:
            self._last_time_list = self.s.keys()
            # self.start_update_data()
            self._update_complete = True

    def modify_document(self, doc):
        curdoc().clear()
        # doc = curdoc()
        try:
            curdoc().remove_periodic_callback(self._pcb)
        except:
            pass
        doc.clear()
        self.build_plot()
        layout = gridplot(self.plots, ncols=2)

        doc.add_root(layout)
        self._pcb = doc.add_periodic_callback(self.update_data, 10000)
        return doc

    def plan_update_data(self):
        doc = curdoc()
        if self._update_complete == True:
            self._update_complete = False
            self._ntcb = doc.add_next_tick_callback(self.update_data)

    def stop_update_data(self):
        doc = curdoc()
        if self._recurring_update.is_running:
            self._recurring_update.stop()
            while self._recurring_update.is_running:
                pass
            try:
                doc.remove_next_tick_callback(self._ntcb)
            except (ValueError, RuntimeError):
                pass  # Already gone

    def start_update_data(self):
        if not self._recurring_update.is_running:
            try:
                self._recurring_update.start()
                while not self._recurring_update.is_running:
                    pass
            except RuntimeError:
                pass
예제 #4
0
class BokehPlot(object):
    def __init__(self,
                 device,
                 points_list,
                 *,
                 title='My title',
                 show_notes=True,
                 update_data=True):
        self.device = device
        if len(points_list) < 3:
            raise ValueError("Provide at least 3 objects to the chart")
        self.points_list = points_list
        self.title = title
        self.units = {}
        self.show_notes = show_notes

        self.lst = self.points_list

        self.multi_states = self.device.multi_states
        self.binary_states = self.device.binary_states
        self.analog_units = self.device.analog_units

        plot = self.build_plot()

        self.device.properties.network.bokeh_document.add_plot(
            plot, infos=self.device.properties)
        #curdoc().add_root(plot)
        if update_data:
            self.device.properties.network.bokeh_document.add_periodic_callback(
                self.update_data, 100)
        print('Chart created, please reload your web page to see changes')

    # Get data
    def read_lst(self):
        df = self.device[self.lst]
        try:
            df = df.fillna(method='ffill').fillna(method='bfill').replace(
                ['inactive', 'active'], [0, 1])
        except TypeError:
            df = df.fillna(method='ffill').fillna(method='bfill')

        df = df.reset_index()
        df['name'] = 'nameToReplace'
        df['units'] = 'waiting for refresh'
        df['time_s'] = df['index'].apply(str)
        return df

    def read_notes(self):
        notes_df = self.device.notes.reset_index()
        notes_df['value'] = -5
        notes_df['desc'] = 'Notes'
        notes_df['time_s'] = notes_df['index'].apply(str)
        return notes_df

    def build_plot(self):
        df = self.read_lst()
        notes_df = self.read_notes()

        TOOLS = "pan,box_zoom,wheel_zoom,save,reset"
        self.p = Figure(x_axis_type="datetime",
                        x_axis_label="Time",
                        y_axis_label="Numeric Value",
                        title=self.title,
                        tools=TOOLS,
                        plot_width=700,
                        plot_height=600,
                        toolbar_location='above')

        if self.show_notes:
            self.notes_source = ColumnDataSource(
                data=dict(x=notes_df['index'],
                          y=notes_df['value'],
                          time=notes_df['time_s'],
                          desc=notes_df['desc'],
                          units=notes_df[0]))

            self.p.asterisk(
                'x',
                'y',
                source=self.notes_source,
                name='Notes',
                #color = "#%06x" % random.randint(0x000000, 0x777777),
                legend='Notes',
                size=40)

        self.p.legend.location = 'top_left'
        self.p.extra_y_ranges = {
            "bool": Range1d(start=0, end=1.1),
            "enum": Range1d(start=0, end=10)
        }
        self.p.add_layout(LinearAxis(y_range_name="bool", axis_label="Binary"),
                          'left')
        self.p.add_layout(
            LinearAxis(y_range_name="enum", axis_label="Enumerated"), 'right')
        self.p.legend.location = "bottom_left"

        hover = HoverTool(tooltips=[
            ('name', '@desc'),
            ('value', '@y'),
            ('units', '@units'),
            ('time', '@time'),
        ])
        self.p.add_tools(hover)

        self.sources = {}
        if len(self.lst) <= 10:
            color_mapper = dict(zip(self.lst, d3['Category10'][len(self.lst)]))
        else:
            # This would be a very loaded trend...
            color_mapper = dict(zip(self.lst, Spectral6[:len(self.lst)]))

        for each in self.lst:

            try:
                df['name'] = df['name'].replace(
                    'nameToReplace',
                    ('%s / %s' % (each, self.device[each]['description'])))
            except TypeError:
                continue
            self.sources[each] = ColumnDataSource(data=dict(x=df['index'],
                                                            y=df[each],
                                                            time=df['time_s'],
                                                            name=df['name'],
                                                            units=df['units']))

            if each in self.binary_states:
                self.p.circle(
                    'x',
                    'y',
                    source=self.sources[each],
                    name=each,
                    color=color_mapper[each],
                    legend=("%s/%s (OFF-ON)" %
                            (each, self.device[each]['description'])),
                    y_range_name="bool",
                    size=10)
            elif each in self.multi_states:
                self.p.diamond(
                    'x',
                    'y',
                    source=self.sources[each],
                    name=each,
                    color=color_mapper[each],
                    legend=("%s/%s (%s)" %
                            (each, self.device[each]['description'],
                             self.device[each].properties.units_state)),
                    y_range_name="enum",
                    size=20)
            else:
                self.p.line(
                    'x',
                    'y',
                    source=self.sources[each],
                    name=each,
                    color=color_mapper[each],
                    legend=("%s/%s (%s)" %
                            (each, self.device[each]['description'],
                             self.device[each].properties.units_state)),
                    line_width=2)
        if self.show_notes:
            columns = [
                TableColumn(field="x",
                            title="Date",
                            formatter=DateFormatter(format='yy-mm-dd')),
                TableColumn(field="units", title="Notes"),
            ]
            data_table = DataTable(source=self.notes_source, columns=columns)
            return (self.p, data_table)
        else:
            return (self.p, None)

    def update_data(self):
        if self.device.properties.network._started:
            df = self.read_lst()
            for renderer in self.p.renderers:
                name = renderer.name
                glyph_renderer = renderer
                new_data = {}
                if name in self.points_list:
                    df['name'] = ('%s / %s' %
                                  (name, self.device[name]['description']))
                    new_data['x'] = df['index']
                    new_data['y'] = df[name]
                    new_data['desc'] = df['name']
                    new_data['time'] = df['time_s']
                    if name in self.multi_states:
                        new_data['units'] = [
                            self.multi_states[name][int(math.fabs(x - 1))]
                            for x in df[name]
                        ]
                    elif name in self.binary_states:
                        new_data['y'] = df[name]
                        new_data['units'] = [
                            self.binary_states[name][int(x / 1)]
                            for x in df[name]
                        ]
                    else:
                        df['units'] = self.analog_units[name]
                        new_data['units'] = df['units']
                    glyph_renderer.data_source.data = new_data
                elif name == 'Notes':
                    notes_df = self.read_notes()
                    new_data['x'] = notes_df['index']
                    new_data['y'] = notes_df['value']
                    new_data['desc'] = notes_df['desc']
                    new_data['units'] = notes_df[0]
                    new_data['time'] = notes_df['time_s']
                    glyph_renderer.data_source.data = new_data
예제 #5
0
tground_syms = p1.triangle(tground['semi'] / a_rad,
                           tground['msini'] * mjup,
                           color='lightblue',
                           fill_alpha=0.8,
                           line_alpha=1.,
                           size=8)

# transits - space
tspace = Table.read(
    '/Users/tumlinson/Dropbox/LUVOIR_STDT/luvoir_simtools/planetspace/transit_space.dat',
    format='ascii',
    names=['name', 'msini', 'semi', 'mstar'])
a_rad = 2.7 * tspace['mstar']
tground_syms = p1.diamond(tspace['semi'] / a_rad,
                          tspace['msini'] * mjup,
                          color='darkblue',
                          fill_alpha=0.4,
                          line_alpha=1.,
                          size=8)

# RV
rv = Table.read(
    '/Users/tumlinson/Dropbox/LUVOIR_STDT/luvoir_simtools/planetspace/rv.dat',
    format='ascii',
    names=['name', 'msini', 'semi', 'mstar'])
a_rad = 2.7 * rv['mstar']
rv_syms = p1.circle(rv['semi'] / a_rad,
                    rv['msini'] * mjup,
                    color='red',
                    fill_alpha=0.4,
                    line_alpha=1.,
                    size=8)
예제 #6
0
class BokehPlot(object):
    def __init__(self,
                 device,
                 points_list,
                 *,
                 title='My title',
                 show_notes=True,
                 update_data=True):
        self.device = device
        self.points_list = points_list
        self.title = title
        self.units = {}
        self.show_notes = show_notes

        self.lst = self.points_list

        self.multi_states = self.device.multi_states
        self.binary_states = self.device.binary_states
        self.analog_units = self.device.analog_units

        plot = self.build_plot()

        self.device.properties.network.bokeh_document.add_plot(plot)
        if update_data:
            self.device.properties.network.bokeh_document.add_periodic_callback(
                self.update_data, 100)
        print('Chart created, please reload your web page to see changes')

    # Get data
    def read_lst(self):
        df = self.device[self.lst]
        try:
            df = df.fillna(method='ffill').fillna(method='bfill').replace(
                ['inactive', 'active'], [0, 1])
        except TypeError:
            df = df.fillna(method='ffill').fillna(method='bfill')

        df = df.reset_index()
        df['name'] = 'nameToReplace'
        df['units'] = 'waiting for refresh'
        df['time_s'] = df['index'].apply(str)
        return df

    def read_notes(self):
        notes_df = self.device.notes.reset_index()
        notes_df['value'] = -5
        notes_df['desc'] = 'Notes'
        notes_df['time_s'] = notes_df['index'].apply(str)
        return notes_df

    def build_plot(self):
        df = self.read_lst()
        notes_df = self.read_notes()

        TOOLS = "hover,resize,save,pan,box_zoom,wheel_zoom,reset"
        #plot_width=800, plot_height=600,
        self.p = Figure(x_axis_type="datetime", title=self.title, tools=TOOLS)

        if self.show_notes:
            self.notes_source = ColumnDataSource(
                data=dict(x=notes_df['index'],
                          y=notes_df['value'],
                          time=notes_df['time_s'],
                          desc=notes_df['desc'],
                          units=notes_df[0]))

            self.p.asterisk('x',
                            'y',
                            source=self.notes_source,
                            name='Notes',
                            color="#%06x" % random.randint(0x000000, 0x777777),
                            legend='Notes',
                            size=40)

        self.p.legend.location = 'top_left'
        self.p.extra_y_ranges = {
            "bool": Range1d(start=0, end=1.1),
            "enum": Range1d(start=0, end=10)
        }
        self.p.add_layout(LinearAxis(y_range_name="bool"), 'left')
        self.p.add_layout(LinearAxis(y_range_name="enum"), 'right')

        hover = self.p.select(dict(type=HoverTool))
        hover.tooltips = OrderedDict([
            ('name', '@desc'),
            ('value', '@y'),
            ('units', '@units'),
            ('time', '@time'),
        ])

        self.sources = {}
        for each in self.lst:

            try:
                df['name'] = df['name'].replace(
                    'nameToReplace',
                    ('%s / %s' % (each, self.device[each]['description'])))
            except TypeError:
                continue
            self.sources[each] = ColumnDataSource(data=dict(x=df['index'],
                                                            y=df[each],
                                                            time=df['time_s'],
                                                            name=df['name'],
                                                            units=df['units']))

            if each in self.binary_states:
                self.p.circle('x',
                              'y',
                              source=self.sources[each],
                              name=each,
                              color="#%06x" %
                              random.randint(0x000000, 0x777777),
                              legend=each,
                              y_range_name="bool",
                              size=10)
            elif each in self.multi_states:
                self.p.diamond('x',
                               'y',
                               source=self.sources[each],
                               name=each,
                               color="#%06x" %
                               random.randint(0x000000, 0x777777),
                               legend=each,
                               y_range_name="enum",
                               size=20)
            else:
                self.p.line('x',
                            'y',
                            source=self.sources[each],
                            name=each,
                            color="#%06x" % random.randint(0x000000, 0x777777),
                            legend=each,
                            line_width=2)

        return self.p

    def update_data(self):
        if self.device.properties.network._started:
            df = self.read_lst()
            for renderer in self.p.renderers:
                name = renderer.name
                if name in self.points_list:
                    glyph_renderer = renderer
                    df['name'] = ('%s / %s' %
                                  (name, self.device[name]['description']))
                    glyph_renderer.data_source.data['x'] = df['index']
                    glyph_renderer.data_source.data['y'] = df[name]
                    glyph_renderer.data_source.data['desc'] = df['name']
                    glyph_renderer.data_source.data['time'] = df['time_s']
                    if name in self.multi_states:
                        glyph_renderer.data_source.data['units'] = [
                            self.multi_states[name][int(math.fabs(x - 1))]
                            for x in df[name]
                        ]
                    elif name in self.binary_states:
                        glyph_renderer.data_source.data['y'] = df[name]
                        glyph_renderer.data_source.data['units'] = [
                            self.binary_states[name][int(x / 1)]
                            for x in df[name]
                        ]
                    else:
                        df['units'] = self.analog_units[name]
                        glyph_renderer.data_source.data['units'] = df['units']
                elif name == 'Notes':
                    notes_df = self.read_notes()
                    glyph_renderer = renderer
                    glyph_renderer.data_source.data['x'] = notes_df['index']
                    glyph_renderer.data_source.data['y'] = notes_df['value']
                    glyph_renderer.data_source.data['desc'] = notes_df['desc']
                    glyph_renderer.data_source.data['units'] = notes_df[0]
                    glyph_renderer.data_source.data['time'] = notes_df[
                        'time_s']
예제 #7
0
class BokehPlot(object):
    def __init__(self, device, points_list, *, title = 'My title', show_notes = True, update_data = True):
        self.device = device
        self.points_list = points_list
        self.title = title
        self.units = {}
        self.show_notes = show_notes

        self.lst = self.points_list

        self.multi_states = self.device.multi_states
        self.binary_states = self.device.binary_states
        self.analog_units = self.device.analog_units

        plot = self.build_plot()

        self.device.properties.network.bokeh_document.add_plot(plot)
        if update_data:
            self.device.properties.network.bokeh_document.add_periodic_callback(self.update_data, 100)   
        print('Chart created, please reload your web page to see changes')
        
     # Get data
    def read_lst(self):
        df = self.device[self.lst]
        try:
            df = df.fillna(method='ffill').fillna(method='bfill').replace(['inactive', 'active'], [0, 1])
        except TypeError:
            df = df.fillna(method='ffill').fillna(method='bfill')
                                      
        df = df.reset_index()
        df['name'] = 'nameToReplace'
        df['units'] = 'waiting for refresh'
        df['time_s'] = df['index'].apply(str)
        return df

    def read_notes(self):
        notes_df = self.device.notes.reset_index()
        notes_df['value'] = -5
        notes_df['desc'] = 'Notes'
        notes_df['time_s'] = notes_df['index'].apply(str)
        return notes_df

    def build_plot(self):        
        df = self.read_lst()
        notes_df = self.read_notes()

        TOOLS = "hover,resize,save,pan,box_zoom,wheel_zoom,reset"
        #plot_width=800, plot_height=600,
        self.p = Figure(x_axis_type="datetime", title = self.title, tools = TOOLS)

        if self.show_notes:
            self.notes_source = ColumnDataSource(
                    data=dict(
                        x = notes_df['index'],
                        y = notes_df['value'],
                        time = notes_df['time_s'],
                        desc = notes_df['desc'],
                        units = notes_df[0]
                    )
                )

            self.p.asterisk('x', 
                            'y',
                            source = self.notes_source,
                            name = 'Notes',
                            color = "#%06x" % random.randint(0x000000, 0x777777), 
                            legend='Notes',
                            size = 40) 

        self.p.legend.location = 'top_left'
        self.p.extra_y_ranges = {"bool": Range1d(start=0, end=1.1),
                                 "enum": Range1d(start=0, end=10)}
        self.p.add_layout(LinearAxis(y_range_name="bool"), 'left')
        self.p.add_layout(LinearAxis(y_range_name="enum"), 'right')
                            
        hover = self.p.select(dict(type=HoverTool))
        hover.tooltips = OrderedDict([
            ('name', '@desc'),
            ('value', '@y'),
            ('units', '@units'),
            ('time', '@time'),
        ])

        self.sources = {}               
        for each in self.lst:
            
            try:
                df['name'] = df['name'].replace('nameToReplace', ('%s / %s' % (each, self.device[each]['description'])))            
            except TypeError:
                continue
            self.sources[each] = ColumnDataSource(
                            data=dict(
                            x = df['index'],
                            y = df[each],
                            time = df['time_s'],
                            name = df['name'],
                            units = df['units']
                        )
                    )

            if each in self.binary_states:
                self.p.circle('x', 
                            'y',
                            source = self.sources[each],
                            name = each,
                            color = "#%06x" % random.randint(0x000000, 0x777777),
                            legend=each,
                            y_range_name="bool",
                            size = 10)
            elif each in self.multi_states:
                self.p.diamond('x', 
                            'y',
                            source = self.sources[each],
                            name = each,
                            color = "#%06x" % random.randint(0x000000, 0x777777), 
                            legend=each,
                            y_range_name="enum",
                            size = 20)            
            else:
                self.p.line('x',
                            'y',
                            source = self.sources[each],
                            name = each,
                            color = "#%06x" % random.randint(0x000000, 0x777777),
                            legend=each,
                            line_width = 2)
            
        return self.p
    
    def update_data(self):
        if self.device.properties.network._started:           
            df = self.read_lst()
            for renderer in self.p.renderers:
                name = renderer.name
                if name in self.points_list:
                    glyph_renderer = renderer
                    df['name'] = ('%s / %s' % (name, self.device[name]['description']))
                    glyph_renderer.data_source.data['x'] = df['index']
                    glyph_renderer.data_source.data['y'] = df[name]
                    glyph_renderer.data_source.data['desc'] = df['name']
                    glyph_renderer.data_source.data['time'] = df['time_s']
                    if name in self.multi_states:
                        glyph_renderer.data_source.data['units'] = [self.multi_states[name][int(math.fabs(x-1))] for x in df[name]]
                    elif name in self.binary_states:
                        glyph_renderer.data_source.data['y'] = df[name]
                        glyph_renderer.data_source.data['units'] = [self.binary_states[name][int(x/1)] for x in df[name]]
                    else:
                        df['units'] = self.analog_units[name]
                        glyph_renderer.data_source.data['units'] = df['units']
                elif name == 'Notes':
                    notes_df = self.read_notes()
                    glyph_renderer = renderer
                    glyph_renderer.data_source.data['x'] = notes_df['index']
                    glyph_renderer.data_source.data['y'] = notes_df['value']
                    glyph_renderer.data_source.data['desc'] = notes_df['desc']
                    glyph_renderer.data_source.data['units'] = notes_df[0]
                    glyph_renderer.data_source.data['time'] = notes_df['time_s']
예제 #8
0
               # Set defaults
               fill_color=c_lcog, line_color=c_lcog,
               fill_alpha=a_lcog, line_alpha=a_lcog,
               # set visual properties for selected glyphs
               selection_color=c_lcog,
               selection_alpha=a_lcog,
               # set visual properties for non-selected glyphs
               nonselection_color=c_lcog,
               nonselection_alpha=a_lcog,
               legend = 'LCOGT-g')
f_lcor = fig_lc.diamond('x', 'y', source=source_lco_r, size=9,
               # Set defaults
               fill_color=c_lcor, line_color=c_lcor,
               fill_alpha=a_lcor, line_alpha=a_lcor,                    
               # set visual properties for selected glyphs
               selection_color=c_lcor,
               selection_alpha=a_lcor,
               # set visual properties for non-selected glyphs
               nonselection_color=c_lcor,
               nonselection_alpha=a_lcor,
               legend = 'LCOGT-r')

# Modify the legend's appearance
fig_lc.legend.location = "bottom_right"
fig_lc.legend.border_line_width = 3
fig_lc.legend.border_line_color = "navy"
fig_lc.legend.border_line_alpha = 0.5
fig_lc.legend.label_text_font_style = "bold"
fig_lc.legend.label_text_font_size = '9pt'
fig_lc.legend.spacing = -3
fig_lc.legend.label_standoff = 0