Пример #1
0
        def modify_doc(doc):
            data = {'x': [1,2,3,4], 'y': [10,20,30,40]}
            source = ColumnDataSource(data)

            plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)
            plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data"))))

            table = DataTable(columns=[
                TableColumn(field="x"),
                TableColumn(field="y")
            ], source=source, editable=False)

            btn = Button(label="Click Me!", css_classes=["foo"])

            @btn.on_click
            def btn_click():
                source.data = {'x': [5,6,7,8], 'y': [50,60,70,80]}

            doc.add_root(column(plot, table, btn))
Пример #2
0
def plotExtra_table (decision_vars,dic,path2output):
    """
    This function returns a widgetbox that contains a table with the costs of
    each technology

    Parameters:
        decison_var:        list
                            Each list entry is a decison variable that should
                            be analyzed from the solution

        dic:                dict
                            Dictionary that contains the solution of the model

        path2output:        string
                            path where the widgetbox should be saved (obsolete)

    Results:
        table:              bokeh.layouts.widgetbox
    """
    data = []
    line =[]
    for decision_var in decision_vars:
        if type(dic[decision_var]) == dict:
            formatted_val = []
            for item in list(dic[decision_var].values()):
#                formatted_val.append("%.3e"%item)
                try:
                    formatted_val.append(str(EngNumber(item)))
                except:
                    formatted_val.append(str(item)) 

            line = [[decision_var] + formatted_val]
            data = data + line
    source = ColumnDataSource(pd.DataFrame(data, columns=["topic"]+list(dic["Technologies:"])))

    column0 = [TableColumn(field="topic", title="Topic")]
    columns = [TableColumn(field=x, title=x) for x in dic["Technologies:"]]
    columns = column0+columns

    data_table = DataTable(source=source, columns=columns, width=1200, height=500)
#    output_file(path2output+"\data_table.html")
    return widgetbox(data_table)
 def setup_table_columns(self):
   self.columns = [x['FIELD'] for x in self.col_config]
   tab_cols = []
   self.display_cols = []
   for i, col in enumerate(self.columns):
     dct_col = self.col_config[i]
     if dct_col['DISPLAY'] == 1:
       tab_cols.append(TableColumn(field=col, title=dct_col['TITLE']))
       self.display_cols.append(col)
   self.table_columns = tab_cols
   return
Пример #4
0
 def table(self):  # a very simple view of the data.
     src = self.source
     # Note : index position is None, as that index (not a column) seems not usable in plots...)
     table = DataTable(
         source=src,
         columns=[TableColumn(field=f, title=f) for f in src.column_names],
         sortable=False,
         reorderable=False,
         index_position=None,
     )  # , width=320, height=480)
     return table
Пример #5
0
def _make_complete_stats_tables(all_lang_stats):
    upos_df, text_df = stats_dict2table(all_lang_stats)
    df_tables = (upos_df.round(2), text_df.round(2))
    intervals = [
        'intervals_99', 'intervals_98', 'intervals_95', 'intervals_90',
        'intervals_85', 'intervals_80'
    ]
    cols_to_drop = intervals + [
        'intervals_99_low', 'intervals_98_low', 'intervals_95_low',
        'intervals_90_low', 'intervals_85_low', 'intervals_80_low', 'skew',
        'kurtosis'
    ]
    # separate and clean the data
    df_clean_tables = []
    for df in df_tables:
        for interval in intervals:
            df[[interval + '_low',
                interval + '_high']] = pd.DataFrame(df[interval].tolist(),
                                                    index=df.index)
        df = df.drop(columns=cols_to_drop).round(2)
        df_clean_tables.append(df)

    bk_tables = []

    def _get_title(col_name):
        if col_name == 'lang_code':
            return 'Code'
        elif col_name == 'lang_name':
            return 'Language'
        else:
            return col_name.replace('intervals_',
                                    '').replace('_high',
                                                '').replace('_low', '')

    def _get_width(col_name):
        if col_name == 'lang_code':
            return 60
        elif col_name == 'lang_name':
            return 140
        else:
            return 50

    for table in df_clean_tables:
        columns = [
            TableColumn(field=Ci, title=_get_title(Ci), width=_get_width(Ci))
            for Ci in table.columns
        ]  # bokeh columns
        data_table = DataTable(columns=columns,
                               source=ColumnDataSource(table),
                               sizing_mode='stretch_width',
                               fit_columns=False)  # bokeh table
        bk_tables.append(data_table)

    return bk_tables
