def generate_social_media_comments_table(media_comments_data_source,
                                         sentiment_label="Negative"):
    datetime_formatter, title_link_formatter = get_table_formatters()
    data_columns = [
        TableColumn(field="published",
                    title="Date Published",
                    width=105,
                    formatter=datetime_formatter,
                    name="time_series"),
        TableColumn(
            field="extract",
            title=f"{sentiment_label} Covid-19 Facebook Comments by Engagement",
            formatter=title_link_formatter,
            name="extract",
            width=380)
    ]

    data_table = DataTable(
        source=media_comments_data_source,
        columns=data_columns,
        fit_columns=False,
        selectable=False,
        sortable=True,
        index_position=None,
        width=500,
        row_height=100,
    )

    table_html = file_html(
        data_table, CDN,
        f"Most Engaged {sentiment_label} Social Media Comments")

    return table_html
예제 #2
0
파일: main.py 프로젝트: DServSys/Albatross
    def transform(self):
        print("converting")
        for f in self.__selected:
            print(".")
            f['results'] = self.__extract_observations(f['rdf'])

        print("writing")
        self.__write_geojson(self.__selected)
        print("done converting")

        self.__file_list = self.__get_eurostats()
        geojson_data = {'id': [], 'lvl': []}
        for file in self.__file_list:
            if file['geojson']['nuts1']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(1)

            if file['geojson']['nuts2']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(2)

            if file['geojson']['nuts3']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(3)
        self.__geojson_table_source = ColumnDataSource(geojson_data)
        geojson_table_columns = [
            TableColumn(field='lvl', title='NUTS Level'),
            TableColumn(field='id', title='ID')
        ]
        self.geojson_table = DataTable(source=self.__geojson_table_source,
                                       columns=geojson_table_columns,
                                       width=300,
                                       height=500,
                                       selectable=True)
        self.__layout.children[2] = column(self.geojson_table)
def generate_most_recent_media_table(most_media_datasource):
    datetime_formatter, title_link_formatter = get_table_formatters()

    media_data_columns = [
        TableColumn(field="published",
                    title="Date Published",
                    width=105,
                    formatter=datetime_formatter),
        TableColumn(field="title",
                    title="Media Links",
                    formatter=title_link_formatter,
                    width=1000 - 105),
    ]

    media_data_table = DataTable(source=most_media_datasource,
                                 columns=media_data_columns,
                                 fit_columns=False,
                                 selectable=False,
                                 sortable=True,
                                 index_position=None,
                                 height=300,
                                 width=1000,
                                 sizing_mode="scale_both")

    table_html = file_html(media_data_table, CDN, "Most Recent Media Links")

    return table_html
예제 #4
0
파일: tables.py 프로젝트: sukumarsat/panel
    def _get_columns(self):
        if self.value is None:
            return []

        indexes = self.indexes
        col_names = list(self.value.columns)
        if not self.hierarchical or len(indexes) == 1:
            col_names = indexes + col_names
        else:
            col_names = indexes[-1:] + col_names
        df = self.value.reset_index() if len(indexes) > 1 else self.value
        columns = []
        for col in col_names:
            if col in df.columns:
                data = df[col]
            else:
                data = df.index

            col_kwargs = {}
            kind = data.dtype.kind
            if kind == 'i':
                formatter = NumberFormatter()
                editor = IntEditor()
            elif kind == 'f':
                formatter = NumberFormatter(format='0,0.0[00000]')
                editor = NumberEditor()
            elif isdatetime(data) or kind == 'M':
                formatter = DateFormatter(format='%Y-%m-%d %H:%M:%S')
                editor = DateEditor()
            else:
                formatter = StringFormatter()
                editor = StringEditor()

            if col in self.editors:
                editor = self.editors[col]

            if col in indexes or editor is None:
                editor = CellEditor()

            if col in self.formatters:
                formatter = self.formatters[col]
            if str(col) != col:
                self._renamed_cols[str(col)] = col
            if isinstance(self.widths, int):
                col_kwargs['width'] = self.widths
            elif str(col) in self.widths:
                col_kwargs['width'] = self.widths.get(str(col))

            title = str(col)
            if col in indexes and len(indexes) > 1 and self.hierarchical:
                title = 'Index: %s' % ' | '.join(indexes)
            column = TableColumn(field=str(col),
                                 title=title,
                                 editor=editor,
                                 formatter=formatter,
                                 **col_kwargs)
            columns.append(column)
        return columns
예제 #5
0
파일: main.py 프로젝트: DServSys/Albatross
    def __init__(self, layout):
        self.__layout = layout
        self.__selected = []
        self.__file_list = self.__get_eurostats()

        self.__rdf_table_source = ColumnDataSource(
            dict(id=[f['id'] for f in self.__file_list]))
        self.__rdf_table_source.on_change('selected', self.__on_select)
        rdf_table_columns = [TableColumn(field='id', title='RDF ID')]
        self.rdf_table = DataTable(source=self.__rdf_table_source,
                                   columns=rdf_table_columns,
                                   width=300,
                                   height=500,
                                   selectable=True)

        geojson_data = {'id': [], 'lvl': []}
        for file in self.__file_list:
            if file['geojson']['nuts1']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(1)

            if file['geojson']['nuts2']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(2)

            if file['geojson']['nuts3']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(3)
        self.__geojson_table_source = ColumnDataSource(geojson_data)
        geojson_table_columns = [
            TableColumn(field='lvl', title='NUTS Level'),
            TableColumn(field='id', title='ID')
        ]
        self.geojson_table = DataTable(source=self.__geojson_table_source,
                                       columns=geojson_table_columns,
                                       width=300,
                                       height=500,
                                       selectable=True)
        convert_button = Button(label="Convert to GeoJSON",
                                button_type="success")
        convert_button.on_click(self.transform)
        # todo: creates bug - empty table
        #self.__layout.children[1] = column(widgetbox(self.rdf_table), convert_button)
        self.__layout.children[2] = column(self.geojson_table)
