Beispiel #1
0
    def read_file_tab(self):

        """Lets the user choose a data file to read"""

        # Drop down list
        self.file_select = Select(name='Data files',
                                  value='',
                                  options=[],
                                  title='Data files')
        # Status text
        self.file_status = Div(text='', width=self.page_width)

        # Update the file_select and file_status controls with scan data
        self.scan_folder()

        # This line is here deliberately. The scan_folder would trigger
        # the on-change function and we don't want that first time around.
        self.file_select.on_change('value', self.file_changed)

        # Re-scan button
        file_rescan = Button(label="Rescan folder", button_type="success")
        file_rescan.on_click(self.scan_folder)

        # Layout
        c = column(self.file_select,
                   self.file_status,
                   file_rescan)

        return Panel(child=c, title="Read from file")
Beispiel #2
0
    def __init__(self, ut330):

        self.ut330 = ut330

        self.device_name = TextInput(title="Device name")

        self.device_time = TextInput(title="Device time")
        self.computer_time = TextInput(title="Computer time")

        self.t_high = TextInput(title="High temperature alarm (C)")
        self.t_low = TextInput(title="Low temperature alarm (C)")
        self.h_high = TextInput(title="High humidity alarm (%RH)")
        self.h_low = TextInput(title="Low humidity alarm (%RH)")
        self.p_high = TextInput(title="High pressure alarm")
        self.p_low = TextInput(title="Low pressure alarm")

        self.sampling = TextInput(title="Sampling interval (s)")
        self.overwrite_records = Select(title="Overwrite records",
                                        options=['False', 'True'])

        self.delay_start = Select(title="Delay start",
                                  options=['No delay', 'Delay'])
        self.delay = TextInput(title="Delay (s)")

        self.power = TextInput(title="Battery power (%)")
        self.readings = TextInput(title="Readings")

        self.read_config = Button(label='Read config')
        self.write_config = Button(label='Write config')
Beispiel #3
0
    def run(self):
        """ Start the CLI logic creating the input source, data conversions,
        chart instances to show and all other niceties provided by CLI
        """
        try:
            self.limit_source(self.source)

            children = []
            if self.smart_filters:
                copy_selection = Button(label="copy current selection")
                copy_selection.on_click(self.on_copy)
                children.append(copy_selection)

            self.chart = create_chart(
                self.series, self.source, self.index, self.factories,
                self.map_options, children=children, **self.chart_args
            )
            self.chart.show()

            self.has_ranged_x_axis = 'ranged_x_axis' in self.source.columns
            self.columns = [c for c in self.source.columns if c != 'ranged_x_axis']

            if self.smart_filters:
                for chart in self.chart.charts:
                    chart.source.on_change('selected', self, 'on_selection_changed')
                self.chart.session.poll_document(self.chart.doc)

        except TypeError:
            if not self.series:
                series_list = ', '.join(self.chart.values.keys())
                print(hm.ERR_MSG_TEMPL % series_list)
                raise

        if self.sync_with_source:
            keep_source_input_sync(self.input, self.update_source, self.last_byte)
	def mass_plotting(self, filename):


		data_dict = self.data_generation(filename)
		self.data_test(data_dict)
		name_check = data_dict["gen_info"]["DATA FILES"]
		attr_id = name_check[1][4][:-3] + "_" + name_check[2][2]

		TOOLS="pan,wheel_zoom,box_zoom,reset, hover, previewsave"
		figure_obj = figure(plot_width = 1000, plot_height = 800, y_axis_type = "log",
			title = attr_id, tools = TOOLS)

		figure_obj.yaxis.axis_label = data_dict["data"][0]["y_unit"]
		figure_obj.xaxis.axis_label = data_dict["data"][0]["x_unit"]

		hover = figure_obj.select(dict(type = HoverTool))
		hover.tooltips=[("Value:", "$top")]

		hist, edges = np.histogram(data_dict["data"][0]["y"],  bins = data_dict["data"][0]["x"])
		source = ColumnDataSource(data = dict(top = hist, left = edges[:-1], right = edges[1:], 
					x_unit = data_dict["data"][0]["x_unit"], y_unit = data_dict["data"][0]["y_unit"],
					edges = edges))
		#hist = figure_obj.Histogram(source )
		figure_obj.quad(top = "top", bottom = 0, left = "left" , right = "right", source = source)

		matplot_button = Button(label = "create matplotlib plot")

		matplot_button.on_click(lambda source_list = source:
							self.matplotlib_export_ms(source_list))


		return Panel(child = hplot(figure_obj, matplot_button), title = attr_id)
Beispiel #5
0
    def __init__(self, ut330):

        self.ut330 = ut330

        self.source = ColumnDataSource(data=dict(ts=[], t=[], h=[]))

        self.plot = figure(x_axis_type="datetime")
        self.plot.title = "Temperature and humidity vs. time"

        self.plot.line(x="ts",
                       y="t",
                       source=self.source,
                       color="blue",
                       legend="Temperature",
                       line_width=2)

        self.plot.xaxis.axis_label = "Timestamp"
        self.plot.yaxis.axis_label = "Temperature (C)"

        self.plot.extra_y_ranges = {"humidity": Range1d(0, 100)}

        self.plot.line(x="ts",
                       y="h",
                       source=self.source,
                       y_range_name="humidity",
                       color="green",
                       legend="Humidity",
                       line_width=2)

        self.plot.add_layout(LinearAxis(y_range_name="humidity",
                                        axis_label="Relative humidity (%)"),
                             'right')

        self.read = Button(label='Read data')
        self.delete = Button(label='Delete data')
Beispiel #6
0
def button_print_page():
    """Button to print currently displayed webpage to paper or pdf.

    Notes
    -----
    * Available styles: 'default', 'primary', 'success', 'warning', 'danger'
    """
    button = Button(label="Print this page", button_type="success")
    button.callback = CustomJS(code="""print()""")
    return widgetbox(button)
Beispiel #7
0
class Offsets_Panel(object):

    def __init__(self, ut330):

        self.ut330 = ut330

        self.t_current = TextInput(title="Temperature current")
        self.h_current = TextInput(title="Humidity current")
        self.p_current = TextInput(title="Pressure current")

        self.t_offset = TextInput(title="Temperature offset")
        self.h_offset = TextInput(title="Humidity offset")
        self.p_offset = TextInput(title="Pressure offset")

        self.read_offsets = Button(label='Read offsets')
        self.write_offsets = Button(label='Write offsets')

    def _layout_(self):
        return VBox(HBox(self.t_current, self.t_offset, width=500),
                    HBox(self.h_current, self.h_offset, width=500),
                    HBox(self.p_current, self.p_offset, width=500),
                    HBox(self.read_offsets, self.write_offsets, width=500))

    def panel(self):

        return Panel(child=self._layout_(), title="Offsets")

    def _read_(self):

        offsets = self.ut330.read_offsets()

        self.t_current.value = str(offsets['temperature'])
        self.h_current.value = str(offsets['humidity'])
        self.p_current.value = str(offsets['pressure'])

        self.t_offset.value = str(offsets['temperature offset'])
        self.h_offset.value = str(offsets['humidity offset'])
        self.p_offset.value = str(offsets['pressure offset'])

    def _write_(self):

        offsets = {'temperature offset': float(self.t_offset.value),
                   'humidity offset': float(self.h_offset.value),
                   'pressure offset': float(self.p_offset.value)}

        self.ut330.write_offsets(offsets)

    def callbacks(self):

        self.read_offsets.on_click(self._read_)
        self.write_offsets.on_click(self._write_)

    def device_read(self):

        self._read_()
Beispiel #8
0
def make_layout():
    plot, source = make_plot()
    columns = [
        TableColumn(field="dates", title="Date", editor=DateEditor(), formatter=DateFormatter()),
        TableColumn(field="downloads", title="Downloads", editor=IntEditor()),
    ]
    data_table = DataTable(source=source, columns=columns, width=400, height=400, editable=True)
    button = Button(label="Randomize data", button_type="success")
    button.on_click(click_handler)
    buttons = WidgetBox(children=[button],width=800)
    column = Column(children=[buttons, plot, data_table])
    return column
Beispiel #9
0
def make_layout():
    plot, source = make_plot()
    columns = [
        TableColumn(field="dates", title="Date"),
        TableColumn(field="downloads", title="Downloads"),
    ]
    data_table = DataTable(source=source, columns=columns, width=400, height=400)
    button = Button(label="Randomize data", type="success")
    button.on_click(click_handler)
    buttons = VBox(children=[button])
    vbox = VBox(children=[buttons, plot, data_table])
    return vbox
Beispiel #10
0
def button_save_table(table):
    """Button to save selected data table as csv.

    Notes
    -----
    * Does not work for column values containing tuples (like 'neighbors')
    * Currently columns being saved are hard coded in the javascript callback
    * Available styles: 'default', 'primary', 'success', 'warning', 'danger'
    """
    button = Button(label="Download selected data", button_type="success")
    button.callback = CustomJS(args=dict(source=table.source),
                               code=open(join(dirname(__file__),
                                              "js/download_data.js")).read())
    return widgetbox(button)
Beispiel #11
0
    def __init__(self, ut330):

        self.ut330 = ut330

        self.t_current = TextInput(title="Temperature current")
        self.h_current = TextInput(title="Humidity current")
        self.p_current = TextInput(title="Pressure current")

        self.t_offset = TextInput(title="Temperature offset")
        self.h_offset = TextInput(title="Humidity offset")
        self.p_offset = TextInput(title="Pressure offset")

        self.read_offsets = Button(label='Read offsets')
        self.write_offsets = Button(label='Write offsets')
Beispiel #12
0
    def offset_tab(self):

        """Reading/writing device offsets"""

        # True if the offset device data has been read, false otherwise
        self.offset_device_read = False

        offset_status_h = Div(text="<strong>Status</strong>")
        self.offset_status = Div(text="", width=self.page_width)

        # Connect to device button
        # ========================
        offset_controls_h = Div(text="<strong>Device controls</strong>")
        offset_connect = Button(label='Connect to UT330',
                                button_type="success")
        offset_read = Button(label='Read offset', button_type="success")
        offset_write = Button(label='Write offset', button_type="success")
        offset_disconnect = Button(label='Disconnect from UT330',
                                   button_type="success")

        offset_connect.on_click(self.offset_connect)
        offset_read.on_click(self.offset_read)
        offset_write.on_click(self.offset_write)
        offset_disconnect.on_click(self.offset_disconnect)

        # Offsets
        # =======
        offset_offsets_h = Div(text="<strong>Offsets</strong>")
        self.offset_t_current = TextInput(title="Temperature current")
        self.offset_h_current = TextInput(title="Humidity current")
        self.offset_p_current = TextInput(title="Pressure current")

        self.offset_t = TextInput(title="Temperature offset")
        self.offset_h = TextInput(title="Humidity offset")
        self.offset_p = TextInput(title="Pressure offset")

        # Values to widgets
        # =================
        if self.device_connected:
            self.offset_connected()
        else:
            self.offset_not_connected()

        if self.device_connected:
            self.offset_status.text = ('UT330 device connected. The Read, '
                                       'Write, and Disconnect buttons '
                                       'will work.')
        else:
            self.offset_status.text = ('UT330 device is <strong>NOT</strong> '
                                       'connected. The '
                                       'Read, Write, and Disconnect buttons '
                                       'will <strong>not work</strong>. '
                                       'Click the '
                                       'Connect button if the UT330 is '
                                       'connected on a USB port.')
        # Layout
        # ======
        l = layout([[offset_status_h],
                    [self.offset_status],
                    [offset_controls_h],
                    [offset_connect,
                     offset_read,
                     offset_write,
                     offset_disconnect],
                    [offset_offsets_h],
                    [self.offset_t_current,
                     self.offset_h_current,
                     self.offset_p_current],
                    [self.offset_t,
                     self.offset_h,
                     self.offset_p]],
                   width=self.page_width)

        return Panel(child=l,
                     title="Read/write offset")
Beispiel #13
0
              x_axis_type="log",
              x_axis_label='Time since end of outburst (days)',
              y_axis_label='Teff (eV)')
plot.line('x', 'y', source=source, line_width=2, line_alpha=0.6)

source2 = ColumnDataSource(data=dict(x=tobs, y=Teffobs))
plot.scatter('x',
             'y',
             source=source2,
             size=8,
             marker='circle',
             fill_color='red',
             line_color='black')

# Set up the controls
go_button = Button(label="Go", button_type="success")
go_button.on_click(button_handler)

def_button = Button(label="Defaults", button_type="default")
def_button.on_click(def_handler)

Q_slider = Slider(title="Qimp",
                  value=params['Qimp'],
                  start=0.0,
                  end=30.0,
                  step=0.1)
Q_slider.on_change('value', Q_slider_handler)