Пример #6
0
 def preview_input_df(self):
     # https://stackoverflow.com/questions/40942168/how-to-create-a-bokeh-datatable-datetime-formatter
     columns = [
         TableColumn(field=Ci, title=Ci, width=DATATABLE_PREVIEW_COL_WIDTH)
         for Ci in self.input_df.columns
     ]
     self.data_table.update(columns=columns)
     self.data_table.update(
         source=ColumnDataSource(self.input_df.head(DF_NUM_PREVIEW_ROWS)))
     self.data_table.visible = True
     self.data_preview_paragraph.visible = True
Пример #7
0
def app_catalogs():
    global blc
    global trc
    global im
    if blc is None or trc is None or im is None: load_image()

    searchString = '{} {}'.format(np.mean([blc[0], trc[0]]),
                                  np.mean([blc[1], trc[1]]))
    catalogData = Catalogs.query_object(searchString,
                                        radius=0.2,
                                        catalog="GAIAdr2")

    # get plot
    p = make_base_bokeh()

    source = ColumnDataSource(catalogData.to_pandas())
    p.scatter('ra',
              'dec',
              source=source,
              legend="GAIA DR2",
              alpha=0.7,
              size=10)

    # Add hover tooltip for GAIA data
    tooltip = [("RA", "@ra"), ("Dec", "@dec"), ("Desig.", "@designation"),
               ("parallax", "@parallax"),
               ("phot_g_mean_mag", "@phot_g_mean_mag")]
    p.add_tools(HoverTool(tooltips=tooltip))

    p.legend.click_policy = "hide"

    # Table data
    columns = []
    for col in catalogData.to_pandas().columns:
        if col not in ('ra', 'dec', 'designation', 'parallax'):
            continue
        columns.append(TableColumn(field=col, title=col))
    data_table = DataTable(source=source,
                           columns=columns,
                           width=1200,
                           height=280)

    # Fails to load anything
    # script, div_dict = components({'plot': p, 'table': widgetbox(data_table)})
    # return render_template('catalogs.html', script=script, div=div_dict)

    # Fails to load table
    # script1, div1 = components(p)
    # script2, div2 = components(widgetbox(data_table))
    # return render_template('catalogs.html', script1=script1, div1=div1, script2=script2, div2=div2)

    # No table
    script, div = components(p)
    return render_template('base.html', script=script, plot=div)
Пример #8
0
    def add_data_table(self, source_label, columns='all', **kwargs):

        self._validate_workflow('add_data_table')

        source = self.columndatasources[source_label]

        if isinstance(columns, (list, tuple)):
            columns = {
                k: max([len(str(val)) for val in v] + [len(k)])
                for k, v in source.data.items() if k in columns
            }
        else:
            if columns == 'all':
                omit_cols = ('xsf', 'ysf', 'xsp', 'ysp')
            elif columns == 'point':
                omit_cols = ('xsf', 'ysf', 'xsp', 'ysp', 'raw_data')
            elif columns == 'raw_data':
                omit_cols = ('xsf', 'ysf', 'xsp', 'ysp', 'x_coord_point',
                             'y_coord_point')
            elif columns == 'meta':
                omit_cols = ('xsf', 'ysf', 'xsp', 'ysp', 'x_coord_point',
                             'y_coord_point', 'raw_data')
            else:
                omit_cols = list()

            columns = {
                k: max([len(str(val)) for val in v] + [len(k)])
                for k, v in source.data.items() if k not in omit_cols
            }

        default_kw = {
            'editable': False,
            'index_position': None,
            'reorderable': True,
            'scroll_to_selection': True,
            'selectable': 'checkbox',
            'sortable': True,
            'fit_columns': False
        }

        for k, v in default_kw.items():
            if k not in kwargs.keys():
                kwargs[k] = v

        data_table = DataTable(source=source,
                               columns=[
                                   TableColumn(field=k, title=k, width=v * 8)
                                   for k, v in columns.items()
                               ],
                               **kwargs)

        self.data_tables.append(data_table)

        return self