예제 #6
0
    def _init_datatable(self):
        columns = [
            TableColumn(
                width=80,
                field="parameter",
                title="Parameter",
                formatter=self.param_formatter,
                editor=CellEditor()  # non editable
            ),
            TableColumn(width=50,
                        field="value",
                        title="Value",
                        formatter=self.value_formatter,
                        editor=CellEditor()),
            TableColumn(width=40,
                        field="flag",
                        title="Flag",
                        formatter=self.flag_formatter,
                        editor=StringEditor()),
        ]
        self.table_df = pd.DataFrame(
            dict(
                parameter=self.params,
                value=[''] * len(self.params),
                flag=[''] * len(self.params),
            ))
        table_cds = ColumnDataSource(self.table_df)
        self.data_table = DataTable(
            width=190,
            height=125,
            source=table_cds,
            columns=columns,
            editable=
            True,  # TODO: check if there is a better way than https://stackoverflow.com/a/49424647/4891717
            fit_columns=False,  # avoids horizontal scrolls bar
            index_position=None,  # hides index column
            selectable=True,  # this is needed to edit cells
            reorderable=
            False,  # NOTE: this needs jquery ui, but it is not needed
            scroll_to_selection=False,  # not needed
            sortable=False,  # not needed
        )

        self.data_table.source.on_change('data', self.on_change_data_source)
예제 #7
0
파일: main_kh.py 프로젝트: desihub/desilo
    def weather_tab(self):
        data = pd.DataFrame(columns = ['time','desc','temp','wind','humidity'])
        self.weather_source = ColumnDataSource(data)

        self.weather_subtitle = Div(text="Weather", css_classes=['subt-style'])

        columns = [TableColumn(field='time', title='Time (local)', width=75),
                   TableColumn(field='desc', title='Description', width=200, editor=StringEditor()),
                   TableColumn(field='temp', title='Temperature (C)', width=100, editor=NumberEditor()),
                   TableColumn(field='wind', title='Wind Speed (mph)', width=120, editor=NumberEditor()),
                   TableColumn(field='humidity', title='Humidity (%)', width=100, editor=PercentEditor())]
        self.weather_inst = Div(text="Every hour include a description of the weather and any other relevant information, as well as fill in all the fields below.  Click the Update Night Log button after every hour's entry. To update a cell: double click in it, record the information, click out of the cell.", width=1000, css_classes=['inst-style'])
        self.weather_time = TextInput(placeholder='17:00', value=None, width=100) #title='Time in Kitt Peak local time', 
        self.weather_desc = TextInput(title='Description', placeholder='description', value=None)
        self.weather_temp = TextInput(title='Temperature (C)', placeholder='50', value=None)
        self.weather_wind = TextInput(title='Wind Speed (mph)', placeholder='10', value=None)
        self.weather_humidity = TextInput(title='Humidity (%)', placeholder='5', value=None)
        self.weather_table = DataTable(source=self.weather_source, columns=columns)
        self.weather_btn = Button(label='Add Weather', css_classes=['add_button'])
예제 #8
0
    def __init__(self):
        # extend __init__ super class
        _DataSource.__init__(self)

        # overwrite base class filepath with FileInput widget
        self.filepath = FileInput(accept=".xlsx")
        self.filepath.on_change('value', self.update_data)

        # add columndatasource and table
        self.cds = ColumnDataSource(data=dict(values=['']))
        self.table = DataTable(source=self.cds, columns=[TableColumn(field='', title='')], editable=True)
예제 #9
0
파일: main.py 프로젝트: DServSys/Albatross
    def __init__(self, layout):
        self.__layout = layout
        self.__selected = []
        self.__file_list = self.__get_eurostats()

        geojson_data = {'id': [], 'lvl': []}
        for file in self.__file_list:
            if file['geojson']['nuts1']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(1)

            if file['geojson']['nuts2']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(2)

            if file['geojson']['nuts3']['exists']:
                geojson_data['id'].append(file['id'])
                geojson_data['lvl'].append(3)
        self.__geojson_table_source = ColumnDataSource(geojson_data)
        geojson_table_columns = [
            TableColumn(field='lvl', title='NUTS Level'),
            TableColumn(field='id', title='ID')
        ]
        self.geojson_table = DataTable(source=self.__geojson_table_source,
                                       columns=geojson_table_columns,
                                       width=300,
                                       height=500,
                                       selectable=True)

        convert_button = Button(label="Convert to GeoJSON",
                                button_type="success")
        convert_button.on_click(self.transform)
        self.__endpoint_input = TextInput(placeholder="SPARQL Endpoint")
        self.__graph_input = TextInput(placeholder="Graph")
        self.__layout.children[1] = column(self.__endpoint_input,
                                           self.__graph_input, convert_button)
        self.__layout.children[2] = column(self.geojson_table)
예제 #10
0
def get_nightlytable(exposures):
    '''
    Generates a summary table of the exposures from the night observed.
    Args:
        exposures: Table of exposures with columns...
    Returns a bokeh DataTable object.
    '''

    source = ColumnDataSource(
        data=dict(expid=np.array(exposures['EXPID']),
                  flavor=np.array(exposures['FLAVOR'], dtype='str'),
                  exptime=np.array(exposures['EXPTIME']),
                  tileid=np.array(exposures['TILEID']),
                  airmass=np.array(exposures['AIRMASS']),
                  seeing=np.array(exposures['SEEING']),
                  transp=np.array(exposures['TRANSP']),
                  sky=np.array(exposures['SKY']),
                  hourangle=np.array(exposures['HOURANGLE'])))

    formatter = NumberFormatter(format='0,0.00')
    columns = [
        TableColumn(field='expid', title='Exposure ID'),
        TableColumn(field='flavor', title='Flavor'),
        TableColumn(field='exptime', title='Exposure Time'),
        TableColumn(field='tileid', title='Tile ID'),
        TableColumn(field='airmass', title='Airmass', formatter=formatter),
        TableColumn(field='seeing', title='Seeing', formatter=formatter),
        TableColumn(field='transp', title='Transparency', formatter=formatter),
        TableColumn(field='sky', title='Sky', formatter=formatter),
        TableColumn(field='hourangle', title='Hour Angle', formatter=formatter)
    ]

    nightly_table = DataTable(source=source,
                              columns=columns,
                              width=1000,
                              sortable=True)

    return nightly_table
예제 #11
0
파일: main.py 프로젝트: DServSys/Albatross
    def generate_rdf_column_data_source(self, files, column_title="ID"):
        """
        Generate data table based on files list with ``id``.
    
        :param List files: List of Dictionaries that contain the key ``id``.
        :param string column_title: Title of the data table column.
        :return: Data table containing the file IDs.
        """
        ids = [tmp_id['id'] for tmp_id in files]
        data = dict(id=ids)
        table_source = ColumnDataSource(data)

        columns = [TableColumn(field="id", title=column_title)]
        data_table = DataTable(source=table_source,
                               columns=columns,
                               width=500,
                               height=400,
                               selectable=True)
        return data_table