Tb_slider = Slider(title="Top temperature (1e8 K)",
                   value=params['Tb'] / 1e8,
                   start=0.3,
Beispiel #14
0
from __future__ import print_function

from bokeh.util.browser import view
from bokeh.document import Document
from bokeh.embed import file_html
from bokeh.resources import INLINE

from bokeh.models import CustomJS, WidgetBox
from bokeh.models.widgets import (
    Button, Toggle, Dropdown, CheckboxGroup, RadioGroup, CheckboxButtonGroup, RadioButtonGroup,
)

button = Button(label="Button (enabled) - has click event", button_type="primary")
button.js_on_click(CustomJS(code="console.log('button: click', this.toString())"))

button_disabled = Button(label="Button (disabled) - no click event", button_type="primary", disabled=True)
button_disabled.js_on_click(CustomJS(code="console.log('button_disabled: click', this.toString())"))

toggle_inactive = Toggle(label="Toggle button (initially inactive)", button_type="success")
toggle_inactive.js_on_click(CustomJS(code="console.log('toggle_inactive: ' + this.active, this.toString())"))

toggle_active = Toggle(label="Toggle button (initially active)", button_type="success", active=True)
toggle_active.js_on_click(CustomJS(code="console.log('toggle_active: ' + this.active, this.toString())"))

menu = [("Item 1", "item_1_value"), ("Item 2", "item_2_value"), None, ("Item 3", "item_3_value")]

dropdown = Dropdown(label="Dropdown button", button_type="warning", menu=menu)
dropdown.js_on_click(CustomJS(code="console.log('dropdown: ' + this.value, this.toString())"))

dropdown_disabled = Dropdown(label="Dropdown button (disabled)", button_type="warning", disabled=True, menu=menu)
dropdown_disabled.js_on_click(CustomJS(code="console.log('dropdown_disabled: ' + this.value, this.toString())"))
Beispiel #15
0
def bokeh_ajax(request):
    startDt = dfDict['time'][0].to_pydatetime()
    endDt = dfStatic['time'].iloc[-1].to_pydatetime()
    # note: need the below in order to display the bokeh plot
    jsResources = INLINE.render_js()
    # need the below in order to be able to properly interact with the plot and have the default bokeh plot
    # interaction tool to display
    cssResources = INLINE.render_css()

    source2 = ColumnDataSource(data={"time": [], "temperature": [], "id": []})
    livePlot2 = figure(x_axis_type="datetime",
                       x_range=[startDt, endDt],
                       y_range=(0, 25),
                       y_axis_label='Temperature (Celsius)',
                       title="Sea Surface Temperature at 43.18, -70.43",
                       plot_width=800)
    livePlot2.line("time", "temperature", source=source2)

    updateStartJS = CustomJS(args=dict(plotRange=livePlot2.x_range),
                             code="""
         var newStart = Date.parse(cb_obj.value)
         plotRange.start = newStart
         plotRange.change.emit()
     """)

    updateEndJS = CustomJS(args=dict(plotRange=livePlot2.x_range),
                           code="""
         var newEnd = Date.parse(cb_obj.value)
         plotRange.end = newEnd
         plotRange.change.emit()
     """)

    startInput = TextInput(value=startDt.strftime(dateFmt),
                           title="Enter Date in format: YYYY-mm-dd")
    startInput.js_on_change('value', updateStartJS)
    endInput = TextInput(value=endDt.strftime(dateFmt),
                         title="Enter Date in format: YYYY-mm-dd")
    endInput.js_on_change('value', updateEndJS)
    textWidgets = row(startInput, endInput)

    # https://stackoverflow.com/questions/37083998/flask-bokeh-ajaxdatasource
    # above stackoverflow helped a lot and is what the below CustomJS is based on

    callback = CustomJS(args=dict(source=source2),
                        code="""
        var time_values = "time";
        var temperatures = "temperature";
        var plot_data = source.data;

        jQuery.ajax({
            type: 'POST',
            url: '/AJAXdata2',
            data: {},
            dataType: 'json',
            success: function (json_from_server) {
                plot_data['temperature'] = plot_data['temperature'].concat(json_from_server['temperature']);
                plot_data['time'] = plot_data['time'].concat(json_from_server['time']);
                plot_data['id'] = plot_data['id'].concat(json_from_server['id']);
                source.change.emit();
            },
            error: function() {
                alert("Oh no, something went wrong. Search for an error " +
                      "message in Flask log and browser developer tools.");
            }
        });
        """)

    manualUpdate = Button(label="update graph", callback=callback)
    widgets = widgetbox([manualUpdate])
    # IMPORTANT: key is that the widget you want to control plot X has to be in the same layout object as
    # said plot X . Therefore, when you call the components() method on it both widget and plot live within the
    # object, if they are not then the JS callbacks don't work because I think they do not know how to communicate
    # with one another
    layout2 = column(widgets, textWidgets, livePlot2)
    script2, div2 = components(layout2)
    return {
        'someword': "hello",
        'jsResources': jsResources,
        'cssResources': cssResources,
        'script2': script2,
        'div2': div2
    }
Beispiel #16
0
        start_button.label = 'Start recording data'
        curdoc().remove_periodic_callback(callback_id)


filename = "readings " + str(datetime.datetime.now()) + ".csv"
f = open(filename, 'w+')
f.write(
    "Index,Date Stamp,Time Stamp,Channel 0,Channel 1,Channel 2,Channel 3,Channel 4,Channel 5,Channel 6,Channel 7\n"
)
f.close()
my_supply = rg()

file_control = TextInput(title='Name of save file', value=filename)
comment_box = TextInput(
    title='Annotation (Will be added when box is unselected)')
start_button = Button(label='Start recording data')
directory_control = TextInput(
    title='Absolute path to desired directory (Ex: /home/pi/Documents/)')
plot1 = figure(x_range=(0, 100),
               y_range=(0, 5),
               x_axis_label='Time (100 ms)',
               y_axis_label='Volts',
               title='Channel 0',
               plot_width=500,
               plot_height=200)
plot2 = figure(x_range=(0, 100),
               y_range=(0, 5),
               x_axis_label="Time (100 ms)",
               y_axis_label="Volts",
               title="Channel 1",
               plot_width=500,
Beispiel #17
0
def colorbar_slider(fig):
    '''
    Adds interactive sliders and text input boxes for the colorbar.
    Returns a layout object to be put into a gridplot
    '''
    cb = get_colorbar_renderer(fig)
    data = get_image_data(fig)
    data = reject_outliers_quick(data)
    datamin = nanmin(data)
    datamax = nanmax(data)
    im = get_glyph_renderer(fig) # Get image renderer

    from bokeh.models import CustomJS, Slider, TextInput
    from bokeh.models.widgets import Button
    from bokeh.layouts import widgetbox

    model = Slider() # trick it into letting datamin and datamax into CustomJS
    model.tags.append(datamin) # Hide these in here
    model.tags.append(datamax)

    callback_u = CustomJS(args=dict(cb=cb, im=im, model=model), code="""
        var cm = cb.color_mapper;
        var upp = upper_slider.get('value');
        upper_input.value = upp.toString()
        lower_slider.end = upp
        cm.high = upp;
        im.glyph.color_mapper.high = upp;
        if (cm.low >= cm.high){
        cm.low = upp/1.1 // to prevent limits being the same
        im.glyph.color_mapper.low = low/1.1;
        }
        if (upp > model.tags[1]){
            upper_slider.end = upp
        }
        """)

    callback_l = CustomJS(args=dict(cb=cb, im=im, model=model), code="""
        var cm = cb.color_mapper;
        var low = lower_slider.get('value');
        lower_input.value = low.toString()
        upper_slider.start = low
        cm.low = low;
        im.glyph.color_mapper.low = low;
        if (cm.high <=  cm.low){
        cm.high = low*1.1 // to prevent limits being the same
        im.glyph.color_mapper.high = low*1.1;
        }
        if (low < model.tags[0]){
            lower_slider.start = low
        }""")

    callback_ut = CustomJS(args=dict(cb=cb, im=im, model=model), code="""
        var cm = cb.color_mapper;
        var upp = parseFloat(upper_input.get('value'));
        upper_slider.value = upp
        cm.high = upp;
        im.glyph.color_mapper.high = upp;
        if (cm.low >=  cm.high){
        cm.low = upp/1.1 // to prevent limits being the same
        im.glyph.color_mapper.low = upp/1.1;
        }
        if (upp > model.tags[1]){
            upper_slider.end = upp
        }
        """)

    callback_lt = CustomJS(args=dict(cb=cb, im=im, model=model), code="""
        var cm = cb.color_mapper;
        var low = parseFloat(lower_input.get('value'));
        lower_slider.value = low
        cm.low = low;
        im.glyph.color_mapper.low = low;
        if (cm.high <=  cm.low){
        cm.high = low*1.1 // to prevent limits being the same
        im.glyph.color_mapper.high = low*1.1;
        }
        if (low < model.tags[0]){
            lower_slider.start = low
        }
        """)

    callback_reset_js = CustomJS(args=dict(cb=cb, im=im, model=model), code="""
        var cm = cb.color_mapper;
        var low = model.tags[0];
        var high = model.tags[1];
        low = parseFloat(low.toPrecision(3)) // 3 sig figs
        high = parseFloat(high.toPrecision(3)) // 3 sig figs
        lower_slider.value = low;
        lower_slider.set('step', (high-low)/50);
        cm.low = low;
        upper_slider.value = high;
        upper_slider.set('step', (high-low)/50);
        cm.high = high;
        im.glyph.color_mapper.low = low;
        im.glyph.color_mapper.high = high;
        lower_input.value = low.toString();
        upper_input.value = high.toString();
        lower_slider.start = low;
        lower_slider.end = high;
        upper_slider.start = low;
        upper_slider.end = high;
        model.trigger('change')
        cb_obj.trigger('change)')
    """)

    reset_button = Button(label='Reset', callback = callback_reset_js)

    def callback_reset(*args, **kwargs):
        from IPython.display import Javascript, display

        # display(callback_reset_js)
        # callback_reset_js.name = None
        # callback_reset_js.name = 'test'
        # display('Plot updated, press reset to rescale!')
        # cb.color_mapper.low = datamin
        # cb.color_mapper.high = datamax
        # im.glyph.color_mapper.low = datamin
        # im.glyph.color_mapper.high = datamax
        # lower_slider.start = datamin
        # lower_slider.end = datamax
        # lower_slider.value = datamin
        # upper_slider.start = datamin
        # upper_slider.end = datamax
        # lower_slider.value = datamax
        # lower_input.value = str(datamin)
        # upper_input.value = str(datamax)
        # update()
        # fig.text(x=0,y=0,text='Plot updated, press reset to rescale!')
        # reset_button.label='Reset: Data changed! Press me!'

    # reset_button.trigger('clicks',0,1)
    reset_button.on_click(callback_reset)

    # def callback_die(attr, old, new):
    #     from IPython.display import display
    #     display('yoooo')
    #     display(old)
    #     display(new)
    #     raise Exception()
    # exception_button = Button(label='KILL ME')
    # exception_button.on_click(callback_die)

    lower_slider = Slider(start=datamin, end=datamax, value=datamin, step=(datamax-datamin)/50, # smallest step is 1e-5
                        title="Lower lim", callback=callback_l)
    lower_slider.width=100

    upper_slider = Slider(start=datamin, end=datamax, value=datamax, step=(datamax-datamin)/50,
                         title="Upper lim", callback=callback_u)
    upper_slider.width=100

    lower_input = TextInput(callback=callback_lt, value = str(datamin), width=50)
    upper_input = TextInput(callback=callback_ut, value = str(datamax), width=50)

    # add all of these widgets as arguments to the callback functions
    for callback in ['l', 'u', 'lt', 'ut', 'reset_js']:
        for widget in ['lower_slider', 'upper_slider','lower_input','upper_input', 'reset_button']:
            exec('callback_%s.args["%s"] = %s' %(callback, widget, widget))

    wb = widgetbox([upper_slider, upper_input, lower_slider, lower_input, reset_button], width=100, sizing_mode = 'stretch_both')
    return wb
Beispiel #18
0
# open a session to keep our local document in sync with server
session = push_session(curdoc())

def start_handler():
    global playing
    if not playing:
        curdoc().add_periodic_callback(update, 50)
        playing = True

def stop_handler():
    global playing
    if playing:
        curdoc().remove_periodic_callback(update)
        playing = False

button_start = Button(label="Start", button_type="success")
button_start.on_click(start_handler)

button_stop = Button(label="Stop", button_type="danger")
button_stop.on_click(stop_handler)

controls = hplot(button_start, button_stop)
layout = vplot(controls, p)

@cosine(w=0.03)
def update(step):
    if playing:
        r2.data_source.data["y"] = y * step
        r2.glyph.line_alpha = 1 - 0.8 * abs(step)

playing = True
Beispiel #19
0
    def create_interact_ui(doc):
        # The data source includes metadata for hover-over tooltips
        lc_source = prepare_lightcurve_datasource(lc)
        tpf_source = prepare_tpf_datasource(tpf, aperture_mask)

        # Create the lightcurve figure and its vertical marker
        fig_lc, vertical_line = make_lightcurve_figure_elements(
            lc, lc_source, ylim_func=ylim_func)

        # Create the TPF figure and its stretch slider
        pedestal = -np.nanmin(tpf.flux.value) + 1
        if scale == 'linear':
            pedestal = 0
        fig_tpf, stretch_slider = make_tpf_figure_elements(tpf,
                                                           tpf_source,
                                                           pedestal=pedestal,
                                                           fiducial_frame=0,
                                                           vmin=vmin,
                                                           vmax=vmax,
                                                           scale=scale,
                                                           cmap=cmap,
                                                           tools=tools)

        # Helper lookup table which maps cadence number onto flux array index.
        tpf_index_lookup = {cad: idx for idx, cad in enumerate(tpf.cadenceno)}

        # Interactive slider widgets and buttons to select the cadence number
        cadence_slider = Slider(start=np.min(tpf.cadenceno),
                                end=np.max(tpf.cadenceno),
                                value=np.min(tpf.cadenceno),
                                step=1,
                                title="Cadence Number",
                                width=490)
        r_button = Button(label=">", button_type="default", width=30)
        l_button = Button(label="<", button_type="default", width=30)
        export_button = Button(label="Save Lightcurve",
                               button_type="success",
                               width=120)
        message_on_save = Div(text=' ', width=600, height=15)

        # Callbacks
        def _create_lightcurve_from_pixels(tpf,
                                           selected_pixel_indices,
                                           transform_func=transform_func):
            """Create the lightcurve from the selected pixel index list"""
            selected_indices = np.array(selected_pixel_indices)
            selected_mask = np.isin(pixel_index_array, selected_indices)
            lc_new = tpf.to_lightcurve(aperture_mask=selected_mask)
            lc_new.meta['aperture_mask'] = selected_mask
            if transform_func is not None:
                lc_transformed = transform_func(lc_new)
                if (len(lc_transformed) != len(lc_new)):
                    warnings.warn(
                        'Dropping cadences in `transform_func` is not '
                        'yet supported due to fixed time coordinates.'
                        'Skipping the transformation...', LightkurveWarning)
                else:
                    lc_new = lc_transformed
                    lc_new.meta['aperture_mask'] = selected_mask
            return lc_new

        def update_upon_pixel_selection(attr, old, new):
            """Callback to take action when pixels are selected."""
            # Check if a selection was "re-clicked", then de-select
            if ((sorted(old) == sorted(new)) & (new != [])):
                # Trigger recursion
                tpf_source.selected.indices = new[1:]

            if new != []:
                lc_new = _create_lightcurve_from_pixels(
                    tpf, new, transform_func=transform_func)
                lc_source.data['flux'] = lc_new.flux.value

                if ylim_func is None:
                    ylims = get_lightcurve_y_limits(lc_source)
                else:
                    ylims = ylim_func(lc_new)
                fig_lc.y_range.start = ylims[0]
                fig_lc.y_range.end = ylims[1]
            else:
                lc_source.data['flux'] = lc.flux.value * 0.0
                fig_lc.y_range.start = -1
                fig_lc.y_range.end = 1

            message_on_save.text = " "
            export_button.button_type = "success"

        def update_upon_cadence_change(attr, old, new):
            """Callback to take action when cadence slider changes"""
            if new in tpf.cadenceno:
                frameno = tpf_index_lookup[new]
                fig_tpf.select('tpfimg')[0].data_source.data['image'] = \
                    [tpf.flux.value[frameno, :, :] + pedestal]
                vertical_line.update(location=tpf.time.value[frameno])
            else:
                fig_tpf.select('tpfimg')[0].data_source.data['image'] = \
                    [tpf.flux.value[0, :, :] * np.NaN]
            lc_source.selected.indices = []

        def go_right_by_one():
            """Step forward in time by a single cadence"""
            existing_value = cadence_slider.value
            if existing_value < np.max(tpf.cadenceno):
                cadence_slider.value = existing_value + 1

        def go_left_by_one():
            """Step back in time by a single cadence"""
            existing_value = cadence_slider.value
            if existing_value > np.min(tpf.cadenceno):
                cadence_slider.value = existing_value - 1

        def save_lightcurve():
            """Save the lightcurve as a fits file with mask as HDU extension"""
            if tpf_source.selected.indices != []:
                lc_new = _create_lightcurve_from_pixels(
                    tpf,
                    tpf_source.selected.indices,
                    transform_func=transform_func)
                lc_new.to_fits(
                    exported_filename,
                    overwrite=True,
                    flux_column_name='SAP_FLUX',
                    aperture_mask=lc_new.meta['aperture_mask'].astype(np.int),
                    SOURCE='lightkurve interact',
                    NOTE='custom mask',
                    MASKNPIX=np.nansum(lc_new.meta['aperture_mask']))
                if message_on_save.text == " ":
                    text = '<font color="black"><i>Saved file {} </i></font>'
                    message_on_save.text = text.format(exported_filename)
                    export_button.button_type = "success"
                else:
                    text = '<font color="gray"><i>Saved file {} </i></font>'
                    message_on_save.text = text.format(exported_filename)
            else:
                text = '<font color="gray"><i>No pixels selected, no mask saved</i></font>'
                export_button.button_type = "warning"
                message_on_save.text = text

        def jump_to_lightcurve_position(attr, old, new):
            if new != []:
                cadence_slider.value = lc.cadenceno[new[0]]

        # Map changes to callbacks
        r_button.on_click(go_right_by_one)
        l_button.on_click(go_left_by_one)
        tpf_source.selected.on_change('indices', update_upon_pixel_selection)
        lc_source.selected.on_change('indices', jump_to_lightcurve_position)
        export_button.on_click(save_lightcurve)
        cadence_slider.on_change('value', update_upon_cadence_change)

        # Layout all of the plots
        sp1, sp2, sp3, sp4 = (Spacer(width=15), Spacer(width=30),
                              Spacer(width=80), Spacer(width=60))
        widgets_and_figures = layout([fig_lc, fig_tpf], [
            l_button, sp1, r_button, sp2, cadence_slider, sp3, stretch_slider
        ], [export_button, sp4, message_on_save])
        doc.add_root(widgets_and_figures)
Beispiel #20
0
def animate_update():
    year = slider.value + 1
    if year > 2017:
        year = 1973
    slider.value = year

callback_id='0'#declare a variable like this
def animate():
    global callback_id
    if button.label == 'Play':
        button.label = 'Pause'
        callback_id = curdoc().add_periodic_callback(animate_update, 500)
    else:
        button.label = 'Play'
        curdoc().remove_periodic_callback(callback_id)
button = Button(label='Play', width=60)
button.on_click(animate)


def plotAvgTrend():   
    source1 = ColumnDataSource(data=filterDB(place=commune1,houseType=propertyType))
    source2 = ColumnDataSource(data=filterDB(place=commune2,houseType=propertyType))
    
    fig=figure(width=700,title='Belgian real estate transactions 1973-2017: average trend in euros by commune and type')
    fig.line(x="CD_YEAR", y=Yaxis,color='blue',source=source1,legend=commune1)
    fig.line(x="CD_YEAR", y=Yaxis,color='red',source=source2,legend=commune2)
    fig.xaxis.axis_label = 'Year'
    fig.x_range = Range1d(1973,2017)
    fig.yaxis.formatter = NumeralTickFormatter(format="{}0")
    
    if Yaxis=='Mean Price':
Beispiel #21
0
            y=[],
            x1=[],
            y1=[],
            cx=[],
            cy=[],
        )
        pre.text = '<h4 style="border-top: 2px solid #778899;width: 1600px"><br><b style="color:slategray">Error! Try expanding date slider</b><br></h4>'
    pdict['active'] = radio_button_group.active


def update_click():
    pre.text = '<h4 style="border-top: 2px solid #778899;width: 1600px"><br><b style="color:slategray">Update in Progress....</b><br></h4>'
    curdoc().add_next_tick_callback(my_slider_handler)


bt = Button(label='Update Plot', button_type="success")
bt.on_click(update_click)
"""
WIDGETS

"""

sdate_input = TextInput(value="2020-01-03 00:00:00",
                        title="Start Date: (YYYY-MM-DD HH:MM:SS)")
#sdate_input.on_change("value", my_slider_handler)

edate_input = TextInput(value="2020-01-03 01:00:00",
                        title="End Date: (YYYY-MM-DD HH:MM:SS)")
#edate_input.on_change("value", my_slider_handler)
count_threshold = TextInput(value="1", title="Count Threshold Value")
Beispiel #22
0
from bokeh.plotting import figure
from bokeh.layouts import layout
from bokeh.models import ColumnDataSource, Range1d
from bokeh.models.widgets import Button
from bokeh.io import curdoc

import numpy as np

source = ColumnDataSource(data=dict(x=[], y=[]))

p = figure()
unit_range = Range1d(0, 1)
p.x_range, p.y_range = unit_range, unit_range
p.circle(x='x', y='y', source=source)


def generate():
    values = [[v] for v in np.random.random(size=2)]
    source.data = dict(x=values[0], y=values[1])


generate_button = Button(label='Generate')
generate_button.on_click(generate)

l = layout([[p], [generate_button]])

generate()

curdoc().add_root(l)
curdoc().title = 'Random point in unit square'
Beispiel #23
0
from bokeh.plotting import curdoc
from bokeh.models.widgets import Button


def button_clicked():
    print('Button Clicked')


my_button = Button(label="Click Here!")
my_button.on_click(button_clicked)
curdoc().add_root(my_button)
from bokeh.plotting import figure
from bokeh.models.widgets import Select, Button, Slider, Paragraph, Panel, Tabs
from bokeh.layouts import layout, widgetbox
from Plot.ann_data_instance import ANNData
import ann
from bokeh.io import curdoc
from bokeh.models import ColumnDataSource

learning_rate_select = Select(title="Öğrenme Hızını Seçiniz:",
                              options=['1e-5', '1e-3', '0.01', '0.1', '1'],
                              value="0.01")
activation_func_select = Select(title="Aktivasyon Fonksiyonunu Seçiniz:",
                                options=['ReLu', 'Tanh', 'Sigmoid'],
                                value='ReLu')
add_layer_button = Button(label="Katman Ekle", button_type="success")
remove_layer_select = Select(title="Katman Çıkar:", options=["Seçiniz", "1"])
layer_select = Select(title="Düğüm Eklemek/Çıkarmak İçin Katman Seç:",
                      options=["1"])
add_node_button = Button(label="+", button_type="warning")
remove_node_button = Button(label="-", button_type="warning")
epoch_slider = Slider(start=500,
                      end=50000,
                      value=500,
                      step=500,
                      title="Adım Sayısı Belirle")
play_button = Button(label="Oynat", button_type="success")
play_button_info = Paragraph(text="")
widgets = widgetbox(learning_rate_select,
                    activation_func_select,
                    add_layer_button,
                    remove_layer_select,
Beispiel #25
0
    def make_document(self, doc):
        # source = ColumnDataSource({'x': [], 'y': [], 'color': []})
        # x = []
        # y = []

        colors = [
            "#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1",
            "#cc7878", "#933b41", "#550b1d"
        ]
        mapper = LinearColorMapper(palette=colors, low=0, high=1)
        button = Button(label="Start", button_type="success")
        # create three plots

        plot = {
            'time': [self.env.now],
            'running': [len(self.simulation.cluster.running_tasks)],
            'finished': [len(self.simulation.cluster.finished_tasks)]
        }

        plotdata = ColumnDataSource(plot)

        def update_start():
            if not self.start:
                self.start = True

        p = figure(plot_width=400, plot_height=400)
        p.line(x='time',
               y='running',
               legend_label='Running tasks',
               alpha=0.2,
               line_width=3,
               color='navy',
               source=plotdata)
        p.line(x='time',
               y='finished',
               legend_label='Finished tasks',
               alpha=0.8,
               line_width=2,
               color='orange',
               source=plotdata)
        p.xaxis.axis_label = 'Time'
        p.yaxis.axis_label = 'Tasks'

        def update_plot():
            if self.env:
                updata = {
                    'time': [self.env.now],
                    'running': [len(self.simulation.cluster.running_tasks)],
                    'finished': [len(self.simulation.cluster.finished_tasks)]
                }
                plotdata.stream(updata)

        """
		SETUP TABLE 
		"""
        columns = [
            TableColumn(field="name", title="Name"),
            TableColumn(field="start", title="Start Time"),
            TableColumn(field="demand", title="No. Antennas"),
            TableColumn(field="duration", title="Observation Length"),
            TableColumn(field="running", title="Running Status")
        ]

        sourcedata = dict(name=[],
                          start=[],
                          duration=[],
                          demand=[],
                          running=[])
        tablesource = ColumnDataSource(data=sourcedata)
        for observation in self.simulation.telescope.observations:
            sourcedata['name'].append(observation.name)
            sourcedata['start'].append(observation.start)
            sourcedata['duration'].append(observation.duration)
            sourcedata['demand'].append(observation.demand)
            sourcedata['running'].append(observation.status)
        data_table = DataTable(source=tablesource,
                               columns=columns,
                               width=600,
                               height=280)

        def update_table():
            if self.env:
                for i, observation in enumerate(
                        self.simulation.telescope.observations):
                    dictionary = {"running": [(i, observation.status)]}
                    tablesource.patch(dictionary)

        doc.add_periodic_callback(update_plot, 500)
        doc.add_periodic_callback(update_table, 500)
        button.on_click(update_start)

        # fig.xgrid.grid_line_color = None
        # fig.x_range.start = 0
        # fig.x_range.end = 350
        # fig.legend.orientation = "horizontal"
        # fig.legend.location = "top_center"

        doc.title = "TopSim Dashboard"
        doc.add_root(layout([button], [p, data_table]))
        return doc
Beispiel #26
0
    def time_tab(self):

        """The date and time setting and getting tab"""

        self.time_status = Div(text="", width=self.page_width)

        time_connect = Button(label='Connect to UT330',
                              button_type="success")

        time_disconnect = Button(label='Disconnect from UT330',
                                 button_type="success")

        time_get = Button(label='Get UT330 date and time',
                          button_type="success")

        self.time_compare = Div(text="", width=self.page_width)

        time_set = Button(label='Set the UT330 date and time',
                          button_type="success")

        time_connect.on_click(self.time_connect)
        time_disconnect.on_click(self.time_disconnect)
        time_get.on_click(self.time_get)
        time_set.on_click(self.time_set)

        l = layout([self.time_status],
                   [time_connect, time_disconnect],
                   [time_get, self.time_compare],
                   [time_set])

        return Panel(child=l, title="Date and time setting")
 def getBokehComponent(self):
     self.bk = Button(label=self._settings['label'])
     self.bk.on_event(ButtonClick, self.handle_click)
     return self.bk
Beispiel #28
0
windowsize = Slider(title="Window Size", value=30, start=0, end=60, step=2)

# Set up callbacks
def update_title(attrname, old, new):
    p1.title.text = text.value

def update_window(attrname, old, new):

    # Get the current slider values
    window_size = windowsize.value

    # re calculate average and re-draw line
    window = np.ones(window_size)/float(window_size)
    avg = np.convolve(source.data[col2], window, 'same')
    p1.line(source.data[col1], avg, color='navy', legend='avg')

checkbox_group = CheckboxGroup(
        labels=["Option 1", "Option 2", "Option 3"], active=[0, 1])
button = Button(label="Foo", button_type="success")

text.on_change('value', update_title)
windowsize.on_change('value', update_window)


tabs = Tabs(tabs=create_panels(files, names), width=800)
inputs = widgetbox(text, windowsize, checkbox_group, button)#, amplitude, phase, freq)



curdoc().add_root(row(inputs, tabs))
curdoc().title = "Dashboard"
        curdoc().remove_periodic_callback(update)
toggle = Toggle(label="Start", type="success")
toggle.on_click(toggle_handler)
toggle.active = False

# Set up reset button
def reset_handler():
    global ii, current_time
    ii = 0
    current_time = 0
    l_forward.data_source.data["y"] = forward_wave()
    l_reverse.data_source.data["y"] = reverse_wave()
    l_sum.data_source.data["y"] = l_forward.data_source.data["y"] + \
                                  l_reverse.data_source.data["y"]
    #t2.data_source.data["text"] = ['t = {:.3f} s'.format(current_time)]
button_reset = Button(label="Reset", type="success")
button_reset.on_click(reset_handler)

# Set up checkboxes to show/hide forward & reverse propagating waves
def checkbox_group_handler(active):
    global alpha, alpha_slider
    if 0 in active:
        #l_forward.glyph.visible = True
        l_forward.glyph.line_alpha = alpha_forward_reverse_waves
    else:
        #l_forward.glyph.visible = False
        l_forward.glyph.line_alpha = 0.0
    if 1 in active:
        #l_reverse.glyph.visible = True
        l_reverse.glyph.line_alpha = alpha_forward_reverse_waves
    else:
Beispiel #30
0
ndvis = TextInput(title='NDVIs', value=str(raster_info[band_list[0]]['ndvis']))
tir_max = TextInput(title='Tmax',
                    value=str(raster_info[band_list[0]]['tir_max']))
tir_min = TextInput(title='Tmin',
                    value=str(raster_info[band_list[0]]['tir_min']))

warm_t1 = TextInput(title='Warm T1',
                    value=str(raster_info[band_list[0]]['we_points'][0, 0]))
warm_t2 = TextInput(title='Warm T2',
                    value=str(raster_info[band_list[0]]['we_points'][0, 1]))
warm_n1 = TextInput(title='Warm N1',
                    value=str(raster_info[band_list[0]]['we_points'][1, 0]))
warm_n2 = TextInput(title='Warm N2',
                    value=str(raster_info[band_list[0]]['we_points'][1, 1]))

save_button = Button(label='Save All', button_type='default')

src = ColumnDataSource(data=dict(tir=[], ndvi=[], tstar=[], fr=[], ef=[]))
we_src = ColumnDataSource(data=dict(we=[], tirs=[]))


#Based on https://ideone.com/ItifKv
#Converts string output from TextInput to float, returns 0 if it can't
def convert_to_float(frac_str):
    try:
        return float(frac_str)
    except ValueError:
        try:
            num, denom = frac_str.split('/')
        except:
            return np.nan
Beispiel #31
0
def launch_order(symbol, qty, OrderType, clientOrderId = 13):
    global newOrderSide
    global newOrderSymbol
    newOrderSymbol = symbol
    newOrderSide = OrderType

    NewOrder = {'type': 'NewOrder', 'clientOrderId': str(clientOrderId), 'symbol': symbol , 'buySell': OrderType, 'qty': qty}
    with SocketIO(server) as socketIO:
        socketIO.emit('submitOrder', NewOrder)
        socketIO.on('onOrderMessage', order_response)
        socketIO.wait()




buyButton = Button(label="BUY", button_type="success")
buyButton.on_click(buyThreadFunc)

sellButton = Button(label="SELL", button_type="warning")
sellButton.on_click(sellThreadFunc)

select = Select(title="Ticker:", value=stocks_list[0], options=stocks_list)
select.on_change("value", ticker_handler)

quantity_input = TextInput(value="100", title="quantity:")
quantity_input.on_change("value", quantity_handler)


if currentPNL == 0 : 
    PNLbutton = Button(label="PNL : " + str(currentPNL), button_type="warning")
elif currentPNL >0 : 
Beispiel #32
0
class DatabaseEditor:
    def __init__(self, roi_manager):

        column_width = 600

        self.roi_manager = roi_manager  # allows ROI Name manager updates after importing data

        self.source = ColumnDataSource(data=dict())
        self.source_csv = ColumnDataSource(data=dict(text=[]))

        self.import_inbox_button = Button(label='Import all from inbox',
                                          button_type='success',
                                          width=200)
        self.import_inbox_button.on_click(self.import_inbox)
        self.import_inbox_force = CheckboxGroup(
            labels=['Force Update', 'Import Latest Only', 'Move Files'],
            active=[1, 2])
        self.rebuild_db_button = Button(label='Rebuild database',
                                        button_type='warning',
                                        width=200)
        self.rebuild_db_button.on_click(self.rebuild_db_button_click)

        self.query_table = Select(
            value='Plans',
            options=['DVHs', 'Plans', 'Rxs', 'Beams', 'DICOM_Files'],
            width=200,
            title='Table:')
        self.query_columns = MultiSelect(
            title="Columns (Ctrl or Shift Click enabled):",
            width=250,
            options=[tuple(['', ''])],
            size=10)
        self.query_condition = TextInput(value='',
                                         title="Condition:",
                                         width=450)
        self.query_button = Button(label='Query',
                                   button_type='primary',
                                   width=100)

        self.query_table.on_change('value', self.update_query_columns_ticker)
        self.query_button.on_click(self.update_query_source)

        self.update_db_title = Div(text="<b>Update Database</b>",
                                   width=column_width)
        self.update_db_table = Select(
            value='DVHs',
            options=['DVHs', 'Plans', 'Rxs', 'Beams'],
            width=80,
            title='Table:')
        self.update_db_column = Select(value='',
                                       options=[''],
                                       width=175,
                                       title='Column')
        self.update_db_value = TextInput(value='', title="Value:", width=200)
        self.update_db_condition = TextInput(value='',
                                             title="Condition:",
                                             width=350)
        self.update_db_button = Button(label='Update DB',
                                       button_type='warning',
                                       width=100)

        self.update_db_table.on_change('value',
                                       self.update_update_db_columns_ticker)
        self.update_db_button.on_click(self.update_db)

        self.update_query_columns()
        self.update_update_db_column()

        self.reimport_title = Div(text="<b>Reimport from DICOM</b>",
                                  width=column_width)
        self.reimport_mrn_text = TextInput(value='', width=200, title='MRN:')
        self.reimport_study_date_select = Select(value='',
                                                 options=[''],
                                                 width=200,
                                                 title='Sim Study Date:')
        self.reimport_uid_select = Select(value='',
                                          options=[''],
                                          width=425,
                                          title='Study Instance UID:')
        self.reimport_old_data_select = Select(
            value='Delete from DB',
            options=['Delete from DB', 'Keep in DB'],
            width=150,
            title='Current Data:')
        self.reimport_button = Button(label='Reimport',
                                      button_type='warning',
                                      width=100)

        self.reimport_mrn_text.on_change('value', self.reimport_mrn_ticker)
        self.reimport_study_date_select.on_change(
            'value', self.reimport_study_date_ticker)
        self.reimport_button.on_click(self.reimport_button_click)

        self.query_data_table = DataTable(source=self.source,
                                          columns=[],
                                          width=column_width,
                                          editable=True,
                                          height=600)

        self.delete_from_db_title = Div(
            text="<b>Delete all data with mrn or study_instance_uid</b>",
            width=column_width)
        self.delete_from_db_column = Select(
            value='mrn',
            options=['mrn', 'study_instance_uid'],
            width=200,
            title='Patient Identifier:')
        self.delete_from_db_value = TextInput(value='',
                                              title="Value (required):",
                                              width=300)
        self.delete_from_db_button = Button(label='Delete',
                                            button_type='warning',
                                            width=100)
        self.delete_auth_text = TextInput(
            value='', title="Type 'delete' here to authorize:", width=300)
        self.delete_auth_text.on_change('value', self.delete_auth_text_ticker)
        self.delete_from_db_button.on_click(self.delete_from_db)

        self.change_mrn_uid_title = Div(
            text="<b>Change mrn or study_instance_uid in all tables</b>",
            width=column_width)
        self.change_mrn_uid_column = Select(
            value='mrn',
            options=['mrn', 'study_instance_uid'],
            width=200,
            title='Patient Identifier:')
        self.change_mrn_uid_old_value = TextInput(value='',
                                                  title="Old:",
                                                  width=300)
        self.change_mrn_uid_new_value = TextInput(value='',
                                                  title="New:",
                                                  width=300)
        self.change_mrn_uid_button = Button(label='Rename',
                                            button_type='warning',
                                            width=100)
        self.change_mrn_uid_button.on_click(self.change_mrn_uid)

        self.calculations_title = Div(text="<b>Post Import Calculations</b>",
                                      width=column_width)
        self.calculate_condition = TextInput(value='',
                                             title="Condition:",
                                             width=350)
        self.calculate_options = [
            'Default Post-Import', 'PTV Distances', 'PTV Overlap',
            'ROI Centroid', 'ROI Spread', 'ROI Cross-Section',
            'OAR-PTV Centroid Dist', 'Beam Complexities', 'Plan Complexities',
            'All (except age)', 'Patient Ages'
        ]
        self.calculate_select = Select(value=self.calculate_options[0],
                                       options=self.calculate_options,
                                       title='Calculate:',
                                       width=150)
        self.calculate_missing_only = CheckboxGroup(
            labels=['Only Calculate Missing Values'], active=[0], width=280)
        self.calculate_exec_button = Button(label='Perform Calc',
                                            button_type='primary',
                                            width=150)
        self.calculate_exec_button.on_click(self.calculate_exec)

        self.download = Button(label="Download Table",
                               button_type="default",
                               width=150)
        self.download.callback = CustomJS(args=dict(source=self.source_csv),
                                          code=open(
                                              join(dirname(dirname(__file__)),
                                                   'download_new.js')).read())

        self.layout = row(
            column(
                row(self.import_inbox_button, Spacer(width=20),
                    self.rebuild_db_button, Spacer(width=50),
                    self.import_inbox_force), self.calculations_title,
                row(self.calculate_select, Spacer(width=20),
                    self.calculate_missing_only,
                    self.calculate_exec_button), self.calculate_condition,
                Div(text="<hr>", width=column_width), self.update_db_title,
                row(self.update_db_table, self.update_db_column,
                    self.update_db_value, Spacer(width=45),
                    self.update_db_button), self.update_db_condition,
                Div(text="<hr>", width=column_width), self.reimport_title,
                row(self.reimport_mrn_text,
                    Spacer(width=10), self.reimport_old_data_select,
                    Spacer(width=140), self.reimport_button),
                row(self.reimport_study_date_select, self.reimport_uid_select),
                Div(text="<hr>", width=column_width),
                row(self.delete_from_db_title),
                row(self.delete_from_db_column, Spacer(width=300),
                    self.delete_from_db_button),
                row(self.delete_from_db_value, self.delete_auth_text),
                Div(text="<hr>", width=column_width),
                row(self.change_mrn_uid_title),
                row(self.change_mrn_uid_column, Spacer(width=300),
                    self.change_mrn_uid_button),
                row(self.change_mrn_uid_old_value,
                    self.change_mrn_uid_new_value)),
            column(Div(text="<b>Query Database</b>", width=column_width),
                   row(self.query_table,
                       self.query_columns), self.query_condition,
                   row(self.query_button, Spacer(width=25), self.download),
                   self.query_data_table))

    def update_query_columns_ticker(self, attr, old, new):
        self.update_query_columns()

    def update_query_columns(self):
        new_options = DVH_SQL().get_column_names(
            self.query_table.value.lower())
        if self.query_table.value.lower() == 'dvhs':
            new_options.pop(new_options.index('dvh_string'))
            new_options.pop(new_options.index('roi_coord_string'))
            new_options.pop(new_options.index('dth_string'))
        options_tuples = [tuple([option, option]) for option in new_options]
        self.query_columns.options = options_tuples
        self.query_columns.value = ['']

    def update_update_db_columns_ticker(self, attr, old, new):
        self.update_update_db_column()

    def update_update_db_column(self):
        new_options = DVH_SQL().get_column_names(
            self.update_db_table.value.lower())
        new_options.pop(new_options.index('import_time_stamp'))
        if self.update_db_table.value.lower() == 'dvhs':
            new_options.pop(new_options.index('dvh_string'))
            new_options.pop(new_options.index('roi_coord_string'))

        self.update_db_column.options = new_options
        self.update_db_column.value = new_options[0]

    def update_query_source(self):
        columns = [v for v in self.query_columns.value if v]
        for i, key in enumerate([
                'mrn', 'study_instance_uid'
        ]):  # move/add mrn and study_instance_uid to the front
            if key in columns:
                columns.pop(columns.index(key))
            columns.insert(i, key)

        table_columns = [TableColumn(field=c, title=c) for c in columns]

        query_cursor = DVH_SQL().query(self.query_table.value,
                                       ','.join(columns).strip(),
                                       self.query_condition.value,
                                       order_by='mrn')
        new_data = {
            c: [str(line[i]) for line in query_cursor]
            for i, c in enumerate(columns)
        }

        if new_data:
            self.source.data = new_data
            self.query_data_table.columns = table_columns
            self.query_data_table.width = [700, 150 * len(table_columns)
                                           ][len(table_columns) > 5]
            self.update_csv()

    def update_db(self):
        if self.update_db_condition.value and self.update_db_value.value:
            self.update_db_button.label = 'Updating...'
            self.update_db_button.button_type = 'danger'
            update_value = self.update_db_value.value
            if self.update_db_column.value in {'birth_date', 'sim_study_date'}:
                update_value = update_value + "::date"
            DVH_SQL().update(self.update_db_table.value,
                             self.update_db_column.value, update_value,
                             self.update_db_condition.value)
            self.update_query_source()
            self.update_db_button.label = 'Update'
            self.update_db_button.button_type = 'warning'

            self.roi_manager.update_uncategorized_variation_select()
            self.roi_manager.update_ignored_variations_select()

    def delete_from_db(self):
        if self.delete_from_db_value.value and self.delete_auth_text.value == 'delete':
            condition = self.delete_from_db_column.value + " = '" + self.delete_from_db_value.value + "'"
            DVH_SQL().delete_rows(condition)
            self.update_query_source()
            self.delete_from_db_value.value = ''
            self.delete_auth_text.value = ''

            self.roi_manager.update_uncategorized_variation_select()
            self.roi_manager.update_ignored_variations_select()

    def change_mrn_uid(self):
        self.change_mrn_uid_button.label = 'Updating...'
        self.change_mrn_uid_button.button_type = 'danger'
        old = self.change_mrn_uid_old_value.value
        new = self.change_mrn_uid_new_value.value
        if old and new and old != new:
            if self.change_mrn_uid_column.value == 'mrn':
                DVH_SQL().change_mrn(old, new)
            elif self.change_mrn_uid_column.value == 'study_instance_uid':
                DVH_SQL().change_uid(old, new)
        self.change_mrn_uid_old_value.value = ''
        self.change_mrn_uid_new_value.value = ''
        self.change_mrn_uid_button.label = 'Rename'
        self.change_mrn_uid_button.button_type = 'warning'
        self.update_query_source()

    def delete_auth_text_ticker(self, attr, old, new):
        self.delete_from_db_button.button_type = ['warning',
                                                  'danger'][new == 'delete']

    def import_inbox(self):
        if self.import_inbox_button.label in {'Cancel'}:
            self.rebuild_db_button.label = 'Rebuild database'
            self.rebuild_db_button.button_type = 'warning'
        else:
            self.import_inbox_button.button_type = 'warning'
            self.import_inbox_button.label = 'Importing...'

            force_update = 0 in self.import_inbox_force.active
            move_files = 2 in self.import_inbox_force.active
            import_latest_only = 1 in self.import_inbox_force.active

            dicom_to_sql(force_update=force_update,
                         import_latest_only=import_latest_only,
                         move_files=move_files)

        self.roi_manager.update_uncategorized_variation_select()

        self.import_inbox_button.button_type = 'success'
        self.import_inbox_button.label = 'Import all from inbox'

    def rebuild_db_button_click(self):
        if self.rebuild_db_button.button_type in {'warning'}:
            self.rebuild_db_button.label = 'Are you sure?'
            self.rebuild_db_button.button_type = 'danger'
            self.import_inbox_button.button_type = 'success'
            self.import_inbox_button.label = 'Cancel'

        else:
            directories = load_directories()
            self.rebuild_db_button.label = 'Rebuilding...'
            self.rebuild_db_button.button_type = 'danger'
            self.import_inbox_button.button_type = 'success'
            self.import_inbox_button.label = 'Import all from inbox'
            rebuild_database(directories['imported'])
            self.rebuild_db_button.label = 'Rebuild database'
            self.rebuild_db_button.button_type = 'warning'

    def update_all_min_distances_in_db(self, *condition):
        if condition and condition[0]:
            condition = " AND (" + condition[0] + ")"
        else:
            condition = ''
        condition = "(LOWER(roi_type) IN ('organ', 'ctv', 'gtv') AND (" \
                    "LOWER(roi_name) NOT IN ('external', 'skin') OR " \
                    "LOWER(physician_roi) NOT IN ('uncategorized', 'ignored', 'external', 'skin')))" + condition
        if 0 in self.calculate_missing_only.active:
            if condition:
                condition = "(%s) AND dist_to_ptv_min is NULL" % condition
            else:
                condition = "dist_to_ptv_min is NULL"
        rois = DVH_SQL().query('dvhs',
                               'study_instance_uid, roi_name, physician_roi',
                               condition)

        total_rois = float(len(rois))
        for i, roi in enumerate(rois):
            self.calculate_exec_button.label = str(
                int((float(i) / total_rois) * 100)) + '%'
            if roi[1].lower() not in {'external', 'skin'} and \
                    roi[2].lower() not in {'uncategorized', 'ignored', 'external', 'skin'}:
                print('updating dist to ptv:', roi[1], sep=' ')
                db_update.min_distances(roi[0], roi[1])
            else:
                print('skipping dist to ptv:', roi[1], sep=' ')

    def update_all(self, variable, *condition):
        variable_function_map = {
            'ptv_overlap': db_update.treatment_volume_overlap,
            'centroid': db_update.centroid,
            'spread': db_update.spread,
            'cross_section': db_update.cross_section,
            'ptv_centroids': db_update.dist_to_ptv_centroids
        }
        null_variable = variable
        if variable == 'ptv_centroids':
            null_variable = 'dist_to_ptv_centroids'
        elif variable == 'spread':
            null_variable = 'spread_x'
        elif variable == 'cross_section':
            null_variable = 'cross_section_max'
        elif variable == 'plan_complexity':
            null_variable = 'complexity'

        final_condition = {
            True: ["(%s is NULL)" % null_variable],
            False: []
        }[0 in self.calculate_missing_only.active]
        if condition and condition[0]:
            final_condition.append('(%s)' % condition[0])
        final_condition = ' AND '.join(final_condition)

        rois = DVH_SQL().query('dvhs',
                               'study_instance_uid, roi_name, physician_roi',
                               final_condition)

        total_rois = float(len(rois))
        for i, roi in enumerate(rois):
            self.calculate_exec_button.label = str(
                int((float(i) / total_rois) * 100)) + '%'
            print('updating %s:' % variable, roi[1], sep=' ')
            variable_function_map[variable](roi[0], roi[1])

    def update_all_tv_overlaps_in_db(self, condition):
        self.update_all('ptv_overlap', condition)

    def update_all_centroids_in_db(self, condition):
        self.update_all('centroid', condition)

    def update_all_spreads_in_db(self, condition):
        self.update_all('spread', condition)

    def update_all_cross_sections_in_db(self, condition):
        self.update_all('cross_section', condition)

    def update_all_dist_to_ptv_centoids_in_db(self, condition):
        self.update_all('ptv_centroids', condition)

    def update_all_plan_complexities_in_db(self, condition):
        final_condition = {
            True: ["(complexity is NULL)"],
            False: []
        }[0 in self.calculate_missing_only.active]
        if condition and condition[0]:
            final_condition.append('(%s)' % condition[0])
        final_condition = ' AND '.join(final_condition)

        db_update.plan_complexities(final_condition)

    def update_all_beam_complexities_in_db(self, condition):
        final_condition = {
            True: ["(complexity_min is NULL)"],
            False: []
        }[0 in self.calculate_missing_only.active]
        if condition and condition[0]:
            final_condition.append('(%s)' % condition[0])
        final_condition = ' AND '.join(final_condition)

        db_update.beam_complexities(final_condition)

    def update_all_except_age_in_db(self, *condition):
        for f in self.calculate_select.options:
            if f not in {'Patient Ages', 'Default Post-Import'}:
                self.calculate_select.value = f
                self.calculate_exec()

    def update_default_post_import(self, *condition):
        for f in [
                'PTV Distances', 'PTV Overlap', 'OAR-PTV Centroid Dist',
                'Plan Complexities'
        ]:
            self.calculate_select.value = f
            self.calculate_exec()
        self.calculate_select.value = 'Default Post-Import'

    # Calculates volumes using Shapely, not dicompyler
    # This function is not in the GUI
    @staticmethod
    def recalculate_roi_volumes(*condition):
        rois = DVH_SQL().query('dvhs',
                               'study_instance_uid, roi_name, physician_roi',
                               condition[0])

        counter = 0.
        total_rois = float(len(rois))
        for roi in rois:
            counter += 1.
            print('updating volume:',
                  roi[1],
                  int(100. * counter / total_rois),
                  sep=' ')
            db_update.volumes(roi[0], roi[1])

    # Calculates surface area using Shapely
    # This function is not in the GUI
    @staticmethod
    def recalculate_surface_areas(*condition):
        rois = DVH_SQL().query('dvhs',
                               'study_instance_uid, roi_name, physician_roi',
                               condition[0])

        roi_count = float(len(rois))
        for i, roi in enumerate(rois):
            print('updating surface area:',
                  roi[1],
                  int(100. * float(i) / roi_count),
                  sep=' ')
            db_update.surface_area(roi[0], roi[1])

    def reimport_mrn_ticker(self, attr, old, new):
        new_options = DVH_SQL().get_unique_values('Plans', 'sim_study_date',
                                                  "mrn = '%s'" % new)
        if not new_options:
            new_options = ['MRN not found']
        self.reimport_study_date_select.options = new_options
        self.reimport_study_date_select.value = new_options[0]

    def reimport_study_date_ticker(self, attr, old, new):
        if new != 'MRN not found':
            if new == 'None':
                new_options = DVH_SQL().get_unique_values(
                    'Plans', 'study_instance_uid',
                    "mrn = '%s'" % self.reimport_mrn_text.value)
            else:
                new_options = DVH_SQL().get_unique_values(
                    'Plans', 'study_instance_uid',
                    "mrn = '%s' and sim_study_date = '%s'" %
                    (self.reimport_mrn_text.value, new))
        else:
            new_options = ['Study Date not found']

        self.reimport_uid_select.options = new_options
        self.reimport_uid_select.value = new_options[0]

    def reimport_button_click(self):
        dicom_directory = DVH_SQL().query(
            'DICOM_Files', "folder_path",
            "study_instance_uid = '%s'" % self.reimport_uid_select.value)[0][0]
        if os.path.isdir(dicom_directory):
            if not os.listdir(dicom_directory):
                print("WARNING: %s is empty." % dicom_directory)
                print("Aborting DICOM reimport.")
            else:
                self.reimport_button.label = "Updating..."
                self.reimport_button.button_type = 'danger'
                if self.reimport_old_data_select.value == "Delete from DB":
                    DVH_SQL().delete_rows("study_instance_uid = '%s'" %
                                          self.reimport_uid_select.value,
                                          ignore_table=['DICOM_Files'])

                dicom_to_sql(start_path=dicom_directory,
                             force_update=True,
                             move_files=False,
                             update_dicom_catalogue_table=False)
                self.reimport_button.label = "Reimport"
                self.reimport_button.button_type = 'warning'

                self.roi_manager.update_uncategorized_variation_select()
                self.roi_manager.update_ignored_variations_select()
        else:
            print("WARNING: %s does not exist" % dicom_directory)
            print("Aborting DICOM reimport.")

    def calculate_exec(self):
        calc_map = {
            'PTV Distances': self.update_all_min_distances_in_db,
            'PTV Overlap': self.update_all_tv_overlaps_in_db,
            'Patient Ages': recalculate_ages,
            'ROI Centroid': self.update_all_centroids_in_db,
            'ROI Spread': self.update_all_spreads_in_db,
            'ROI Cross-Section': self.update_all_cross_sections_in_db,
            'OAR-PTV Centroid Dist':
            self.update_all_dist_to_ptv_centoids_in_db,
            'Beam Complexities': self.update_all_beam_complexities_in_db,
            'Plan Complexities': self.update_all_plan_complexities_in_db,
            'All (except age)': self.update_all_except_age_in_db,
            'Default Post-Import': self.update_default_post_import
        }

        start_time = datetime.now()
        print(str(start_time),
              'Beginning %s calculations' % self.calculate_select.value,
              sep=' ')

        self.calculate_exec_button.label = 'Calculating...'
        self.calculate_exec_button.button_type = 'warning'

        calc_map[self.calculate_select.value](self.calculate_condition.value)

        self.update_query_source()

        self.calculate_exec_button.label = 'Perform Calc'
        self.calculate_exec_button.button_type = 'primary'

        end_time = datetime.now()
        print(str(end_time), 'Calculations complete', sep=' ')

        print_run_time(start_time, end_time,
                       "Calculations for %s" % self.calculate_select.value)

    def update_csv(self):
        src_data = [self.source.data]
        src_names = ['Queried Data']
        columns = list(src_data[0])
        columns.sort()

        for i, key in enumerate([
                'mrn', 'study_instance_uid'
        ]):  # move/add mrn and study_instance_uid to the front
            if key in columns:
                columns.pop(columns.index(key))
            columns.insert(i, key)

        csv_text = get_csv(src_data, src_names, columns)

        self.source_csv.data = {'text': [csv_text]}
        sliders['{0} exponent'.format(par_name)] = Slider(
            start=-30,
            end=0,
            value=exponents[par_name],
            step=1,
            title='{0}: Exponent'.format(par_name))
    elif par_name == 'Shunt Resistance' or par_name == 'Series Resistance':
        sliders['{0} exponent'.format(par_name)] = Slider(
            start=-2,
            end=20,
            value=exponents[par_name],
            step=1,
            title='{0}: Exponent'.format(par_name))

#Buttons for saving and fitting
Fit_button = Button(label="Perform Fit")
Save_button = Button(label="Save Fit")

#Button for saving IV data without outliers
Save_data_wo_outlier_button = Button(label="Save data without outliers")

#Define Drop-down menu for fitting method
methods_select = Select(title='Fitting to:',
                        value='Log',
                        options=['Log', 'Linear'])
fit_methods_select = Select(title='Fitting method:',
                            value='by eye',
                            options=[
                                'By Eye', 'Gradient Descent',
                                'Brute Force - I_0', 'Brute Force - R_S'
                            ])
Beispiel #34
0
    def __init__(self, roi_manager):

        column_width = 600

        self.roi_manager = roi_manager  # allows ROI Name manager updates after importing data

        self.source = ColumnDataSource(data=dict())
        self.source_csv = ColumnDataSource(data=dict(text=[]))

        self.import_inbox_button = Button(label='Import all from inbox',
                                          button_type='success',
                                          width=200)
        self.import_inbox_button.on_click(self.import_inbox)
        self.import_inbox_force = CheckboxGroup(
            labels=['Force Update', 'Import Latest Only', 'Move Files'],
            active=[1, 2])
        self.rebuild_db_button = Button(label='Rebuild database',
                                        button_type='warning',
                                        width=200)
        self.rebuild_db_button.on_click(self.rebuild_db_button_click)

        self.query_table = Select(
            value='Plans',
            options=['DVHs', 'Plans', 'Rxs', 'Beams', 'DICOM_Files'],
            width=200,
            title='Table:')
        self.query_columns = MultiSelect(
            title="Columns (Ctrl or Shift Click enabled):",
            width=250,
            options=[tuple(['', ''])],
            size=10)
        self.query_condition = TextInput(value='',
                                         title="Condition:",
                                         width=450)
        self.query_button = Button(label='Query',
                                   button_type='primary',
                                   width=100)

        self.query_table.on_change('value', self.update_query_columns_ticker)
        self.query_button.on_click(self.update_query_source)

        self.update_db_title = Div(text="<b>Update Database</b>",
                                   width=column_width)
        self.update_db_table = Select(
            value='DVHs',
            options=['DVHs', 'Plans', 'Rxs', 'Beams'],
            width=80,
            title='Table:')
        self.update_db_column = Select(value='',
                                       options=[''],
                                       width=175,
                                       title='Column')
        self.update_db_value = TextInput(value='', title="Value:", width=200)
        self.update_db_condition = TextInput(value='',
                                             title="Condition:",
                                             width=350)
        self.update_db_button = Button(label='Update DB',
                                       button_type='warning',
                                       width=100)

        self.update_db_table.on_change('value',
                                       self.update_update_db_columns_ticker)
        self.update_db_button.on_click(self.update_db)

        self.update_query_columns()
        self.update_update_db_column()

        self.reimport_title = Div(text="<b>Reimport from DICOM</b>",
                                  width=column_width)
        self.reimport_mrn_text = TextInput(value='', width=200, title='MRN:')
        self.reimport_study_date_select = Select(value='',
                                                 options=[''],
                                                 width=200,
                                                 title='Sim Study Date:')
        self.reimport_uid_select = Select(value='',
                                          options=[''],
                                          width=425,
                                          title='Study Instance UID:')
        self.reimport_old_data_select = Select(
            value='Delete from DB',
            options=['Delete from DB', 'Keep in DB'],
            width=150,
            title='Current Data:')
        self.reimport_button = Button(label='Reimport',
                                      button_type='warning',
                                      width=100)

        self.reimport_mrn_text.on_change('value', self.reimport_mrn_ticker)
        self.reimport_study_date_select.on_change(
            'value', self.reimport_study_date_ticker)
        self.reimport_button.on_click(self.reimport_button_click)

        self.query_data_table = DataTable(source=self.source,
                                          columns=[],
                                          width=column_width,
                                          editable=True,
                                          height=600)

        self.delete_from_db_title = Div(
            text="<b>Delete all data with mrn or study_instance_uid</b>",
            width=column_width)
        self.delete_from_db_column = Select(
            value='mrn',
            options=['mrn', 'study_instance_uid'],
            width=200,
            title='Patient Identifier:')
        self.delete_from_db_value = TextInput(value='',
                                              title="Value (required):",
                                              width=300)
        self.delete_from_db_button = Button(label='Delete',
                                            button_type='warning',
                                            width=100)
        self.delete_auth_text = TextInput(
            value='', title="Type 'delete' here to authorize:", width=300)
        self.delete_auth_text.on_change('value', self.delete_auth_text_ticker)
        self.delete_from_db_button.on_click(self.delete_from_db)

        self.change_mrn_uid_title = Div(
            text="<b>Change mrn or study_instance_uid in all tables</b>",
            width=column_width)
        self.change_mrn_uid_column = Select(
            value='mrn',
            options=['mrn', 'study_instance_uid'],
            width=200,
            title='Patient Identifier:')
        self.change_mrn_uid_old_value = TextInput(value='',
                                                  title="Old:",
                                                  width=300)
        self.change_mrn_uid_new_value = TextInput(value='',
                                                  title="New:",
                                                  width=300)
        self.change_mrn_uid_button = Button(label='Rename',
                                            button_type='warning',
                                            width=100)
        self.change_mrn_uid_button.on_click(self.change_mrn_uid)

        self.calculations_title = Div(text="<b>Post Import Calculations</b>",
                                      width=column_width)
        self.calculate_condition = TextInput(value='',
                                             title="Condition:",
                                             width=350)
        self.calculate_options = [
            'Default Post-Import', 'PTV Distances', 'PTV Overlap',
            'ROI Centroid', 'ROI Spread', 'ROI Cross-Section',
            'OAR-PTV Centroid Dist', 'Beam Complexities', 'Plan Complexities',
            'All (except age)', 'Patient Ages'
        ]
        self.calculate_select = Select(value=self.calculate_options[0],
                                       options=self.calculate_options,
                                       title='Calculate:',
                                       width=150)
        self.calculate_missing_only = CheckboxGroup(
            labels=['Only Calculate Missing Values'], active=[0], width=280)
        self.calculate_exec_button = Button(label='Perform Calc',
                                            button_type='primary',
                                            width=150)
        self.calculate_exec_button.on_click(self.calculate_exec)

        self.download = Button(label="Download Table",
                               button_type="default",
                               width=150)
        self.download.callback = CustomJS(args=dict(source=self.source_csv),
                                          code=open(
                                              join(dirname(dirname(__file__)),
                                                   'download_new.js')).read())

        self.layout = row(
            column(
                row(self.import_inbox_button, Spacer(width=20),
                    self.rebuild_db_button, Spacer(width=50),
                    self.import_inbox_force), self.calculations_title,
                row(self.calculate_select, Spacer(width=20),
                    self.calculate_missing_only,
                    self.calculate_exec_button), self.calculate_condition,
                Div(text="<hr>", width=column_width), self.update_db_title,
                row(self.update_db_table, self.update_db_column,
                    self.update_db_value, Spacer(width=45),
                    self.update_db_button), self.update_db_condition,
                Div(text="<hr>", width=column_width), self.reimport_title,
                row(self.reimport_mrn_text,
                    Spacer(width=10), self.reimport_old_data_select,
                    Spacer(width=140), self.reimport_button),
                row(self.reimport_study_date_select, self.reimport_uid_select),
                Div(text="<hr>", width=column_width),
                row(self.delete_from_db_title),
                row(self.delete_from_db_column, Spacer(width=300),
                    self.delete_from_db_button),
                row(self.delete_from_db_value, self.delete_auth_text),
                Div(text="<hr>", width=column_width),
                row(self.change_mrn_uid_title),
                row(self.change_mrn_uid_column, Spacer(width=300),
                    self.change_mrn_uid_button),
                row(self.change_mrn_uid_old_value,
                    self.change_mrn_uid_new_value)),
            column(Div(text="<b>Query Database</b>", width=column_width),
                   row(self.query_table,
                       self.query_columns), self.query_condition,
                   row(self.query_button, Spacer(width=25), self.download),
                   self.query_data_table))
def selection_plot(response):
    # Let's move these into a settings file somewhere?
    # height/width could potentially be driven by the request?


    # Include color data in the ColumnDataSource to allow for changing the color on
    # the client side.
    urls = [x[0] for x in response["pages"]]
    xdata = [x[1] for x in response["pages"]]
    ydata = [x[2] for x in response["pages"]]
    tags = [x[3] for x in response["pages"]]
    color = [colormap(x[0]) if x else colormap(None) for x in tags]

    source = ColumnDataSource(
        data=dict(
            x=xdata,
            y=ydata,
            urls=urls,
            tags=tags,
            color=color,
        )
    )
    # Callback code for CDS.
    source.callback = CustomJS(code="""
        var inds = cb_obj.get('selected')["1d"].indices;
        var data = cb_obj.get('data');
        BokehPlots.showPages(inds);
    """)


    # Create the figure with FIGURE_WIDTH and FIGURE_HEIGHT
    p = figure(tools="hover", width=FIGURE_WIDTH,
            toolbar_location=None, responsive=True, tags=["clusterPlot"])

    # Ensure that the lasso only selects with mouseup, not mousemove.
    p.add_tools(LassoSelectTool(select_every_mousemove=False))

    # These turn off the x/y axis ticks
    p.axis.visible = None

    # These turn the major grid off
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None

    # Plot non-selected circles with a particular style using CIRCLE_SIZE and
    # 'color' list
    p.circle("x", "y", size=13, line_width=2, line_alpha=1,
            line_color=None, fill_alpha=1, color='color', source=source,
            name="urls")
    nonselected_circle = Circle(fill_alpha=0.1, line_alpha=0.1, fill_color='color',
            line_color='color')
    renderer = p.select(name="urls")
    renderer.nonselection_glyph = nonselected_circle


    # Create buttons and their callbacks, use button_code string for callbacks.
    button_code = """
        event.preventDefault();
        var inds = source.get('selected')["1d"].indices;
        var data = source.get('data');
        var selected = [];
        tag = "%s";
        for(var i = 0; i < inds.length; i++){
            selected.push({
                x: data.x[inds[i]],
                y: data.y[inds[i]],
                url: data.urls[inds[i]],
                tags: data.tags[inds[i]],
                selected: true,
                possible: false,
            });
            data["color"][inds[i]] = "%s";
        }
        BokehPlots.updateTags(selected, tag, inds);
        source.trigger("change");
    """

    # Supply color with print formatting.
    button1 = Button(label="Relevant", type="success")
    button1.callback = CustomJS(args=dict(source=source),
            code=button_code % ("Relevant", POSITIVE_COLOR))

    button2 = Button(label="Irrelevant", type="success")
    button2.callback = CustomJS(args=dict(source=source),
            code=button_code % ("Irrelevant", NEGATIVE_COLOR))

    button3 = Button(label="Neutral", type="success")
    button3.callback = CustomJS(args=dict(source=source),
            code=button_code % ("Neutral", NEUTRAL_COLOR))


    # Adjust what attributes are displayed by the HoverTool
    hover = p.select(dict(type=HoverTool))
    hover.tooltips = [
        ("urls", "@urls"),
    ]
    layout = vform(p, button1, button2, button3)

    # Combine script and div into a single string.
    plot_code = components(layout)
    return plot_code[0] + plot_code[1]
Beispiel #36
0
                      width=140,
                      min_date=datetime.date(2020, 1, 1),
                      max_date=today,
                      value=today)
end_date.on_change('value', refresh_plot)
end_hour = select = Select(title='hour', value="23", options=hours, width=70)
end_minute = select = Select(title='min',
                             value="59",
                             options=minutes,
                             width=70)
end_hour.on_change('value', refresh_plot)
end_minute.on_change('value', refresh_plot)

## live button
live_button = Button(width=130,
                     margin=[15, 10, 15, 10],
                     label="live",
                     button_type="default")
live_button.js_on_click(CustomJS(code=""" window.location.href='./live'; """))

## force update_data()
history_button = Button(width=130,
                        margin=[15, 10, 15, 10],
                        label="history",
                        button_type="primary")
history_button.on_click(plot_data)

tz_text = Paragraph(text=f"timezone: {timezone}", width=340)

controls = column(row(live_button, history_button), instrum_select,
                  row(start_date, start_hour, start_minute),
                  row(end_date, end_hour, end_minute), tz_text)
Beispiel #37
0
### NOTE: The csv export will not work on Safari
import bokeh
import pandas as pd

from bokeh.plotting import ColumnDataSource
from bokeh.models import CustomJS, HBox, VBox, VBoxForm
from bokeh.models.widgets import Slider, Button, DataTable, TableColumn
from bokeh.io import curdoc, vform

# note this is fake data
df = pd.read_csv('salary_data.csv')

salary_range = Slider(title="Max Salary", start=10000, end=250000, value=150000, step=1000)
button = Button(label="Download")
button.button_type = "success"

source = ColumnDataSource(data=dict())

columns = [TableColumn(field="name", title="Employee Name"),
           TableColumn(field="salary", title="Income"),
           TableColumn(field="years_experience", title="Experience (years)")]

data_table = DataTable(source=source, columns=columns)

def update(attr, old, new):
    curr_df = df[df['salary'] <= salary_range.value].dropna()
    source.data = dict(name=curr_df['name'].tolist(),
                       salary=curr_df['salary'].tolist(),
                       years_experience=curr_df['years_experience'].tolist())

Beispiel #38
0
def start_handler():
    global playing
    if not playing:
        curdoc().add_periodic_callback(update, 50)
        playing = True


def stop_handler():
    global playing
    if playing:
        curdoc().remove_periodic_callback(update)
        playing = False


button_start = Button(label="Start", button_type="success")
button_start.on_click(start_handler)

button_stop = Button(label="Stop", button_type="danger")
button_stop.on_click(stop_handler)

controls = hplot(button_start, button_stop)
layout = vplot(controls, p)


@cosine(w=0.03)
def update(step):
    if playing:
        r2.data_source.data["y"] = y * step
        r2.glyph.line_alpha = 1 - 0.8 * abs(step)
Beispiel #39
0
    def config_tab(self):

        """Reading/writing device configuration"""

        # True if the config device data has been read, false otherwise
        self.config_device_read = False

        # Device connectivity
        # ===================
        config_conn_head = Div(text="<strong>Connectivity</strong>")
        self.config_status = Div(text="", width=self.page_width)
        config_connect = Button(label='Connect to UT330',
                                button_type="success")
        config_read = Button(label='Read config', button_type="success")
        config_write = Button(label='Write config', button_type="success")
        config_disconnect = Button(label='Disconnect from UT330',
                                   button_type="success")

        config_connect.on_click(self.config_connect)
        config_read.on_click(self.config_read)
        config_write.on_click(self.config_write)
        config_disconnect.on_click(self.config_disconnect)

        # Show the configuration data
        # ===========================
        # Set up the widgets
        config_device_head = Div(text="<strong>Configuration</strong>")
        self.config_device_name = TextInput(title="Device name")
        self.config_device_time = TextInput(title="Device time")
        self.config_computer_time = TextInput(title="Computer time")
        self.config_t_high = TextInput(title="High temperature alarm (C)")
        self.config_t_low = TextInput(title="Low temperature alarm (C)")
        self.config_h_high = TextInput(title="High humidity alarm (%RH)")
        self.config_h_low = TextInput(title="Low humidity alarm (%RH)")
        self.config_p_high = TextInput(title="High pressure alarm")
        self.config_p_low = TextInput(title="Low pressure alarm")
        self.config_sampling = TextInput(title="Sampling interval (s)")
        self.config_overwrite_records = Select(title="Overwrite records",
                                               options=['False', 'True'])
        self.config_delay_start = Select(title="Delay start",
                                         options=['No delay', 'Delay'])
        self.config_delay = TextInput(title="Delay (s)")

        # Status data
        # ===========
        config_status_head = Div(text="<strong>Status</strong>")
        self.config_power = TextInput(title="Battery power (%)")
        self.config_readings = TextInput(title="Readings")

        # Disable user input for these widgets
        self.config_power.disabled = True
        self.config_readings.disabled = True

        # Values to widgets
        # =================
        if self.device_connected:
            self.config_connected()
        else:
            self.config_not_connected()

        # Set up the display
        layout = column(row(config_conn_head),
                        row(self.config_status),
                        row(config_connect,
                            config_read,
                            config_write,
                            config_disconnect),
                        row(config_device_head),
                        row(self.config_device_name,
                            self.config_device_time,
                            self.config_computer_time),
                        row(self.config_t_low,
                            self.config_h_low,
                            self.config_p_low),
                        row(self.config_t_high,
                            self.config_h_high,
                            self.config_p_high),
                        row(self.config_sampling),
                        row(self.config_overwrite_records,
                            self.config_delay_start,
                            self.config_delay),
                        row(config_status_head),
                        row(self.config_power, self.config_readings))

        return Panel(child=layout,
                     title="Read/write configuration")
Beispiel #40
0
def make_document(doc):
    doc.title = "Hello, world!"
    
    df = pd.read_csv(fileName) # return dataframe
    if False:
        df = df.set_index('date')
    ''' make a copy of df. therefor changing the source will not affect df.
        using df in update() will ~reset the source to original values '''
    source = ColumnDataSource(data=df) # dict())  
        
    columns = [
        TableColumn(field="name", title="Employee Name"),
        TableColumn(field="salary", title="Income", formatter=NumberFormatter(format="$0,0.00")),
        TableColumn(field="years_experience", title="Experience (years)")
    ]
    
    data_table = DataTable(source=source, columns=columns, width=800) # ,row_headers=None)
    table = widgetbox(data_table, width=880)
    
    def slider_table_update(attr, old, new):
        print ("slider update")
        print(attr)
        print(old)
        print(new)
        current = df[df['salary'] <= slider.value].dropna()  # df ## 
        source.data = {
            'name'             : current.name,
            'salary'           : current.salary,
            'years_experience' : current.years_experience
        }
        return None
    slider = Slider(title="values range", start=0, end=100000, value=21000, step=1, width=800)
    slider.on_change('value', lambda attr, old, new: slider_table_update(attr, old, new))
    
#    fig1 = figure(title='Line plot!') #, sizing_mode='scale_width')
#    fig1.line(x=[1, 2, 3], y=[1, 4, 9])
                  #, sizing_mode='scale_width') ) #  , y_range=(00000, 100000),
#    fig2.scatter(x=source.data['years_experience'], y=source.data['salary'])
#                 title="scatter  example") #, xlabel="xlable", ylabel="ylabel")
#    plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

    selected_tools = 'pan,wheel_zoom,xbox_select,reset'
    fig2 = figure(title='salary - vs years scatter plot', width=500, height=400, tools='pan, wheel_zoom')
    fig2.scatter(x='years_experience', y='salary', source=source)

#    https://stackoverflow.com/questions/34646270/how-do-i-work-with-images-in-bokeh-python    
#   img_path = 'https://bokeh.pydata.org/en/latest/_static/images/logo.png'
    img_path = join(DATA_DIR,'logoScrnSht.png')
#    img_path = r'C:\Users\Ran_the_User\Documents\GitHub\TAILOR\bokeh\bokeh_pages\static\logoScrnSht.png'
    
    x_range = (-20,10) # could be anything - e.g.(0,1)
    y_range = (20,30)
    factor = 1.2
    
    figImg = figure(x_range=x_range, y_range=y_range)
#    figImg = figure(x_range=x_range, y_range=y_range, width=500, height=400)
    print (img_path)
    figImg.image_url(url=[img_path], x=x_range[0], y=y_range[1], w=x_range[1]-x_range[0], h=y_range[1]-y_range[0])
#    figImg.image_url(url=[img_path], x=x_range[0]/factor, y=(y_range[0]+y_range[1])/2, w=(x_range[1]-x_range[0])/factor, h=(y_range[1]-y_range[0])/factor, anchor="bottom_left") 
    
    toggle_callback = CustomJS(args=dict(source=source), code="""
        var data = source.data;
        
        var A   = a.value;
        var k   = b.value;
        var phi = c.value;
        var B   = d.value;
        
        var x = data['years_experience']
        var y = data['salary']
        
        for (var i = 0; i < x.length; i++) {
            y[i] =i*2.;
        }
        source.change.emit();
    """)
    
    def isToggleActive(status):
        print("toggle case")
        print(status)
    def on_chkbx_clicked(list_of_checked_options):
        print("chkbx case")
        print(list_of_checked_options)
    def on_radio_clicked(checked_option_ndx):
        print("cradio case")
        print(checked_option_ndx)
#    toggle   = Toggle(label='Some on/off', button_type='success')
    toggle   = Button(label='change table by source', button_type='success', callback=toggle_callback)
#    toggleLayout = layout([toggle])
    
    checkbox = CheckboxGroup(labels=['foo', 'bar', 'baz'])
    radio = RadioGroup(labels=['2000', '2010', '2020'])    
#    toggle.on_click(isToggleActive)
    checkbox.on_click(on_chkbx_clicked)
    radio.on_click(on_chkbx_clicked)
    
    checkbox_button_group = CheckboxButtonGroup(
            labels=["Option 1", "Option 2", "Option 3"], active=[0, 1])

    
    def set_vbar():
        fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
        
        fig3 = figure(x_range=fruits, plot_height=250, title="Fruit Counts", toolbar_location=None, tools="")
        
        fig3.vbar(x=fruits, top=[5, 3, 4, 2, 4, 6], width=0.9)
        
        fig3.xgrid.grid_line_color = None
        fig3.y_range.start = 0
    
        return fig3 
    
    def event_chart():
        factors = ["a","b","c,","d"]
        x = [24.3, -22.3, -25, 6]
        
        LineColor=["green" if a>=0 else "red" for a in x]
        
        Tooltips = [
            ("index", "$index"),
            ("(x,y)", "($x, $y)")
#            ("radius", "@radius"),
#            ("fill color", "$color[hex, swatch]:fill_color"),
#            ("x", "@x"),
#            ("bar", "@bar"),
        ]
        dots_fig = figure(title="exapmple", y_range = factors, x_range = [-30,30], toolbar_location="below",  toolbar_sticky=False, \
                          tools='lasso_select, poly_select, undo, redo, reset')
#                          , \
#                          tooltips=Tooltips)
        
        dots_fig.segment(0, factors, x, factors, line_width=2, line_color=LineColor)
        c1 = dots_fig.circle(x, factors, size=15, fill_color="orange", line_width=3, line_color=LineColor)
        
#        tool = BoxEditTool(renderers=[c1])
        tool2 = BoxSelectTool(dimensions="width") # To make a multiple selection, press the SHIFT key. To clear the selection, press the ESC key
        
#        dots_fig.add_tools(tool) # disappears the points..
        dots_fig.add_tools(tool2)
        dots_fig.add_tools(CrosshairTool(dimensions='height'))
        
        return dots_fig

#    fig2.axis.visible = False
#    fig2.image

    phase1 = column(table, slider)
    phase2 = row(phase1, fig2)
    phase3 = row(event_chart(), set_vbar())
    phase4 = column(phase2, phase3 , checkbox, radio)
    
#    phase5 = bk_example.bk_example()
#    doc.add_root(phase5)
    
#    doc.add_root(phase4)
    
    tab1 = Panel(child=phase4, title="phase4 part")
    
#    doc.add_root(toggle)
#    doc.add_root(figImg)
    
    secPanelLy = column(toggle, figImg, checkbox_button_group)
    tab2 = Panel(child=secPanelLy, title="other parts", closable=False)
    
    tabs = Tabs(tabs=[ tab1, tab2 ])
    
    if __name__!='__main__':    
        print("doc : ", doc)
        print("name : ",__name__)
        doc().add_root(tabs)
    else:
        doc.add_root(tabs)

#    doc.add_root(event_chart_example())
    
    toggle_callback.args['a']=slider
    toggle_callback.args['b']=toggle
    toggle_callback.args['c']=checkbox
    toggle_callback.args['d']=radio
Beispiel #41
0
    def device_data_tab(self):

        """Reading device data"""
        self.data_status = Div(text="", width=self.page_width)

        data_connect = Button(label='Connect to UT330',
                              button_type="success")
        data_read = Button(label='Read data',
                           button_type="success")
        data_write = Button(label='Write data to disk',
                            button_type="success")
        data_erase = Button(label='Erase data',
                            button_type="success")
        data_disconnect = Button(label='Disconnect from UT330',
                                 button_type="success")

        data_connect.on_click(self.data_connect)
        data_read.on_click(self.data_read)
        data_write.on_click(self.data_write)
        data_erase.on_click(self.data_erase)
        data_disconnect.on_click(self.data_disconnect)

        if self.device_connected:
            self.data_status.text = ('UT330 device connected. The Read, '
                                     'Write, Erase, and Disconnect buttons '
                                     'will work.')
        else:
            self.data_status.text = ('UT330 device is <strong>NOT</strong> '
                                     'connected. The '
                                     'Read, Write, Erase, and Disconnect '
                                     'buttons will <strong>not work</strong>. '
                                     'Press the '
                                     'Connect button if the UT330 is '
                                     'connected on a USB port.')

        # Layout
        l = layout([[self.data_status],
                    [data_connect, data_disconnect],
                    [data_read, data_write, data_erase]],
                   width=self.page_width)

        return Panel(child=l,
                     title="Read from device")
f_photo.title.text_color = (0.7, 0.7, 0.7)
f_photo.title.text_font = 'helvetica'
f_photo.title.text_font_size = '20pt'
f_photo.title.align = 'left'

#Style the grid
f_photo.grid.grid_line_color = (1, 1, 1)
f_photo.grid.grid_line_alpha = 0.3
f_photo.grid.grid_line_dash = [5, 3]

f_aux.grid.grid_line_color = (1, 1, 1)
f_aux.grid.grid_line_alpha = 0.3
f_aux.grid.grid_line_dash = [5, 3]

#add widgets (dropdown button) to save data as csv. CustomJS required to download data in browser
button = Button(label='Export data', button_type='danger')
js_download = """
var csv = source.get('data');
var filetext = 'time;photo_current;laser_current;temperature;date\\n';
for (i=0; i < csv['date'].length; i++) {
    var currRow = [csv['time'][i].toString(),
                   csv['photo_current'][i].toString(),
                   csv['laser_current'][i].toString(),
                   csv['date'][i].toString().concat('\\n')];

    var joined = currRow.join(';');
    filetext = filetext.concat(joined);
}

var filename = 'sensor_data.csv';
var blob = new Blob([filetext], { type: 'text/csv;charset=utf-8;' });
	print 'After: ' + str(undefinedSource.data) + '\n'

###########################################################################
# Setup figure, glyphs, and a datasource

glyphDict = create_glyphs()
undefinedSource = bkM.ColumnDataSource(data=dict(x=[0,4,8], y=[0,0,0], width=[0.25,0.25,0.25], height=[2,2,2]))
fig = create_fig()

###########################################################################
# Add widgets and their callbacks

from bokeh.models.widgets import Button, TextInput

changeA_button = Button(label='UpdateFig A')
changeA_button.on_click(update_figure_A)

changeB_button = Button(label='UpdateFig B')
changeB_button.on_click(update_figure_B)

widgets = [changeA_button, changeB_button]

from bokeh.layouts import widgetbox
widgetBox = widgetbox(*widgets, sizing_mode='fixed')

# Add figure and widgets to a layout
###########################################################################
from bokeh.layouts import layout
layout = layout( [[fig], [widgetBox]], sizing_mode='fixed')
Beispiel #44
0
df = pd.read_csv(join(dirname(__file__), 'salary_data.csv'))

source = ColumnDataSource(data=dict())

def update():
    current = df[(df['salary'] >= slider.value[0]) & (df['salary'] <= slider.value[1])].dropna()
    source.data = {
        'name'             : current.name,
        'salary'           : current.salary,
        'years_experience' : current.years_experience,
    }

slider = RangeSlider(title="Max Salary", start=10000, end=110000, value=(10000, 50000), step=1000, format="0,0")
slider.on_change('value', lambda attr, old, new: update())

button = Button(label="Download", button_type="success")
button.callback = CustomJS(args=dict(source=source),
                           code=open(join(dirname(__file__), "download.js")).read())

columns = [
    TableColumn(field="name", title="Employee Name"),
    TableColumn(field="salary", title="Income", formatter=NumberFormatter(format="$0,0.00")),
    TableColumn(field="years_experience", title="Experience (years)")
]

data_table = DataTable(source=source, columns=columns, width=800)

controls = widgetbox(slider, button)
table = widgetbox(data_table)

curdoc().add_root(row(controls, table))
	def plotting(self):

		if self.debug:
			self.debug_file = open("debug_output.txt", "w")
			self.debug_file.write("Initialized plotting subroutine \n")
			 

		TOOLS="pan,wheel_zoom,box_zoom,reset,hover,previewsave"

		tab_plots = []
		self.all_elements = []
		self.elements_comparison = []

		for filename in self.filenames:
			if "ITO" in filename:
				tab_plots.append(self.mass_plotting(filename))
				continue
	
			data_dict = self.data_generation(filename)
			self.data_test(data_dict)

			name_check = data_dict["gen_info"]["DATA FILES"]
			attr_id = name_check[1][4][:-3] + "_" + name_check[2][2]
			self.attribute_ids.append(attr_id)

			attr_extra_y_ranges = False
			attr_extra_x_ranges = False

			local_source_line = []

			"""
			create plots for each datafile and put them in a tab.
			"""

			y_axis_units = [x["y_unit"] for x in data_dict["data"]]
			x_axis_units = [x["x_unit"] for x in data_dict["data"]]

			figure_obj = figure(plot_width = 1000, plot_height = 800, y_axis_type = "log",
			title = attr_id, tools = TOOLS)
			#figure_obj.axes.major_label_text_font_size("12pt")
			#figure_obj.major_label_text_font_size("12pt")

			hover = figure_obj.select(dict(type = HoverTool))
			hover.tooltips = [
							("Element:", "@element"),
							("(x, y):", "($x, $y)")]

			self.figure_data.append((figure_obj, data_dict))
		
			figure_obj.yaxis.axis_label = y_axis_units[0]
			figure_obj.xaxis.axis_label = x_axis_units[0]

			if not all(x == y_axis_units[0] for x in y_axis_units):
				for unit, dataset in zip(y_axis_units, data_dict["data"]): 
					if not unit == y_axis_units[0]:
						
						extra_y_ranges_exists = attr_extra_y_ranges
						extra_y_ranges_exists = True

						if self.debug:
							  
							self.debug_file.write("Added extra y-axis for file_id: %s, element: %s | New length %g \n" 
								%(attr_id, dataset["sample_element"], len(figure_obj.yaxis)))
							 

						figure_obj.extra_y_ranges =  {"foo": Range1d(start = np.amin(dataset["y"]),
						end = np.amax(dataset["y"]))}
						figure_obj.add_layout(LogAxis(y_range_name = "foo", axis_label = unit), "right")
						break

			if not all(x == x_axis_units[0] for x in x_axis_units):
				for unit, dataset in zip(x_axis_units, data_dict["data"]): 
					if not unit == x_axis_units[0]:
						
						extra_x_ranges_exists = attr_extra_x_ranges
						extra_x_ranges_exists = True
						
						if self.debug:
							  
							self.debug_file.write("Added extra x-axis for file_id: %s, element: %s. | New length %g \n" 
								%(attr_id, dataset["sample_element"], len(figure_obj.yaxis)))
							 
			
						figure_obj.extra_x_ranges =  {"bar": Range1d(start = np.amin(dataset["x"]),
						end = np.amax(dataset["x"]))}
						figure_obj.add_layout(LinearAxis(x_range_name = "bar", axis_label = unit), "above")
						break

			figure_obj.xaxis.axis_label = x_axis_units[0]
			colour_list = Spectral11 + RdPu9 + Oranges9
			colour_indices = [0, 2, 8, 10, 12, 14, 20, 22, 1, 3, 9, 11, 13, 15]


			list_of_elements = []
			source_list = []
			line_list = []

			for dataset, color_index in zip(data_dict["data"], colour_indices):

				self.all_elements.append(dataset["sample_element"]) #strip isotope number 
				color = colour_list[color_index]

				source = ColumnDataSource(data = dataset) #Datastructure for source of plotting

				self.source_test(source)

				list_of_elements.append(dataset["sample_element"])
				line_glyph = figure_obj.line("x", "y", source = source, 
							line_width = 2,
							line_color = color, 
							legend = dataset["sample_element"])

				if self.debug:
					self.debug_file.write("Create line object on figure %s  at %s \n" %(id(figure_obj), id(line_glyph)))
					 

				line_list.append(line_glyph)
				source_list.append(source)

			local_source_line.append([[source, line] for source, line in zip(source_list, line_list)])
			self.source_line.append(local_source_line)

			#Calculations on the dataset
			text_input_rsf = TextInput(value = "default", title = "RSF or SF (at/cm^3): ")
			do_integral_button = Button(label = "Calibration integral")
			smoothing_button = Button(label = "smth selct elem")
			matplot_button = Button(label = "Create matplotlib fig")

			text_input_sputter = TextInput(value = "default", title = "Sputter speed: number unit")
			text_input_crater_depth = TextInput(value = "default", title = "Depth of crater in: number unit")
			


			radio_group = RadioGroup(labels = list_of_elements, active=0)


			text_input_xval_integral = TextInput(value = "0", title = "x-delimiter ")
			text_input_dose = TextInput(value = "0", title = "Dose[cm^-2] ")

			#Save files for later use
			save_flexDPE_button = Button(label = "Save element for FlexPDE")
			save_all_flexDPE_button = Button(label = "Save all elements for FlexPDE")
			save_textfile_button = Button(label = "Sava Data in textfile")

			#Pointers to methods on click / change handlers
			radio_group.on_change("active", lambda attr, old, new: None)

			matplot_button.on_click(lambda source_list = source_list:
										self.matplotlib_export(source_list))
			
			do_integral_button.on_click(lambda 
											source_list = source_list, 
											line_list = line_list, 
											source_line = self.source_line,
											figure_data = self.figure_data,
											data_dict = data_dict,
											radio = radio_group,
											x_box = text_input_xval_integral, 
											dose = text_input_dose,
											extra_y_ranges = attr_extra_y_ranges: 
										self.integrate(data_dict, source_list, line_list, source_line, figure_data, radio, x_box, dose, extra_y_ranges))

			smoothing_button.on_click(lambda 
										source_list = source_list,
										radio = radio_group, 
										data_dict = data_dict,
										x_box = text_input_xval_integral: 
									self.smoothing(source_list, data_dict, radio, x_box) )

			save_flexDPE_button.on_click(lambda 
											source_list = source_list,
											attrname = attr_id,
											radio = radio_group: 
										self.write_to_flexPDE(source_list, attrname, radio))

			save_all_flexDPE_button.on_click(lambda 
												source_list = source_list, 
												attrname = attr_id:
												self.write_all_to_flexPDE(source_list, attrname))

			save_textfile_button.on_click(lambda 
											data_dict = data_dict, 
											source_list = source_list,
											attrname = attr_id,
											radio = radio_group:
											self.write_new_datafile(data_dict, source_list, attrname,radio))


			text_input_rsf.on_change("value", lambda attr, old, new, 
												radio = radio_group, 
												data_dict = data_dict,
												figure = figure_obj,
												source_list = source_list,
												text_input = text_input_rsf,
												line_list = line_list,
												which = "rsf":
												self.update_data(line_list, data_dict, source_list, figure, radio, text_input, new, which))


			text_input_sputter.on_change("value", lambda attr, old, new, 
													radio = radio_group, 
													data_dict = data_dict,
													figure = figure_obj,
													source_list = source_list, 
													text_input = text_input_sputter,
													which = "sputter":
													self.update_data(data_dict, source_list, figure, radio, text_input, new, which))

			text_input_crater_depth.on_change("value", lambda attr, old, new, 
														radio = radio_group, 
														data_dict = data_dict,
														source_list = source_list,
														figure = figure_obj,
														text_input = text_input_crater_depth, 
														which = "crater_depth":
														self.update_data(data_dict, source_list, figure, radio, text_input, new, which))


			#Initialization of actual plotting. 
			tab_plots.append(Panel(child = hplot(figure_obj, 
										   vform(
										   vform(radio_group, save_flexDPE_button, save_all_flexDPE_button, save_textfile_button, matplot_button), 
										   vform(text_input_rsf, smoothing_button, text_input_sputter, text_input_crater_depth)
										   ),
										   vform(text_input_xval_integral, text_input_dose, do_integral_button)),
										   title = attr_id))



		"""
		Check to see if one or more element exists in the samples and creat a comparison plot for each 
		of those elements.
		"""
		
		for element in self.all_elements:
			checkers = list(self.all_elements)
			checkers.remove(element)
			if element in checkers and not element in self.elements_comparison:
				self.elements_comparison.append(element)

		"""create plots for each element that is to be compared """
	
		for comparison_element in self.elements_comparison: 

			figure_obj = figure(plot_width = 1000, plot_height = 800, y_axis_type = "log", title = comparison_element, tools = TOOLS)
			#figure_obj.xaxis.major_label_text_font_size("12pt")
			#figure_obj.yaxis.major_label_text_font_size("12pt")
			
			y_axis_units = []
			x_axis_units = []

			comparison_datasets = []

			for data_dict_iter in self.column(self.figure_data, 1):

				for dataset in data_dict_iter["data"]:

					if dataset["sample_element"] == comparison_element:
						comparison_datasets.append(dataset)
						y_axis_units.append(dataset["y_unit"])
						x_axis_units.append(dataset["x_unit"])

			figure_obj.xaxis.axis_label = comparison_datasets[-1]["x_unit"]
			figure_obj.yaxis.axis_label = comparison_datasets[-1]["y_unit"]

			if not all(x == y_axis_units[-1] for x in y_axis_units):
				for unit, data in zip(y_axis_units, comparison_datasets): 
					if not unit == y_axis_units[-1]:
						figure_obj.extra_y_ranges =  {"foo": Range1d(start = np.amin(data["y"]),
						end = np.amax(data["y"]))}
						figure_obj.add_layout(LogAxis(y_range_name = "foo", axis_label = unit), "right")
						break

			if not all(x == x_axis_units[-1] for x in x_axis_units):
				for unit, data in zip(x_axis_units, comparison_datasets): 
					if not unit == x_axis_units[-1]:
						figure_obj.extra_x_ranges =  {"bar": Range1d(start = np.amin(data["x"]),
						end = np.amax(data["x"]))}
						figure_obj.add_layout(LinearAxis(x_range_name = "bar", axis_label = unit), "above")
						break

			active_sources = []
			for data_dict, source_line_nested, attr_id, color_index  in zip(self.column(self.figure_data, 1), self.source_line,  self.attribute_ids,  colour_indices):

				for dataset, source_lis_coup, in zip(data_dict["data"], source_line_nested[0]):
					
					source_local = source_lis_coup[0]
					active_sources.append(source_local)

					self.source_test(source_local)
					self.source_dataset_test(source_local, dataset)

					if dataset["sample_element"] == comparison_element:
						color = colour_list[color_index]

						"""
						Logic that ensures that plots get put with correspoinding axes. 
						"""
						if dataset["x_unit"] != x_axis_units[-1] or dataset["y_unit"] != y_axis_units[-1]:

							if dataset["x_unit"] != x_axis_units[-1] and dataset["y_unit"] != y_axis_units[-1]:
								name_check = data_dict["gen_info"]["DATA FILES"]
								attr_id = name_check[1][4][:-3] + "_" + name_check[2][2]

								figure_obj.line("x", "y", source = source_local,
								line_width = 2, 
								line_color = color, 
								legend = attr_id,
								x_range_name = "bar", 
								y_range_name = "foo")

							elif dataset["x_unit"] != x_axis_units[-1]:

								figure_obj.line("x", "y", source = source_local,
								line_width = 2, 
								line_color = color, 
								legend = attr_id, 
								x_range_name = "bar")

							else: 

								figure_obj.line("x", "y", source = source_local,
								line_width = 2, 
								line_color = color, 
								legend = attr_id, 
								y_range_name = "foo")

						else: 
							figure_obj.line("x", "y", source = source_local,
							line_width = 2, 
							line_color = color, 
							legend = attr_id)


			matplot_button = Button(label = "Create matplotlib fig")
			save_all_flexDPE_button = Button(label = "Save all elements for FlexPDE")

			matplot_button.on_click(lambda source_list = active_sources:
							self.matplotlib_export(source_list))	

			save_all_flexDPE_button.on_click(lambda 
									source_list = active_sources, 
									attrname = comparison_element:
									self.write_all_to_flexPDE(source_list, attrname))


			tab_plots.append(Panel(child = hplot(figure_obj, vform(save_all_flexDPE_button, matplot_button)), 
				title = comparison_element))	


		tabs = Tabs(tabs = tab_plots)
		#curdoc().add_root(tabs)
		session = push_session(curdoc())
		session.show()
		session.loop_until_closed()
def plot():

    # FIGURES AND X-AXIS
    fig1 = Figure(title = 'Dive Profile',  plot_width = WIDTH, plot_height = HEIGHT, tools = TOOLS)
    fig2 = Figure(title = 'Dive Controls', plot_width = WIDTH, plot_height = HEIGHT, tools = TOOLS, x_range=fig1.x_range)
    fig3 = Figure(title = 'Attitude',      plot_width = WIDTH, plot_height = HEIGHT, tools = TOOLS, x_range=fig1.x_range)
    figs = gridplot([[fig1],[fig2],[fig3]])

    # Formatting x-axis
    timeticks = DatetimeTickFormatter(formats=dict(seconds =["%b%d %H:%M:%S"],
                                                   minutes =["%b%d %H:%M"],
                                                   hourmin =["%b%d %H:%M"],
                                                   hours =["%b%d %H:%M"],
                                                   days  =["%b%d %H:%M"],
                                                   months=["%b%d %H:%M"],
                                                   years =["%b%d %H:%M %Y"]))
    fig1.xaxis.formatter = timeticks
    fig2.xaxis.formatter = timeticks
    fig3.xaxis.formatter = timeticks

    # removing gridlines
    fig1.xgrid.grid_line_color = None
    fig1.ygrid.grid_line_color = None
    fig2.xgrid.grid_line_color = None
    fig2.ygrid.grid_line_color = None
    fig3.xgrid.grid_line_color = None
    fig3.ygrid.grid_line_color = None

    # INPUT WIDGETS
    collection_list = CONN[DB].collection_names(include_system_collections=False)
    gliders = sorted([platformID for platformID in collection_list if len(platformID)>2])
    gliders = Select(title = 'PlatformID', value = gliders[0], options = gliders)
    prev_glider = Button(label = '<')
    next_glider = Button(label = '>')
    glider_controlbox = HBox(children = [gliders, prev_glider, next_glider], height=80)

    chunkations = Select(title = 'Chunkation', value = 'segment', options = ['segment', '24hr', '30days', '-ALL-'])
    chunk_indicator = TextInput(title = 'index', value = '0')
    prev_chunk = Button(label = '<')
    next_chunk = Button(label = '>')
    chunk_ID   = PreText(height=80)
    chunk_controlbox = HBox(chunkations,
                            HBox(chunk_indicator, width=25),
                            prev_chunk, next_chunk,
                            chunk_ID,
                            height = 80)

    control_box = HBox(glider_controlbox,
                        chunk_controlbox)

    # DATA VARS
    deadby_date = ''
    depth    = ColumnDataSource(dict(x=[],y=[]))
    vert_vel = ColumnDataSource(dict(x=[],y=[]))

    mbpump   = ColumnDataSource(dict(x=[],y=[]))
    battpos  = ColumnDataSource(dict(x=[],y=[]))
    pitch    = ColumnDataSource(dict(x=[],y=[]))

    mfin      = ColumnDataSource(dict(x=[],y=[]))
    cfin      = ColumnDataSource(dict(x=[],y=[]))
    mroll     = ColumnDataSource(dict(x=[],y=[]))
    mheading = ColumnDataSource(dict(x=[],y=[]))
    cheading = ColumnDataSource(dict(x=[],y=[]))

    # AXIS setup
    colors = COLORS[:]

    fig1.y_range.flipped = True
    fig1.yaxis.axis_label = 'm_depth (m)'
    fig1.extra_y_ranges = {'vert_vel': Range1d(start=-50, end=50),
                           'dummy':    Range1d(start=0, end=100)}
    fig1.add_layout(place = 'right',
                    obj = LinearAxis(y_range_name = 'vert_vel',
                                     axis_label   = 'vertical velocity (cm/s)'))
    fig1.add_layout(place = 'left',
                    obj = LinearAxis(y_range_name = 'dummy',
                                     axis_label   = ' '))
    fig1.yaxis[1].visible = False
    fig1.yaxis[1].axis_line_alpha = 0
    fig1.yaxis[1].major_label_text_alpha = 0
    fig1.yaxis[1].major_tick_line_alpha = 0
    fig1.yaxis[1].minor_tick_line_alpha = 0


    fig2.yaxis.axis_label = 'pitch (deg)'
    fig2.y_range.start, fig2.y_range.end = -40,40
    fig2.extra_y_ranges = {'battpos': Range1d(start=-1, end = 1),
                           'bpump':   Range1d(start=-275, end=275)}
    fig2.add_layout(place = 'right',
                    obj = LinearAxis(y_range_name = 'battpos',
                                     axis_label = 'battpos (in)'))
    fig2.add_layout(place = 'left',
                    obj = LinearAxis(y_range_name = 'bpump',
                                     axis_label   = 'bpump (cc)'))
    fig2.yaxis[1].visible = False # necessary for spacing. later gets set to true


    fig3.yaxis.axis_label = 'fin/roll (deg)'
    fig3.y_range.start, fig3.y_range.end = -30, 30
    fig3.extra_y_ranges = {'heading': Range1d(start=0, end=360), #TODO dynamic avg centering
                           'dummy':   Range1d(start=0, end=100)}
    fig3.add_layout(place = 'right',
                    obj = LinearAxis(y_range_name = 'heading',
                                     axis_label   = 'headings (deg)'))
    fig3.add_layout(place = 'left',
                    obj = LinearAxis(y_range_name = 'dummy',
                                     axis_label   = ' '))
    fig3.yaxis[1].visible = False
    fig3.yaxis[1].axis_line_alpha = 0
    fig3.yaxis[1].major_label_text_alpha = 0
    fig3.yaxis[1].major_tick_line_alpha = 0
    fig3.yaxis[1].minor_tick_line_alpha = 0

    # PLOT OBJECTS
    fig1.line(  'x', 'y', source = depth,    legend = 'm_depth',     color = 'red')
    fig1.circle('x', 'y', source = depth,    legend = 'm_depth',     color = 'red')
    fig1.line(  'x', 'y', source = vert_vel, legend = 'vert_vel',    color = 'green',     y_range_name = 'vert_vel')
    fig1.circle('x', 'y', source = vert_vel, legend = 'vert_vel',    color = 'green',     y_range_name = 'vert_vel')
    fig1.renderers.append(Span(location = 0, dimension = 'width',    y_range_name = 'vert_vel',
                               line_color= 'green', line_dash='dashed', line_width=1))

    fig2.line(  'x', 'y', source = pitch,   legend = "m_pitch",    color = 'indigo')
    fig2.circle('x', 'y', source = pitch,   legend = "m_pitch",    color = 'indigo')
    fig2.line(  'x', 'y', source = battpos, legend = 'm_battpos',  color = 'magenta',   y_range_name = 'battpos')
    fig2.circle('x', 'y', source = battpos, legend = 'm_battpos',  color = 'magenta',   y_range_name = 'battpos')
    fig2.line(  'x', 'y', source = mbpump,  legend = "m_'bpump'",  color = 'blue',      y_range_name = 'bpump')
    fig2.circle('x', 'y', source = mbpump,  legend = "m_'bpump'",  color = 'blue',      y_range_name = 'bpump')
    fig2.renderers.append(Span(location = 0, dimension = 'width',
                               line_color= 'black', line_dash='dashed', line_width=1))
    fig3.line(  'x', 'y', source = mfin,       legend = 'm_fin',     color = 'cyan')
    fig3.circle('x', 'y', source = mfin,       legend = 'm_fin',     color = 'cyan')
    fig3.line(  'x', 'y', source = cfin,       legend = 'c_fin',     color = 'orange')
    fig3.circle('x', 'y', source = cfin,       legend = 'c_fin',     color = 'orange')
    fig3.line(  'x', 'y', source = mroll,      legend = 'm_roll',    color = 'magenta')
    fig3.circle('x', 'y', source = mroll,      legend = 'm_roll',    color = 'magenta')
    fig3.line(  'x', 'y', source = mheading,   legend = 'm_heading', color = 'blue',    y_range_name = 'heading')
    fig3.circle('x', 'y', source = mheading,   legend = 'm_heading', color = 'blue',    y_range_name = 'heading')
    fig3.line(  'x', 'y', source = cheading,   legend = 'c_heading', color = 'indigo',  y_range_name = 'heading')
    fig3.circle('x', 'y', source = cheading,   legend = 'c_heading', color = 'indigo',  y_range_name = 'heading')
    fig3.renderers.append(Span(location = 0, dimension = 'width',    y_range_name = 'default',
                               line_color= 'black', line_dash='dashed', line_width=1))

    # CALLBACK FUNCS
    def update_data(attrib,old,new):
        g = gliders.value
        chnk = chunkations.value
        chindex = abs(int(chunk_indicator.value))

        depth.data    = dict(x=[],y=[])
        vert_vel.data = dict(x=[],y=[])
        mbpump.data   = dict(x=[],y=[])
        battpos.data  = dict(x=[],y=[])
        pitch.data    = dict(x=[],y=[])

        mfin.data     = dict(x=[],y=[])
        cfin.data     = dict(x=[],y=[])
        mroll.data    = dict(x=[],y=[])
        mheading.data = dict(x=[],y=[])
        cheading.data = dict(x=[],y=[])


        depth.data,startend   = load_sensor(g, 'm_depth', chnk, chindex)

        if chnk == 'segment':
            xbd = startend[2]
            chunk_ID.text = '{} {} \n{} ({}) \nSTART: {} \nEND:   {}'.format(g, xbd['mission'],
                                                                             xbd['onboard_filename'], xbd['the8x3_filename'],
                                                                             e2ts(xbd['start']), e2ts(xbd['end']))
            if len(set(depth.data['x']))<=1 and attrib == 'chunk':
                if old > new:
                    next_chunk.clicks += 1
                else:
                    prev_chunk.clicks += 1
                return
            elif len(set(depth.data['x']))<=1 and chunk_indicator.value == 0:
                chunk_indicator.value = 1

        elif chnk in ['24hr', '30days']:
            chunk_ID.text = '{} \nSTART: {} \nEND:   {}'.format(g, e2ts(startend[0]), e2ts(startend[1]))
        elif chnk == '-ALL-':
            chunk_ID.text = '{} \nSTART: {} \nEND:   {}'.format(g,e2ts(depth.data['x'][0] /1000),
                                                                  e2ts(depth.data['x'][-1]/1000))


        vert_vel.data  = calc_vert_vel(depth.data)

        mbpump.data,_     = load_sensor(g, 'm_de_oil_vol', chnk, chindex)
        if len(mbpump.data['x']) > 1:
            #for yax in fig2.select('mbpump'):
            #    yax.legend = 'm_de_oil_vol'
            pass
        else:
            mbpump.data,_     = load_sensor(g, 'm_ballast_pumped', chnk, chindex)
            #for yax in fig2.select('mbpump'):
            #    yax.legend = 'm_ballast_pumped'
        battpos.data,_ = load_sensor(g, 'm_battpos',    chnk, chindex)
        pitch.data,_   = load_sensor(g, 'm_pitch',      chnk, chindex)
        pitch.data['y'] = [math.degrees(y) for y in pitch.data['y']]

        mfin.data,_     = load_sensor(g, 'm_fin',     chnk, chindex)
        cfin.data,_     = load_sensor(g, 'c_fin',     chnk, chindex)
        mroll.data,_    = load_sensor(g, 'm_roll',    chnk, chindex)
        mheading.data,_ = load_sensor(g, 'm_heading', chnk, chindex)
        cheading.data,_ = load_sensor(g, 'c_heading', chnk, chindex)
        mfin.data['y']     = [math.degrees(y) for y in mfin.data['y']]
        cfin.data['y']     = [math.degrees(y) for y in cfin.data['y']]
        mheading.data['y'] = [math.degrees(y) for y in mheading.data['y']]
        cheading.data['y'] = [math.degrees(y) for y in cheading.data['y']]
        mroll.data['y']    = [math.degrees(y) for y in mroll.data['y']]

        fig1.yaxis[1].visible = True
        fig2.yaxis[1].visible = True
        fig3.yaxis[1].visible = True


    #GLIDER SELECTS
    def glider_buttons(increment):
        ops = gliders.options
        new_index = ops.index(gliders.value) + increment
        if new_index >= len(ops):
            new_index = 0
        elif new_index < 0:
            new_index = len(ops)-1
        gliders.value = ops[new_index]
        chunkation_update(None, None, None) #reset chunk indicator and clicks
    def next_glider_func():
        glider_buttons(1)
    def prev_glider_func():
        glider_buttons(-1)
    def update_glider(attrib,old,new):
        chunk_indicator.value = '0'
        #update_data(None,None,None)


    gliders.on_change('value', update_glider)
    next_glider.on_click(next_glider_func)
    prev_glider.on_click(prev_glider_func)


        #CHUNK SELECTS
    def chunkation_update(attrib,old,new):
        chunk_indicator.value = '0'
        prev_chunk.clicks = 0
        next_chunk.clicks = 0
        update_data(None,None,None)
        if new == '-ALL-':
            chunk_indicator.value = '-'

    def chunk_func():
        chunkdiff = prev_chunk.clicks - next_chunk.clicks
        if chunkdiff < 0:
            prev_chunk.clicks = 0
            next_chunk.clicks = 0
            chunkdiff = 0
        print (chunkdiff)
        chunk_indicator.value = str(chunkdiff)

    def chunk_indicator_update(attrib,old,new):
        try:
            if abs(int(old)-int(new))>1: #manual update, triggers new non-manual indicator update, ie else clause below
                prev_chunk.clicks = int(new)
                next_chunk.clicks = 0
            else:
                update_data('chunk',int(old),int(new))
            print("UPDATE", old, new)
        except Exception as e:
            print(type(e),e, old, new)

    chunkations.on_change('value', chunkation_update)
    chunk_indicator.on_change('value', chunk_indicator_update)
    next_chunk.on_click(chunk_func)
    prev_chunk.on_click(chunk_func)

    update_data(None,None,None)

    return vplot(control_box, figs)
Beispiel #47
0
    # show a separate signal for each file in a group
    selected_file.show_files_separately(1 in new)


def change_displayed_doc():
    if doc.roots[0] == landing_page:
        doc.remove_root(landing_page)
        doc.add_root(layout)


# ---------------- Build Website Layout -------------------

# select file
file_selection_button = Button(label="Select Files",
                               button_type="success",
                               width=120)
file_selection_button.on_click(load_files_group)

files_selector_spacer = Spacer(width=10)

group_selection_button = Button(label="Select Directory",
                                button_type="primary",
                                width=140)
group_selection_button.on_click(load_directory_group)

unload_file_button = Button(label="Unload", button_type="danger", width=50)
unload_file_button.on_click(unload_file)

# files selection box
files_selector = Select(title="Files:", options=[])
Beispiel #48
0
    def _create_interact_ui(doc,
                            minp=minimum_period,
                            maxp=maximum_period,
                            resolution=resolution):
        """Create BLS interact user interface."""
        if minp is None:
            minp = 0.3
        if maxp is None:
            maxp = (lc.time[-1].value - lc.time[0].value) / 2
        # TODO: consider to accept Time as minp / maxp, and convert it to unitless days

        time_format = ""
        if lc.time.format == "bkjd":
            time_format = " - 2454833 days"
        if lc.time.format == "btjd":
            time_format = " - 2457000 days"

        # Some sliders
        duration_slider = Slider(
            start=0.01,
            end=0.5,
            value=0.05,
            step=0.01,
            title="Duration [Days]",
            width=400,
        )

        npoints_slider = Slider(
            start=500,
            end=10000,
            value=resolution,
            step=100,
            title="BLS Resolution",
            width=400,
        )

        # Set up the period values, BLS model and best period
        period_values = np.logspace(np.log10(minp), np.log10(maxp),
                                    npoints_slider.value)
        period_values = period_values[(period_values > duration_slider.value)
                                      & (period_values < maxp)]
        model = BoxLeastSquares(lc.time, lc.flux)
        result = model.power(period_values, duration_slider.value)
        loc = np.argmax(result.power)
        best_period = result.period[loc]
        best_t0 = result.transit_time[loc]

        # Some Buttons
        double_button = Button(label="Double Period",
                               button_type="danger",
                               width=100)
        half_button = Button(label="Half Period",
                             button_type="danger",
                             width=100)
        text_output = Paragraph(
            text="Period: {} days, T0: {}{}".format(
                _round_strip_unit(best_period, 7),
                _round_strip_unit(best_t0, 7),
                time_format,
            ),
            width=350,
            height=40,
        )

        # Set up BLS source
        bls_source = prepare_bls_datasource(result, loc)
        bls_source_units = dict(
            transit_time_format=result["transit_time"].format,
            transit_time_scale=result["transit_time"].scale,
            period=result["period"].unit,
        )
        bls_help_source = prepare_bls_help_source(bls_source,
                                                  npoints_slider.value)

        # Set up the model LC
        mf = model.model(lc.time, best_period, duration_slider.value, best_t0)
        mf /= np.median(mf)
        mask = ~(convolve(np.asarray(mf == np.median(mf)), Box1DKernel(2)) >
                 0.9)
        model_lc = _to_lc(lc.time[mask], mf[mask])

        model_lc_source = _to_ColumnDataSource(
            data=dict(time=model_lc.time, flux=model_lc.flux))

        # Set up the LC
        nb = int(np.ceil(len(lc.flux) / 5000))
        lc_source = prepare_lightcurve_datasource(lc[::nb])
        lc_help_source = prepare_lc_help_source(lc)

        # Set up folded LC
        nb = int(np.ceil(len(lc.flux) / 10000))
        f = lc.fold(best_period, best_t0)
        f_source = prepare_folded_datasource(f[::nb])
        f_help_source = prepare_f_help_source(f)

        f_model_lc = model_lc.fold(best_period, best_t0)
        f_model_lc = _to_lc(_as_1d(f.time.min()), [1]).append(f_model_lc)
        f_model_lc = f_model_lc.append(_to_lc(_as_1d(f.time.max()), [1]))

        f_model_lc_source = _to_ColumnDataSource(
            data=dict(phase=f_model_lc.time, flux=f_model_lc.flux))

        def _update_light_curve_plot(event):
            """If we zoom in on LC plot, update the binning."""
            mint, maxt = fig_lc.x_range.start, fig_lc.x_range.end
            inwindow = (lc.time.value > mint) & (lc.time.value < maxt)
            nb = int(np.ceil(inwindow.sum() / 5000))
            temp_lc = lc[inwindow]
            _update_source(lc_source, {
                "time": temp_lc.time[::nb],
                "flux": temp_lc.flux[::nb]
            })

        def _update_folded_plot(event):
            loc = np.argmax(bls_source.data["power"])
            best_period = bls_source.data["period"][loc]
            best_t0 = bls_source.data["transit_time"][loc]
            # Otherwise, we can just update the best_period index
            minphase, maxphase = fig_folded.x_range.start, fig_folded.x_range.end
            f = lc.fold(best_period, best_t0)
            inwindow = (f.time > minphase) & (f.time < maxphase)
            nb = int(np.ceil(inwindow.sum() / 10000))
            _update_source(
                f_source,
                {
                    "phase": f[inwindow].time[::nb],
                    "flux": f[inwindow].flux[::nb]
                },
            )

        # Function to update the widget
        def _update_params(all=False, best_period=None, best_t0=None):
            if all:
                # If we're updating everything, recalculate the BLS model
                minp, maxp = fig_bls.x_range.start, fig_bls.x_range.end
                period_values = np.logspace(np.log10(minp), np.log10(maxp),
                                            npoints_slider.value)
                ok = (period_values > duration_slider.value) & (period_values <
                                                                maxp)
                if ok.sum() == 0:
                    return
                period_values = period_values[ok]
                result = model.power(period_values, duration_slider.value)
                ok = (_isfinite(result["power"])
                      & _isfinite(result["duration"])
                      & _isfinite(result["transit_time"])
                      & _isfinite(result["period"]))
                ok_result = dict(
                    period=result["period"]
                    [ok],  # useful for accessing values with units needed later
                    power=result["power"][ok],
                    duration=result["duration"][ok],
                    transit_time=result["transit_time"][ok],
                )
                _update_source(bls_source, ok_result)
                loc = np.nanargmax(ok_result["power"])
                best_period = ok_result["period"][loc]
                best_t0 = ok_result["transit_time"][loc]

                minpow, maxpow = (
                    bls_source.data["power"].min() * 0.95,
                    bls_source.data["power"].max() * 1.05,
                )
                fig_bls.y_range.start = minpow
                fig_bls.y_range.end = maxpow

            # Otherwise, we can just update the best_period index
            minphase, maxphase = fig_folded.x_range.start, fig_folded.x_range.end
            f = lc.fold(best_period, best_t0)
            inwindow = (f.time > minphase) & (f.time < maxphase)
            nb = int(np.ceil(inwindow.sum() / 10000))
            _update_source(
                f_source,
                {
                    "phase": f[inwindow].time[::nb],
                    "flux": f[inwindow].flux[::nb]
                },
            )

            mf = model.model(lc.time, best_period, duration_slider.value,
                             best_t0)
            mf /= np.median(mf)
            mask = ~(convolve(np.asarray(mf == np.median(mf)), Box1DKernel(2))
                     > 0.9)
            model_lc = _to_lc(lc.time[mask], mf[mask])

            _update_source(model_lc_source, {
                "time": model_lc.time,
                "flux": model_lc.flux
            })

            f_model_lc = model_lc.fold(best_period, best_t0)
            f_model_lc = _to_lc(_as_1d(f.time.min()), [1]).append(f_model_lc)
            f_model_lc = f_model_lc.append(_to_lc(_as_1d(f.time.max()), [1]))

            _update_source(f_model_lc_source, {
                "phase": f_model_lc.time,
                "flux": f_model_lc.flux
            })

            vertical_line.update(location=best_period.value)
            fig_folded.title.text = "Period: {} days \t T0: {}{}".format(
                _round_strip_unit(best_period, 7),
                _round_strip_unit(best_t0, 7),
                time_format,
            )
            text_output.text = "Period: {} days, \t T0: {}{}".format(
                _round_strip_unit(best_period, 7),
                _round_strip_unit(best_t0, 7),
                time_format,
            )

        # Callbacks
        def _update_upon_period_selection(attr, old, new):
            """When we select a period we should just update a few things, but we should not recalculate model"""
            if len(new) > 0:
                new = new[0]
                best_period = (bls_source.data["period"][new] *
                               bls_source_units["period"])
                best_t0 = Time(
                    bls_source.data["transit_time"][new],
                    format=bls_source_units["transit_time_format"],
                    scale=bls_source_units["transit_time_scale"],
                )
                _update_params(best_period=best_period, best_t0=best_t0)

        def _update_model_slider(attr, old, new):
            """If the duration slider is updated, then update the whole model set."""
            _update_params(all=True)

        def _update_model_slider_EVENT(event):
            """If we update the duration slider, we should update the whole model set.
            This is the same as the _update_model_slider but it has a different call signature...
            """
            _update_params(all=True)

        def _double_period_event():
            fig_bls.x_range.start *= 2
            fig_bls.x_range.end *= 2
            _update_params(all=True)

        def _half_period_event():
            fig_bls.x_range.start /= 2
            fig_bls.x_range.end /= 2
            _update_params(all=True)

        # Help Hover Call Backs
        def _update_folded_plot_help_reset(event):
            f_help_source.data["phase"] = [_at_ratio(f.time, 0.95)]
            f_help_source.data["flux"] = [_at_ratio(f.flux, 0.95)]

        def _update_folded_plot_help(event):
            f_help_source.data["phase"] = [_at_ratio(fig_folded.x_range, 0.95)]
            f_help_source.data["flux"] = [_at_ratio(fig_folded.y_range, 0.95)]

        def _update_lc_plot_help_reset(event):
            lc_help_source.data["time"] = [_at_ratio(lc.time, 0.98)]
            lc_help_source.data["flux"] = [_at_ratio(lc.flux, 0.95)]

        def _update_lc_plot_help(event):
            lc_help_source.data["time"] = [_at_ratio(fig_lc.x_range, 0.98)]
            lc_help_source.data["flux"] = [_at_ratio(fig_lc.y_range, 0.95)]

        def _update_bls_plot_help_event(event):
            # cannot use _at_ratio helper for period, because period is log scaled.
            bls_help_source.data["period"] = [
                bls_source.data["period"][int(npoints_slider.value * 0.95)]
            ]
            bls_help_source.data["power"] = [
                _at_ratio(bls_source.data["power"], 0.98)
            ]

        def _update_bls_plot_help(attr, old, new):
            bls_help_source.data["period"] = [
                bls_source.data["period"][int(npoints_slider.value * 0.95)]
            ]
            bls_help_source.data["power"] = [
                _at_ratio(bls_source.data["power"], 0.98)
            ]

        # Create all the figures.
        fig_folded = make_folded_figure_elements(f, f_model_lc, f_source,
                                                 f_model_lc_source,
                                                 f_help_source)
        fig_folded.title.text = "Period: {} days \t T0: {}{}".format(
            _round_strip_unit(best_period, 7),
            _round_strip_unit(best_t0, 5),
            time_format,
        )
        fig_bls, vertical_line = make_bls_figure_elements(
            result, bls_source, bls_help_source)
        fig_lc = make_lightcurve_figure_elements(lc, model_lc, lc_source,
                                                 model_lc_source,
                                                 lc_help_source)

        # Map changes

        # If we click a new period, update
        bls_source.selected.on_change("indices", _update_upon_period_selection)

        # If we change the duration, update everything, including help button for BLS
        duration_slider.on_change("value", _update_model_slider)
        duration_slider.on_change("value", _update_bls_plot_help)

        # If we increase resolution, update everything
        npoints_slider.on_change("value", _update_model_slider)

        # Make sure the vertical line always goes to the best period.
        vertical_line.update(location=best_period.value)

        # If we pan in the BLS panel, update everything
        fig_bls.on_event(PanEnd, _update_model_slider_EVENT)
        fig_bls.on_event(Reset, _update_model_slider_EVENT)

        # If we pan in the LC panel, rebin the points
        fig_lc.on_event(PanEnd, _update_light_curve_plot)
        fig_lc.on_event(Reset, _update_light_curve_plot)

        # If we pan in the Folded panel, rebin the points
        fig_folded.on_event(PanEnd, _update_folded_plot)
        fig_folded.on_event(Reset, _update_folded_plot)

        # Deal with help button
        fig_bls.on_event(PanEnd, _update_bls_plot_help_event)
        fig_bls.on_event(Reset, _update_bls_plot_help_event)
        fig_folded.on_event(PanEnd, _update_folded_plot_help)
        fig_folded.on_event(Reset, _update_folded_plot_help_reset)
        fig_lc.on_event(PanEnd, _update_lc_plot_help)
        fig_lc.on_event(Reset, _update_lc_plot_help_reset)

        # Buttons
        double_button.on_click(_double_period_event)
        half_button.on_click(_half_period_event)

        # Layout the widget
        doc.add_root(
            layout([
                [fig_bls, fig_folded],
                fig_lc,
                [
                    Spacer(width=70),
                    duration_slider,
                    Spacer(width=50),
                    npoints_slider,
                ],
                [
                    Spacer(width=70),
                    double_button,
                    Spacer(width=70),
                    half_button,
                    Spacer(width=300),
                    text_output,
                ],
            ]))
x = [i for i in xrange(np.shape(rec)[0])]
y = [v for v in rec]
source = ColumnDataSource(data=dict(x=x, y=y))

# Set up plot
plot = Figure(plot_height=800, plot_width=1200, title="Eigenvector Analysis",
              tools="",
              x_range=[0, 289], y_range=[0, 1500.], x_axis_label='Time', y_axis_label='Veh/5m')
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

# Set up widgets
v0 = Slider(title="V0_Coefficient", value=m_projection[0], start=v0_struct[0], end=v0_struct[1])
v1 = Slider(title="V1_Coefficient", value=m_projection[1], start=v1_struct[0], end=v1_struct[1])
v2 = Slider(title="V2_Coefficient", value=m_projection[2], start=v2_struct[0], end=v2_struct[1])
v3 = Slider(title="V3_Coefficient", value=m_projection[3], start=v3_struct[0], end=v3_struct[1])
button= Button(label='Reset')


# Set up callbacks
def update_data(attrname, old, new):
    # Get the current slider values
    v0_value = v0.value
    v1_value = v1.value
    v2_value = v2.value
    v3_value = v3.value

    # Generate the new curve
    m_projection = [v0_value, v1_value, v2_value, v3_value]
    rec = get_reconstruction(m_eigs_t, m_projection, m_mean_vector)
    x = [i for i in xrange(np.shape(rec)[0])]
    y = [v for v in rec]
Beispiel #50
0
def generate_plots(ulog, px4_ulog, db_data, vehicle_data, link_to_3d_page):
    """ create a list of bokeh plots (and widgets) to show """

    plots = []
    data = ulog.data_list

    # COMPATIBILITY support for old logs
    if any(elem.name == 'vehicle_air_data' or elem.name == 'vehicle_magnetometer' for elem in data):
        baro_alt_meter_topic = 'vehicle_air_data'
        magnetometer_ga_topic = 'vehicle_magnetometer'
    else: # old
        baro_alt_meter_topic = 'sensor_combined'
        magnetometer_ga_topic = 'sensor_combined'
    for topic in data:
        if topic.name == 'system_power':
            # COMPATIBILITY: rename fields to new format
            if 'voltage5V_v' in topic.data:     # old (prior to PX4/Firmware:213aa93)
                topic.data['voltage5v_v'] = topic.data.pop('voltage5V_v')
            if 'voltage3V3_v' in topic.data:    # old (prior to PX4/Firmware:213aa93)
                topic.data['voltage3v3_v'] = topic.data.pop('voltage3V3_v')

    # initialize flight mode changes
    flight_mode_changes = get_flight_mode_changes(ulog)

    # VTOL state changes & vehicle type
    is_multicopter = False # this is False for VTOLs as well
    vtol_states = None
    try:
        cur_dataset = ulog.get_dataset('vehicle_status')
        if np.amax(cur_dataset.data['is_vtol']) == 1:
            vtol_states = cur_dataset.list_value_changes('in_transition_mode')
            # find mode after transitions (states: 1=transition, 2=FW, 3=MC)
            for i in range(len(vtol_states)):
                if vtol_states[i][1] == 0:
                    t = vtol_states[i][0]
                    idx = np.argmax(cur_dataset.data['timestamp'] >= t) + 1
                    vtol_states[i] = (t, 2 + cur_dataset.data['is_rotary_wing'][idx])
            vtol_states.append((ulog.last_timestamp, -1))
        elif np.amax(cur_dataset.data['is_rotary_wing']) == 1:
            is_multicopter = True
    except (KeyError, IndexError) as error:
        vtol_states = None



    # Heading
    curdoc().template_variables['title_html'] = get_heading_html(
        ulog, px4_ulog, db_data, link_to_3d_page)

    # info text on top (logging duration, max speed, ...)
    curdoc().template_variables['info_table_html'] = \
        get_info_table_html(ulog, px4_ulog, db_data, vehicle_data, vtol_states)

    curdoc().template_variables['error_labels_html'] = get_error_labels_html()

    hardfault_html = get_hardfault_html(ulog)
    if hardfault_html is not None:
        curdoc().template_variables['hardfault_html'] = hardfault_html


    # Position plot
    data_plot = DataPlot2D(data, plot_config, 'vehicle_local_position',
                           x_axis_label='[m]', y_axis_label='[m]', plot_height='large')
    data_plot.add_graph('y', 'x', colors2[0], 'Estimated',
                        check_if_all_zero=True)
    if not data_plot.had_error: # vehicle_local_position is required
        data_plot.change_dataset('vehicle_local_position_setpoint')
        data_plot.add_graph('y', 'x', colors2[1], 'Setpoint')
        # groundtruth (SITL only)
        data_plot.change_dataset('vehicle_local_position_groundtruth')
        data_plot.add_graph('y', 'x', color_gray, 'Groundtruth')
        # GPS + position setpoints
        plot_map(ulog, plot_config, map_type='plain', setpoints=True,
                 bokeh_plot=data_plot.bokeh_plot)
        if data_plot.finalize() is not None:
            plots.append(data_plot.bokeh_plot)

            # Leaflet Map
            try:
                pos_datas, flight_modes = ulog_to_polyline(ulog, flight_mode_changes)
                curdoc().template_variables['pos_datas'] = pos_datas
                curdoc().template_variables['pos_flight_modes'] = flight_modes
            except:
                pass
            curdoc().template_variables['has_position_data'] = True

    # initialize parameter changes
    changed_params = None
    if not 'replay' in ulog.msg_info_dict: # replay can have many param changes
        if len(ulog.changed_parameters) > 0:
            changed_params = ulog.changed_parameters
            plots.append(None) # save space for the param change button

    ### Add all data plots ###

    x_range_offset = (ulog.last_timestamp - ulog.start_timestamp) * 0.05
    x_range = Range1d(ulog.start_timestamp - x_range_offset, ulog.last_timestamp + x_range_offset)

    # Altitude estimate
    data_plot = DataPlot(data, plot_config, 'vehicle_gps_position',
                         y_axis_label='[m]', title='Altitude Estimate',
                         changed_params=changed_params, x_range=x_range)
    data_plot.add_graph([lambda data: ('alt', data['alt']*0.001)],
                        colors8[0:1], ['GPS Altitude'])
    data_plot.change_dataset(baro_alt_meter_topic)
    data_plot.add_graph(['baro_alt_meter'], colors8[1:2], ['Barometer Altitude'])
    data_plot.change_dataset('vehicle_global_position')
    data_plot.add_graph(['alt'], colors8[2:3], ['Fused Altitude Estimation'])
    data_plot.change_dataset('position_setpoint_triplet')
    data_plot.add_circle(['current.alt'], [plot_config['mission_setpoint_color']],
                         ['Altitude Setpoint'])
    data_plot.change_dataset('actuator_controls_0')
    data_plot.add_graph([lambda data: ('thrust', data['control[3]']*100)],
                        colors8[6:7], ['Thrust [0, 100]'])
    plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

    if data_plot.finalize() is not None: plots.append(data_plot)



    # Roll/Pitch/Yaw angle & angular rate
    for axis in ['roll', 'pitch', 'yaw']:

        # angle
        axis_name = axis.capitalize()
        data_plot = DataPlot(data, plot_config, 'vehicle_attitude',
                             y_axis_label='[deg]', title=axis_name+' Angle',
                             plot_height='small', changed_params=changed_params,
                             x_range=x_range)
        data_plot.add_graph([lambda data: (axis, np.rad2deg(data[axis]))],
                            colors3[0:1], [axis_name+' Estimated'], mark_nan=True)
        data_plot.change_dataset('vehicle_attitude_setpoint')
        # in fixed-wing, the attitude setpoint is allowed to be NaN
        data_plot.add_graph([lambda data: (axis+'_d', np.rad2deg(data[axis+'_d']))],
                            colors3[1:2], [axis_name+' Setpoint'],
                            mark_nan=is_multicopter, use_step_lines=True)
        if axis == 'yaw':
            data_plot.add_graph(
                [lambda data: ('yaw_sp_move_rate', np.rad2deg(data['yaw_sp_move_rate']))],
                colors3[2:3], [axis_name+' FF Setpoint [deg/s]'],
                use_step_lines=True)
        data_plot.change_dataset('vehicle_attitude_groundtruth')
        data_plot.add_graph([lambda data: (axis, np.rad2deg(data[axis]))],
                            [color_gray], [axis_name+' Groundtruth'])
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        if data_plot.finalize() is not None: plots.append(data_plot)

        # rate
        data_plot = DataPlot(data, plot_config, 'vehicle_attitude',
                             y_axis_label='[deg/s]', title=axis_name+' Angular Rate',
                             plot_height='small', changed_params=changed_params,
                             x_range=x_range)
        data_plot.add_graph([lambda data: (axis+'speed', np.rad2deg(data[axis+'speed']))],
                            colors3[0:1], [axis_name+' Rate Estimated'], mark_nan=True)
        data_plot.change_dataset('vehicle_rates_setpoint')
        data_plot.add_graph([lambda data: (axis, np.rad2deg(data[axis]))],
                            colors3[1:2], [axis_name+' Rate Setpoint'],
                            mark_nan=True, use_step_lines=True)
        axis_letter = axis[0].upper()
        rate_int_limit = '(*100)'
        # this param is MC/VTOL only (it will not exist on FW)
        rate_int_limit_param = 'MC_' + axis_letter + 'R_INT_LIM'
        if rate_int_limit_param in ulog.initial_parameters:
            rate_int_limit = '[-{0:.0f}, {0:.0f}]'.format(
                ulog.initial_parameters[rate_int_limit_param]*100)
        data_plot.change_dataset('rate_ctrl_status')
        data_plot.add_graph([lambda data: (axis, data[axis+'speed_integ']*100)],
                            colors3[2:3], [axis_name+' Rate Integral '+rate_int_limit])
        data_plot.change_dataset('vehicle_attitude_groundtruth')
        data_plot.add_graph([lambda data: (axis+'speed', np.rad2deg(data[axis+'speed']))],
                            [color_gray], [axis_name+' Rate Groundtruth'])
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        if data_plot.finalize() is not None: plots.append(data_plot)



    # Local position
    for axis in ['x', 'y', 'z']:
        data_plot = DataPlot(data, plot_config, 'vehicle_local_position',
                             y_axis_label='[m]', title='Local Position '+axis.upper(),
                             plot_height='small', changed_params=changed_params,
                             x_range=x_range)
        data_plot.add_graph([axis], colors2[0:1], [axis.upper()+' Estimated'], mark_nan=True)
        data_plot.change_dataset('vehicle_local_position_setpoint')
        data_plot.add_graph([axis], colors2[1:2], [axis.upper()+' Setpoint'],
                            mark_nan=True, use_step_lines=True)
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        if data_plot.finalize() is not None: plots.append(data_plot)



    # Velocity
    data_plot = DataPlot(data, plot_config, 'vehicle_local_position',
                         y_axis_label='[m/s]', title='Velocity',
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph(['vx', 'vy', 'vz'], colors8[0:3], ['X', 'Y', 'Z'])
    data_plot.change_dataset('vehicle_local_position_setpoint')
    data_plot.add_graph(['vx', 'vy', 'vz'], [colors8[5], colors8[4], colors8[6]],
                        ['X Setpoint', 'Y Setpoint', 'Z Setpoint'], use_step_lines=True)
    plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

    if data_plot.finalize() is not None: plots.append(data_plot)


    # Visual Odometry (only if topic found)
    if any(elem.name == 'vehicle_visual_odometry' for elem in data):
        # Vision position
        data_plot = DataPlot(data, plot_config, 'vehicle_visual_odometry',
                             y_axis_label='[m]', title='Visual Odometry Position',
                             plot_height='small', changed_params=changed_params,
                             x_range=x_range)
        data_plot.add_graph(['x', 'y', 'z'], colors3, ['X', 'Y', 'Z'], mark_nan=True)
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        data_plot.change_dataset('vehicle_local_position_groundtruth')
        data_plot.add_graph(['x', 'y', 'z'], colors8[2:5],
                            ['Groundtruth X', 'Groundtruth Y', 'Groundtruth Z'])

        if data_plot.finalize() is not None: plots.append(data_plot)


        # Vision velocity
        data_plot = DataPlot(data, plot_config, 'vehicle_visual_odometry',
                             y_axis_label='[m]', title='Visual Odometry Velocity',
                             plot_height='small', changed_params=changed_params,
                             x_range=x_range)
        data_plot.add_graph(['vx', 'vy', 'vz'], colors3, ['X', 'Y', 'Z'], mark_nan=True)
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        data_plot.change_dataset('vehicle_local_position_groundtruth')
        data_plot.add_graph(['vx', 'vy', 'vz'], colors8[2:5],
                            ['Groundtruth VX', 'Groundtruth VY', 'Groundtruth VZ'])
        if data_plot.finalize() is not None: plots.append(data_plot)


        # Vision attitude
        data_plot = DataPlot(data, plot_config, 'vehicle_visual_odometry',
                             y_axis_label='[deg]', title='Visual Odometry Attitude',
                             plot_height='small', changed_params=changed_params,
                             x_range=x_range)
        data_plot.add_graph([lambda data: ('roll', np.rad2deg(data['roll'])),
                             lambda data: ('pitch', np.rad2deg(data['pitch'])),
                             lambda data: ('yaw', np.rad2deg(data['yaw']))],
                            colors3, ['Roll', 'Pitch', 'Yaw'], mark_nan=True)
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        data_plot.change_dataset('vehicle_attitude_groundtruth')
        data_plot.add_graph([lambda data: ('roll', np.rad2deg(data['roll'])),
                             lambda data: ('pitch', np.rad2deg(data['pitch'])),
                             lambda data: ('yaw', np.rad2deg(data['yaw']))],
                            colors8[2:5],
                            ['Roll Groundtruth', 'Pitch Groundtruth', 'Yaw Groundtruth'])

        # Vision attitude rate
        data_plot = DataPlot(data, plot_config, 'vehicle_visual_odometry',
                             y_axis_label='[deg]', title='Visual Odometry Attitude Rate',
                             plot_height='small', changed_params=changed_params,
                             x_range=x_range)
        data_plot.add_graph([lambda data: ('rollspeed', np.rad2deg(data['rollspeed'])),
                             lambda data: ('pitchspeed', np.rad2deg(data['pitchspeed'])),
                             lambda data: ('yawspeed', np.rad2deg(data['yawspeed']))],
                            colors3, ['Roll Rate', 'Pitch Rate', 'Yaw Rate'], mark_nan=True)
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        data_plot.change_dataset('vehicle_attitude_groundtruth')
        data_plot.add_graph([lambda data: ('rollspeed', np.rad2deg(data['rollspeed'])),
                             lambda data: ('pitchspeed', np.rad2deg(data['pitchspeed'])),
                             lambda data: ('yawspeed', np.rad2deg(data['yawspeed']))],
                            colors8[2:5],
                            ['Roll Rate Groundtruth', 'Pitch Rate Groundtruth',
                             'Yaw Rate Groundtruth'])

        if data_plot.finalize() is not None: plots.append(data_plot)


    # Airspeed vs Ground speed: but only if there's valid airspeed data
    try:
        cur_dataset = ulog.get_dataset('airspeed')
        if np.amax(cur_dataset.data['indicated_airspeed_m_s']) > 0.1:
            data_plot = DataPlot(data, plot_config, 'vehicle_global_position',
                                 y_axis_label='[m/s]', title='Airspeed',
                                 plot_height='small',
                                 changed_params=changed_params, x_range=x_range)
            data_plot.add_graph([lambda data: ('groundspeed_estimated',
                                               np.sqrt(data['vel_n']**2 + data['vel_e']**2))],
                                colors3[2:3], ['Ground Speed Estimated'])
            data_plot.change_dataset('airspeed')
            data_plot.add_graph(['indicated_airspeed_m_s'], colors2[0:1], ['Airspeed Indicated'])

            plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

            if data_plot.finalize() is not None: plots.append(data_plot)
    except (KeyError, IndexError) as error:
        pass



    # manual control inputs
    # prefer the manual_control_setpoint topic. Old logs do not contain it
    if any(elem.name == 'manual_control_setpoint' for elem in data):
        data_plot = DataPlot(data, plot_config, 'manual_control_setpoint',
                             title='Manual Control Inputs (Radio or Joystick)',
                             plot_height='small', y_range=Range1d(-1.1, 1.1),
                             changed_params=changed_params, x_range=x_range)
        data_plot.add_graph(['y', 'x', 'r', 'z',
                             lambda data: ('mode_slot', data['mode_slot']/6),
                             'aux1', 'aux2',
                             lambda data: ('kill_switch', data['kill_switch'] == 1)],
                            colors8,
                            ['Y / Roll', 'X / Pitch', 'Yaw', 'Throttle [0, 1]',
                             'Flight Mode', 'Aux1', 'Aux2', 'Kill Switch'])
        # TODO: add RTL switch and others? Look at params which functions are mapped?
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        if data_plot.finalize() is not None: plots.append(data_plot)

    else: # it's an old log (COMPATIBILITY)
        data_plot = DataPlot(data, plot_config, 'rc_channels',
                             title='Raw Radio Control Inputs',
                             plot_height='small', y_range=Range1d(-1.1, 1.1),
                             changed_params=changed_params, x_range=x_range)
        num_rc_channels = 8
        if data_plot.dataset:
            max_channels = np.amax(data_plot.dataset.data['channel_count'])
            if max_channels < num_rc_channels: num_rc_channels = max_channels
        legends = []
        for i in range(num_rc_channels):
            channel_names = px4_ulog.get_configured_rc_input_names(i)
            if channel_names is None:
                legends.append('Channel '+str(i))
            else:
                legends.append('Channel '+str(i)+' ('+', '.join(channel_names)+')')
        data_plot.add_graph(['channels['+str(i)+']' for i in range(num_rc_channels)],
                            colors8[0:num_rc_channels], legends, mark_nan=True)
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        if data_plot.finalize() is not None: plots.append(data_plot)



    # actuator controls 0
    data_plot = DataPlot(data, plot_config, 'actuator_controls_0',
                         y_start=0, title='Actuator Controls 0', plot_height='small',
                         changed_params=changed_params, x_range=x_range)
    data_plot.add_graph(['control[0]', 'control[1]', 'control[2]', 'control[3]'],
                        colors8[0:4], ['Roll', 'Pitch', 'Yaw', 'Thrust'], mark_nan=True)
    plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)
    if data_plot.finalize() is not None: plots.append(data_plot)

    # actuator controls (Main) FFT (for filter & output noise analysis)
    data_plot = DataPlotFFT(data, plot_config, 'actuator_controls_0',
                            title='Actuator Controls FFT')
    data_plot.add_graph(['control[0]', 'control[1]', 'control[2]'],
                        colors3, ['Roll', 'Pitch', 'Yaw'])
    if not data_plot.had_error:
        if 'MC_DTERM_CUTOFF' in ulog.initial_parameters:
            data_plot.mark_frequency(
                ulog.initial_parameters['MC_DTERM_CUTOFF'],
                'MC_DTERM_CUTOFF')
        if 'IMU_GYRO_CUTOFF' in ulog.initial_parameters:
            data_plot.mark_frequency(
                ulog.initial_parameters['IMU_GYRO_CUTOFF'],
                'IMU_GYRO_CUTOFF', 20)

    if data_plot.finalize() is not None: plots.append(data_plot)


    # actuator controls 1
    # (only present on VTOL, Fixed-wing config)
    data_plot = DataPlot(data, plot_config, 'actuator_controls_1',
                         y_start=0, title='Actuator Controls 1 (VTOL in Fixed-Wing mode)',
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph(['control[0]', 'control[1]', 'control[2]', 'control[3]'],
                        colors8[0:4], ['Roll', 'Pitch', 'Yaw', 'Thrust'], mark_nan=True)
    plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)
    if data_plot.finalize() is not None: plots.append(data_plot)


    # actuator outputs 0: Main
    data_plot = DataPlot(data, plot_config, 'actuator_outputs',
                         y_start=0, title='Actuator Outputs (Main)', plot_height='small',
                         changed_params=changed_params, x_range=x_range)
    num_actuator_outputs = 8
    if data_plot.dataset:
        max_outputs = np.amax(data_plot.dataset.data['noutputs'])
        if max_outputs < num_actuator_outputs: num_actuator_outputs = max_outputs
    data_plot.add_graph(['output['+str(i)+']' for i in
                         range(num_actuator_outputs)], colors8[0:num_actuator_outputs],
                        ['Output '+str(i) for i in range(num_actuator_outputs)], mark_nan=True)
    plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

    if data_plot.finalize() is not None: plots.append(data_plot)

    # actuator outputs 1: AUX
    data_plot = DataPlot(data, plot_config, 'actuator_outputs',
                         y_start=0, title='Actuator Outputs (AUX)', plot_height='small',
                         changed_params=changed_params, topic_instance=1,
                         x_range=x_range)
    num_actuator_outputs = 8
    # only plot if at least one of the outputs is not constant
    all_constant = True
    if data_plot.dataset:
        max_outputs = np.amax(data_plot.dataset.data['noutputs'])
        if max_outputs < num_actuator_outputs: num_actuator_outputs = max_outputs

        for i in range(num_actuator_outputs):
            output_data = data_plot.dataset.data['output['+str(i)+']']
            if not np.all(output_data == output_data[0]):
                all_constant = False
    if not all_constant:
        data_plot.add_graph(['output['+str(i)+']' for i in
                             range(num_actuator_outputs)], colors8[0:num_actuator_outputs],
                            ['Output '+str(i) for i in range(num_actuator_outputs)], mark_nan=True)
        plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)

        if data_plot.finalize() is not None: plots.append(data_plot)


    # raw acceleration
    data_plot = DataPlot(data, plot_config, 'sensor_combined',
                         y_axis_label='[m/s^2]', title='Raw Acceleration',
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph(['accelerometer_m_s2[0]', 'accelerometer_m_s2[1]',
                         'accelerometer_m_s2[2]'], colors3, ['X', 'Y', 'Z'])
    if data_plot.finalize() is not None: plots.append(data_plot)



    # raw angular speed
    data_plot = DataPlot(data, plot_config, 'sensor_combined',
                         y_axis_label='[deg/s]', title='Raw Angular Speed (Gyroscope)',
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph([
        lambda data: ('gyro_rad[0]', np.rad2deg(data['gyro_rad[0]'])),
        lambda data: ('gyro_rad[1]', np.rad2deg(data['gyro_rad[1]'])),
        lambda data: ('gyro_rad[2]', np.rad2deg(data['gyro_rad[2]']))],
                        colors3, ['X', 'Y', 'Z'])
    if data_plot.finalize() is not None: plots.append(data_plot)



    # magnetic field strength
    data_plot = DataPlot(data, plot_config, magnetometer_ga_topic,
                         y_axis_label='[gauss]', title='Raw Magnetic Field Strength',
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph(['magnetometer_ga[0]', 'magnetometer_ga[1]',
                         'magnetometer_ga[2]'], colors3,
                        ['X', 'Y', 'Z'])
    if data_plot.finalize() is not None: plots.append(data_plot)


    # distance sensor
    data_plot = DataPlot(data, plot_config, 'distance_sensor',
                         y_start=0, y_axis_label='[m]', title='Distance Sensor',
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph(['current_distance', 'covariance'], colors3[0:2],
                        ['Distance', 'Covariance'])
    if data_plot.finalize() is not None: plots.append(data_plot)



    # gps uncertainty
    # the accuracy values can be really large if there is no fix, so we limit the
    # y axis range to some sane values
    data_plot = DataPlot(data, plot_config, 'vehicle_gps_position',
                         title='GPS Uncertainty', y_range=Range1d(0, 40),
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph(['eph', 'epv', 'satellites_used', 'fix_type'], colors8[::2],
                        ['Horizontal position accuracy [m]', 'Vertical position accuracy [m]',
                         'Num Satellites used', 'GPS Fix'])
    if data_plot.finalize() is not None: plots.append(data_plot)


    # gps noise & jamming
    data_plot = DataPlot(data, plot_config, 'vehicle_gps_position',
                         y_start=0, title='GPS Noise & Jamming',
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph(['noise_per_ms', 'jamming_indicator'], colors3[0:2],
                        ['Noise per ms', 'Jamming Indicator'])
    if data_plot.finalize() is not None: plots.append(data_plot)


    # thrust and magnetic field
    data_plot = DataPlot(data, plot_config, magnetometer_ga_topic,
                         y_start=0, title='Thrust and Magnetic Field', plot_height='small',
                         changed_params=changed_params, x_range=x_range)
    data_plot.add_graph(
        [lambda data: ('len_mag', np.sqrt(data['magnetometer_ga[0]']**2 +
                                          data['magnetometer_ga[1]']**2 +
                                          data['magnetometer_ga[2]']**2))],
        colors2[0:1], ['Norm of Magnetic Field'])
    data_plot.change_dataset('actuator_controls_0')
    data_plot.add_graph([lambda data: ('thrust', data['control[3]'])],
                        colors2[1:2], ['Thrust'])
    if data_plot.finalize() is not None: plots.append(data_plot)


    # Acceleration Spectrogram
    data_plot = DataPlotSpec(data, plot_config, 'sensor_combined',
                             y_axis_label='[Hz]', title='Acceleration Power Spectral Density',
                             plot_height='small', x_range=x_range)
    data_plot.add_graph(['accelerometer_m_s2[0]', 'accelerometer_m_s2[1]', 'accelerometer_m_s2[2]'],
                        ['X', 'Y', 'Z'])
    if data_plot.finalize() is not None: plots.append(data_plot)

    # power
    data_plot = DataPlot(data, plot_config, 'battery_status',
                         y_start=0, title='Power',
                         plot_height='small', changed_params=changed_params,
                         x_range=x_range)
    data_plot.add_graph(['voltage_v', 'voltage_filtered_v',
                         'current_a', lambda data: ('discharged_mah', data['discharged_mah']/100),
                         lambda data: ('remaining', data['remaining']*10)],
                        colors8[::2]+colors8[1:2],
                        ['Battery Voltage [V]', 'Battery Voltage filtered [V]',
                         'Battery Current [A]', 'Discharged Amount [mAh / 100]',
                         'Battery remaining [0=empty, 10=full]'])
    data_plot.change_dataset('system_power')
    if data_plot.dataset:
        if 'voltage5v_v' in data_plot.dataset.data and \
                        np.amax(data_plot.dataset.data['voltage5v_v']) > 0.0001:
            data_plot.add_graph(['voltage5v_v'], colors8[7:8], ['5 V'])
        if 'voltage3v3_v' in data_plot.dataset.data and \
                        np.amax(data_plot.dataset.data['voltage3v3_v']) > 0.0001:
            data_plot.add_graph(['voltage3v3_v'], colors8[5:6], ['3.3 V'])
    if data_plot.finalize() is not None: plots.append(data_plot)



    # estimator watchdog
    try:
        data_plot = DataPlot(data, plot_config, 'estimator_status',
                             y_start=0, title='Estimator Watchdog',
                             plot_height='small', changed_params=changed_params,
                             x_range=x_range)
        estimator_status = ulog.get_dataset('estimator_status').data
        plot_data = []
        plot_labels = []
        input_data = [
            ('Health Flags (vel, pos, hgt)', estimator_status['health_flags']),
            ('Timeout Flags (vel, pos, hgt)', estimator_status['timeout_flags']),
            ('Velocity Check Bit', (estimator_status['innovation_check_flags'])&0x1),
            ('Horizontal Position Check Bit', (estimator_status['innovation_check_flags']>>1)&1),
            ('Vertical Position Check Bit', (estimator_status['innovation_check_flags']>>2)&1),
            ('Mag X, Y, Z Check Bits', (estimator_status['innovation_check_flags']>>3)&0x7),
            ('Yaw Check Bit', (estimator_status['innovation_check_flags']>>6)&1),
            ('Airspeed Check Bit', (estimator_status['innovation_check_flags']>>7)&1),
            ('Synthetic Sideslip Check Bit', (estimator_status['innovation_check_flags']>>8)&1),
            ('Height to Ground Check Bit', (estimator_status['innovation_check_flags']>>9)&1),
            ('Optical Flow X, Y Check Bits', (estimator_status['innovation_check_flags']>>10)&0x3),
            ]
        # filter: show only the flags that have non-zero samples
        for cur_label, cur_data in input_data:
            if np.amax(cur_data) > 0.1:
                data_label = 'flags_'+str(len(plot_data)) # just some unique string
                plot_data.append(lambda d, data=cur_data, label=data_label: (label, data))
                plot_labels.append(cur_label)
                if len(plot_data) >= 8: # cannot add more than that
                    break

        if len(plot_data) == 0:
            # add the plot even in the absence of any problem, so that the user
            # can validate that (otherwise it's ambiguous: it could be that the
            # estimator_status topic is not logged)
            plot_data = [lambda d: ('flags', input_data[0][1])]
            plot_labels = [input_data[0][0]]
        data_plot.add_graph(plot_data, colors8[0:len(plot_data)], plot_labels)
        if data_plot.finalize() is not None: plots.append(data_plot)
    except (KeyError, IndexError) as error:
        print('Error in estimator plot: '+str(error))



    # RC Quality
    data_plot = DataPlot(data, plot_config, 'input_rc',
                         title='RC Quality', plot_height='small', y_range=Range1d(0, 1),
                         changed_params=changed_params, x_range=x_range)
    data_plot.add_graph([lambda data: ('rssi', data['rssi']/100), 'rc_lost'],
                        colors3[0:2], ['RSSI [0, 1]', 'RC Lost (Indicator)'])
    data_plot.change_dataset('vehicle_status')
    data_plot.add_graph(['rc_signal_lost'], colors3[2:3], ['RC Lost (Detected)'])
    if data_plot.finalize() is not None: plots.append(data_plot)



    # cpu load
    data_plot = DataPlot(data, plot_config, 'cpuload',
                         title='CPU & RAM', plot_height='small', y_range=Range1d(0, 1),
                         changed_params=changed_params, x_range=x_range)
    data_plot.add_graph(['ram_usage', 'load'], [colors3[1], colors3[2]],
                        ['RAM Usage', 'CPU Load'])
    data_plot.add_span('load', line_color=colors3[2])
    data_plot.add_span('ram_usage', line_color=colors3[1])
    plot_flight_modes_background(data_plot, flight_mode_changes, vtol_states)
    if data_plot.finalize() is not None: plots.append(data_plot)


    # sampling: time difference
    try:
        data_plot = DataPlot(data, plot_config, 'sensor_combined', y_range=Range1d(0, 25e3),
                             y_axis_label='[us]',
                             title='Sampling Regularity of Sensor Data', plot_height='small',
                             changed_params=changed_params, x_range=x_range)
        sensor_combined = ulog.get_dataset('sensor_combined').data
        sampling_diff = np.diff(sensor_combined['timestamp'])
        min_sampling_diff = np.amin(sampling_diff)

        plot_dropouts(data_plot.bokeh_plot, ulog.dropouts, min_sampling_diff)

        data_plot.add_graph([lambda data: ('timediff', np.append(sampling_diff, 0))],
                            [colors3[2]], ['delta t (between 2 logged samples)'])
        data_plot.change_dataset('estimator_status')
        data_plot.add_graph([lambda data: ('time_slip', data['time_slip']*1e6)],
                            [colors3[1]], ['Estimator time slip (cumulative)'])
        if data_plot.finalize() is not None: plots.append(data_plot)
    except:
        pass



    # exchange all DataPlot's with the bokeh_plot and handle parameter changes

    param_changes_button = Button(label="Hide Parameter Changes", width=170)
    param_change_labels = []
    # FIXME: this should be a CustomJS callback, not on the server. However this
    # did not work for me.
    def param_changes_button_clicked():
        """ callback to show/hide parameter changes """
        for label in param_change_labels:
            if label.visible:
                param_changes_button.label = 'Show Parameter Changes'
                label.visible = False
                label.text_alpha = 0 # label.visible does not work, so we use this instead
            else:
                param_changes_button.label = 'Hide Parameter Changes'
                label.visible = True
                label.text_alpha = 1
    param_changes_button.on_click(param_changes_button_clicked)


    jinja_plot_data = []
    for i in range(len(plots)):
        if plots[i] is None:
            plots[i] = widgetbox(param_changes_button, width=int(plot_width * 0.99))
        if isinstance(plots[i], DataPlot):
            if plots[i].param_change_label is not None:
                param_change_labels.append(plots[i].param_change_label)

            plot_title = plots[i].title
            plots[i] = plots[i].bokeh_plot

            fragment = 'Nav-'+plot_title.replace(' ', '-') \
                .replace('&', '_').replace('(', '').replace(')', '')
            jinja_plot_data.append({
                'model_id': plots[i].ref['id'],
                'fragment': fragment,
                'title': plot_title
                })


    # changed parameters
    plots.append(get_changed_parameters(ulog.initial_parameters, plot_width))



    # information about which messages are contained in the log
# TODO: need to load all topics for this (-> log loading will take longer)
#       but if we load all topics and the log contains some (external) topics
#       with buggy timestamps, it will affect the plotting.
#    data_list_sorted = sorted(ulog.data_list, key=lambda d: d.name + str(d.multi_id))
#    table_text = []
#    for d in data_list_sorted:
#        message_size = sum([ULog.get_field_size(f.type_str) for f in d.field_data])
#        num_data_points = len(d.data['timestamp'])
#        table_text.append((d.name, str(d.multi_id), str(message_size), str(num_data_points),
#           str(message_size * num_data_points)))
#    topics_info = '<table><tr><th>Name</th><th>Topic instance</th><th>Message Size</th>' \
#            '<th>Number of data points</th><th>Total bytes</th></tr>' + ''.join(
#            ['<tr><td>'+'</td><td>'.join(list(x))+'</td></tr>' for x in table_text]) + '</table>'
#    topics_div = Div(text=topics_info, width=int(plot_width*0.9))
#    plots.append(widgetbox(topics_div, width=int(plot_width*0.9)))


    # log messages
    plots.append(get_logged_messages(ulog.logged_messages, plot_width))


    # perf & top output
    top_data = ''
    perf_data = ''
    for state in ['pre', 'post']:
        if 'perf_top_'+state+'flight' in ulog.msg_info_multiple_dict:
            current_top_data = ulog.msg_info_multiple_dict['perf_top_'+state+'flight'][0]
            flight_data = escape('\n'.join(current_top_data))
            top_data += '<p>'+state.capitalize()+' Flight:<br/><pre>'+flight_data+'</pre></p>'
        if 'perf_counter_'+state+'flight' in ulog.msg_info_multiple_dict:
            current_perf_data = ulog.msg_info_multiple_dict['perf_counter_'+state+'flight'][0]
            flight_data = escape('\n'.join(current_perf_data))
            perf_data += '<p>'+state.capitalize()+' Flight:<br/><pre>'+flight_data+'</pre></p>'

    additional_data_html = ''
    if len(top_data) > 0:
        additional_data_html += '<h5>Processes</h5>'+top_data
    if len(perf_data) > 0:
        additional_data_html += '<h5>Performance Counters</h5>'+perf_data
    if len(additional_data_html) > 0:
        # hide by default & use a button to expand
        additional_data_html = '''
<button class="btn btn-secondary" data-toggle="collapse" style="min-width:0;"
 data-target="#show-additional-data">Show additional Data</button>
<div id="show-additional-data" class="collapse">
{:}
</div>
'''.format(additional_data_html)
        additional_data_div = Div(text=additional_data_html, width=int(plot_width*0.9))
        plots.append(widgetbox(additional_data_div, width=int(plot_width*0.9)))


    curdoc().template_variables['plots'] = jinja_plot_data

    return plots
t.patches(xs="xss", ys="yss", color="colors", source=session_source, line_width=0, alpha=1)

hover = t.select_one(HoverTool)
hover.point_policy = "follow_mouse"
hover.tooltips = [
	("task type", "@tasktype"),
	("#tasks", "@running_tasks"),
]

# Function that clears all checkboxes and calls checkbox to redraw the plots
def clear():
	checkbox_group_p.active = []
	checkbox("", "", "")

# Button to clear all checkboxes
clear_button = Button(label="clear all", width=20)
clear_button.on_click(clear)

# Function that sets all checkboxes and calls checkbox to redraw the plots
def select_all():
	checkbox_group_p.active = [i for i in range(len(attributes[1:]))]
	checkbox("", "", "")

# Button to select all checkboxes
all_button = Button(label="select all", width=20)
all_button.on_click(select_all)

layout = column(
	#row(WidgetBox(dropdown, width=405, height=100), WidgetBox(width=500),WidgetBox(runID)),
	row(WidgetBox(dropdown, width=410, height=100)),
	row(runID, startTime),
Beispiel #52
0
def openLog(doc):
    '''

    :param doc:
    :return: document
    '''
    doc.theme = settings.colortheme

    global data
    try:
        data = user_equations(data)
    except:
        print("Bad user equations, contact developer for erro code #03")
    #with pd.option_context('display.max_columns', None):  # more options can be specified also
    #    print(data)

    #atention to not overflow bokeh server starting
    maxSizeArray = 80000

    if maxSizeArray > len(data['time']):
        maxSizeArray = len(data['time'])-1

    last_t = 0
    for index, df in data.iterrows():
        t=df['time']
        if t-last_t>150:
            remove_time = t-last_t
            print('Developer note: difftime: ' + str((t-last_t)/1000) + ' on data point time: ' + str(t/1000) + '. Index: ' + str(index))
            data.iloc[index:,data.columns.get_loc("time")] -= remove_time
        last_t = t


    data['time'] = data['time']/1000
    source = ColumnDataSource(data=data.iloc[0:maxSizeArray,:])

    ##################### TIMER SLIDER GLOBAL ######################
    def update(event):
        '''
        callback for button to upgrade plots
        :param event: handler
        :return: none
        '''
        new = time_slider.value
        min_index = 0
        max_index = len(data['time'])
        for j in range(0, int(len(data['time'])/1000)):
            if data['time'].iloc[j*1000] > new[0]:
                min_index = j*1000
                break

        for j in range(0, int(len(data['time'])/1000)):
            if data['time'].iloc[j*1000] > new[1]:
                max_index = j*1000
                break

        #to block max size of source
        #if max_index-min_index > maxSizeArray:
        #    max_index = min_index + maxSizeArray
        #    time_slider.value = [data['time'].iloc[min_index], data['time'].iloc[maxSizeArray]]
        try:
            source.data = ColumnDataSource.from_df(data.iloc[min_index:max_index, :])
        except:
            print("Cotact developer: Error code #2")

    btn_update = Button(label = 'Update', button_type="success", width_policy='min')#, width_policy='min', button_type='primary')
    btn_update.on_click(update)
    time_slider = RangeSlider(value=(data['time'].min(), data['time'].iloc[maxSizeArray]), start=data['time'].min(), end=data['time'].max(), step=10, title="Timing Data", default_size = 1300)

    def end(event):
        '''
        callback function button for end program
        :param event:
        :return: none
        '''
        sys.exit()

    btn_end = Button(label='Exit', button_type="success", width_policy='min')  # , width_policy='min', button_type='primary')
    btn_end.on_click(end)

    doc.add_root(row(btn_update, time_slider, btn_end))
    #Check if descompressed file have an CSV named correctly inside

    setup_tabs = open('projectfolder/configuration/tabs/globalSetup.txt').readlines()
    title_tabs = setup_tabs[0].split(':')[1]
    #title_tabs = (title_tabs.encode()[:-2]).decode()

    number_tabs = setup_tabs[1].split(':')[1]
    #number_tabs = (number_tabs.encode()[:-2]).decode()

    global go
    if go:

        #if (len(data.columns) == 83):
        if (True):
            '''
            #Configure the HTML final to the output graphics
            logHTMLFile = 'finalReport_ncu/logFinal_part_' + str(l) + '.html'

            output_file(logHTMLFile, title='NCU LOG ' + str(l) + ' | FORMULA UFSM')

            curdoc().theme = 'dark_minimal'

            #Get each tab pannel to render the HTML file

            tab0 = pilot(data)
            tab1 = BAT(data)
            tab2 = LVDT(data)
            tab3 = TK(data)
            tab4 = mpu6050(data)
            tab5 = suspFFT(data)
            tab6 = suspHisto(data)
            tab7 = gps(data)
            tab8 = ncu(data)
            tab9 = engine(data)
            tab10 = tireTemp(data)
            '''

            # Join tabs
            tabs = Tabs(tabs=make_ncu_tabs(source, number_tabs), name=title_tabs)

            '''
            #for ensure the program, try to save the file with the tabs.
            canShow = True
            try:
                save(tabs)
            except:
                print("Error... contact developer for error code #01")
                canShow = False

            #if not get exception, display the HTML
            if(canShow):
                show(tabs)

                #remove the full HTML archive to clean disk space, HTML files is higher
                time.sleep(10)
                os.remove(logHTMLFile)
            '''
            doc.add_root(tabs)

            doc.title = 'NCU LOG'

        wculogcol = pd.read_csv('./projectfolder/configuration/dataWCU.csv').shape[0] #number of lines indicates the number of collumn in a log file
        if ((data.shape[1]) == wculogcol):
            # Configure the HTML final to the output graphics
            #logHTMLFile = 'finalReport_ncu/logWCU.html'

            #output_file(logHTMLFile, title='LOG WCU | FORMULA UFSM')

            # curdoc().theme = 'dark_minimal'

            # Get each tab pannel to render the HTML file
            tab0 = pilot(data)
            tab7 = gps(data)
            tab9 = engine(data)
            tab10 = tireTemp(data)

            # Join tabs
            tabs = Tabs(tabs=[
                tab0,
                tab9,
                tab7,
                tab10,
            ], name='WCU TABS')

            '''
            # for ensure the program, try to save the file with the tabs.
            canShow = True
            try:
                save(tabs)
            except:
                print("Error... contact developer for error code #01")
                canShow = False

            # if not get exception, display the HTML
            if (canShow):
                show(tabs)

                # remove the full HTML archive to clean disk space, HTML files is higher
                time.sleep(10)
                os.remove(logHTMLFile)
            '''

            doc.add_root(tabs)
            doc.title = 'WCU LOG'

    return doc
Beispiel #53
0
class SeparationDash():
    """
    A dashboard that displays separation data.

    Pass a reference to the Bokeh document for threading access.
    """
    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']

    # #########################################################################
    # Graph generators

    def top_graph(self, ind, title, d_source, e_source, tooltip, **kwargs):
        """Generate the top graphs (KH, uptake, WC)."""

        # Generate figure dict
        plot_side_size = 400
        fig_dict = dict(tools="pan,wheel_zoom,tap,reset,save",
                        active_scroll="wheel_zoom",
                        plot_width=plot_side_size,
                        plot_height=plot_side_size,
                        title=title)
        fig_dict.update(kwargs)

        # Create a colour mapper for number of isotherms
        mapper = log_cmap(field_name='{0}_n'.format(ind),
                          palette="Viridis256",
                          low_color='grey',
                          high_color='yellow',
                          low=3,
                          high=100)

        # Create a new plot
        graph = figure(**fig_dict)

        # Add the hover tooltip
        graph.add_tools(
            HoverTool(names=["{0}_data".format(ind)],
                      tooltips=tooltip.render(p=ind)))

        # Plot the data
        rend = graph.circle("{0}_x".format(ind),
                            "{0}_y".format(ind),
                            source=d_source,
                            size=10,
                            line_color=mapper,
                            color=mapper,
                            name="{0}_data".format(ind))

        # Plot guide line
        graph.add_layout(
            Slope(gradient=1,
                  y_intercept=0,
                  line_color='black',
                  line_dash='dashed',
                  line_width=2))

        # Plot the error margins
        graph.segment('{0}_x0'.format(ind),
                      '{0}_y0'.format(ind),
                      '{0}_x1'.format(ind),
                      '{0}_y1'.format(ind),
                      source=e_source,
                      color="black",
                      line_width=2,
                      line_cap='square',
                      line_dash='dotted')

        # Plot labels next to selected materials
        graph.add_layout(
            LabelSet(
                x='{0}_x'.format(ind),
                y='{0}_y'.format(ind),
                source=e_source,
                text='labels',
                level='glyph',
                x_offset=5,
                y_offset=5,
                render_mode='canvas',
                text_font_size='10pt',
            ))

        # Add the colorbar to the side
        graph.add_layout(
            ColorBar(color_mapper=mapper['transform'],
                     ticker=LogTicker(desired_num_ticks=10),
                     width=8,
                     location=(0, 0)), 'right')

        return graph, rend

    def top_graph_labels(self):
        """Generate the top graph labels from selected ads_list."""
        self.p_loading.xaxis.axis_label = '{0} (mmol/g)'.format(self.model.g1)
        self.p_loading.yaxis.axis_label = '{0} (mmol/g)'.format(self.model.g2)
        self.p_henry.xaxis.axis_label = '{0} (mmol/bar)'.format(self.model.g1)
        self.p_henry.yaxis.axis_label = '{0} (mmol/bar)'.format(self.model.g2)
        self.p_wc.xaxis.axis_label = '{0} (mmol/g)'.format(self.model.g1)
        self.p_wc.yaxis.axis_label = '{0} (mmol/g)'.format(self.model.g2)

    def bottom_graph(self, source, ads):
        """Generate the bottom graphs (isotherm display)."""

        graph = figure(tools="pan,wheel_zoom,reset",
                       active_scroll="wheel_zoom",
                       plot_width=400,
                       plot_height=250,
                       x_range=(-0.01, 0.01),
                       y_range=(-0.01, 0.01),
                       title='Isotherms {0}'.format(ads))
        rend = graph.multi_line('x',
                                'y',
                                source=source,
                                alpha=0.6,
                                line_width=3,
                                hover_line_alpha=1.0,
                                hover_line_color="black",
                                line_color='color')

        # Make clicking a graph open the NIST database

        graph.add_tools(
            HoverTool(show_arrow=False,
                      line_policy='nearest',
                      tooltips="""Click for details"""))

        graph.add_tools(
            TapTool(renderers=[rend],
                    callback=CustomJS(args={
                        'tp': load_details().render(),
                    },
                                      code=load_details_js())))

        source.selected.js_on_change(
            'indices',
            CustomJS(
                code=
                'if (cb_obj.indices.length == 0) document.getElementById("iso-details").style.display = \"none\"'
            ))

        graph.xaxis.axis_label = 'Pressure (bar)'
        graph.yaxis.axis_label = 'Uptake (mmol/g)'

        return graph
Beispiel #54
0
def make_document(doc):
    TICKER = ""
    base = "http://192.168.50.62/get?accX=%s|acc_time&acc_time=%s&accY=%s|acc_time&accZ=%s|acc_time"
    data = ColumnDataSource(
        dict(
            time=[],
            # display_time=[],
            x=[],
            y=[],
            z=[],
        ))

    def get_last():
        global current_time
        # print(current_time)

        raw = requests.get(
            base % (current_time, current_time, current_time, current_time))
        j = raw.json()

        ln = min(
            len(j['buffer']["acc_time"]["buffer"]),
            len(j['buffer']["accX"]["buffer"]),
            len(j['buffer']["accY"]["buffer"]),
            len(j['buffer']["accZ"]["buffer"]),
        )

        prices_df = pd.DataFrame.from_dict({
            "time":
            j['buffer']["acc_time"]["buffer"][:ln],
            "x":
            j['buffer']["accX"]["buffer"][:ln],
            "y":
            j['buffer']["accY"]["buffer"][:ln],
            "z":
            j['buffer']["accZ"]["buffer"][:ln],
        })

        if len(j['buffer']["acc_time"]["buffer"]) == 0:
            current_time = 0
        else:
            current_time = j['buffer']["acc_time"]["buffer"][-1]

        # prices_df["time"] = pd.to_datetime(prices_df["time"], unit="ms")
        # prices_df["display_time"] = prices_df["time"].dt.strftime("%m-%d-%Y %H:%M:%S.%f")

        return prices_df

    def update_price():

        new_price = get_last()
        print(len(new_price['time']), end='\n\n')
        data.stream(
            dict(time=new_price["time"],
                 x=new_price["x"],
                 y=new_price["y"],
                 z=new_price["z"]), 1000)
        return

    hover = HoverTool(
        tooltips=[("Time", "@display_time"), ("IEX Real-Time Price",
                                              "@price")])

    fig_x = figure(plot_width=800,
                   plot_height=400,
                   x_axis_type='datetime',
                   tools=[WheelZoomTool(),
                          ResetTool(),
                          PanTool(),
                          SaveTool()],
                   title="Real-Time Price Plot")

    fig_x.line(source=data, color="navy", x='time', y='x')
    fig_x.xaxis.axis_label = "Time"
    fig_x.yaxis.axis_label = "IEX Real-Time Price"
    fig_x.title.text = "IEX Real Time Price: " + TICKER

    fig_y = figure(plot_width=800,
                   plot_height=400,
                   x_axis_type='datetime',
                   tools=[WheelZoomTool(),
                          ResetTool(),
                          PanTool(),
                          SaveTool()],
                   title="Real-Time Price Plot",
                   x_range=fig_x.x_range,
                   y_range=fig_x.y_range)

    fig_y.line(source=data, color="navy", x='time', y='y')
    fig_y.xaxis.axis_label = "Time"
    fig_y.yaxis.axis_label = "IEX Real-Time Price"
    fig_y.title.text = "IEX Real Time Price: " + TICKER

    fig_z = figure(plot_width=800,
                   plot_height=400,
                   x_axis_type='datetime',
                   tools=[WheelZoomTool(),
                          ResetTool(),
                          PanTool(),
                          SaveTool()],
                   title="Real-Time Price Plot",
                   x_range=fig_x.x_range,
                   y_range=fig_x.y_range)

    fig_z.line(source=data, color="navy", x='time', y='z')
    fig_z.xaxis.axis_label = "Time"
    fig_z.yaxis.axis_label = "IEX Real-Time Price"
    fig_z.title.text = "IEX Real Time Price: " + TICKER

    ticker_textbox = TextInput(placeholder="Ticker")
    update = Button(label="Update")

    inputs = widgetbox([ticker_textbox, update], width=200)

    doc.add_root(column(fig_x, fig_y, fig_z, width=1600))
    doc.title = "Real-Time Price Plot from IEX"
    doc.add_periodic_callback(update_price, 30)
Beispiel #55
0
    print("checkbox_group_handler: %s" % active)
    session.store_document(document)

def radio_group_handler(active):
    print("radio_group_handler: %s" % active)
    session.store_document(document)

def checkbox_button_group_handler(active):
    print("checkbox_button_group_handler: %s" % active)
    session.store_document(document)

def radio_button_group_handler(active):
    print("radio_button_group_handler: %s" % active)
    session.store_document(document)

button = Button(label="Push button", icon=Icon(name="check"), type="primary")
button.on_click(button_handler)

toggle = Toggle(label="Toggle button", type="success")
toggle.on_click(toggle_handler)

menu = [("Item 1", "item_1"), ("Item 2", "item_2"), None, ("Item 3", "item_3")]
dropdown = Dropdown(label="Dropdown button", type="warning", menu=menu)
dropdown.on_click(dropdown_handler)

menu = [("Item 1", "foo"), ("Item 2", "bar"), None, ("Item 3", "baz")]
split = Dropdown(label="Split button", type="danger", menu=menu, default_action="baz")
split.on_click(split_handler)

checkbox_group = CheckboxGroup(labels=["Option 1", "Option 2", "Option 3"], active=[0, 1])
checkbox_group.on_click(checkbox_group_handler)
Beispiel #56
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']
tsne_figure.select(BoxSelectTool).select_every_mousemove = False
tsne_figure.select(LassoSelectTool).select_every_mousemove = False


def on_tsne_data_update(attr, old, new):
    global previously_selected_spike_indices

    previously_selected_spike_indices = np.array(old['1d']['indices'])


tsne_source.on_change('selected', on_tsne_data_update)



# Undo button
undo_selected_points_button = Button(label='Undo last selection')

def on_button_undo_selection():
    global previously_selected_spike_indices
    tsne_source.data = {'tsne-x': tsne[0], 'tsne-y': tsne[1]}
    tsne_source.selected['1d']['indices'] = previously_selected_spike_indices
    old = new = tsne_source.selected
    tsne_source.trigger('selected', old, new)

undo_selected_points_button.on_click(on_button_undo_selection)


# Layout
lay = column(tsne_figure, undo_selected_points_button)

session = push_session(curdoc())
Beispiel #58
0
from bokeh.io import curdoc

from jsmol_bokeh_extension import JSMol
#from import_db import get_cif_content
from detail.query import get_sqlite_data as get_data

html = bmd.Div(text=open(join(dirname(__file__), "description.html")).read(),
               width=800)

download_js = open(join(dirname(__file__), "static", "download.js")).read()

script_source = bmd.ColumnDataSource()

plot_info = PreText(text='', width=300, height=100)

btn_download_table = Button(label="Download json", button_type="primary")
btn_download_cif = Button(label="Download cif", button_type="primary")


def get_name_from_url():
    args = curdoc().session_context.request.arguments
    try:
        name = args.get('name')[0]
        if isinstance(name, bytes):
            name = name.decode()
    except (TypeError, KeyError):
        name = 'linker91_CH_linker92_N_clh_relaxed'

    return name

glyphDict = create_glyphs()
fig = make_trial_figure()

# Setup callbacks for tools and sources
trialSourceDict['undefined'].on_change('selected', undefined_selected)
trialSourceDict['saccade'].on_change('selected', saccade_selected)
trialSourceDict['pursuit'].on_change('selected', pursuit_selected)
trialSourceDict['fixation'].on_change('selected', fixation_selected)

###########################################################################
# Add widgets and their callbacks
#widgets = add_widgets()

from bokeh.models.widgets import Button, TextInput

label_saccade_button = Button(label='saccade')
label_saccade_button.on_click(label_saccade_cb)

label_pursuit_button = Button(label='pursuit')
label_pursuit_button.on_click(label_pursuit_cb)

label_fixation_button = Button(label='fixation')
label_fixation_button.on_click(label_fixation_cb)

remove_button = Button(label='remove')
remove_button.on_click(remove_cb)

trial_text = TextInput(value=str(trialNum))
trial_text.on_change('value', trial_text_cb)

nextTrial_button = Button(label='+trial')
Beispiel #60
0
    def create_interact_ui(doc):
        # The data source includes metadata for hover-over tooltips
        lc_source = prepare_lightcurve_datasource(lc)
        tpf_source = prepare_tpf_datasource(tpf)

        # Create the lightcurve figure and its vertical marker
        fig_lc, vertical_line = make_lightcurve_figure_elements(lc, lc_source)

        # Create the TPF figure and its stretch slider
        pedestal = np.nanmin(tpf.flux)
        fig_tpf, stretch_slider = make_tpf_figure_elements(tpf,
                                                           tpf_source,
                                                           pedestal=pedestal)

        # Helper lookup table which maps cadence number onto flux array index.
        tpf_index_lookup = {cad: idx for idx, cad in enumerate(tpf.cadenceno)}

        # Interactive slider widgets and buttons to select the cadence number
        cadence_slider = Slider(start=np.min(tpf.cadenceno),
                                end=np.max(tpf.cadenceno),
                                value=np.min(tpf.cadenceno),
                                step=1,
                                title="Cadence Number",
                                width=490)
        r_button = Button(label=">", button_type="default", width=30)
        l_button = Button(label="<", button_type="default", width=30)

        # Callbacks
        def update_upon_pixel_selection(attr, old, new):
            """Callback to take action when pixels are selected."""
            if ((sorted(old) == sorted(new)) & (new != [])):
                # Trigger recursion
                tpf_source.selected.indices = new[1:]

            if new != []:
                selected_indices = np.array(new)
                selected_mask = np.isin(pixel_index_array, selected_indices)
                lc_new = tpf.to_lightcurve(aperture_mask=selected_mask)
                lc_source.data['flux'] = lc_new.flux
                ylims = get_lightcurve_y_limits(lc_source)
                fig_lc.y_range.start = ylims[0]
                fig_lc.y_range.end = ylims[1]
            else:
                lc_source.data['flux'] = lc.flux * 0.0
                fig_lc.y_range.start = -1
                fig_lc.y_range.end = 1

        def update_upon_cadence_change(attr, old, new):
            '''Callback to take action when cadence slider changes'''
            if new in tpf.cadenceno:
                frameno = tpf_index_lookup[new]
                fig_tpf.select('tpfimg')[0].data_source.data['image'] = [
                    tpf.flux[frameno, :, :] - pedestal
                ]
                vertical_line.update(location=tpf.time[frameno])
            else:
                fig_tpf.select('tpfimg')[0].data_source.data['image'] = [
                    tpf.flux[0, :, :] * np.NaN
                ]
            lc_source.selected.indices = []

        def go_right_by_one():
            existing_value = cadence_slider.value
            if existing_value < np.max(tpf.cadenceno):
                cadence_slider.value = existing_value + 1

        def go_left_by_one():
            existing_value = cadence_slider.value
            if existing_value > np.min(tpf.cadenceno):
                cadence_slider.value = existing_value - 1

        def jump_to_lightcurve_position(attr, old, new):
            if new != []:
                cadence_slider.value = lc.cadenceno[new[0]]

        # Map changes to callbacks
        r_button.on_click(go_right_by_one)
        l_button.on_click(go_left_by_one)
        tpf_source.selected.on_change('indices', update_upon_pixel_selection)
        lc_source.selected.on_change('indices', jump_to_lightcurve_position)
        cadence_slider.on_change('value', update_upon_cadence_change)

        # Layout all of the plots
        space1, space2, space3 = Spacer(width=15), Spacer(width=30), Spacer(
            width=80)
        widgets_and_figures = layout([fig_lc, fig_tpf], [
            l_button, space1, r_button, space2, cadence_slider, space3,
            stretch_slider
        ])
        doc.add_root(widgets_and_figures)