Пример #9
0
def create_not_normalize_plot(df):
	"""Crea tabla de variables afectando en cada tipo de calidad de agua con valores sin normalizar
	
	Parameters:
		df (Dataframe): Dataframe con los datos a mostrar en la visualización

	Returns:
		DataTable: Tabla de variables afectando en cada tipo de calidad de agua con valores sin normalizar
	"""
	units = 4*["tuni1","tuni2","tuni3","tuni4","tuni5","tuni6","tuni7","tuni8","tuni9","tuni10"]
	source = ColumnDataSource(df.assign(Units=units))
	columns = [
		TableColumn(field='cluster', title='Cluster', width=20),
		TableColumn(field='Indicador', title='Indicador (promedio)', width=72),
		TableColumn(field='valor', title='Valor', width=30),
		TableColumn(field='Units', title='Unidad', width=30)
	]

	data_table = DataTable(source=source, columns=columns, selectable=False, sizing_mode='stretch_width', max_width=650, height=200)

	return data_table
Пример #10
0
        def modify_doc(doc):
            data = {'x': [1, 2, 3, 4], 'y': [10, 20, 30, 40]}
            source = ColumnDataSource(data)

            plot = Plot(plot_height=400,
                        plot_width=400,
                        x_range=Range1d(0, 1),
                        y_range=Range1d(0, 1),
                        min_border=0)
            plot.add_tools(
                CustomAction(callback=CustomJS(args=dict(s=source),
                                               code=RECORD("data", "s.data"))))

            table = DataTable(columns=[
                TableColumn(field="x"),
                TableColumn(field="y", editor=NumberEditor())
            ],
                              source=source,
                              editable=True)

            doc.add_root(column(plot, table))
def create_age_gender_stats_subtab():
    source_df, source_CDS = get_line_list_analysis()

    columns = [
        TableColumn(field='age_group', title='Age Group'),
        TableColumn(field='gender', title='Gender'),
        TableColumn(field='proportion',
                    title='Fraction of Cases',
                    formatter=NumberFormatter(format='0.00%')),
        TableColumn(field='death_rate',
                    title='Death Rate',
                    formatter=NumberFormatter(format='0.00%'))
    ]

    data_table = DataTable(columns=columns,
                           source=source_CDS,
                           sizing_mode='stretch_height')

    child = row(column([data_table]))

    return Panel(child=child, title='Infection Statistics by Age & Gender')
Пример #12
0
def make_table(editor, values):
    source = ColumnDataSource({'values': values})
    column = TableColumn(field='values', title='values', editor=editor())
    table = DataTable(source=source,
                      columns=[column],
                      editable=True,
                      width=600)
    # this is triggered on selection changes
    source.selected.js_on_change(
        'indices',
        CustomJS(args=dict(s=source), code=RECORD("values", "s.data.values")))
    return table
Пример #13
0
 def loadData(self):
     self.graph.getFromDB(self.sqlsession)
     # reregister select callback
     self.graph.renderer.node_renderer.data_source.on_change(
         'selected', self.nodeSelectCallback)
     self.graph.renderer.node_renderer.data_source.trigger(
         'selected', [],
         self.graph.renderer.node_renderer.data_source.selected)
     '''Data Table'''
     col = self.graph.renderer.node_renderer.data_source
     colnames = [TableColumn(field=k, title=k) for k in col.data.keys()]
     self.dTable = DataTable(source=col, columns=colnames)
Пример #14
0
def create_table(data, filename, width=1400, height=300):
    source = ColumnDataSource(data)
    column_list = []
    for column in source.column_names:
        column_list.append(
            TableColumn(field=column, title=column.split('|')[0]))

    data_table = DataTable(source=source,
                           columns=column_list,
                           sizing_mode='scale_both',
                           width=width,
                           height=height)
    return data_table
Пример #15
0
    def _draw(self):
        d = self._gene_data

        for condition in self._conditions:
            d[condition] = [
                self._condition_data[condition][
                    self._condition_data["Sample"].index(sample)]
                for sample in d["Sample"]
                if sample in self._condition_data["Sample"]
            ]

        template_update_1 = '<% if (value === "True") {print(\'<div style="height: 20px; width: 20px; background-color:'
        template_update_2 = ';"></div>\')} %>'

        def make_template(color):
            return template_update_1 + str(color) + template_update_2

        template_update_1_esc = template_update_1.replace("'", "\\'")
        template_update_2_esc = template_update_2.replace("'", "\\'")

        formatters = [
            HTMLTemplateFormatter(template=make_template(
                color=self._color_pickers[cond].color))
            for cond in self._conditions
        ]

        condition_columns = [
            TableColumn(field=cond, title=cond, formatter=form, width=10)
            for cond, form in zip(self._conditions, formatters)
        ]
        columns = [
            TableColumn(field="Sample", title="Sample", width=200),
            TableColumn(field="Gene", title="Gene", width=10),
            TableColumn(field="R1", title="R1"),
            TableColumn(field="R2", title="R2"),
            TableColumn(field="R3", title="R3"), *condition_columns
        ]

        dt = DataTable(source=ColumnDataSource(d),
                       columns=columns,
                       width_policy="fit")

        code = f"form.template = '{template_update_1_esc}' + cp.color + '{template_update_2_esc}'; dt.change.emit();"

        for cp, formatter, col in zip(self._color_pickers.values(), formatters,
                                      condition_columns):
            cp.js_on_change(
                "color",
                CustomJS(args={
                    "cp": cp,
                    "col": col,
                    "form": formatter,
                    "dt": dt
                },
                         code=code))

        self._root.children.append(dt)

        dt.source.patch({})