예제 #12
0
    def import_data(self):
        """
        This overrides the base class method

        :return:
        """
        # # decode file (received as b64 encoded) and write to xlsx locally
        decoded = base64.b64decode(self.filepath.value)

        # stream data to pandas df without saving locally
        toread = io.BytesIO()
        toread.write(decoded)  # pass your `decrypted` string as the argument here
        toread.seek(0)  # reset the pointer

        self.df = get_one_table(toread, 'quote_table').dropna(axis=0, how='all')

        cols = [TableColumn(field=_, title=_) for _ in self.df.columns]  # bokeh columns

        self.table.columns = cols
        self.cds.data = self.df
예제 #13
0
파일: report_kh.py 프로젝트: desihub/desilo
    def get_nl_layout(self):
        exp_data = pd.DataFrame(columns = ['date_obs','id','program','sequence','flavor','exptime'])
        self.explist_source = ColumnDataSource(exp_data)

        columns = [TableColumn(field='date_obs', title='Time (UTC)', width=50, formatter=self.datefmt),
                   TableColumn(field='id', title='Exposure', width=50),
                   TableColumn(field='sequence', title='Sequence', width=100),
                   TableColumn(field='flavor', title='Flavor', width=50),
                   TableColumn(field='exptime', title='Exptime', width=50),
                   TableColumn(field='program', title='Program', width=300)]

        self.exp_table = DataTable(source=self.explist_source, columns=columns, width=1000)

        nl_layout = layout([self.title,
                        self.nl_subtitle,
                        self.nl_alert,
                        self.nl_text,
                        self.exptable_alert,
                        self.exp_table], width=1000)
        self.nl_tab = Panel(child=nl_layout, title="Current DESI Night Log")
예제 #14
0
    def _get_column_definitions(self, col_names, df):
        import pandas as pd
        indexes = self.indexes
        columns = []
        for col in col_names:
            if col in df.columns:
                data = df[col]
            else:
                data = df.index

            if isinstance(data, pd.DataFrame):
                raise ValueError("DataFrame contains duplicate column names.")

            col_kwargs = {}
            kind = data.dtype.kind
            if kind == 'i':
                formatter = NumberFormatter()
                editor = IntEditor()
            elif kind == 'b':
                formatter = StringFormatter()
                editor = CheckboxEditor()
            elif kind == 'f':
                formatter = NumberFormatter(format='0,0.0[00000]')
                editor = NumberEditor()
            elif isdatetime(data) or kind == 'M':
                if len(data) and isinstance(data.values[0], dt.date):
                    date_format = '%Y-%m-%d'
                else:
                    date_format = '%Y-%m-%d %H:%M:%S'
                formatter = DateFormatter(format=date_format)
                editor = DateEditor()
            else:
                formatter = StringFormatter()
                editor = StringEditor()

            if col in self.editors and not isinstance(self.editors[col],
                                                      (dict, str)):
                editor = self.editors[col]

            if col in indexes or editor is None:
                editor = CellEditor()

            if col in self.formatters and not isinstance(
                    self.formatters[col], (dict, str)):
                formatter = self.formatters[col]

            if str(col) != col:
                self._renamed_cols[str(col)] = col

            if isinstance(self.widths, int):
                col_kwargs['width'] = self.widths
            elif str(col) in self.widths:
                col_kwargs['width'] = self.widths.get(str(col))

            title = self.titles.get(col, str(col))
            if col in indexes and len(indexes) > 1 and self.hierarchical:
                title = 'Index: %s' % ' | '.join(indexes)
            column = TableColumn(field=str(col),
                                 title=title,
                                 editor=editor,
                                 formatter=formatter,
                                 **col_kwargs)
            columns.append(column)
        return columns