Пример #16
0
    def __create_product_histogram_table(self, source):
        """Function creates and returns DataTable based on provided DataSource source.

            Provided source should be a ColumnDataSource including two parameters in it's .data dictionary:
                - index
                - .product attribute
            DataTable is created and this data is incorporated into it as "Product" and "Buy Count" columns
            appropriately. This Table generally shows how many

            DataTable has it's index column (counter) removed for clarity.

            Returns DataTable.
        """

        columns = [
            TableColumn(field="index", title="Product"),
            TableColumn(field=self.product, title="Buy Count")
        ]

        dt = DataTable(source=source, columns=columns, header_row=True, index_position=None)

        return dt
Пример #17
0
        def modify_doc(doc):

            plot = Plot(plot_height=400,
                        plot_width=400,
                        x_range=Range1d(0, 1),
                        y_range=Range1d(0, 1),
                        min_border=0)
            plot.add_tools(
                CustomAction(callback=CustomJS(args=dict(s=source),
                                               code=RECORD("data", "s.data"))))

            table = DataTable(columns=[
                TableColumn(field="x", title="x", sortable=True),
                TableColumn(field="y",
                            title="y",
                            sortable=True,
                            editor=NumberEditor())
            ],
                              source=source,
                              editable=True)

            doc.add_root(column(plot, table))
Пример #18
0
        def modify_doc(doc):
            plot = Plot(plot_height=400,
                        plot_width=400,
                        x_range=Range1d(0, 1),
                        y_range=Range1d(0, 1),
                        min_border=0)

            table = DataTable(columns=[
                TableColumn(field="x", title="x", sortable=True),
                TableColumn(field="y",
                            title="y",
                            sortable=True,
                            editor=NumberEditor())
            ],
                              source=source,
                              editable=True)

            def cb(attr, old, new):
                result.append("CALLED")

            source.on_change('data', cb)
            doc.add_root(column(plot, table))
Пример #19
0
    def test_server_source_callback_triggered_after_edit(
            self, bokeh_server_page: BokehServerPage) -> None:
        data = {'x': [1, 2, 5, 6], 'y': [60, 50, 20, 10]}
        source = ColumnDataSource(data)

        table = DataTable(columns=[
            TableColumn(field="x", title="x", sortable=True),
            TableColumn(field="y",
                        title="y",
                        sortable=True,
                        editor=NumberEditor())
        ],
                          source=source,
                          editable=True)

        result = []

        def modify_doc(doc):
            plot = Plot(height=400,
                        width=400,
                        x_range=Range1d(0, 1),
                        y_range=Range1d(0, 1),
                        min_border=0)

            def cb(attr, old, new):
                result.append("CALLED")

            source.on_change('data', cb)
            doc.add_root(column(plot, table))

        page = bokeh_server_page(modify_doc)

        assert result == []

        cell = get_table_cell(page.driver, table, 3, 2)
        assert cell.text == '20'
        enter_text_in_cell(page.driver, table, 3, 2, '100')

        assert result == ["CALLED"]
Пример #20
0
    def test_click_nonsortable(self, bokeh_model_page: BokehModelPage) -> None:
        data = {'x': [1,2,3,4], 'y': [4, 3, 2, 1], 'd': ['foo', 'bar', 'baz', 'quux']}
        source = ColumnDataSource(data)
        table = DataTable(columns=[
            TableColumn(field="x", title="x"),
            TableColumn(field="y", title="y", sortable=False),
            TableColumn(field="d", title="d", sortable=True),
        ], source=source)

        page = bokeh_model_page(table)

        for i, x in enumerate(['foo', 'bar', 'baz', 'quux'], 1):
            elt = get_table_cell(page.driver, table, i, 3)
            assert elt.text == x

        h3 = get_table_header(page.driver, table, 3)
        h3.click()

        for i, x in enumerate(['foo', 'bar', 'baz', 'quux'], 1):
            elt = get_table_cell(page.driver, table, i, 3)
            assert elt.text == x

        assert page.has_no_console_errors()
    def save_df_as_image(df: 'DataFrame', path: str, height: int = 1400, width: int = 700) -> None:
        """Saves the given DataFrame as a PNG image"""

        source = ColumnDataSource(df)
        df_columns = [df.index.name]
        df_columns.extend(df.columns.values)
        columns_for_table=[]
        for column in df_columns:
            # Adding all TableColumn props
            columns_for_table.append(TableColumn(field=column, title=column))

        # Preparing Bokeh table with all TableColumns
        data_table = DataTable(source=source, columns=columns_for_table, height = height, width = width, height_policy="auto", width_policy="auto", index_position=None)
        export_png(data_table, filename = path)
Пример #22
0
    def make_data_source(self):
        if self.dynamic:
            ck = self.columns_kwargs
            columns = [
                TableColumn(field=column, title=column, **ck.get(column, {}))
                for column in self.df.columns
            ]

            self.dt.columns = columns

        self.shown_df = self.df

        if not self.keep_selections:
            self.source.selected.indices = []