예제 #15
0
    def __init__(self):

        # app variables
        self.active = True
        self.playAnimation = None
        self.start_epoch = None
        self.stop_epoch = None
        self.current_epoch = None

        # get initial configuration
        self.available_models = inspect.getmembers(StandardEphemerisModels,
                                                   inspect.isfunction)
        self.ephemeris_model = self.available_models[0][1]()
        self.spice_provider = SpiceProvider()
        self.spice_provider.SPICE_IDS = self.ephemeris_model.objects
        self.spice_provider.SPICE_NAMES = {
            v: k
            for k, v in self.ephemeris_model.objects.items()
        }

        # init data sources
        self.plot_source = self.spice_provider.state_source
        self.table_source = self.spice_provider.ephemeris_source
        self.cum_source = self.spice_provider.cum_source

        # gather options from ephemeris model and spice provider
        self.allowed_models = {
            model[1]().name: model[1]
            for model in self.available_models
        }
        allowed_objects = [
            self.spice_provider.fromId(name)
            for name in self.ephemeris_model.objects
        ]
        allowed_frames = self.ephemeris_model.FRAMES
        allowed_corrections = [name for name in SpiceProvider.CORRECTIONS]
        allowed_durations = [
            str(v) for v in self.ephemeris_model.DURATION_DAYS
        ]
        allowed_intervals = [name for name in SpiceProvider.INTERVALS]

        # set up widgets
        self.model = Select(title="Ephemeris Model",
                            options=list(self.allowed_models.keys()))

        self.center = Select(title="Center",
                             value=self.ephemeris_model.center,
                             options=allowed_objects)

        self.target = Select(title="Target",
                             value=self.ephemeris_model.target,
                             options=allowed_objects)

        self.frames = Select(title="Frame",
                             value=self.ephemeris_model.frame,
                             options=allowed_frames)

        self.planes = RadioButtonGroup(labels=['XY', 'YZ', 'XZ'], active=0)

        self.vector = Select(title='Vector Type',
                             value=self.ephemeris_model.vector_type,
                             options=allowed_corrections)

        self.epoch = DatePicker(title="Select Epoch",
                                value=datetime.strftime(
                                    self.ephemeris_model.epoch, "%Y-%m-%d"))

        self.offset = Slider(title="Days Since Epoch",
                             value=self.ephemeris_model.offset,
                             start=0,
                             end=self.ephemeris_model.duration,
                             step=1)

        self.duration = Select(title="Duration (Days)",
                               value=str(self.ephemeris_model.duration),
                               options=allowed_durations)

        self.interval = Select(title="Time Step",
                               value=str(self.ephemeris_model.step_size),
                               options=allowed_intervals)

        # create buttons
        self.play_button = Button(label="Play")
        self.exportRange = Div(text="Start and Stop Epoch: ")
        self.update_button = Button(label="Play")
        self.export_button = Button(label="Export")

        self.infoDiv = Div(
            text=
            "<hr>All ephemeris data shown on this website was obtained from publicly available "
            "SPICE files located at <a href='https://naif.jpl.nasa.gov/naif/data.html'>"
            "https://naif.jpl.nasa.gov/naif/data.html</a>, which is hosted by the  "
            "Navigation and Ancillary Information Facility (NAIF) at the NASA Jet Propulsion "
            "Laboratory. The exception is the SPICE kernel for the Parker Solar Probe, which is "
            "available at <a href='https://sppgway.jhuapl.edu/ancil_products'>"
            "https://sppgway.jhuapl.edu/ancil_products</a>, hosted by the Johns Hopkins University "
            "Applied Physics Laboratory. SpiceyPy is being used to process the SPICE files.",
            sizing_mode='stretch_width')

        # create plot tab objects
        self.plot = figure(match_aspect=True,
                           sizing_mode="stretch_both",
                           title="Astropynamics",
                           tools="hover, pan, reset, save",
                           tooltips=[("name", "@index")])

        self.plot.add_tools(BoxZoomTool(match_aspect=True))
        self.plot.circle('px',
                         'py',
                         size='radii',
                         source=self.plot_source,
                         line_width=3,
                         line_alpha=0.5,
                         name='XY')
        self.plot.circle('px',
                         'pz',
                         size='radii',
                         source=self.plot_source,
                         line_width=3,
                         line_alpha=0.5,
                         name='XZ').visible = False
        self.plot.circle('py',
                         'pz',
                         size='radii',
                         source=self.plot_source,
                         line_width=3,
                         line_alpha=0.5,
                         name='YZ').visible = False
        self.plot.line('px',
                       'py',
                       source=self.cum_source,
                       line_width=2,
                       line_alpha=0.5,
                       color='red',
                       name='XYOrbit')
        self.plot.line('px',
                       'pz',
                       source=self.cum_source,
                       line_width=2,
                       line_alpha=0.5,
                       color='red',
                       name='XZOrbit').visible = False
        self.plot.line('py',
                       'pz',
                       source=self.cum_source,
                       line_width=2,
                       line_alpha=0.5,
                       color='red',
                       name='YZOrbit').visible = False

        self.plotLayout = column(self.plot,
                                 self.offset,
                                 sizing_mode="stretch_width")
        self.plotTab = Panel(child=self.plotLayout, title="Display")

        # create data table tab objects
        fmt = NumberFormatter(format='0.000', text_align=TextAlign.right)
        columns = [
            TableColumn(field="index",
                        title="Epoch",
                        formatter=DateFormatter(format="%m/%d/%Y %H:%M:%S")),
            TableColumn(field="px", title="PX", formatter=fmt, width=10),
            TableColumn(field="py", title="PY", formatter=fmt),
            TableColumn(field="pz", title="PZ", formatter=fmt),
            TableColumn(field="vx", title="VX", formatter=fmt),
            TableColumn(field="vy", title="VY", formatter=fmt),
            TableColumn(field="vz", title="VZ", formatter=fmt)
        ]

        self.ephemerisTable = DataTable(source=self.table_source,
                                        columns=columns,
                                        sizing_mode="stretch_both")
        self.ephemerisLayout = column(self.exportRange,
                                      self.ephemerisTable,
                                      sizing_mode="stretch_width")
        self.dataTab = Panel(child=self.ephemerisLayout, title="Table")

        self.kernels = Div()
        self.kernelTab = Panel(child=self.kernels, title="Kernels")

        self.tabs = Tabs(tabs=[self.plotTab, self.dataTab, self.kernelTab])

        # init data
        self.model.value = "The Solar System"
        self.update_model(None, 0, self.model.value)
        self.update_epochs(None, 0, 0)
        self.update_states(None, 0, 0)

        self.model.on_change('value', self.update_model)
        self.frames.on_change('value', self.update_epochs)
        self.planes.on_change('active', self.update_plot_view)
        self.center.on_change('value', self.update_epochs)
        self.target.on_change('value', self.update_epochs)
        self.offset.on_change('value', self.update_offset)
        self.epoch.on_change('value', self.update_epochs)
        self.duration.on_change('value', self.update_epochs)
        self.interval.on_change('value', self.update_epochs)
        self.update_button.on_click(self.update_onclick)
        self.tabs.on_change('active', self.update_button_type)

        self.inputs = column(self.model, self.frames, self.planes, self.center,
                             self.target, self.epoch, self.duration,
                             self.interval, self.update_button)