Пример #23
0
    def __columns(self):
        width = self.__theme.width
        fmt = DpxNumberFormatter(format=self.__theme.zformat,
                                 text_align='right')
        dim = self.__tasks.instrumentdim

        def _rep(ind):
            title = self.__theme.columns[ind]
            if 'm)' in title:
                title = title.split('(')[0] + f' ({dim})'
            return title

        return [
            TableColumn(field='bases',
                        title=_rep(0),
                        editor=IntEditor(),
                        width=width // 2),
            TableColumn(field='z',
                        title=_rep(1),
                        editor=NumberEditor(step=self.__theme.zstep),
                        formatter=fmt,
                        width=width // 2)
        ]
Пример #24
0
def save_df_as_image(df, path):
    source = ColumnDataSource(df)
    df_columns = []
    df_columns.extend(df.columns.values)
    columns_for_table = []
    for column in df_columns:
        columns_for_table.append(TableColumn(field=column, title=column))

    data_table = DataTable(source=source,
                           columns=columns_for_table,
                           index_position=None,
                           width=1600,
                           height=280)
    export_png(data_table, filename=path)
Пример #25
0
    def test_glyph_selection_updates_table(self, single_plot_page) -> None:
        plot = Plot(height=800, width=1000)

        data = {'x': [1,2,3,4], 'y': [1, 1, 1, 1]}
        source = ColumnDataSource(data)
        table = DataTable(columns=[
            TableColumn(field="x", title="x", sortable=True),
            TableColumn(field="y", title="y", sortable=True, editor=NumberEditor())
        ], source=source, editable=True)

        plot.add_glyph(source, Rect(x='x', y='y', width=1.5, height=1))
        plot.add_tools(TapTool(callback=CustomJS(code=RECORD("indices", "cb_data.source.selected.indices"))))

        page = single_plot_page(column(plot, table))

        page.click_canvas_at_position(500, 400)
        assert set(page.results["indices"]) == {1, 2}

        assert get_table_selected_rows(page.driver) == {1, 2}

        assert page.has_no_console_errors()

        assert page.has_no_console_errors()
Пример #26
0
        def _fill_variables_table(self):
            self.vars_short_names = list(self.meta_variables.keys())

            vars_names = list(map(self.to_long_name, self.vars_short_names))
            vars_dims = list(
                map(
                    lambda v: ", ".join(
                        list(map(self.to_long_name, v["shape"]))),
                    self.meta_variables.values()))
            self.vars_data = dict(
                names=vars_names,
                dims=vars_dims,
            )
            self.vars_source = ColumnDataSource(self.vars_data)
            vars_columns = [
                TableColumn(field="names", title="Variable name"),
                TableColumn(field="dims", title="Variable dimensions"),
            ]
            self.vars_table = DataTable(source=self.vars_source,
                                        columns=vars_columns,
                                        width=600,
                                        height=350,
                                        selectable=True)
Пример #27
0
def mnist_cm():
    label = int(request.args.get('label', '-1'))
    if label == -1:
        return "label not found", 404
    pred = int(request.args.get('pred', '-1'))
    if pred == -1:
        return "pred not found", 404
    ##### セッションデータ読み込み開始
    user_id = session.get('user_id', str(uuid.uuid4()))
    session['user_id'] = user_id
    user = User.query.get(user_id)
    target_data = pd.DataFrame()
    if user is None:
        user = User(id=user_id, csv_data=pd.DataFrame().to_json())
        db.session.add(user)
        db.session.commit()

    try:
        target_data = pd.read_json(user.csv_data)
    except Exception as e:
        warn = str(e)

    df_columns = target_data.columns.tolist()
    # 正解ラベルカラムと推論ラベルカラムの読み込み
    label_column = session.get('label_column', '')
    pred_column = session.get('pred_column', '')
    cm = target_data[target_data[label_column]==label & target_data[pred_column]==pred]

    table_columns = []
    for column in cm.columns.tolist():
        table_columns.append(TableColumn(field=column, title=column))

    source = ColumnDataSource(data = cm)
    table =DataTable(source=source,selectable = True, columns=table_columns,
                sortable = True)
    layout_disp = table
    # render template
    script, div = components(layout_disp)
    return render_template(
        'index.html.j2',
        warn=warn,
        columns=df_columns,
        label_column=label_column,
        pred_column=pred_column,
        plot_script=script,
        plot_div=div,
        js_resources=js_resources,
        css_resources=css_resources,
    )
Пример #28
0
    def setup_method(self):
        source = ColumnDataSource({'values': self.values})
        column = TableColumn(field='values',
                             title='values',
                             editor=self.editor())
        self.table = DataTable(source=source,
                               columns=[column],
                               editable=True,
                               width=600)

        # this is triggered on selection changes
        source.selected.js_on_change(
            'indices',
            CustomJS(args=dict(s=source),
                     code=RECORD("values", "s.data.values")))
Пример #29
0
    def create_table(self) -> None:
        """
        Creates the bokeh table and populates variable data.
        """
        x_vals = [self._labels[var] for var in self._output_values.keys()]
        y_vals = list(self._output_values.values())

        table_data = dict(x=x_vals, y=y_vals)
        self._source = ColumnDataSource(table_data)
        columns = [
            TableColumn(
                field="x",
                title="Variable",
                formatter=StringFormatter(font_style="bold"),
            ),
            TableColumn(field="y", title="Current Value"),
        ]

        self.table = DataTable(
            source=self._source,
            columns=columns,
            sizing_mode="stretch_both",
            index_position=None,
        )
Пример #30
0
def modify_doc(doc):
    satellite = TextInput(title="Satellite:", value="TELSTAR 12V")
    tle1 = TextInput(title="TLE line 1:", value="1 41036U 15068A   18304.93002776 -.00000131  00000-0  00000-0 0  9990")
    tle2 = TextInput(title="TLE line 2:", value="2 41036   0.0170 254.0407 0001996 337.8139 128.1274  1.00270199 10707")

    maneuvers = ColumnDataSource(data=
                                 {"date": [datetime(2002, month=5, day=5, hour=12, minute=0, second=0, microsecond=0,
                                                    tzinfo=timezone.utc),
                                           datetime(2002, month=5, day=6, hour=12, minute=0, second=0, microsecond=0,
                                                    tzinfo=timezone.utc),
                                           datetime(2002, month=5, day=7, hour=12, minute=0, second=0, microsecond=0,
                                                    tzinfo=timezone.utc)],
                                  "deltaV_X": [100, 0, 0],
                                  "deltaV_Y": [0, 100, 0],
                                  "deltaV_Z": [0, 0, 100],
                                  "isp": [300, 300, 300]})
    maneuvers_table = DataTable(source=maneuvers, columns=[TableColumn(field="date", title="date"),
                                                           TableColumn(field="deltaV_X", title="deltaV_X"),
                                                           TableColumn(field="deltaV_Y", title="deltaV_Y"),
                                                           TableColumn(field="deltaV_Z", title="deltaV_Z")],
                                editable=True)

    ephemeris = ColumnDataSource()

    def recompute():
        compute(ephemeris, tle1.value, tle2.value)

    recompute()
    fig_long_sma = create_figure(x='longitude', y='a', source=ephemeris, title="SMA vs longitude")
    fig_ex_ey = create_figure(x='ex', y='ey', source=ephemeris, title="ex ey")
    fig_hx_hy = create_figure(x='hx', y='hy', source=ephemeris, title="hx hy")

    recompute_button = Button(label="Recompute")
    recompute_button.on_click(recompute)
    doc.add_root(layout([[widgetbox(satellite, tle1, tle2, recompute_button), widgetbox(maneuvers_table)],
                         [fig_long_sma, fig_ex_ey, fig_hx_hy]]))