예제 #16
0
파일: plot.py 프로젝트: henryrobbins/vinal
def assisted_dijkstras_plot(G, s=0, **kw) -> GridBox:
    """Return a plot in which the user creates a shortest path tree from s.

    Args:
        G (nx.Graph): Networkx graph.
        s (int): The vertex to generate a shortest path tree from.

    Returns:
        GridBox: Plot in which the user creates a shortest path tree from s.
    """
    G = G.copy()
    plot = _blank_plot(G, **kw)

    _set_edge_positions(G)
    _set_graph_colors(G)

    nodes_src, nodes_glyph = _add_nodes(G, plot)
    nodes_src.data['fill_color'][s] = SECONDARY_COLOR
    nodes_src.data['line_color'][s] = SECONDARY_DARK_COLOR
    edges_src, edges_glyph = _add_edges(G, plot, show_labels=True)

    src_data = _get_blank_src_data(G)
    dist = [float('inf')] * len(G)
    dist[s] = 0
    src_data['dist'] = dist
    src_data['prev'] = [float('nan')] * len(G)
    src_data['settled'] = []
    src_data['frontier'] = [s]

    edge_ids, G_matrix = _edge_src_maps(G, edges_src)
    src_data['edge_ids'] = edge_ids
    cost_matrix = ColumnDataSource(data={'G': G_matrix})

    # docs indicate that each value should be of the same length but this works
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        source = ColumnDataSource(data=src_data)

    error_msg = Div(text='', width=int(plot.plot_width / 3), align='center')

    table_data = {str(i): ['inf', '-'] for i in range(len(G))}
    table_data['index'] = ['label', 'prev']

    table_data[str(s)][1] = '0'
    table_src = ColumnDataSource(data=table_data)
    columns = [TableColumn(field='index', title='')]
    for i in range(len(G)):
        columns.append(TableColumn(field=str(i), title=str(i)))
    table = DataTable(source=table_src,
                      columns=columns,
                      height=80,
                      width_policy='fit',
                      max_width=plot.plot_width,
                      width=plot.plot_width,
                      background='white',
                      index_position=None,
                      editable=False,
                      reorderable=False,
                      sortable=False,
                      selectable=False)

    on_click = PLOT_CREATE_JS + 'check_done()\nload_data()\ndijkstras()\n'

    _add_tools(plot,
               on_click=on_click,
               nodes_glyph=nodes_glyph,
               renderer=nodes_glyph,
               source=source,
               nodes_src=nodes_src,
               edges_src=edges_src,
               cost_matrix=cost_matrix,
               error_msg=error_msg,
               table_src=table_src)

    grid = gridplot([[plot], [table], [row(error_msg)]],
                    plot_width=plot.plot_width,
                    plot_height=plot.plot_height,
                    toolbar_location=None,
                    toolbar_options={'logo': None})

    return grid
예제 #17
0
파일: plot.py 프로젝트: henryrobbins/vinal
def _graph_iterations_plot(G: nx.Graph,
                           nodes: List[List[int]] = None,
                           edges: List[List[List[int]]] = None,
                           costs: List[float] = None,
                           tables: List[pd.DataFrame] = None,
                           swaps: List[List[int]] = None,
                           show_all_edges: bool = True,
                           show_labels: bool = True,
                           **kw) -> GridBox:
    """Return a plot of multiple iterations of a graph.

    Args:
        G (nx.Graph): Networkx graph.
        nodes (List[List[int]]): Highlighted nodes at every iteration.
        edges (List[List[List[int]]]): Highlighted edges at every iteration.
        costs (List[float]): Cost at every iteration.
        tables (List[pd.DataFrame]): Table to be shown at every iteration.
        swaps (List[List[int]]): Edge swap to highlight at every iteration.
        show_all_edges (bool, optional): True iff all edges should be shown.
        show_labels (bool, optional): True iff labels should be shown.

    Returns:
        GridBox: Plot of multiple iterations of a graph.
    """
    G = G.copy()
    plot = _blank_plot(G, **kw)

    _set_edge_positions(G)
    _set_graph_colors(G)

    args_dict = {}  # keep track of objects to pass to JS callback

    # nodes and edges
    nodes_src, nodes_glyph = _add_nodes(G, plot)
    args_dict['nodes_src'] = nodes_src
    if nodes is not None:
        for i in nodes[0]:
            nodes_src.data['line_color'][i] = PRIMARY_DARK_COLOR
            nodes_src.data['fill_color'][i] = PRIMARY_DARK_COLOR

    if show_all_edges:
        edges_src, edges_glyph = _add_edges(G, plot, show_labels=show_labels)

    # current iteration
    n = Div(text='0', width=plot.plot_width, align='center')
    args_dict['n'] = n

    # total number of iterations
    features = [edges, nodes, costs, tables, swaps]
    k = max([0 if feature is None else len(feature) for feature in features])
    k = Div(text=str(k), width=plot.plot_width, align='center')
    args_dict['k'] = k

    # indicate if on final iteration
    done = Div(text='', width=int(plot.plot_width / 2), align='center')
    args_dict['done'] = done

    source_data = {}

    if edges is not None:
        tmp = list(zip(*[_edge_positions(G, edge) for edge in edges]))
        edge_xs, edge_ys = tmp
        source_data['edge_xs'] = edge_xs
        source_data['edge_ys'] = edge_ys
        edge_subset_src = ColumnDataSource(data={
            'xs': edge_xs[0],
            'ys': edge_ys[0]
        })
        plot.multi_line('xs',
                        'ys',
                        line_color=TERTIARY_DARK_COLOR,
                        line_width=LINE_WIDTH,
                        level=EDGE_LEVEL,
                        line_cap='round',
                        source=edge_subset_src)
        args_dict['edge_subset_src'] = edge_subset_src

    if nodes is not None:
        source_data['nodes'] = nodes

    if costs is not None:
        source_data['costs'] = costs
        cost = Div(text=str(costs[0]),
                   width=int(plot.plot_width / 2),
                   align='center')
        args_dict['cost'] = cost

    if tables is not None:
        tables = [table.to_dict(orient='list') for table in tables]
        source_data['tables'] = tables
        table_src = ColumnDataSource(data=tables[0])
        columns = [TableColumn(field='index', title='')]
        for i in range(len(tables[0]) - 1):
            columns.append(TableColumn(field=str(i), title=str(i)))
        table = DataTable(source=table_src,
                          columns=columns,
                          height=80,
                          width_policy='fit',
                          max_width=plot.plot_width,
                          width=plot.plot_width,
                          background='white',
                          index_position=None,
                          editable=False,
                          reorderable=False,
                          sortable=False,
                          selectable=False)
        args_dict['table_src'] = table_src

    if swaps is not None:
        tmp = list(zip(*[_swap_positions(G, swap) for swap in swaps]))
        swaps_before_x, swaps_before_y, swaps_after_x, swaps_after_y = tmp
        source_data['swaps_before_x'] = swaps_before_x
        source_data['swaps_before_y'] = swaps_before_y
        source_data['swaps_after_x'] = swaps_after_x
        source_data['swaps_after_y'] = swaps_after_y
        swaps_src = ColumnDataSource(
            data={
                'swaps_before_x': swaps_before_x[0],
                'swaps_before_y': swaps_before_y[0],
                'swaps_after_x': swaps_after_x[0],
                'swaps_after_y': swaps_after_y[0]
            })
        plot.multi_line(xs='swaps_before_x',
                        ys='swaps_before_y',
                        line_color=SECONDARY_COLOR,
                        line_width=LINE_WIDTH,
                        line_cap='round',
                        level=EDGE_LEVEL,
                        source=swaps_src)
        plot.multi_line(xs='swaps_after_x',
                        ys='swaps_after_y',
                        line_color=SECONDARY_COLOR,
                        line_width=LINE_WIDTH,
                        line_cap='round',
                        level=EDGE_LEVEL,
                        line_dash=[10, 12],
                        source=swaps_src)
        args_dict['swaps_src'] = swaps_src

    source = ColumnDataSource(data=source_data)
    args_dict['source'] = source

    code = ('done_update()\n' + 'cost_update()\n' * (costs is not None) +
            'edge_subset_update()\n' * (edges is not None) +
            'table_update()\n' * (tables is not None) + 'nodes_update()\n' *
            (nodes is not None) + 'swaps_update()\n' * (swaps is not None))
    next_btn_code = PLOT_GRAPH_ITERATIONS_JS + 'increment_iteration()\n' + code
    prev_btn_code = PLOT_GRAPH_ITERATIONS_JS + 'decrement_iteration()\n' + code

    # buttons
    next_button = Button(label="Next",
                         button_type="primary",
                         max_width=int(plot.plot_width / 2),
                         width_policy='fit',
                         sizing_mode='stretch_width')
    next_button.js_on_click(CustomJS(args=args_dict, code=next_btn_code))
    prev_button = Button(label="Previous",
                         button_type="primary",
                         max_width=int(plot.plot_width / 2),
                         width_policy='fit',
                         sizing_mode='stretch_width')
    prev_button.js_on_click(CustomJS(args=args_dict, code=prev_btn_code))

    plot.add_tools(
        HoverTool(tooltips=[("Index", "$index"), ("Name", "@name")],
                  renderers=[nodes_glyph]))

    # create layout
    layout = [[plot],
              [
                  row(prev_button,
                      next_button,
                      max_width=plot.plot_width,
                      sizing_mode='stretch_both')
              ], [row(cost, done) if costs else row(done)]]
    if tables is not None:
        layout.insert(1, [table])

    grid = gridplot(layout,
                    plot_width=plot.plot_width,
                    plot_height=plot.plot_height,
                    toolbar_location=None,
                    toolbar_options={'logo': None})

    return grid
예제 #18
0
    DataTable, TableColumn, SelectEditor, IntEditor, NumberEditor)
from bokeh.layouts import column, layout
import numpy as np
np.seterr(all='raise')


fpa_experts = ['Duan', 'Fanning', 'Fagrelius', 'Schubnell', 'Silber',
               'Poppett', 'Kai']
pcm = pm.PosCalManager()
pi = pm.get_positioner_index()
source = ColumnDataSource(data=pcm.table)
source.selected.indices = [pcm.i_selected]  # ['1d']['indices'] = [i_selected]
title = Div(text='''
<font size="4">Positioner Calibrations</font> (some columns editable)''',
            width=500)
columns = [TableColumn(field='UTC', title='UTC', width=160),
           TableColumn(field='expid', title='expid', width=50),
           TableColumn(field='test name', title='test name', width=260),
           TableColumn(field='exptime', title='exptime/s', width=60,
                       editor=NumberEditor()),
           TableColumn(field='dome', title='dome', width=50,
                       editor=SelectEditor(options=['open', 'closed', '?'])),
           TableColumn(field='zenith angle', title='zenith angle', width=69,
                       editor=IntEditor()),
           TableColumn(field='tracking', title='tracking', width=50,
                       editor=SelectEditor(options=['on', 'off', '?'])),
           TableColumn(field='T ambient', title='T ambient/°C', width=75,
                       editor=NumberEditor()),
           TableColumn(field='T mirror', title='T mirror/°C', width=65,
                       editor=NumberEditor()),
           TableColumn(field='PMTC', title='PMTC', width=50,
예제 #19
0
파일: summary.py 프로젝트: sbailey/surveyqa
def get_summarytable(exposures):
    '''
    Generates a summary table of key values for each night observed. Uses collections.Counter(), OrderedDict()

    Args:
        exposures: Table of exposures with columns...

    Returns a bokeh DataTable object.
    '''
    nights = np.unique(exposures['NIGHT'])

    isbright = (exposures['PROGRAM'] == 'BRIGHT')
    isgray = (exposures['PROGRAM'] == 'GRAY')
    isdark = (exposures['PROGRAM'] == 'DARK')
    iscalib = (exposures['PROGRAM'] == 'CALIB')

    num_nights = len(nights)
    brights = list()
    grays = list()
    darks = list()
    calibs = list()
    totals = list()
    for n in nights:
        thisnight = exposures['NIGHT'] == n
        totals.append(np.count_nonzero(thisnight))
        brights.append(np.count_nonzero(thisnight & isbright))
        grays.append(np.count_nonzero(thisnight & isgray))
        darks.append(np.count_nonzero(thisnight & isdark))
        calibs.append(np.count_nonzero(thisnight & iscalib))

    med_air = get_median('AIRMASS', exposures)
    med_seeing = get_median('SEEING', exposures)
    med_exptime = get_median('EXPTIME', exposures)
    med_transp = get_median('TRANSP', exposures)
    med_sky = get_median('SKY', exposures)

    source = ColumnDataSource(data=dict(
        nights=list(nights),
        totals=totals,
        brights=brights,
        grays=grays,
        darks=darks,
        calibs=calibs,
        med_air=med_air,
        med_seeing=med_seeing,
        med_exptime=med_exptime,
        med_transp=med_transp,
        med_sky=med_sky,
    ))

    formatter = NumberFormatter(format='0,0.00')
    template_str = '<a href="night-<%= nights %>.html"' + ' target="_blank"><%= value%></a>'

    columns = [
        TableColumn(field='nights',
                    title='NIGHT',
                    width=100,
                    formatter=HTMLTemplateFormatter(template=template_str)),
        TableColumn(field='totals', title='Total', width=50),
        TableColumn(field='brights', title='Bright', width=50),
        TableColumn(field='grays', title='Gray', width=50),
        TableColumn(field='darks', title='Dark', width=50),
        TableColumn(field='calibs', title='Calibs', width=50),
        TableColumn(field='med_exptime', title='Median Exp. Time', width=100),
        TableColumn(field='med_air',
                    title='Median Airmass',
                    width=100,
                    formatter=formatter),
        TableColumn(field='med_seeing',
                    title='Median Seeing',
                    width=100,
                    formatter=formatter),
        TableColumn(field='med_sky',
                    title='Median Sky',
                    width=100,
                    formatter=formatter),
        TableColumn(field='med_transp',
                    title='Median Transparency',
                    width=115,
                    formatter=formatter),
    ]

    summary_table = DataTable(source=source,
                              columns=columns,
                              width=900,
                              sortable=True,
                              fit_columns=False)
    return summary_table
예제 #20
0
    def __init__(self, model):
        """
        Construct separation dashboard
        """
        # Save reference to model
        self.model = model

        ################################
        # Process button
        ################################

        self.process = Button(label="Generate",
                              button_type="primary",
                              name='process',
                              sizing_mode='scale_width',
                              css_classes=['generate'])
        self.process.js_on_click(CustomJS(code="toggleLoading()"))

        ################################
        # Widgets
        ################################

        # Data type selection
        self.data_type = RadioButtonGroup(
            labels=["All Data", "Experimental", "Simulated"],
            active=0,
            css_classes=['dtypes'])

        # Adsorbate drop-down selections
        self.g1_sel = Select(title="Adsorbate 1",
                             options=self.model.ads_list,
                             value=self.model.g1,
                             css_classes=['g-selectors'])
        self.g2_sel = Select(title="Adsorbate 2",
                             options=self.model.ads_list,
                             value=self.model.g2)

        # Temperature selection
        self.t_absolute = Spinner(value=self.model.t_abs,
                                  title='Temperature:',
                                  css_classes=['t-abs'])
        self.t_tolerance = Spinner(value=self.model.t_tol,
                                   title='Tolerance:',
                                   css_classes=['t-tol'])

        # Combined in a layout
        self.dsel_widgets = layout([
            [self.data_type],
            [self.g1_sel, self.g2_sel, self.t_absolute, self.t_tolerance],
        ],
                                   sizing_mode='scale_width',
                                   name="widgets")

        ################################
        # KPI Plots
        ################################

        # Top graph generation
        tooltip = load_tooltip()
        self.p_henry, rend1 = self.top_graph("K", "Henry coefficient (log)",
                                             self.model.data,
                                             self.model.errors, tooltip)
        self.p_loading, rend2 = self.top_graph(
            "L", "Uptake at selected pressure (bar)", self.model.data,
            self.model.errors, tooltip)
        self.p_wc, rend3 = self.top_graph(
            "W", "Working capacity in selected range (bar)", self.model.data,
            self.model.errors, tooltip)

        # Give graphs the same hover and select effect
        sel = Circle(fill_alpha=1, fill_color="red", line_color=None)
        nonsel = Circle(fill_alpha=0.2, fill_color="blue", line_color=None)
        for rend in [rend1, rend2, rend3]:
            rend.selection_glyph = sel
            rend.nonselection_glyph = nonsel
            rend.hover_glyph = sel

        # Pressure slider
        self.p_slider = Slider(
            title="Pressure (bar)",
            value=0.5,
            start=0,
            end=20,
            step=0.5,
            callback_policy='throttle',
            callback_throttle=200,
        )

        # Working capacity slider
        self.wc_slider = RangeSlider(
            title="Working capacity (bar)",
            value=(0.5, 5),
            start=0,
            end=20,
            step=0.5,
            callback_policy='throttle',
            callback_throttle=200,
        )

        # Material datatable
        self.mat_list = DataTable(
            columns=[
                TableColumn(field="labels", title="Material", width=300),
                TableColumn(field="sel",
                            title="KH2/KH1",
                            width=35,
                            formatter=NumberFormatter(format='‘0.0a’')),
                TableColumn(field="psa_W",
                            title="PSA-API",
                            width=35,
                            formatter=NumberFormatter(format='‘0.0a’')),
            ],
            source=self.model.data,
            index_position=None,
            selectable='checkbox',
            scroll_to_selection=True,
            width=400,
            fit_columns=True,
        )

        # Custom css classes for interactors
        self.p_henry.css_classes = ['g-henry']
        self.p_loading.css_classes = ['g-load']
        self.p_wc.css_classes = ['g-wcap']
        self.mat_list.css_classes = ['t-details']

        # Generate the axis labels
        self.top_graph_labels()

        self.kpi_plots = layout([
            [
                gridplot([[self.mat_list, self.p_henry],
                          [self.p_loading, self.p_wc]],
                         sizing_mode='scale_width')
            ],
            [self.p_slider, self.wc_slider],
        ],
                                sizing_mode='scale_width',
                                name="kpiplots")
        self.kpi_plots.children[0].css_classes = ['kpi']
        self.kpi_plots.children[1].css_classes = ['p-selectors']

        ################################
        # Isotherm details explorer
        ################################

        # Isotherm display graphs
        self.p_g1iso = self.bottom_graph(self.model.g1_iso_sel, self.model.g1)
        self.p_g2iso = self.bottom_graph(self.model.g2_iso_sel, self.model.g2)

        # Isotherm display palette
        self.c_cyc = cycle(gen_palette(20))

        self.detail_plots = layout([
            [self.p_g1iso, self.p_g2iso],
        ],
                                   sizing_mode='scale_width',
                                   name="detailplots")
        self.detail_plots.children[0].css_classes = ['isotherms']
예제 #21
0
        'O4: Lieutenant Commander', 'O5: Commander', 'O6: Captain',
        'O7: Rear Admiral (lower half)', 'O8: Rear Admiral (upper half)',
        'O9: Vice Admiral', 'O10: Admiral'
    ]
}
dictDT3 = {
    'RankNames': [
        'CWO2: Chief Warrant Officer', 'CWO3: Chief Warrant Officer',
        'CWO4: Chief Warrant Officer', 'CWO5: Chief Warrant Officer'
    ]
}

sourceDT1 = ColumnDataSource(data=dictDT1)
sourceDT2 = ColumnDataSource(data=dictDT1)
sourceDT3 = ColumnDataSource(data=dictDT1)
columnsDT = [TableColumn(field="RankNames", title="Rank")]
data_table1 = DataTable(source=sourceDT1,
                        columns=columnsDT,
                        width=170,
                        editable=True,
                        reorderable=False,
                        index_position=None)
data_table2 = DataTable(source=sourceDT2,
                        columns=columnsDT,
                        width=170,
                        editable=True,
                        reorderable=False,
                        index_position=None)
data_table3 = DataTable(source=sourceDT3,
                        columns=columnsDT,
                        width=170,
예제 #22
0
파일: main.py 프로젝트: DServSys/Albatross
    def transform(self):
        if self.__graph_input.value and self.__endpoint_input.value:
            filename = self.__graph_input.value.split('/')[-1].split('.')[0]

            print("converting")
            sparql = SPARQLWrapper("https://www.foodie-cloud.org/sparql")
            query_a = """
            prefix obs: <http://purl.org/linked-data/sdmx/2009/measure#>
            prefix prop: <http://eurostat.linked-statistics.org/property#>
            prefix qb: <http://purl.org/linked-data/cube#>
            prefix sdmx-dimension: <http://purl.org/linked-data/sdmx/2009/dimension#>
            
            select distinct ?designation ?time ?value ?unit
            """

            graph = "from <{}>".format(self.__graph_input.value)

            query_b = """
            where {
                ?observation a qb:Observation.
                ?observation prop:geo ?designation.
                ?observation prop:unit ?unit.
                ?observation sdmx-dimension:timePeriod ?time.
                ?observation obs:obsValue ?value.
            }
            """

            query = "{}\n{}\n{}".format(query_a, graph, query_b)

            sparql.setQuery(query)
            sparql.setReturnFormat(JSON)
            results = sparql.query().convert()

            print("writing")
            self.__write_geojson(results, filename)
            print("done converting")

            self.__file_list = self.__get_eurostats()
            geojson_data = {'id': [], 'lvl': []}
            for file in self.__file_list:
                if file['geojson']['nuts1']['exists']:
                    geojson_data['id'].append(file['id'])
                    geojson_data['lvl'].append(1)

                if file['geojson']['nuts2']['exists']:
                    geojson_data['id'].append(file['id'])
                    geojson_data['lvl'].append(2)

                if file['geojson']['nuts3']['exists']:
                    geojson_data['id'].append(file['id'])
                    geojson_data['lvl'].append(3)
            self.__geojson_table_source = ColumnDataSource(geojson_data)
            geojson_table_columns = [
                TableColumn(field='lvl', title='NUTS Level'),
                TableColumn(field='id', title='ID')
            ]
            self.geojson_table = DataTable(source=self.__geojson_table_source,
                                           columns=geojson_table_columns,
                                           width=300,
                                           height=500,
                                           selectable=True)
            self.__layout.children[2] = column(self.geojson_table)
예제 #23
0
main_scatter_plot = figure(tools='box_select,lasso_select,pan,wheel_zoom,reset,resize,save')
main_scatter_plot.add_tools(hover)
main_scatter_df = df[(df.attr_rank==0) & (df.attr_name==selected_attribute) & (df.attr_rank==0)]
main_scatter_source=ColumnDataSource(main_scatter_df)
color = to_color(main_scatter_df)
r=main_scatter_plot.circle('x','y', source=main_scatter_source, radius=0.25, fill_alpha=0.8, color=color)

# calculate context
context_df = df.groupby(['attr_value']).agg({'id':'count'}).rename(columns={'id':'n'})

# setup attribute table
table_df = df[df.attr_name==selected_attribute].groupby(['attr_value']).agg({'id':'count'})
table_df = table_df.sort_values(by='id', ascending=False).rename(columns={'id':'n'})
joined_df = calculate_ratio(table_df)
table_source = ColumnDataSource(joined_df)
table_source_column = [TableColumn(field="attr_value", title="Attribute Value"),TableColumn(field="n", title="Counts"),TableColumn(field="ratio", title="Ratio"),]
table_data_table = DataTable(source=table_source, columns=table_source_column, width=400, height=800)

# setup dropdowns
main_dropdown = Select(title="Chart Attributes", options=attributes_name, value=selected_attribute)
table_dropdown = Select(title="Histogram Attributes", options=attributes_name, value=selected_attribute)

# setup text input
threshold_input = TextInput(value=str(threshold), title="Threshold:")

# setup layout
layout_left = VBox(main_scatter_plot, main_dropdown)
layout_right = VBox(HBox(table_dropdown,threshold_input), table_data_table)
layout = HBox(layout_left,layout_right)

def update_threshold_callback(attr_name, old, new):
예제 #24
0
 def init_source(self):
     self.source = ColumnDataSource(data=data)
     self.data_table = DataTable(source=self.source,
                                 columns=[
                                     TableColumn(field='fpid',
                                                 title='FPID'),
                                     TableColumn(field='chromophore_name',
                                                 title='chromophore_name'),
                                     TableColumn(field='chromophore_class',
                                                 title='chromophore_class'),
                                     TableColumn(field='protein_name',
                                                 title='Protein name'),
                                     TableColumn(field='excitation_new',
                                                 title='Excitation'),
                                     TableColumn(field='emission_new',
                                                 title='Emission'),
                                     TableColumn(field='pdb_id',
                                                 title='PDB ID'),
                                     TableColumn(field='genbank',
                                                 title='Genbank ID'),
                                     TableColumn(field='mutation',
                                                 title='Mutation'),
                                     TableColumn(field='quantum_yield',
                                                 title='Quantum Yield'),
                                     TableColumn(field='pka', title='pka'),
                                     TableColumn(
                                         field='amino_acid_sequence',
                                         title='Sequence'),
                                 ])
     self.data_table.width = 1200
예제 #25
0
                fill_color='bar_color')
plot_dc.add_glyph(ColumnDataSource(dc_df), glyph_dc)
plot_dc.add_layout(
    LinearAxis(axis_label='Number of articles', **axis_defaults), 'left')
plot_dc.add_layout(
    CategoricalAxis(axis_label='Date',
                    major_label_orientation=pi / 2,
                    **axis_defaults), 'below')

# most popular table
pop_dt = DataTable(row_headers=False,
                   selectable=False,
                   sortable=True,
                   sizing_mode='scale_both')
pop_dt.columns = [
    TableColumn(field='rank', title='Rank', sortable=True, width=50),
    TableColumn(field='section_name',
                title='Section',
                sortable=True,
                width=150),
    TableColumn(field='pub_date', title='Date', sortable=True, width=150),
    TableColumn(field='headline', title='Headline', sortable=True),
    TableColumn(field='emails rank',
                title='Email rank',
                sortable=True,
                width=125),
    TableColumn(field='shares rank',
                title='Share rank',
                sortable=True,
                width=125),
    TableColumn(field='views rank',