Beispiel #1
0
def range_column_filter(colname, stepsize, title=None):
    """Create a column filter, if the column exists and contains at least one\
    not-None value.  Creates the slider for the filter and returns a getter\
    for the slider's current range"""
    if colname in entries[0]:
        column_data = [entry[colname] for entry in entries]
        if validate_column(column_data, colname):
            top = stepUp(max((val for val in column_data if val is not None)), stepsize)
            col_filter = RangeSlider(
                title = cols[colname] if title is None else title,
                range=(0, top),
                start = 0,
                end = top,
                step=stepsize
            )
            getter = lambda :col_filter.range
            col_filter.on_change(
                'range',
                lambda a,r,g: debounce(
                    update,
                    getter,
                    150,
                    curdoc()
                )
            )
            widgets.append(col_filter)
            return getter
Beispiel #2
0
def range_column_filter(colname, stepsize, title=None):
    """Create a column filter, if the column exists and contains at least one\
    not-None value.  Creates the slider for the filter and returns a getter\
    for the slider's current range"""
    if colname in entries[0]:
        column_data = [entry[colname] for entry in entries]
        if validate_column(column_data, colname):
            top = stepUp(max((val for val in column_data if val is not None)), stepsize)
            col_filter = RangeSlider(
                title = cols[colname] if title is None else title,
                value=(0, top),
                start = 0,
                end = top,
                step=stepsize
            )
            getter = lambda :col_filter.value
            col_filter.on_change(
                'value',
                lambda a,r,g: debounce(
                    update,
                    getter,
                    150,
                    curdoc()
                )
            )
            widgets.append(col_filter)
            return getter
 def modify_doc(doc):
     plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)
     slider = RangeSlider(start=0, end=10, value=(1, 5), title="bar", css_classes=["foo"], width=300)
     def cb(attr, old, new):
         slider.bar_color = "rgba(255, 255, 0, 1)"
     slider.on_change('value', cb)
     doc.add_root(column(slider, plot))
Beispiel #4
0
class OffsetPage(object):
	def __init__(self):
		sel_vals = ['All', 'Shot']

		self._data = OffsetData(r'fb_on_Shots_4TEST_FB_v2.csv',
							   r'Shots_4TEST_FB_part.pickle')
		self._offset = None

		# self._div_debug = Div(text='Debug: <br>', width=1000)
		self._sel_type = Select(title="Slice type:", value=sel_vals[0], options=sel_vals)
		self._sld_slice = RangeSlider(start=0, end=10, value=(0,100), step=1, title="Slice Num")
		self._set_slider()
		self._sld_slice.on_change('value', self._update_all)
		self._sel_type.on_change('value', self.change_type)

		self._plot_image = figure(plot_width=800, plot_height=600,title='Offset')
	  
		self._set_index()
		self._breaks = self._data.get_breaks()
		self._ds_offset = ColumnDataSource(data=self._get_offset())
		colormap = plt.cm.seismic
		create_colors = [colormap(i) for i in np.arange(0,self._data._shots.max()+1,1)]
		colors = [None]*self._data._breaks.size
		
		for i in range(self._data._breaks.size):
			colors[i]=matplotlib.colors.to_hex(create_colors[self._data._shots[i]])
		mapper = LinearColorMapper(palette=colors, low=self._data._shots.min(), high=self._data._shots.max())
		self._plot_image.scatter(x='x', y='y', source=self._ds_offset, line_color=None, fill_color=transform('shot', mapper), size=2)

	def _get_offset(self):
		self._offset = self._data.get_offset()
		xs = self._offset
		ys = self._breaks
	
		return {'x': xs, 'y': ys}
	def _set_index(self):
		self._data.set_indices_offset(self._sel_type.value, self._sld_slice.value[0], self._sld_slice.value[1])
	def _set_slider(self):
		min_val, max_val = self._data.get_minmax(self._sel_type.value)
		self._sld_slice.start = min_val
		self._sld_slice.end = max_val
		self._sld_slice.value = (0,min_val + (max_val - min_val) // 2)
	def change_type(self, attr, old, new):
		min_val, max_val = self._data.get_minmax(self._sel_type.value)
		self._sld_slice.value = (0,min_val + (max_val - min_val) // 2)
		self._sld_slice.start = min_val
		self._sld_slice.end = max_val
		_update_all
	def _update_all(self, attr, old, new):
		self._set_index()
		self._ds_offset.data = self._get_offset()

	def get_layout(self):
		wbox = widgetbox(self._sel_type, self._sld_slice)
		plots = row(self._plot_image)

		# return [wbox, plots, self._div_debug]
		return [column(wbox, plots)]
Beispiel #5
0
        def modify_doc(doc):
            plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)
            slider = RangeSlider(start=0, end=10, value=(1, 5), title="bar", css_classes=["foo"], width=300)

            def cb(attr, old, new):
                slider.bar_color = "rgba(255, 255, 0, 1)"

            slider.on_change('value', cb)
            doc.add_root(column(slider, plot))
 def modify_doc(doc):
     source = ColumnDataSource(dict(x=[1, 2], y=[1, 1], val=["a", "b"]))
     plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)
     plot.add_glyph(source, Circle(x='x', y='y', size=20))
     plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data"))))
     slider = RangeSlider(start=0, end=10, value=(1, 5), title="bar", css_classes=["foo"], width=300)
     def cb(attr, old, new):
         source.data['val'] = [old, new]
     slider.on_change('value', cb)
     doc.add_root(column(slider, plot))
Beispiel #7
0
        def modify_doc(doc):
            source = ColumnDataSource(dict(x=[1, 2], y=[1, 1], val=["a", "b"]))
            plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)
            plot.add_glyph(source, Circle(x='x', y='y', size=20))
            plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data"))))
            slider = RangeSlider(start=0, end=10, value=(1, 9), title="bar", css_classes=["foo"], width=300)

            def cb(attr, old, new):
                source.data['val'] = [old, new]

            slider.on_change('value', cb)
            doc.add_root(column(slider, plot))
Beispiel #8
0
def update_map(attr, old, new):
    global selection, vizual, gvplot, hvplot, heatmap, feats, points, world_map, range_slider, controls3, max_cur_feature, min_cur_feature, temp_feats
    max_cur_feature = temp_feats[choice.value].max()
    min_cur_feature = temp_feats[choice.value].min()
    range_slider = RangeSlider(start=min_cur_feature,
                               end=max_cur_feature,
                               value=(min_cur_feature, max_cur_feature),
                               step=(max_cur_feature - min_cur_feature) / 20,
                               title="Feature_range")
    range_slider.on_change('value', update_map_val)
    controls3 = widgetbox([range_slider], width=250)
    new_loc_feats = temp_feats.loc[
        (temp_feats[choice.value] < range_slider.value[1])
        & (temp_feats[choice.value] > range_slider.value[0])]
    feats = gv.Dataset(new_loc_feats, kdims=['Longitude', 'Latitude', new])
    points = feats.to(gv.Points, ['Longitude', 'Latitude'], [new])
    if len(new_loc_feats) <= 20000:
        world_map = gv.Overlay(tiles * points).options(
            'Points',
            size=5,
            cmap='viridis',
            colorbar=True,
            tools=TOOLS,
            color_index=2,
            width=900,
            height=800,
            global_extent=True,
            colorbar_opts={'scale_alpha': 0.5},
            fill_alpha=0.5,
            line_alpha=0.5)
    else:
        world_map = decimate(gv.Points(points), max_samples=20000).options(
            'Points',
            size=5,
            cmap='viridis',
            colorbar=True,
            tools=TOOLS,
            color_index=2,
            width=900,
            height=800,
            global_extent=True,
            colorbar_opts={'scale_alpha': 0.5},
            fill_alpha=0.5,
            line_alpha=0.5)
    selection = hv.streams.Selection1D(source=world_map)
    heatmap = hv.DynamicMap(selected_points, streams=[selection])
    zoom = hv.DynamicMap(test_bounds, streams=[box])
    hvplot = renderer.get_plot(heatmap, curdoc())
    gvplot = renderer.get_plot(world_map, curdoc())
    bvplot = renderer.get_plot(zoom, curdoc())
    vizual.children[1].children = [gvplot.state, hvplot.state, bvplot.state]
Beispiel #9
0
def _histogram_widgets(col, y, n_bins, col_max, col_min, callback):
    if col_max is None:
        col_max = col.max()
    if col_min is None:
        col_min = col.min()

    slider = Slider(start=1, end=100, value=n_bins, step=1, title="Bins")
    slider.on_change('value', callback)

    range_select = RangeSlider(start=col.min(),
                               end=col.max(),
                               value=(col_min, col_max),
                               step=5,
                               title='Histogram Range')
    range_select.on_change('value', callback)
    return slider, range_select
    def make_extrema_slider(absolute_min, absolute_max, extrema_values, step,
                            label, environment_callback):
        slider = RangeSlider(start=absolute_min,
                             end=absolute_max,
                             value=(extrema_values["minimum"],
                                    extrema_values["maximum"]),
                             step=step,
                             title=label)

        def update_extrema_callback(new_min, new_max):
            extrema_values["minimum"] = new_min
            extrema_values["maximum"] = new_max
            environment_callback()

        slider.on_change(
            "value", lambda _attr, _old, new_value: update_extrema_callback(
                new_value[0], new_value[1]))
        return slider
                     ', SigmaP = ' + "{0:.3}".format(ST_values[1]) + 
                     ', Q = ' + "{0:.2E}".format(ST_values[2]) + 
                     ', A = '+ "{0:.2E}".format(ST_values[3]) + 
                     ', n = ' + "{0:.3}".format(ST_values[4]))
    fig_590.title.text = values_string

# Set checkboxes
LABELS = ["SigmaR", "SigmaP", "Q", "A", "n"]
checkbox_group = CheckboxGroup(labels=LABELS)
checkbox_group.on_change('active', callback)

# insert sliders for the max and min values
SigmaR_range_slider = RangeSlider(start=0, end=100, value=(0,50), step=.1, title="SigmaR")
SigmaP_range_slider = RangeSlider(start=0, end=100, value=(0,50), step=.1, title="SigmaP")
Q_range_slider = RangeSlider(start=0.5e5, end=3e5, value=(0.5e5,3e5), step=1e3, title="Q")
A_range_slider = RangeSlider(start=1.00e7, end=1.00e9, value=(1.00e7,1.00e9), step=1.00e7, title="A")
n_range_slider = RangeSlider(start=0, end=10, value=(3,6), step=.1, title="n")

# When slider values change call the callback function
SigmaR_range_slider.on_change('value', callback)
SigmaP_range_slider.on_change('value', callback)
Q_range_slider.on_change('value', callback)
A_range_slider.on_change('value', callback)
n_range_slider.on_change('value', callback)

# Set the layout of the sliders
sliders = column(SigmaR_range_slider,SigmaP_range_slider,Q_range_slider,A_range_slider,n_range_slider)

# Set layout of the figure
plot_layout = layout([[fig_590,[[checkbox_group],[sliders]]]])
curdoc().add_root(plot_layout)#serve it via "bokeh serve main.py --show --allow-websocket-origin=localhost:5006"
Beispiel #12
0
    def _make_echelle_elements(self,
                               deltanu,
                               cmap='viridis',
                               minimum_frequency=None,
                               maximum_frequency=None,
                               smooth_filter_width=.1,
                               scale='linear',
                               plot_width=490,
                               plot_height=340,
                               title='Echelle'):
        """Helper function to make the elements of the echelle diagram for bokeh plotting.
        """
        if not hasattr(deltanu, 'unit'):
            deltanu = deltanu * self.periodogram.frequency.unit

        if smooth_filter_width:
            pgsmooth = self.periodogram.smooth(
                filter_width=smooth_filter_width)
            freq = pgsmooth.frequency  # Makes code below more readable below
        else:
            freq = self.periodogram.frequency  # Makes code below more readable

        ep, x_f, y_f = self._clean_echelle(
            deltanu=deltanu,
            minimum_frequency=minimum_frequency,
            maximum_frequency=maximum_frequency,
            smooth_filter_width=smooth_filter_width,
            scale=scale)

        fig = figure(plot_width=plot_width,
                     plot_height=plot_height,
                     x_range=(0, 1),
                     y_range=(y_f[0].value, y_f[-1].value),
                     title=title,
                     tools='pan,box_zoom,reset',
                     toolbar_location="above",
                     border_fill_color="white")

        fig.yaxis.axis_label = r'Frequency [{}]'.format(freq.unit.to_string())
        fig.xaxis.axis_label = r'Frequency / {:.3f} Mod. 1'.format(deltanu)

        lo, hi = np.nanpercentile(ep.value, [0.1, 99.9])
        vlo, vhi = 0.3 * lo, 1.7 * hi
        vstep = (lo - hi) / 500
        color_mapper = LogColorMapper(palette="RdYlGn10", low=lo, high=hi)

        fig.image(image=[ep.value],
                  x=0,
                  y=y_f[0].value,
                  dw=1,
                  dh=y_f[-1].value,
                  color_mapper=color_mapper,
                  name='img')

        stretch_slider = RangeSlider(start=vlo,
                                     end=vhi,
                                     step=vstep,
                                     title='',
                                     value=(lo, hi),
                                     orientation='vertical',
                                     width=10,
                                     height=230,
                                     direction='rtl',
                                     show_value=False,
                                     sizing_mode='fixed',
                                     name='stretch')

        def stretch_change_callback(attr, old, new):
            """TPF stretch slider callback."""
            fig.select('img')[0].glyph.color_mapper.high = new[1]
            fig.select('img')[0].glyph.color_mapper.low = new[0]

        stretch_slider.on_change('value', stretch_change_callback)
        return fig, stretch_slider
Beispiel #13
0
    date_text.text = '<b style="color:black">' + str(
        NMindate) + '&nbsp;&nbsp;&nbsp;to&nbsp;&nbsp;&nbsp;' + str(
            NMaxdate) + '<br></b>'

    #fine_date_text.text='<b style="color:black">'+str(fNMindate)+'&nbsp;&nbsp;&nbsp;to&nbsp;&nbsp;&nbsp;'+str(fNMaxdate)+'<br></b>'


date_widget = RangeSlider(start=0,
                          end=5760,
                          value=(0, 6),
                          step=1,
                          show_value=False,
                          tooltips=False)

date_widget.on_change('value', date_function)

se_select = Select(title="Hex construct on the basis of trip....",
                   value="Start",
                   options=['Start', 'End'])

span_radio = RadioButtonGroup(labels=["Lock Map Area", "Auto Adjust Map Area"],
                              active=0)

alpha_range_slider = Slider(start=0,
                            end=1,
                            value=0.4,
                            step=.1,
                            title="Spot Transparency")

size_range_slider = Slider(start=1, end=50, value=4, step=1, title="Spot Size")
Beispiel #14
0
class BokehLoader(object):
    def __init__(self):
        self.spe_file = None
        self.full_sensor_data = None
        self.selection_data = None

        # setup widgets
        self.directory_input = TextInput(placeholder='Directory',
                                         value=os.path.join(
                                             os.getcwd(), 'data'))
        self.show_files_button = Button(label='Show Files',
                                        button_type='primary')
        self.file_view = MultiSelect(size=5)
        self.open_file_button = Button(label='Open File',
                                       button_type='warning')
        self.update_selection_button = Button(label='Update Selection',
                                              button_type='success')
        self.selection_range = RangeSlider(start=0,
                                           end=1,
                                           value=(0, 1),
                                           step=1,
                                           title='Selected Rows')

        # connect button callbacks
        self.show_files_button.on_click(self.update_file_browser)
        self.open_file_button.on_click(self.open_file_callback)
        self.update_selection_button.on_click(self.update_selection)
        self.selection_range.on_change('value', self.selection_range_callback)

        # setup plots
        self.full_sensor_image = figure(x_range=(0, 1),
                                        y_range=(0, 1023),
                                        tools='pan,box_zoom,wheel_zoom,reset',
                                        plot_width=512,
                                        plot_height=512)
        self.full_sensor_image_label = Label(x=0.1,
                                             y=0.1,
                                             text='Source Data',
                                             text_font_size='36pt',
                                             text_color='#eeeeee')
        self.full_sensor_image.add_tools(BoxSelectTool(dimensions='height'))
        self.full_sensor_image.grid.grid_line_color = None
        self.full_sensor_image.xaxis.major_tick_line_color = None
        self.full_sensor_image.xaxis.minor_tick_line_color = None
        self.full_sensor_image.yaxis.major_tick_line_color = None
        self.full_sensor_image.yaxis.minor_tick_line_color = None
        self.full_sensor_image.xaxis.major_label_text_font_size = '0pt'
        self.full_sensor_image.yaxis.major_label_text_font_size = '0pt'
        self.selection_lines_coords = ColumnDataSource(
            data=dict(x=[[0, 1], [0, 1]], y=[[0, 0], [1, 1]]))

        self.selection_image = figure(x_range=(0, 1),
                                      y_range=(0, 1),
                                      tools='wheel_zoom',
                                      plot_width=1024,
                                      plot_height=180)
        self.selection_image_label = Label(x=0.1,
                                           y=0.2,
                                           text='Selection Region',
                                           text_font_size='36pt',
                                           text_color='#eeeeee')
        self.selection_image.grid.grid_line_color = None

        # build the layout
        controls = [
            self.directory_input, self.show_files_button, self.file_view,
            self.open_file_button, self.selection_range,
            self.update_selection_button
        ]
        widgets = widgetbox(*controls, width=500)
        self.layout = layout(
            children=[[widgets],
                      [self.full_sensor_image, self.selection_image]],
            sizing_mode='fixed')

        # set defaults
        self.initialize_ui()

    def update_file_browser(self):
        active_dir = self.directory_input.value
        if os.path.isdir(active_dir):
            self.file_view.options = [
                f for f in os.listdir(active_dir)
                if os.path.isfile(os.path.join(active_dir, f))
            ]
        else:
            self.file_view.options = ['INVALID DIRECTORY']

    def update_full_sensor_image(self):
        self.full_sensor_image.y_range.start = 0
        self.full_sensor_image.y_range.end = self.full_sensor_data.shape[0] - 1
        self.full_sensor_image.image([self.full_sensor_data],
                                     0,
                                     0,
                                     1,
                                     self.full_sensor_data.shape[0],
                                     palette='Inferno256')
        self.selection_range.start = 0
        self.selection_range.end = self.full_sensor_data.shape[0] - 1
        self.selection_range.value = (0, self.full_sensor_data.shape[0] - 1)
        self.full_sensor_image.multi_line(xs='x',
                                          ys='y',
                                          source=self.selection_lines_coords,
                                          color='red',
                                          line_width=5,
                                          alpha=0.6)

    def update_selection(self):
        self.selection_image_label.text = ''
        self.selection_image.title.text = 'Selected Data'
        ylim = (int(self.selection_range.value[0]),
                int(self.selection_range.value[1]))
        self.selection_data = self.full_sensor_data[ylim[0]:ylim[1] + 1, :]
        self.selection_image.y_range.start = 0
        self.selection_image.y_range.end = ylim[1] - ylim[0]
        self.selection_image.image([self.selection_data],
                                   0,
                                   0,
                                   1,
                                   self.selection_image.y_range.end,
                                   palette='Inferno256')

    def open_file_callback(self):
        path_to_file = os.path.join(self.directory_input.value,
                                    self.file_view.value[0])
        if not os.path.isfile(path_to_file):
            return
        self.spe_file = spe_loader.load_from_files([path_to_file])
        self.full_sensor_data = self.spe_file.data[0][0]
        self.full_sensor_image_label.text = ''
        self.full_sensor_image.title.text = 'Source Data'
        self.update_full_sensor_image()

    def selection_range_callback(self, attr, old, new):
        ylim = (int(self.selection_range.value[0]),
                int(self.selection_range.value[1]))
        x = [[0, 1], [0, 1]]
        y = [[ylim[0], ylim[0]], [ylim[1], ylim[1]]]
        self.selection_lines_coords.data = dict(x=x, y=y)

    def initialize_ui(self):
        self.full_sensor_image.add_layout(self.full_sensor_image_label)
        self.selection_image.add_layout(self.selection_image_label)
        self.update_file_browser()
Beispiel #15
0
rangeslider = RangeSlider(start=140000,
                          end=225000,
                          step=10,
                          value=(140000, 150000),
                          title="X range")
file_selector = Select(value=None, options=nix(None, files))
waveselector = RadioButtonGroup(labels=["P wave", "QRS wave", "T wave"],
                                active=0)
textboxnew = PreText(text="New points:      \t[]")
retrievebutton = Button(label='Retrieve Segmentation')
storebutton = Button(label='Store Segmentation')
writebutton = Button(label='Write to File')

# Set callbacks
file_selector.on_change('value', file_change)
source.selected.on_change('indices', selection_change)
retrievebutton.on_click(retrieve_segmentation)
storebutton.on_click(save_segmentation)
writebutton.on_click(write_segmentation)
rangeslider.on_change('value', change_range)
waveselector.on_change('active', file_change)

# set up layout
buttons = row(waveselector, retrievebutton, storebutton, writebutton)
layout = column(file_selector, textboxnew, rangeslider, buttons, grid)

# initialize
# update()

curdoc().add_root(layout)
curdoc().title = "FullDelineator"
Beispiel #16
0
          'shortened_date',
          'low',
          color="black",
          source=data)
# p.vbar(data.shortened_date[inc], w, data.open[inc], data.close[inc], fill_color="#D5E1DD", line_color="black")
# p.vbar(data.shortened_date[dec], w, data.open[dec], data.close[dec], fill_color="#F2583E", line_color="black")


def callback(attr, old, new):
    points = range_slider.value
    date1, date2 = np.datetime64(points[0]), np.datetime64(points[1])
    data1 = df_apple.loc[(df_apple['shortened_date'] >= np.datetime64(date1)) &
                         (df_apple['shortened_date'] <= np.datetime64(date2))]
    # inc = data1.close > data1.open
    # dec = data1.open > data1.close
    data = {
        'shortened_date': data1.shortened_date,
        'high': data1.high,
        'low': data1.low,
    }


range_slider.on_change('value', callback)
layout = row(slider_widget, plot)
curdoc().add_root(layout)
# output_file("candlestick.html", title="candlestick.py example")

# show(p)  # open a browser

# %%
class rearrangerControls:
    """Class to move around an audio file"""
    def __init__(self):
        logger.logData(source="Rearranger tools",
                       priority="INFO",
                       msgType="Setup start",
                       msgData=())

        self.setupVariables()
        self.setupPlots()

        logger.logData(source="Rearranger tools",
                       priority="INFO",
                       msgType="Setup done",
                       msgData=())

    def showGUI(self):
        show(self.gui)
        curdoc().add_root(self.gui)

    def setupVariables(self):
        #dummy values until tool is used

        self.pctToShift = 0.6
        self.shiftStandardDev = 10
        self.shiftMean = 0
        self.startSample = 0

        self.minGrainSz = 0
        self.maxGrainSz = 10
        self.modeGrainSz = 5

        self.sliderWidth = 400
        self.toolWidth = 1000
        self.subplotSize = 300

    #GUI CALLBACKS
    def grainSizeSliderCallback(self, attr, old, new):
        newMin = new[0]
        newMax = new[1]

        self.minGrainSz = int(newMin)
        self.maxGrainSz = int(newMax)
        self.modeGrainSz = int(.5 * (self.minGrainSz + self.maxGrainSz))

        grainSizePDF = self.maxSamplePlot.select_one({'name': 'sampleSizePDF'})

        numPoints = 10
        chunkSizes = np.linspace(self.minGrainSz, self.maxGrainSz, numPoints)
        probs = np.linspace(0, 1, numPoints / 2)
        probs = np.append(probs, probs[::-1])

        grainSizePDF.data_source.data = {'x': chunkSizes, 'y': probs}

    def setupChunkTimeWindow(self):
        #subtool to control the chunk size distribution
        self.grainSizeSlider = RangeSlider(
            start=0,
            end=300,
            value=[0, 20],
            step=1,
            title="Chunk Time Bounds",
            width=self.sliderWidth)  #, callback=timeSliderCallback)
        self.grainSizeSlider.on_change("value", self.grainSizeSliderCallback)

        maxSamplePlot = figure(height=self.subplotSize,
                               x_range=(0, 300),
                               y_range=(0, 1.1),
                               width=self.subplotSize,
                               toolbar_location=None,
                               title="Grain Size PDF",
                               tools="")  #x_range = (0,len(movedSignal)))
        maxSamplePlot.yaxis.visible = False
        maxSamplePlot.grid.visible = False

        numPoints = 10
        chunkSizes = np.linspace(self.minGrainSz, self.maxGrainSz, numPoints)
        probs = np.linspace(0, 1, int(numPoints / 2))
        probs = np.append(probs, probs[::-1])

        maxSamplePlot.line(chunkSizes, probs, name="sampleSizePDF")
        # maxSampleWindow = column(maxSamplePlot,grainSizeSlider)
        return maxSamplePlot

    def setupSampleDisplacementWindow(self):
        self.sampleDisplacementWidthSlider = Slider(
            start=-10,
            end=10,
            value=self.shiftMean,
            step=1,
            title="Sample Displacement Average",
            width=self.sliderWidth)
        self.sampleDisplacementWidthSlider.on_change(
            "value", self.sampleDisplacementWidthCallback)

        self.sampleDisplacementWidthStdSlider = Slider(
            start=1,
            end=30,
            value=self.shiftStandardDev,
            step=1,
            title="Sample Displacement Std",
            width=self.sliderWidth)
        self.sampleDisplacementWidthStdSlider.on_change(
            "value", self.sampleDisplacementWidthStdCallback)

        sampleDisplacementPlot = figure(height=self.subplotSize,
                                        width=self.subplotSize,
                                        x_range=(-10, 10),
                                        y_range=(0, .2),
                                        toolbar_location=None,
                                        title="Sample Displacement PDF",
                                        tools="")
        # sampleDisplacementPlot.axis.visible = False
        sampleDisplacementPlot.grid.visible = False

        ts = np.linspace(-10, 10)
        sampleDisplacementPlot.line(ts,
                                    norm.pdf(ts, self.shiftMean,
                                             self.shiftStandardDev),
                                    name="sampleDispacePDF")
        return sampleDisplacementPlot

    def updateSampleDisplacementPDF(self):
        sampleDisplacement = self.sampleDisplacementPlot.select_one(
            {'name': 'sampleDispacePDF'})
        ts = np.linspace(-10, 10)
        sampleDisplacement.data_source.data = {
            'x': ts,
            'y': norm.pdf(ts, self.shiftMean, self.shiftStandardDev)
        }

    def sampleDisplacementWidthCallback(self, attr, old, new):
        self.shiftMean = new
        self.updateSampleDisplacementPDF()

    def sampleDisplacementWidthStdCallback(self, attr, old, new):
        self.shiftStandardDev = new
        self.updateSampleDisplacementPDF()

    def setupGeneralControls(self):
        channelRadioButtons = RadioButtonGroup(
            labels=["Independent", "Coupled"], active=0, disabled=True)

        self.switcherooButton = Button(label="Switcheroo",
                                       button_type="success")

        fractionOfWaveToDisturbSlider = Slider(
            start=0,
            end=1,
            value=self.pctToShift,
            step=.1,
            title="Portion Of Wave To Disturb",
            width=self.sliderWidth)  #, callback=timeSliderCallback)
        fractionOfWaveToDisturbSlider.on_change(
            "value", self.fractionOfWaveToDisturbCallback)

        controlButtonsColumn = column(channelRadioButtons,
                                      fractionOfWaveToDisturbSlider,
                                      self.sampleDisplacementWidthSlider,
                                      self.sampleDisplacementWidthStdSlider,
                                      self.grainSizeSlider,
                                      self.switcherooButton)
        return controlButtonsColumn

    def fractionOfWaveToDisturbCallback(self, attr, old, new):
        self.pctToShift = new

    def setupPlots(self):
        sampleDis = self.setupSampleDisplacementWindow()
        self.sampleDisplacementPlot = sampleDis

        maxSampleWindow = self.setupChunkTimeWindow()
        self.maxSamplePlot = maxSampleWindow

        generalControls = self.setupGeneralControls()

        self.gui = row(maxSampleWindow,
                       sampleDis,
                       generalControls,
                       height=self.subplotSize)

    def getGrainSizes(self):
        return (self.minGrainSz, self.modeGrainSz, self.maxGrainSz)

    def getShiftInfo(self):
        return (self.pctToShift, self.shiftStandardDev)
Beispiel #18
0
        (hs[~hs[['var1', 'var2']].apply(frozenset, axis=1).duplicated()]
         ['weight'] > min_corr) &
        (hs[~hs[['var1', 'var2']].apply(frozenset, axis=1).duplicated()]
         ['weight'] < max_corr), True, False)
    # print(len(new_colors), new_colors)
    # print(len(mask), mask)
    new_colors[~mask] = "#1C00ff00"
    graph_renderer.edge_renderer.data_source.data["edge_color"] = new_colors
    # new_corr_bools = [True if ((corr_val < new[1]) and (corr_val > new[0])) else False for corr_val in segment_source.data['r']]
    # new_corr_view = CDSView(source=segment_source, filters=[BooleanFilter(corr_bools)])
    # corr_view.filters[0] = BooleanFilter(new_corr_bools)
    # plot_segment.view = new_corr_view
    # plot_segment.update()


l_slider.on_change('value_throttled', ls_callback)

# plot_scatter.visible = False

G = nx.Graph()
G.add_nodes_from(init_names)
G.add_edges_from(itertools.combinations(init_names, 2))
fixed_positions = dict(zip(init_names, list(zip(init_x, init_y))))
#
graph_renderer = from_networkx(G,
                               nx.spring_layout,
                               pos=fixed_positions,
                               fixed=init_names,
                               center=(0, 0))
node_attrs = {}
Beispiel #19
0
        'x': HDI_Country['Year'], 
        'y': HDI_Country['HDI Score']
    }
    source1.data = New_Data_1
    source2.data = New_Data_2
    source3.data = New_Data_3

Countries = Terrorist_attacks['Country'].dropna()
Countries_list = sorted(Countries.unique())
select = Select(title='Choose Country:', value='Afghanistan', options=Countries_list, width=380)
select.on_change('value', update_line)

str_year = min(success['Year'])
end_year = max(success['Year'])
slider_range = RangeSlider(title="Choose years", start=str_year, end=end_year, value=(str_year, end_year), step=5, width=400)
slider_range.on_change('value', update_line)

text2 = Paragraph(text="""In the figure above, we can see the amount of deaths and the amount of terrorist attacks in the world per year and how these two are related.""")
text3 = Paragraph(text="""In the figure above, we can see the amount of terrorist attacks with success and no success. The years and the country of which the terrorist attacks with success and no success can be seen, depends on the choice you made in the above input fields.There is a chance a country doesn't have had terrorist attacks in the year range you chose, the plot will be blank""")
text4 = Paragraph(text="""In the figure above, we can see the Human Development Index per year. The Human Development Index is a score between 0 and 1000 and measures the poverty, illiteracy, education and life expectancy in a particular country. The years and the country of which the Human Development Index can be seen, depends on the choice you made in the above input fields. There is a chance a country doesn't have had terrorist attacks in the year range you chose, the plot will be blank""")

layout2 = layout([
[button],
[p],
[text2],
[select, slider_range],
[k, t], 
[text3, text4],
], sizing_mode='scale_width')

tab1 = Panel(child=layout1, title='General')
#side menu
plot = figure(title='Movies',
              x_axis_label='Votes',
              y_axis_label='Rank',
              plot_height=700,
              plot_width=700,
              tools=TOOLS)

plot.add_tools(HoverTool(tooltips=tool_tips))

slider = RangeSlider(start=start,
                     end=end,
                     step=1,
                     value=(start, end),
                     title="Year")
slider.on_change('value', update_plot)

renderer = plot.circle(x='x', y='y', source=data_column, size=6, color='blue')

glyph = renderer.glyph
glyph.size = 6
glyph.fill_alpha = 0.5
glyph.line_color = "black"
#glyph.line_dash = [1]
glyph.line_width = 1

selected_circle = Circle(fill_alpha=1, fill_color="firebrick", line_color=None)
nonselected_circle = Circle(fill_alpha=0.2, fill_color="blue", line_color=None)

renderer.selection_glyph = selected_circle
renderer.nonselection_glyph = nonselected_circle
Beispiel #21
0
            waveselector=waveselector,
            sources=sources,
            current_keys=current_keys,
            local_field=local_field,
            local_P=local_P,
            far_field=far_field,
            textbox=textbox,
            all_waves=all_waves))
writebutton.on_click(
    partial(src.write_segmentation,
            all_waves=all_waves,
            local_field=local_field,
            far_field=far_field,
            local_P=local_P,
            test=args.test))
rangeslider.on_change(
    'value', partial(src.change_range, rangeslider=rangeslider, leads=leads))
waveselector.on_change(
    'active',
    partial(src.wave_change,
            args=args,
            all_waves=all_waves,
            file_selector=file_selector,
            local_field=local_field,
            far_field=far_field,
            local_P=local_P,
            previous_local_P=previous_local_P,
            boxes_local_P=boxes_local_P,
            sources=sources,
            current_keys=current_keys,
            previous_local_field=previous_local_field,
            previous_far_field=previous_far_field,
Beispiel #22
0
datatable_columns = [
    TableColumn(field="parameter", title="Parameter"),
    TableColumn(field="value_all", title="All Data"),
    TableColumn(field="value_selection", title="Selected Data"),
]

data_table = DataTable(source=datatable_source,
                       columns=datatable_columns,
                       width=450,
                       height=125,
                       index_position=None)

# callback for updating the plot based on a changes to inputs
station_name_input.on_change('value', update_station)
simulation_number_input.on_change('value', update_n_simulations)
msmt_error_input.on_change('value', update_msmt_error)
sample_size_input.on_change('value', update_simulation_sample_size)
toggle_button.on_click(update_simulated_msmt_error)

# see documentation for threading information
# https://docs.bokeh.org/en/latest/docs/user_guide/server.html

update()

# widgets
ts_plot = create_ts_plot(peak_source, peak_flagged_source)

peak_source.selected.on_change('indices', update_UI)

vh1, pv, hist_source = create_vhist(peak_source, ts_plot)
def bkapp(doc):
    
### Functions ###

    # functions for user dialogs

    def open_file(ftype):
        root = Tk()
        root.withdraw()
        file = askopenfilename(filetypes=ftype,
                               title='Open File',
                               initialdir=os.getcwd())
        root.destroy()
        return file
    
    def choose_directory():
        root = Tk()
        root.withdraw()
        out_dir = askdirectory()
        root.destroy()
        return out_dir

    def write_output_directory(output_dir):
        root = Tk()
        root.withdraw()
        makeDir = askquestion('Make Directory','Output directory not set. Make directory: '
            +output_dir+'? If not, you\'ll be prompted to change directories.',icon = 'warning')
        root.destroy()
        return makeDir

    def overwrite_file():
        root = Tk()
        root.withdraw()
        overwrite = askquestion('Overwrite File','File already exits. Do you want to overwrite?',icon = 'warning')
        root.destroy()
        return overwrite

    def update_filename():
        filetype = [("Video files", "*.mp4")]
        fname = open_file(filetype)
        if fname:
            #print('Successfully loaded file: '+fname)
            load_data(filename=fname)         

    def change_directory():
        out_dir = choose_directory()
        if out_dir:
            source.data["output_dir"] = [out_dir]
            outDir.text = out_dir
        return out_dir

    # load data from file

    def load_data(filename):
        vidcap = cv2.VideoCapture(filename)
        success,frame = vidcap.read()
        img_tmp,_,__ = cv2.split(frame)
        h,w = np.shape(img_tmp)
        img = np.flipud(img_tmp)
        radio_button_gp.active = 0
        fname = os.path.split(filename)[1]
        input_dir = os.path.split(filename)[0]
        if source.data['output_dir'][0]=='':
            output_dir = os.path.join(input_dir,fname.split('.')[0])
        else:
            output_dir = source.data['output_dir'][0]
        if not os.path.isdir(output_dir):
            makeDir = write_output_directory(output_dir)
            if makeDir=='yes':
                os.mkdir(output_dir)
            else:
                output_dir = change_directory()
        if output_dir:
            source.data = dict(image_orig=[img], image=[img], bin_img=[0],
                x=[0], y=[0], dw=[w], dh=[h], num_contours=[0], roi_coords=[0], 
                img_name=[fname], input_dir=[input_dir], output_dir=[output_dir])
            curr_img = p.select_one({'name':'image'})
            if curr_img:
                p.renderers.remove(curr_img)
            p.image(source=source, image='image', x='x', y='y', dw='dw', dh='dh', color_mapper=cmap,level='image',name='image')      
            p.plot_height=int(h/2)
            p.plot_width=int(w/2)
            #p.add_tools(HoverTool(tooltips=IMG_TOOLTIPS))
            inFile.text = fname
            outDir.text = output_dir
        else:
            print('Cancelled. To continue please set output directory.{:<100}'.format(' '),end="\r")

    # resetting sources for new data or new filters/contours

    def remove_plot():
        source.data["num_contours"]=[0]
        contours_found.text = 'Droplets Detected: 0'
        source_contours.data = dict(xs=[], ys=[])
        source_label.data = dict(x=[], y=[], label=[])

    # apply threshold filter and display binary image

    def apply_filter():
        if source.data['input_dir'][0] == '':
            print('No image loaded! Load image first.{:<100}'.format(' '),end="\r")
        else:
            img = np.squeeze(source.data['image_orig'])
            # remove contours if present
            if source.data["num_contours"]!=[0]:
                remove_plot()
            if radio_button_gp.active == 1:
                thresh = filters.threshold_otsu(img)
                binary = img > thresh
                bin_img = binary*255
                source.data["bin_img"] = [bin_img]
            elif radio_button_gp.active == 2:
                thresh = filters.threshold_isodata(img)
                binary = img > thresh
                bin_img = binary*255
                source.data["bin_img"] = [bin_img]
            elif radio_button_gp.active == 3:
                thresh = filters.threshold_mean(img)
                binary = img > thresh
                bin_img = binary*255
                source.data["bin_img"] = [bin_img]
            elif radio_button_gp.active == 4:
                thresh = filters.threshold_li(img)
                binary = img > thresh
                bin_img = binary*255
                source.data["bin_img"] = [bin_img]
            elif radio_button_gp.active == 5:
                thresh = filters.threshold_yen(img)
                binary = img > thresh
                bin_img = binary*255
                source.data["bin_img"] = [bin_img]
            elif radio_button_gp.active == 6:
                off = offset_spinner.value
                block_size = block_spinner.value
                thresh = filters.threshold_local(img,block_size,offset=off)
                binary = img > thresh
                bin_img = binary*255
                source.data["bin_img"] = [bin_img]
            else:
                bin_img = img
            source.data['image'] = [bin_img]

    # image functions for adjusting the binary image
    
    def close_img():
        if source.data["num_contours"]!=[0]:
            remove_plot()
        if radio_button_gp.active == 0:
            print("Please Select Filter for Threshold{:<100}".format(' '),end="\r")
        else:
            source.data["image"] = source.data["bin_img"]
            img = np.squeeze(source.data['bin_img'])
            closed_img = binary_closing(255-img)*255
            source.data['image'] = [255-closed_img]
            source.data['bin_img'] = [255-closed_img]

    def dilate_img():
        if source.data["num_contours"]!=[0]:
            remove_plot()
        if radio_button_gp.active == 0:
            print("Please Select Filter for Threshold{:<100}".format(' '),end="\r")
        else:
            img = np.squeeze(source.data['bin_img'])
            dilated_img = binary_dilation(255-img)*255
            source.data['image'] = [255-dilated_img]
            source.data['bin_img'] = [255-dilated_img]

    def erode_img():
        if source.data["num_contours"]!=[0]:
            remove_plot()
        if radio_button_gp.active == 0:
            print("Please Select Filter for Threshold{:<100}".format(' '),end="\r")
        else:
            img = np.squeeze(source.data['bin_img'])
            eroded_img = binary_erosion(255-img)*255
            source.data['image'] = [255-eroded_img] 
            source.data['bin_img'] = [255-eroded_img]  

    # the function for identifying closed contours in the image

    def find_contours(level=0.8):
        min_drop_size = contour_rng_slider.value[0]
        max_drop_size = contour_rng_slider.value[1]
        min_dim = 20
        max_dim = 200
        if radio_button_gp.active == 0:
            print("Please Select Filter for Threshold{:<100}".format(' '),end="\r")
        elif source.data['input_dir'][0] == '':
            print('No image loaded! Load image first.{:<100}'.format(' '),end="\r")
        else:
            img = np.squeeze(source.data['bin_img'])
            h,w = np.shape(img)        
            contours = measure.find_contours(img, level)
            length_cnt_x = [cnt[:,1] for cnt in contours if np.shape(cnt)[0] < max_drop_size 
                             and np.shape(cnt)[0] > min_drop_size]
            length_cnt_y = [cnt[:,0] for cnt in contours if np.shape(cnt)[0] < max_drop_size 
                             and np.shape(cnt)[0] > min_drop_size]
            matched_cnt_x = []
            matched_cnt_y = []
            roi_coords = []
            label_text = []
            label_y = np.array([])
            count=0
            for i in range(len(length_cnt_x)):
                cnt_x = length_cnt_x[i]
                cnt_y = length_cnt_y[i]
                width = np.max(cnt_x)-np.min(cnt_x)
                height = np.max(cnt_y)-np.min(cnt_y)
                if width>min_dim and width<max_dim and height>min_dim and height<max_dim:
                    matched_cnt_x.append(cnt_x)
                    matched_cnt_y.append(cnt_y)
                    roi_coords.append([round(width),round(height),round(np.min(cnt_x)),round(h-np.max(cnt_y))])
                    label_text.append(str(int(count)+1))
                    label_y = np.append(label_y,np.max(cnt_y))
                    count+=1
            curr_contours = p.select_one({'name':'overlay'})
            if curr_contours:
                p.renderers.remove(curr_contours)
            #if source.data["num_contours"]==[0]:
                #remove_plot()
                #p.image(source=source, image='image_orig', x=0, y=0, dw=w, dh=h, color_mapper=cmap, name='overlay',level='underlay')      
            source.data["image"] = source.data["image_orig"]
            source.data["num_contours"] = [count]
            #source.data["cnt_x"] = [matched_cnt_x]
            #source.data["cnt_y"] = [matched_cnt_y]
            source.data["roi_coords"] = [roi_coords]
            source_contours.data = dict(xs=matched_cnt_x, ys=matched_cnt_y)
            p.multi_line(xs='xs',ys='ys',source=source_contours, color=(255,127,14),line_width=2, name="contours",level='glyph')
            if len(np.array(roi_coords).shape)<2:
                if len(np.array(roi_coords)) <4:
                    print('No contours found. Try adjusting parameters or filter for thresholding.{:<100}'.format(' '),end="\r")
                    source_label.data = dict(x=[],y=[],label=[])
                else:
                    source_label.data = dict(x=np.array(roi_coords)[2], y=label_y, label=label_text)
            else:
                source_label.data = dict(x=np.array(roi_coords)[:,2], y=label_y, label=label_text)
            contours_found.text = 'Droplets Detected: '+str(len(matched_cnt_x))

    # write the contours and parameters to files

    def export_ROIs():
        if source.data["num_contours"]==[0]:
            print("No Contours Found! Find contours first.{:<100}".format(' '),end="\r")
        else:
            hdr = 'threshold filter,contour min,contour max'
            thresh_filter = radio_button_gp.active
            cnt_min = contour_rng_slider.value[0]
            cnt_max = contour_rng_slider.value[1]
            params = [thresh_filter,cnt_min,cnt_max]
            if radio_button_gp.active == 6:
                off = offset_spinner.value
                block_size = block_spinner.value
                hdr = hdr + ',local offset,local block size'
                params.append(off,block_size)
            params_fname = 'ContourParams.csv'
            params_out = os.path.join(source.data['output_dir'][0],params_fname)
            overwrite = 'no'
            if os.path.exists(params_out):
                overwrite = overwrite_file()
            if overwrite == 'yes' or not os.path.exists(params_out):
                np.savetxt(params_out,np.array([params]),delimiter=',',header=hdr,comments='')
            roi_coords = np.array(source.data["roi_coords"][0])
            out_fname = 'ROI_coords.csv'
            out_fullpath = os.path.join(source.data['output_dir'][0],out_fname)
            if overwrite == 'yes' or not os.path.exists(out_fullpath):
                hdr = 'width,height,x,y'
                np.savetxt(out_fullpath,roi_coords,delimiter=',',header=hdr,comments='')
                print('Successfully saved ROIs coordinates as: '+out_fullpath,end='\r')
                source.data['roi_coords'] = [roi_coords]

    # function for loading previously made files or error handling for going out of order

    def check_ROI_files():
        coords_file = os.path.join(source.data["output_dir"][0],'ROI_coords.csv')
        n_cnt_curr = source.data["num_contours"][0]
        roi_coords_curr = source.data["roi_coords"][0]
        if os.path.exists(coords_file):
            df_tmp=pd.read_csv(coords_file, sep=',')
            roi_coords = np.array(df_tmp.values)
            n_cnt = len(roi_coords)
            if n_cnt_curr != n_cnt or not np.array_equal(roi_coords_curr,roi_coords):
                print('Current ROIs are different from saved ROI file! ROIs from saved file will be used instead and plot updated.',end="\r")
            source.data["num_contours"] = [n_cnt]
            source.data["roi_coords"] = [roi_coords]
            params_file = os.path.join(source.data['output_dir'][0],'ContourParams.csv')
            params_df = pd.read_csv(params_file)
            thresh_ind = params_df["threshold filter"].values[0]
            radio_button_gp.active = int(thresh_ind)
            if thresh_ind == 6:
                offset_spinner.value = int(params_df["local offset"].values[0])
                block_spinner.value = int(params_df["local block size"].values[0])
            contour_rng_slider.value = tuple([int(params_df["contour min"].values[0]),int(params_df["contour max"].values[0])])
            find_contours()
        else:
            print("ROI files not found! Check save directory or export ROIs.{:<100}".format(' '),end="\r")

    # use FFMPEG to crop out regions from original mp4 and save to file

    def create_ROI_movies():
        if source.data['input_dir'][0] == '':
            print('No image loaded! Load image first.{:<100}'.format(' '),end="\r")
        else:
            check_ROI_files()
            side = 100 # for square ROIs, replace first two crop parameters with side & uncomment
            padding = 20
            roi_coords_file = os.path.join(source.data['output_dir'][0],'ROI_coords.csv')
            if source.data["num_contours"]==[0]:
                print("No contours found! Find contours first.{:<100}".format(' '),end="\r")
            elif not os.path.exists(roi_coords_file):
                print("ROI file does not exist! Check save directory or export ROIs.{:<100}".format(' '),end="\r")
            else:
                print('Creating Movies...{:<100}'.format(' '),end="\r")
                pbar = tqdm(total=source.data["num_contours"][0])
                for i in range(source.data["num_contours"][0]):
                    roi_coords = np.array(source.data["roi_coords"][0])
                    inPath = os.path.join(source.data['input_dir'][0],source.data['img_name'][0])
                    #out_fname = source.data['filename'][0].split('.')[0] +'_ROI'+str(i+1)+'.mp4'
                    out_fname = 'ROI'+str(i+1)+'.mp4'
                    outPath = os.path.join(source.data['output_dir'][0],out_fname)
                    #command = f"ffmpeg -i \'{(inPath)}\' -vf \"crop={(roi_coords[i,0]+padding*2)}:{(roi_coords[i,1]+padding*2)}:{(roi_coords[i,2]-padding)}:{(roi_coords[i,3]+padding)}\" -y \'{(outPath)}\'"
                    command = f"ffmpeg -i \'{(inPath)}\' -vf \"crop={side}:{side}:{(roi_coords[i,2]-padding)}:{(roi_coords[i,3]-padding)}\" -y \'{(outPath)}\'"
                    overwrite = 'no'
                    if os.path.exists(outPath):
                        overwrite = overwrite_file()
                    if overwrite == 'yes' or not os.path.exists(outPath):
                        saved = subprocess.check_call(command,shell=True)
                        if saved != 0:
                            print('An error occurred while creating movies! Check terminal window.{:<100}'.format(' '),end="\r")
                    pbar.update()

    # change the display range on images from slider values

    def update_image():
        cmap.low = display_range_slider.value[0]
        cmap.high = display_range_slider.value[1]

    # create statistics files for each mp4 region specific file

    def process_ROIs():
        if source.data['input_dir'][0] == '':
            print('No image loaded! Load image first.{:<100}'.format(' '),end="\r")
        else:
            check_ROI_files()
            hdr = 'roi,time,area,mean,variance,min,max,median,skewness,kurtosis,rawDensity,COMx,COMy'
            cols = hdr.split(',')
            all_stats = np.zeros((0,13))
            n_cnt = source.data["num_contours"][0]
            if n_cnt == 0:
                print("No contours found! Find contours first.{:<100}".format(' '),end="\r")
            for i in range(n_cnt): 
                #in_fname = source.data['filename'][0].split('.')[0] +'_ROI'+str(i+1)+'.mp4'
                in_fname = 'ROI'+str(i+1)+'.mp4'
                inPath = os.path.join(source.data['output_dir'][0],in_fname)
                #out_fname = source.data['filename'][0].split('.')[0] +'_ROI'+str(i+1)+'_stats.csv'
                out_fname = 'stats_ROI'+str(i+1)+'.csv'
                outPath = os.path.join(source.data['output_dir'][0],out_fname)
                if not os.path.exists(inPath):
                    print('ROI movie not found! Create ROI movie first.{:<100}'.format(' '),end="\r")
                    break
                vidcap = cv2.VideoCapture(inPath)
                last_frame = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
                if i==0:
                    pbar = tqdm(total=last_frame*n_cnt)
                success,frame = vidcap.read()
                img_tmp,_,__ = cv2.split(frame)
                h,w = np.shape(img_tmp)
                img = np.zeros((last_frame,h,w))
                img_stats = np.zeros((last_frame,13))
                stats = describe(img_tmp,axis=None)
                median = np.median(img_tmp)
                density = np.sum(img_tmp)
                cx, cy = center_of_mass(img_tmp)
                img_stats[0,0:13] = [i,0,stats.nobs,stats.mean,stats.variance,
                        stats.minmax[0],stats.minmax[1],median,stats.skewness,
                        stats.kurtosis,density,cx,cy]
                img[0,:,:] = np.flipud(img_tmp)
                pbar.update()
                overwrite = 'no'
                if os.path.exists(outPath):
                    overwrite = overwrite_file()
                    if overwrite=='no':
                        pbar.update(last_frame-1)
                if overwrite == 'yes' or not os.path.exists(outPath):
                    for j in range(1,last_frame):
                        vidcap.set(1, j)
                        success,frame = vidcap.read()
                        img_tmp,_,__ = cv2.split(frame)
                        stats = describe(img_tmp,axis=None)
                        t = j*5/60
                        density = np.sum(img_tmp)
                        cx, cy = center_of_mass(img_tmp)
                        median = np.median(img_tmp)
                        img_stats[j,0:13] = [i,t,stats.nobs,stats.mean,stats.variance,
                                stats.minmax[0],stats.minmax[1],median,stats.skewness,
                                stats.kurtosis,density,cx,cy]
                        img[j,:,:] = np.flipud(img_tmp)
                        pbar.update(1)
                    all_stats = np.append(all_stats,img_stats,axis=0)
                    np.savetxt(outPath,img_stats,delimiter=',',header=hdr,comments='')
                if i==(n_cnt-1):
                    df = pd.DataFrame(all_stats,columns=cols)
                    group = df.groupby('roi')
                    for i in range(len(group)):
                        sources_stats[i] = ColumnDataSource(group.get_group(i))

    # load statistics CSVs and first ROI mp4 files and display in plots

    def load_ROI_files():
        if source.data['input_dir'][0] == '':
            print('No image loaded! Load image first.{:<100}'.format(' '),end="\r")
        else:
            check_ROI_files()
            n_cnt = source.data["num_contours"][0]
            basepath = os.path.join(source.data["output_dir"][0],'stats')
            all_files = [basepath+'_ROI'+str(i+1)+'.csv' for i in range(n_cnt)]
            files_exist = [os.path.exists(f) for f in all_files]
            if all(files_exist) and n_cnt != 0:
                df = pd.concat((pd.read_csv(f) for f in all_files), ignore_index=True)
                group = df.groupby('roi')
                OPTIONS = []
                LABELS = []
                pbar = tqdm(total=len(stats)*len(group))
                j=0
                colors_ordered = list(Category20[20])
                idx_reorder = np.append(np.linspace(0,18,10),np.linspace(1,19,10))
                idx = idx_reorder.astype(int)
                colors = [colors_ordered[i] for i in idx]
                for roi, df_roi in group:
                    sources_stats[roi] = ColumnDataSource(df_roi)
                    OPTIONS.append([str(int(roi)+1),'ROI '+(str(int(roi)+1))])
                    LABELS.append('ROI '+str(int(roi)+1))
                    color = colors[j]
                    j+=1
                    if j>=20:
                        j=0
                    for i in range(3,len(df.columns)):
                        name = 'ROI '+str(int(roi)+1)
                        plot_check = p_stats[i-3].select_one({'name':name})
                        if not plot_check:
                            p_stats[i-3].line(x='time',y=str(df.columns[i]),source=sources_stats[roi],
                                name=name,visible=False,line_color=color)
                            p_stats[i-3].xaxis.axis_label = "Time [h]"
                            p_stats[i-3].yaxis.axis_label = str(df.columns[i])
                            p_stats[i-3].add_tools(HoverTool(tooltips=TOOLTIPS))
                            p_stats[i-3].toolbar_location = "left"
                        pbar.update(1)
                ROI_multi_select.options = OPTIONS 
                ROI_multi_select.value = ["1"]
                ROI_movie_radio_group.labels = LABELS
                ROI_movie_radio_group.active = 0
            else:
                print('Not enough files! Check save directory or calculate new stats.{:<100}'.format(' '),end="\r")

    # show/hide curves from selected/deselected labels for ROIs in statistics plots

    def update_ROI_plots():
        n_cnt = source.data["num_contours"][0]
        pbar = tqdm(total=len(stats)*n_cnt)
        for j in range(n_cnt):
            for i in range(len(stats)):
                name = 'ROI '+str(int(j)+1)
                glyph = p_stats[i].select_one({'name': name})
                if str(j+1) in ROI_multi_select.value:
                    glyph.visible = True
                else:
                    glyph.visible = False
                pbar.update(1)

    # load and display the selected ROI's mp4

    def load_ROI_movie():
        idx = ROI_movie_radio_group.active
        in_fname = 'ROI'+str(idx+1)+'.mp4'
        inPath = os.path.join(source.data['output_dir'][0],in_fname)
        if not os.path.exists(inPath):
            print('ROI movie not found! Check save directory or create ROI movie.',end="\r")
        else:
            old_plot = p_ROI.select_one({'name': sourceROI.data['img_name'][0]})
            if old_plot:
                p_ROI.renderers.remove(old_plot)
            vidcap = cv2.VideoCapture(inPath)
            last_frame = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
            ROI_movie_slider.end = (last_frame-1)*5/60
            ROI_movie_slider.value = 0
            vidcap.set(1, 0)
            success,frame = vidcap.read()
            img_tmp,_,__ = cv2.split(frame)
            h,w = np.shape(img_tmp)
            img = np.flipud(img_tmp)
            name = 'ROI'+str(idx+1)
            sourceROI.data = dict(image=[img],x=[0], y=[0], dw=[w], dh=[h],
                img_name=[name])
            p_ROI.image(source=sourceROI, image='image', x='x', y='y', 
               dw='dw', dh='dh', color_mapper=cmap, name='img_name')

    # change the displayed frame from slider movement

    def update_ROI_movie():
        frame_idx = round(ROI_movie_slider.value*60/5)
        in_fname = sourceROI.data['img_name'][0]+'.mp4'
        inPath = os.path.join(source.data['output_dir'][0],in_fname)
        vidcap = cv2.VideoCapture(inPath)
        vidcap.set(1, frame_idx)
        success,frame = vidcap.read()
        img_tmp,_,__ = cv2.split(frame)
        img = np.flipud(img_tmp)
        sourceROI.data['image'] = [img]

    # the following 2 functions are used to animate the mp4

    def update_ROI_slider():
        time = ROI_movie_slider.value + 5/60
        end = ROI_movie_slider.end
        if time > end:
            animate_ROI_movie()
        else:
            ROI_movie_slider.value = time
        return callback_id

    def animate_ROI_movie():
        global callback_id
        if ROI_movie_play_button.label == '► Play':
            ROI_movie_play_button.label = '❚❚ Pause'
            callback_id = curdoc().add_periodic_callback(update_ROI_slider, 10)
        else:
            ROI_movie_play_button.label = '► Play'
            curdoc().remove_periodic_callback(callback_id)
        return callback_id

### Application Content ###

    # main plot for segmentation and contour finding

    cmap = LinearColorMapper(palette="Greys256", low=0, high=255)
    TOOLS = "pan,wheel_zoom,box_zoom,reset,save,box_select,lasso_select"
    IMG_TOOLTIPS = [('name', "@img_name"),("x", "$x"),("y", "$y"),("value", "@image")]

    source = ColumnDataSource(data=dict(image=[0],bin_img=[0],image_orig=[0],
            x=[0], y=[0], dw=[0], dh=[0], num_contours=[0], roi_coords=[0],
            input_dir=[''],output_dir=[''],img_name=['']))
    source_label = ColumnDataSource(data=dict(x=[0], y=[0], label=['']))
    source_contours = ColumnDataSource(data=dict(xs=[0], ys=[0]))

    roi_labels = LabelSet(x='x', y='y', text='label',source=source_label, 
        level='annotation',text_color='white',text_font_size='12pt')

    # create a new plot and add a renderer
    p = figure(tools=TOOLS, toolbar_location=("right"))
    p.add_layout(roi_labels)
    p.x_range.range_padding = p.y_range.range_padding = 0

    # turn off gridlines
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None
    p.axis.visible = False


    # ROI plots 

    sourceROI = ColumnDataSource(data=dict(image=[0],
            x=[0], y=[0], dw=[0], dh=[0], img_name=[0]))
    sources_stats = {}

    TOOLTIPS = [('name','$name'),('time', '@time'),('stat', "$y")]
    stats = np.array(['mean','var','min','max','median','skew','kurt','rawDensity','COMx','COMy'])
    p_stats = []
    tabs = []
    for i in range(len(stats)):
        p_stats.append(figure(tools=TOOLS, plot_height=300, plot_width=600))
        p_stats[i].x_range.range_padding = p_stats[i].y_range.range_padding = 0
        tabs.append(Panel(child=p_stats[i], title=stats[i]))

    # create a new plot and add a renderer
    p_ROI = figure(tools=TOOLS, toolbar_location=("right"), plot_height=300, plot_width=300)
    p_ROI.x_range.range_padding = p_ROI.y_range.range_padding = 0  

    # turn off gridlines
    p_ROI.xgrid.grid_line_color = p_ROI.ygrid.grid_line_color = None
    p_ROI.axis.visible = False


    # Widgets - Buttons, Sliders, Text, Etc.

    intro = Div(text="""<h2>Droplet Recognition and Analysis with Bokeh</h2> 
        This application is designed to help segment a grayscale image into 
        regions of interest (ROIs) and perform analysis on those regions.<br>
        <h4>How to Use This Application:</h4>
        <ol>
        <li>Load in a grayscale mp4 file and choose a save directory.</li>
        <li>Apply various filters for thresholding. Use <b>Close</b>, <b>Dilate</b> 
        and <b>Erode</b> buttons to adjust each binary image further.</li>
        <li>Use <b>Find Contours</b> button to search the image for closed shape. 
        The <b>Contour Size Range</b> slider will change size of the perimeter to
        be identified. You can apply new thresholds and repeat until satisfied with
        the region selection. Total regions detected is displayed next to
        the button.</li>
        <li>When satisfied, use <b>Export ROIs</b> to write ROI locations and 
        contour finding parameters to file.</li>
        <li><b>Create ROI Movies</b> to write mp4s of the selected regions.</li>
        <li>Use <b>Calculate ROI Stats</b> to perform calculations on the 
        newly created mp4 files.</li>
        <li>Finally, use <b>Load ROI Files</b> to load in the data that you just
        created and view the plots. The statistics plots can be overlaid by 
        selecting multiple labels. Individual ROI mp4s can be animated or you can
        use the slider to move through the frames.</li>
        </ol>
        Note: messages and progress bars are displayed below the GUI.""",
        style={'font-size':'10pt'},width=1000)

    file_button = Button(label="Choose File",button_type="primary")
    file_button.on_click(update_filename)
    inFile = PreText(text='Input File:\n'+source.data["img_name"][0], background=(255,255,255,0.5), width=500)

    filter_LABELS = ["Original","OTSU", "Isodata", "Mean", "Li","Yen","Local"]
    radio_button_gp = RadioButtonGroup(labels=filter_LABELS, active=0, width=600)
    radio_button_gp.on_change('active', lambda attr, old, new: apply_filter())
    
    offset_spinner = Spinner(low=0, high=500, value=1, step=1, width=100, title="Local: Offset",
                            background=(255,255,255,0.5))
    offset_spinner.on_change('value', lambda attr, old, new: apply_filter())
    block_spinner = Spinner(low=1, high=101, value=25, step=2, width=100, title="Local: Block Size",
                           background=(255,255,255,0.5))
    block_spinner.on_change('value', lambda attr, old, new: apply_filter())
    
    closing_button = Button(label="Close",button_type="default", width=100)
    closing_button.on_click(close_img)
    dilation_button = Button(label="Dilate",button_type="default", width=100)
    dilation_button.on_click(dilate_img)
    erosion_button = Button(label="Erode",button_type="default", width=100)
    erosion_button.on_click(erode_img)

    contour_rng_slider = RangeSlider(start=10, end=500, value=(200,350), step=1, width=300, 
            title="Contour Size Range", background=(255,255,255,0.5), bar_color='gray')
    contour_button = Button(label="Find Contours", button_type="success")
    contour_button.on_click(find_contours)
    contours_found = PreText(text='Droplets Detected: '+str(source.data["num_contours"][0]), background=(255,255,255,0.5))
    
    exportROIs_button = Button(label="Export ROIs", button_type="success", width=200)
    exportROIs_button.on_click(export_ROIs)    

    changeDir_button = Button(label="Change Directory",button_type="primary", width=150)
    changeDir_button.on_click(change_directory)
    outDir = PreText(text='Save Directory:\n'+source.data["output_dir"][0], background=(255,255,255,0.5), width=500)

    create_ROIs_button = Button(label="Create ROI Movies",button_type="success", width=200)
    create_ROIs_button.on_click(create_ROI_movies)

    process_ROIs_button = Button(label="Calculate ROI Stats",button_type="success")
    process_ROIs_button.on_click(process_ROIs)

    display_rng_text = figure(title="Display Range", title_location="left", 
                        width=40, height=300, toolbar_location=None, min_border=0, 
                        outline_line_color=None)
    display_rng_text.title.align="center"
    display_rng_text.title.text_font_size = '10pt'
    display_rng_text.x_range.range_padding = display_rng_text.y_range.range_padding = 0

    display_range_slider = RangeSlider(start=0, end=255, value=(0,255), step=1, 
        orientation='vertical', direction='rtl', 
        bar_color='gray', width=40, height=300, tooltips=True)
    display_range_slider.on_change('value', lambda attr, old, new: update_image())

    load_ROIfiles_button = Button(label="Load ROI Files",button_type="primary")
    load_ROIfiles_button.on_click(load_ROI_files)

    ROI_multi_select = MultiSelect(value=[], width=100, height=300)
    ROI_multi_select.on_change('value', lambda attr, old, new: update_ROI_plots())

    ROI_movie_radio_group = RadioGroup(labels=[],width=60)
    ROI_movie_radio_group.on_change('active', lambda attr, old, new: load_ROI_movie())
    ROI_movie_slider = Slider(start=0,end=100,value=0,step=5/60,title="Time [h]", width=280)
    ROI_movie_slider.on_change('value', lambda attr, old, new: update_ROI_movie())

    callback_id = None

    ROI_movie_play_button = Button(label='► Play',width=50)
    ROI_movie_play_button.on_click(animate_ROI_movie)

# initialize some data without having to choose file
    # fname = os.path.join(os.getcwd(),'data','Droplets.mp4')
    # load_data(filename=fname)


### Layout & Initialize application ###

    ROI_layout = layout([
        [ROI_movie_radio_group, p_ROI],
        [ROI_movie_slider,ROI_movie_play_button]
        ])

    app = layout(children=[
        [intro],
        [file_button,inFile],
        [radio_button_gp, offset_spinner, block_spinner],
        [closing_button, dilation_button, erosion_button],
        [contour_rng_slider, contour_button, contours_found],
        [exportROIs_button, outDir, changeDir_button],
        [create_ROIs_button, process_ROIs_button],
        [display_rng_text, display_range_slider, p],
        [load_ROIfiles_button],
        [ROI_layout, ROI_multi_select, Tabs(tabs=tabs)]
    ])
    
    doc.add_root(app)
Beispiel #24
0
        right='qso_right',
        source=dis_hist_source,
        fill_color='red',
        line_color='black')
p8 = figure(x_axis_label='com_distance', y_axis_label='Numbers')
p8.quad(bottom=0,
        top='com_num',
        left='com_left',
        right='com_right',
        source=dis_hist_source,
        fill_color='blue',
        line_color='black')

# Attach the update_plot callback to the 'value' property of select
#select1.on_change('value', update_plot)
select2.on_change('value', update_plot)
range_slider.on_change('value', update_plot)
range_slider2.on_change('value', update_plot)
range_slider3.on_change('value', update_plot)
slider.on_change('value', update_hist)

# Create layout and add to current document
layout = column(range_slider, range_slider2, range_slider3, select2, plots,
                slider, row(p7, p8))
#show(layout)
curdoc().clear()
curdoc().add_root(layout)
show(p1)
#cd "path_to_the_script"
#bokeh serve --show bokeh_color.py
Beispiel #25
0
def Persistence_EM_Matrix():
    ### ------------ read files ------------
    
    final = pd.read_csv('./data/App_data/AQ_EM_tse_final.csv',encoding='utf-8')
    profit = pd.read_csv('./data/App_data/AQ_EM_tse_final_profibility_1.csv',encoding='utf-8')
    profit['company_name'] = profit.company.astype(str)+" "+profit.company_abbreviation
    #此檔案中放的為dict, key為用途及名稱,value為list
    with open('app_lists.json','r')as f: 
        app_lists = json.load(f)
    with open('smallco.json','r')as f: 
        smallco_index = json.load(f)
        
    ### ------------ 左側的選項 ------------

    year = Select(title='Year:',value='200812',
                        options=list(final.yyyymm.drop_duplicates().sort_values().astype(str)))

    industry = Select(title='Industry:',value='水泥工業',
                          options = list(profit.tse_industry_name.drop_duplicates())+['All Sectors'])

    index_factor = Select(title='Compared Market Index:',value='TWN50',options=["TWN50", "TM100","TF001"])

    company_list = list((profit.query("yyyymm==200812 & tse_industry_name=='水泥工業'").company_name.astype(str)))

    company_code = Select(title='Company Code: ',value='',options=['']+company_list)

    persistence = Select(title='Persistence:',value='ebit_slope_standard',
                         options= app_lists['options_persistence'])

    EM = Select(title='EM:',value='Jones_model_measure',options=app_lists['options_EM'])

    profit_measure = Select(title='Profit Measure:',value='ROA_ebi',
                            options=app_lists['options_profit_measure'])

    Persistence_percent = RangeSlider(start=0, end=100,value=(20,40), step=1, title="Persistence % :")
    EM_percent = RangeSlider(start=0, end=100,value=(20,40), step=1, title="EM %:")

    #根據選擇日期、產業更新公司列表選項
    ###############################################################################
    def update_company_list(attr,old,new):
        selected_year = year.value
        selected_industry = industry.value
        if selected_industry !='All Sectors':
            company_list = list((profit.query("yyyymm==@selected_year & tse_industry_name==@selected_industry").\
                                 company_name.sort_values().astype(str)))
            #前面加入空値,代表沒有選公司
            company_code.options = ['']+company_list
            #default 為空値
            company_code.value = ''
        else:
            company_list = list((profit.query("yyyymm==@selected_year").\
                            company_name.sort_values().astype(str)))
            #前面加入空値,代表沒有選公司
            company_code.options = ['']+company_list
            #default 為空値
            company_code.value = ''

    #選出畫圖的資料
    ###############################################################################
    def get_plot_data():
        selected_year=year.value
        selected_industry = industry.value
        selected_index_factor = index_factor.value
        selected_Persistence = persistence.value
        selected_EM = EM.value
        selected_profit_measure = profit_measure.value
        if selected_industry !='All Sectors':
            data = profit.query('yyyymm == @selected_year & tse_industry_name  == @selected_industry')
        else :
            data = profit.query('yyyymm == @selected_year')
        #依據日期、產業選擇
        data = data[(data[selected_Persistence].notna()) & (data[selected_EM].notna())]
        #因為有可能選擇的資料也是之後要保留的資料,因此先備份,以免在rename後找不到資料
        origin_data = [selected_Persistence,selected_EM,selected_profit_measure]
        origin = data[origin_data]
        #重新命名,在ColumnDataSource中較好使用
        data.rename(columns={selected_Persistence:'Persistence',selected_EM:'EM',selected_index_factor:'index_factor',
                             selected_profit_measure:'profit_measure'} , inplace=True)
        for i in origin_data:
            data[i] = origin[i]
        data['Persistence'] = data.Persistence.apply(lambda x:value_transfrom(x,selected_Persistence))
        data['EM'] = data.EM.apply(lambda x:value_transfrom(x,selected_EM))
        data['color'] = data['index_factor'].apply(lambda x:'green' if x=='Y' else 'blue')
        data['color'] = data.apply(lambda x:'red' if str(x.company) in smallco_index['2020'] else x.color, 1)

        profit_min = data['profit_measure'].min()
        profit_range = data['profit_measure'].max()-data['profit_measure'].min()
        data['profit_score'] = data['profit_measure'].apply(lambda x:((x-profit_min)/profit_range)*25+5\
                                                            if profit_range!=0 else 30 if x==1 else 5)
        table_data = data[app_lists['select_stock_picking_table_column']]
        data_for_source = data.fillna('--')
        if company_code.value!='':
            data_for_source['text'] = data_for_source['company'].apply(lambda x:'.Here' if x==int(company_code.value[:4])else '')
        else :
            data_for_source['text']=''
        data_for_source = data_for_source[~data_for_source.isin([np.nan, np.inf, -np.inf]).any(1)]
        if company_code.value!='':
            select_co = int(company_code.value[:4])
            data_for_source['select_p'] = data.query('company==@select_co')['Persistence'].to_list()[0]
            data_for_source['select_e'] = data.query('company==@select_co')['EM'].to_list()[0]
        else :
            data_for_source['select_p'] = np.nan
            data_for_source['select_e'] = np.nan

        plot_source = ColumnDataSource(data_for_source)
        return (plot_source,table_data)
    def get_stock_picking_table_data(table_data):
        df = table_data
        Persistence_top = df.Persistence.quantile(Persistence_percent.value[1]/100)
        Persistence_low = df.Persistence.quantile(Persistence_percent.value[0]/100)
        EM_top = df.EM.quantile(EM_percent.value[1]/100)
        EM_low = df.EM.quantile(EM_percent.value[0]/100)
        df = df.query('Persistence <= @Persistence_top & Persistence >= @Persistence_low & EM <= @EM_top & EM >= @EM_low')
        df = df.applymap(lambda x:round(x,2) if type(x)==float else x)
        stock_picking_table_co_choice.options = (df.company.astype(str)+' '+df.company_abbreviation).sort_values().to_list()
        stock_picking_table_co_num.text = f'Total: {df.shape[0]} company'
        return ColumnDataSource(df)

    def get_stock_return_table_2_data():
        selected_year=year.value
        selected_index_factor = index_factor.value
        df = profit.rename(columns={selected_index_factor:'index_factor'})
        df = df.query('yyyymm == @selected_year & index_factor=="Y"')
        return ColumnDataSource(df)

    def get_stock_return_table_3_data(stock_picking_table_source,stock_return_table_2_source):
        if stock_picking_table_source.data['yearly_return'].size ==0 :
            stock_average = [' ']
        else : stock_average = [round(np.nanmean(stock_picking_table_source.data['yearly_return']),4)]

        if stock_return_table_2_source.data['yearly_return'].size ==0 :
            etf_average = [' ']
        else : etf_average = [round(np.nanmean(stock_return_table_2_source.data['yearly_return']),4)]

        return ColumnDataSource(data={'Stock Picking Return (Equally Weighted)':stock_average,
                                      "ETF Return (Equally Weighted)" :etf_average 
                                      })
    def get_matrix_plot_data():
        selected_year=year.value
        df = profit.query('yyyymm == @selected_year')
        df = df[app_lists['options_persistence']+app_lists['options_EM']].corr()
        df = df.apply(lambda x:round(x,2))
        return ColumnDataSource(df)
    ###################################################
    # 製作圖、表  
    def make_scatter_plot(plot_source):
        hover = HoverTool( names=['circle'],
                            tooltips=[('Company Abbreviation :','@company_abbreviation'),
                                        ('Company Code :','@company'),
                                        ('Persistence','@Persistence'),
                                        ('EM :','@EM'),('ROA (EBI) :','@ROA_ebi'),
                                        ('EPS :','@eps'),('ROE_b :','@ROE_b'),
                                        ('Diluted EPS :','@eps_diluted'),('Yearly Return','@yearly_return')]
                         )
        plot = figure(plot_height=500, plot_width=800,
                          tools = ['box_zoom','reset',hover],
                          x_axis_label='Persistence (Log Transformed)',
                          y_axis_label='EM (Log Transformed)', 
                          toolbar_location="right"
                     )
        plot.circle(x="Persistence", y="EM", source=plot_source,color= 'color',size='profit_score', name='circle',
                    line_color=None,alpha=0.5)
#         plot.text('Persistence','EM','text',source=plot_source,color='red',text_font_style='bold',text_font_size='20pt')
        plot.asterisk('select_p','select_e',source=plot_source,color='red',size=20)
        plot.toolbar.active_drag = None
        return plot
    def make_stock_picking_table(stock_picking_table_source):
        columns = []
        for colnames in stock_picking_table_source.data.keys():
            if colnames !='index':
                columns.append(TableColumn(field=colnames, title=colnames, width=6*len(colnames)))
        stock_picking_table = DataTable(source=stock_picking_table_source, columns=columns, width=4000, height = 500)
        return (stock_picking_table)

    def make_stock_return_table_1(stock_picking_table_source):
        columns = []
        for colnames in ['tse_industry_name','company','company_abbreviation','index_factor','yearly_return']:
            columns.append(TableColumn(field=colnames, title=colnames, width=6*len(colnames)))
        stock_return_table_1 = DataTable(source=stock_picking_table_source, columns=columns, height = 500)
        return (stock_return_table_1)
    def make_stock_return_table_2(stock_return_table_2_source):
        columns = []
        for colnames in ['tse_industry_name','company','company_abbreviation','index_factor','yearly_return']:
            columns.append(TableColumn(field=colnames, title=colnames, width=6*len(colnames)))
        stock_return_table_2 = DataTable(source=stock_return_table_2_source, columns=columns, height = 500)
        return (stock_return_table_2)

    def make_stock_return_table_3(stock_return_table_3_source): 
        columns = []
        for colnames in stock_return_table_3_source.data.keys():
            if colnames !='index':
                columns.append(TableColumn(field=colnames, title=colnames, width=6*len(colnames)))
        stock_return_table_3 = DataTable(source=stock_return_table_3_source, columns=columns)
        return (stock_return_table_3)

    def make_matrix_plot(matrix_plot_source):
        columns = []
        for colnames in matrix_plot_source.data.keys():
            if colnames =='index':
                columns.append(TableColumn(field=colnames, title=' ', width=200))
            else:
                columns.append(TableColumn(field=colnames, title=colnames, width=6*len(colnames)))
        matrix_plot = DataTable(source=matrix_plot_source, columns=columns, index_position=None, width = 2500, height=300)
        return (matrix_plot)
    ###################################################
    # 更新 
    def update(attr,old,new):
        stock_picking_table_co_choice.value = []
        new_plot_source,new_table_data=get_plot_data()
        plot_source.data.update(new_plot_source.data)


        new_stock_picking_table_source = get_stock_picking_table_data(new_table_data)
        stock_picking_table_source.data.update(new_stock_picking_table_source.data)

        new_stock_return_table_2_source = get_stock_return_table_2_data()
        stock_return_table_2_source.data.update(new_stock_return_table_2_source.data)

        new_stock_return_table_3_source = get_stock_return_table_3_data(new_stock_picking_table_source,new_stock_return_table_2_source)
        stock_return_table_3_source.data.update(new_stock_return_table_3_source.data)

        new_matrix_plot_source = get_matrix_plot_data()
        matrix_plot_source.data.update(new_matrix_plot_source.data)
    def update_stock_picking(attr,old,new):
        
        pick_list = list(map(lambda x:x[:4],stock_picking_table_co_choice.value))
        new_plot_source,new_table_data=get_plot_data()
        new_stock_picking_table_source = get_stock_picking_table_data(new_table_data)
        df = pd.DataFrame(new_stock_picking_table_source.data).iloc[:,1:]
        if len(pick_list)==0:
            df = df
        else:
            df = df.query('company in @pick_list')
        stock_picking_table_source.data.update(ColumnDataSource(df).data)
        stock_picking_table_co_num.text = f'Total: {df.shape[0]} company'
            

    ###################################################
    # initial 

    plot_source,table_data = get_plot_data()
    plot = make_scatter_plot(plot_source)
    plot_explain = Div(text =
                       '''
                       <span style="padding-left:20px">顏色(綠色): 該公司在該年,有被列在所選的Compared Market Index中 <br/>
                       <span style="padding-left:20px">顏色(紅色): 該公司在該年,有被列在中小型成分股中 <br/>
                       <span style="padding-left:20px">大小: 圈圈越大,代表該公司Profit Measure越大
                       ''')
    tab1 = Panel(child=column(Spacer(height=35), plot, Spacer(height=20), plot_explain), title='Persistence EM Matrix')

    
    stock_picking_table_co_choice = MultiChoice(title = 'select_company:', value=[], options=[], placeholder = '選擇想看的公司')
    stock_picking_table_co_choice.js_on_change("value", CustomJS(code="""
        console.log('multi_choice: value=' + this.value, this.toString())
    """))
    stock_picking_table_co_num = Div(text ='Total:   company')
    stock_picking_table_source = get_stock_picking_table_data(table_data)
    stock_picking_table = make_stock_picking_table(stock_picking_table_source)
    tab2 = Panel(child=column(stock_picking_table_co_num, stock_picking_table, stock_picking_table_co_choice), title='Stock Picking Table')

    div1 = Div(text ='Table 1: The next year return of stocks from the matrix')
    stock_return_table_1 = make_stock_return_table_1(stock_picking_table_source)
    div2 = Div(text ='Table 2: The next year return of stocks in ETF')
    stock_return_table_2_source = get_stock_return_table_2_data()
    stock_return_table_2 = make_stock_return_table_2(stock_return_table_2_source)
    div3 = Div(text ='Table 3: The next year return of equally weighted portfolios')
    stock_return_table_3_source = get_stock_return_table_3_data(stock_picking_table_source,stock_return_table_2_source)
    stock_return_table_3 = make_stock_return_table_3(stock_return_table_3_source)
    tab3 = Panel(child=row([column(div1,stock_return_table_1),
                            column(div2,stock_return_table_2),
                            column(div3,stock_return_table_3)]),
                 title='Stock Return Table')

    matrix_plot_source = get_matrix_plot_data()
    matrix_plot = make_matrix_plot(matrix_plot_source)
    matrix_plot_explain = Div(text = 
        '''
        Persistence: <br/>
        <span style="padding-left:50px">ebit_slope_standard <br/>
        <span style="padding-left:50px">operating_slope_standard <br/>
        <span style="padding-left:50px">yoy_ebit_standard <br/>
        <span style="padding-left:50px">yoy_operating_standard <br/>
        <br/><br/>
        EM: <br/>
        <span style="padding-left:50px">Jones_model_measure <br/>
        <span style="padding-left:50px">Modified_Jones_model_measure <br/>
        <span style="padding-left:50px">Performance_matching_measure <br/>
        <span style="padding-left:50px">opacity_Jones_model_measure <br/>
        <span style="padding-left:50px">opacity_modified_Jones_model_measure <br/>
        <span style="padding-left:50px">opacity_performance_matching <br/>
        ''')
    tab4 = Panel(child=column(matrix_plot,row(Spacer(width=20), matrix_plot_explain)), title='Correlation Matrix of Persistence & EM')

    tabs = Tabs(tabs=[tab1,tab2,tab3,tab4])

    ###################################################
    # input change
    year.on_change('value', update, update_company_list)
    industry.on_change('value', update, update_company_list)
    index_factor.on_change('value', update)
    company_code.on_change('value', update)
    persistence.on_change('value', update)
    EM.on_change('value', update)
    profit_measure.on_change('value', update)
    Persistence_percent.on_change('value', update)
    EM_percent.on_change('value', update)
    stock_picking_table_co_choice.on_change('value', update_stock_picking)

    ###################################################
    # layout
    div_title = Div(text ='Persistence & EM Matrix',style={'font-size': '200%', 'color': 'blue'})
    inputs = column(div_title,year, industry, index_factor, company_code,persistence,EM,profit_measure,
                             Persistence_percent,EM_percent, background='gainsboro')
    final_layout = row(inputs, tabs, width=1200)
    return Panel(child = column(Spacer(height = 35), final_layout), title = 'Persistence & EM 概況')
Beispiel #26
0
        div_occurence.text = "{:.2f} planets per Sun<sup>†</sup>".format(eta)
        div_occurence_post.text = "of the types discovered by Kepler."
        div_count_pre.text = 'This implies the presence of at least'
        div_count.text = "{:.0f} billion planets<sup>‡</sup>".format(20 * eta)
        div_count_post.text = 'across our Galaxy.'


period_slider = RangeSlider(start=np.log10(PERIOD_RANGE[0]),
                            end=np.log10(PERIOD_RANGE[1]),
                            value=(np.log10(PERIOD_RANGE[0]),
                                   np.log10(PERIOD_RANGE[1])),
                            step=.01,
                            title=None,
                            show_value=False,
                            css_classes=['period-slider'])
period_slider.on_change('value', update_limits)

radius_slider = RangeSlider(start=np.log10(RADIUS_RANGE[0]),
                            end=np.log10(RADIUS_RANGE[1]),
                            value=(np.log10(RADIUS_RANGE[0]),
                                   np.log10(RADIUS_RANGE[1])),
                            step=.01,
                            title=None,
                            show_value=False,
                            callback_policy='mouseup',
                            css_classes=['radius-slider'])
radius_slider.on_change('value', update_limits)

callback_id = None

layout = layout([
Beispiel #27
0
           title="Confirmed Corona Cases in India Statewise ",
           x_axis_label="No of cases ",
           y_axis_label="States",
           tools="pan,wheel_zoom,box_zoom,reset")
source = ColumnDataSource(data={
    'states': a,
    'cases': b,
    'colors': linear_palette(Magma256, d)
})
slider = RangeSlider(title='Cases Range',
                     start=0,
                     end=100000,
                     step=1,
                     value=(0, 100000),
                     bar_color="green")
slider.on_change('value', changeArea)
p.hbar(y='states',
       right='cases',
       left=0,
       height=0.6,
       fill_color='colors',
       fill_alpha=0.9,
       source=source)
p1 = figure(x_range=a,
            plot_width=1300,
            plot_height=600,
            title=" Cured Corona Cases in India Statewise ",
            x_axis_label="States ",
            y_axis_label="No of cases",
            tools="pan,wheel_zoom,box_zoom,reset")
source1 = ColumnDataSource(data={
Beispiel #28
0
    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.js_on_click(
    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)
def make_start_end_figure(doc):
    """
    Creates a Bokeh app for visualizations of start and end of hurricanes
    """
    df_spawn_end = pd.read_csv('files/df_start_end_bokeh.csv', index_col=0)

    year_min, year_max, lon_boundaries, lat_boundaries = get_boundaries(df_spawn_end)

    gulf_stream_lon1, gulf_stream_lon2, gulf_stream_lat1, gulf_stream_lat2 = get_gulf_stream()

    # credits of the map
    url = 'http://a.basemaps.cartocdn.com/rastertiles/voyager/{Z}/{X}/{Y}.png'
    attribution = "Tiles by Carto, under CC BY 3.0. Data by OSM, under ODbL"

    add_paragraph = additional_legend(loc='tracks')

    # -----------------------------------------------------
    # WIDGETS
    # -----------------------------------------------------

    # definition and configuration of the number selection
    options_number = ['-1'] + [str(x) for x in list(np.arange(1, 21))]
    select_number = Select(title='Number of hurricanes:', value='5', options=options_number)

    # definition and configuration of the zone selection
    options_zone = ['All', 'Mexico_Caribbean', 'Atlantic']
    select_zone = Select(title='Spawning Zone:', value='All', options=options_zone)

    # Definition of buttons for end points and distances
    toggle_month = Toggle(label="Show end points", button_type="success")
    toggle_dist_month = Toggle(label="Show distance traveled", button_type="success")

    # definition and configuration of the year and month sliders
    slider_year = RangeSlider(start=year_min, end=year_max,
                              value=(year_min, year_max), step=1, title="Years")

    slider_month = RangeSlider(start=1, end=12,
                               value=(1, 12), step=1, title="Months")

    # End points
    toggle_season = Toggle(label="Show end points", button_type="success")
    toggle_dist_season = Toggle(label="Show distance traveled", button_type="success")

    # definition and configuration of the number selection
    select_number_season = Select(title='Number of hurricanes:', value='5',
                                  options=options_number)

    # definition and configuration of the zone selection
    select_zone_season = Select(title='Spawning Zone:', value='All', options=options_zone)

    # definition and configuration of the year and sliders
    slider_year_season = RangeSlider(start=year_min, end=year_max,
                                     value=(year_min, year_max), step=1, title="Years")

    # definition and configuration of the season selection
    options_season = ['All', 'Winter', 'Spring', 'Summer', 'Autumn']
    select_season = Select(title='Season:', value='All', options=options_season)

    # -------------------------------------------------------
    # DATA SOURCE AND RANDOMIZATION
    # -------------------------------------------------------
    np.random.seed(42)
    n = 5

    select_list = list(np.random.choice(df_spawn_end.index, size=n, replace=False))
    filtr = df_spawn_end.index.map(lambda x: x in select_list)

    source = ColumnDataSource(data=df_spawn_end[filtr])

    # --------------------------------------------------------
    # FIRST TAB
    # --------------------------------------------------------

    # Initialization of the map
    p = figure(tools='pan, wheel_zoom', x_range=(lon_boundaries[0], lon_boundaries[1]),
               y_range=(lat_boundaries[0], lat_boundaries[1]),
               x_axis_type="mercator", y_axis_type="mercator")

    p.add_tile(WMTSTileSource(url=url, attribution=attribution))

    # Add data points
    # - Start
    # - End
    # - Start with size adjusted to the traveled distance
    c1 = p.circle(x='x_start', y='y_start', fill_color='green', size=8,
                  source=source, legend_label='Start points')

    c2 = p.circle(x='x_end', y='y_end', fill_color='orange', size=8,
                  source=source, legend_label='End points')

    d1 = p.circle(x='x_start', y='y_start', fill_color='green', radius='Distance_draw',
                  source=source)

    # Line between start and end points
    s1 = p.segment(x0='x_start', y0='y_start', x1='x_end', y1='y_end',
                   line_dash='dashed', source=source)

    # Initial configuration of WIDGETS  for FIRST TAB
    # - Don't show end points
    # - Don't show segments between start and end points
    # - Uniform size for starting points
    c2.visible, s1.visible, d1.visible = False, False, False

    # Configuration of the hovertool
    hover = HoverTool(tooltips=[("ID", "@ID"), ("Duration", "@Duration"),
                                ("Distance", "@Distance")],
                      renderers=[c1, c2, d1], formatters={'Duration': 'printf'})
    p.tools.append(hover)

    # Draw the Gulf Stream
    p.segment(x0=gulf_stream_lon1[:-1], y0=gulf_stream_lat1[:-1],
              x1=gulf_stream_lon1[1:], y1=gulf_stream_lat1[1:],
              legend_label='Gulf Stream', color='red', line_alpha=0.5, line_width=2)

    p.segment(x0=gulf_stream_lon2[:-1], y0=gulf_stream_lat2[:-1],
              x1=gulf_stream_lon2[1:], y1=gulf_stream_lat2[1:],
              color='red', line_alpha=0.5, line_width=2)

    p.legend.location = "top_left"

    # DataFrame display
    no_cols = ['x_start', 'x_end', 'y_start', 'y_end', 'Distance_draw']
    cols = [TableColumn(field=col, title=col) for col in df_spawn_end.columns if col not in no_cols]
    data_table = DataTable(columns=cols, source=source, width=1100, selectable=False)

    # ------------------------------------------------------------------------
    # UPDATING FIRST TAB
    # ------------------------------------------------------------------------

    # updating process of the data underlying the map depending on user actions.
    def update_map_se(attr, old, new):

        yr = slider_year.value
        month = slider_month.value
        zone = select_zone.value
        n = select_number.value
        n = int(n)

        if zone == 'All':
            df_temp = df_spawn_end.loc[(df_spawn_end['Year_start'] >= yr[0])
                                       & (df_spawn_end['Year_start'] <= yr[1])
                                       & (df_spawn_end['Month_start'] >= month[0])
                                       & (df_spawn_end['Month_start'] <= month[1])]

        else:
            df_temp = df_spawn_end.loc[(df_spawn_end.Zones_start == zone)
                                       & (df_spawn_end['Year_start'] >= yr[0])
                                       & (df_spawn_end['Year_start'] <= yr[1])
                                       & (df_spawn_end['Month_start'] >= month[0])
                                       & (df_spawn_end['Month_start'] <= month[1])]

        if n == -1:

            source.data = ColumnDataSource.from_df(df_temp)
        else:

            if n > len(df_temp):  # For cases where there are not enough data points
                n = int(len(df_temp))

            np.random.seed(42)

            select_list = list(np.random.choice(df_temp.index, size=n, replace=False))

            filtr = df_temp.index.map(lambda x: x in select_list)

            source.data = ColumnDataSource.from_df(df_temp.loc[filtr])

    def month_active(atrr, old, new):

        active = toggle_month.active
        dist = toggle_dist_month.active

        if not active:

            c2.visible, s1.visible = False, False
            toggle_month.label = "Show end points"

        else:

            c2.visible, s1.visible = True, True
            toggle_month.label= "Unshow end points"

        if not dist:

            c1.visible, d1.visible = True, False
            toggle_dist_month.label = "Show distance traveled"

        else:

            c1.visible, d1.visible = False, True
            toggle_dist_month.label = "Unshow distance traveled"

    # activation of the changes on user action
    select_number.on_change('value', update_map_se)
    slider_year.on_change('value', update_map_se)
    slider_month.on_change('value', update_map_se)
    select_zone.on_change('value', update_map_se)
    toggle_month.on_change('active', month_active)
    toggle_dist_month.on_change('active', month_active)

    # Make first tab
    tab_month = Panel(child=column(row(column(slider_year, slider_month,
                                       select_number, select_zone,
                                       toggle_month, toggle_dist_month), p, add_paragraph), data_table), title="Monthly")

    # ----------------------------------------------------------------------------
    # SECOND TAB
    # ----------------------------------------------------------------------------

    p_season = figure(tools='pan, wheel_zoom', x_range=(lon_boundaries[0], lon_boundaries[1]),
                      y_range=(lat_boundaries[0], lat_boundaries[1]),
                      x_axis_type="mercator", y_axis_type="mercator")

    p_season.add_tile(WMTSTileSource(url=url, attribution=attribution))

    # Add data points
    # - Start
    # - End
    # - Start with size adjusted to the traveled distance
    c3 = p_season.circle(x='x_start', y='y_start', fill_color='green', size=8,
                         source=source, legend_label='Start points')

    c4 = p_season.circle(x='x_end', y='y_end', fill_color='orange', size=8,
                         source=source, legend_label='End points')

    d2 = p_season.circle(x='x_start', y='y_start', fill_color='green', radius='Distance_draw',
                         source=source)

    # line between start and end points
    s2 = p_season.segment(x0='x_start', y0='y_start', x1='x_end', y1='y_end',
                          line_dash='dashed', source=source)

    # Initial configuration of WIDGETS  for SECOND TAB
    # - Don't show end points
    # - Don't show segments between start and end points
    # - Uniform size for starting points
    c4.visible, s2.visible, d2.visible = False, False, False

    # Configuration of the hovertool
    hover_season = HoverTool(tooltips=[("ID", "@ID"), ("Duration", "@Duration"),
                                       ("Distance", "@Distance")],
                             renderers=[c3, c4], formatters={'Duration': 'printf'})
    p_season.tools.append(hover_season)

    # Gulf Stream
    p_season.segment(x0=gulf_stream_lon1[:-1], y0=gulf_stream_lat1[:-1],
                     x1=gulf_stream_lon1[1:], y1=gulf_stream_lat1[1:],
                     legend_label='Gulf Stream', color='red', line_alpha=0.5, line_width=2)

    p_season.segment(x0=gulf_stream_lon2[:-1], y0=gulf_stream_lat2[:-1],
                     x1=gulf_stream_lon2[1:], y1=gulf_stream_lat2[1:],
                     color='red', line_alpha=0.5, line_width=2)

    p_season.legend.location = "top_left"

    # ------------------------------------------------------------------------
    # UPDATING SECOND TAB
    # ------------------------------------------------------------------------

    # updating process of the data underlying the map depending on user actions.
    def update_map_season(attr, old, new):

        yr = slider_year_season.value
        season = select_season.value
        zone = select_zone_season.value
        n = select_number_season.value
        n = int(n)

        if (zone == 'All') & (season == 'All'):
            df_temp = df_spawn_end.loc[(df_spawn_end['Year_start'] >= yr[0])
                                       & (df_spawn_end['Year_start'] <= yr[1])]

        elif (zone != 'All') & (season == 'All'):
            df_temp = df_spawn_end.loc[(df_spawn_end.Zones_start == zone)
                                       & (df_spawn_end['Year_start'] >= yr[0])
                                       & (df_spawn_end['Year_start'] <= yr[1])]

        elif (zone == 'All') & (season != 'All'):
            df_temp = df_spawn_end.loc[(df_spawn_end.Season_start == season)
                                       & (df_spawn_end['Year_start'] >= yr[0])
                                       & (df_spawn_end['Year_start'] <= yr[1])]

        else:
            df_temp = df_spawn_end.loc[(df_spawn_end.Zones_start == zone)
                                       & (df_spawn_end.Season_start == season)
                                       & (df_spawn_end['Year_start'] >= yr[0])
                                       & (df_spawn_end['Year_start'] <= yr[1])]

        if n == -1:

            source.data = ColumnDataSource.from_df(df_temp)
        else:

            if n > len(df_temp):  # For cases where there are not enough data points
                n = int(len(df_temp))

            np.random.seed(42)

            select_list = list(np.random.choice(df_temp.index, size=n, replace=False))

            filtr = df_temp.index.map(lambda x: x in select_list)

            source.data = ColumnDataSource.from_df(df_temp.loc[filtr])

    def season_active(atrr, old, new):

        active = toggle_season.active
        dist = toggle_dist_season.active

        if not active:

            c4.visible, s2.visible = False, False
            toggle_season.label = "Show end points"

        else:

            c4.visible, s2.visible = True, True
            toggle_season.label = "Show end points"

        if not dist:

            c3.visible, d2.visible = True, False
            toggle_dist_season.label = "Show distance traveled"

        else:

            c3.visible, d2.visible = False, True
            toggle_dist_season.label = "Unshow distance traveled"

    select_number_season.on_change('value', update_map_season)
    slider_year_season.on_change('value', update_map_season)
    select_season.on_change('value', update_map_season)
    select_zone_season.on_change('value', update_map_season)
    toggle_season.on_change('active', season_active)
    toggle_dist_season.on_change('active', season_active)

    # Make second tab
    tab_season = Panel(child=column(row(column(slider_year_season, select_number_season, select_season,
                                        select_zone_season,toggle_season, toggle_dist_season),
                                        p_season, add_paragraph), data_table), title="Seasonal")

    # ----------------------------------------------------------------------------
    # FINAL SET UP
    # ----------------------------------------------------------------------------

    tabs = Tabs(tabs=[tab_month, tab_season])

    def tab_change(atrr, old, new):

        if tabs.active == 0:

            update_map_se('', '', '')

        else:

            update_map_season('', '', '')

    tabs.on_change('active', tab_change)

    # Make document
    doc.add_root(tabs)
    doc.title = 'Hurricanes'
    doc.theme = Theme(filename="theme.yaml")
Beispiel #30
0
def make_tpf_figure_elements(tpf,
                             tpf_source,
                             pedestal=None,
                             fiducial_frame=None,
                             plot_width=370,
                             plot_height=340):
    """Returns the lightcurve figure elements.

    Parameters
    ----------
    tpf : TargetPixelFile
        TPF to show.
    tpf_source : bokeh.plotting.ColumnDataSource
        TPF data source.
    pedestal: float
        A scalar value to be added to the TPF flux values, often to avoid
        taking the log of a negative number in colorbars.
        Defaults to `-min(tpf.flux) + 1`
    fiducial_frame: int
        The tpf slice to start with by default, it is assumed the WCS
        is exact for this frame.

    Returns
    -------
    fig, stretch_slider : bokeh.plotting.figure.Figure, RangeSlider
    """
    if pedestal is None:
        pedestal = -np.nanmin(tpf.flux) + 1

    if tpf.mission in ['Kepler', 'K2']:
        title = 'Pixel data (CCD {}.{})'.format(tpf.module, tpf.output)
    elif tpf.mission == 'TESS':
        title = 'Pixel data (Camera {}.{})'.format(tpf.camera, tpf.ccd)
    else:
        title = "Pixel data"

    fig = figure(plot_width=plot_width,
                 plot_height=plot_height,
                 x_range=(tpf.column, tpf.column + tpf.shape[2]),
                 y_range=(tpf.row, tpf.row + tpf.shape[1]),
                 title=title,
                 tools='tap,box_select,wheel_zoom,reset',
                 toolbar_location="below",
                 border_fill_color="whitesmoke")

    fig.yaxis.axis_label = 'Pixel Row Number'
    fig.xaxis.axis_label = 'Pixel Column Number'

    vlo, lo, hi, vhi = np.nanpercentile(tpf.flux + pedestal,
                                        [0.2, 1, 95, 99.8])
    vstep = (np.log10(vhi) - np.log10(vlo)) / 300.0  # assumes counts >> 1.0!
    color_mapper = LogColorMapper(palette="Viridis256", low=lo, high=hi)

    fig.image([tpf.flux[fiducial_frame, :, :] + pedestal],
              x=tpf.column,
              y=tpf.row,
              dw=tpf.shape[2],
              dh=tpf.shape[1],
              dilate=True,
              color_mapper=color_mapper,
              name="tpfimg")

    # The colorbar will update with the screen stretch slider
    # The colorbar margin increases as the length of the tick labels grows.
    # This colorbar share of the plot window grows, shrinking plot area.
    # This effect is known, some workarounds might work to fix the plot area:
    # https://github.com/bokeh/bokeh/issues/5186
    color_bar = ColorBar(color_mapper=color_mapper,
                         ticker=LogTicker(desired_num_ticks=8),
                         label_standoff=-10,
                         border_line_color=None,
                         location=(0, 0),
                         background_fill_color='whitesmoke',
                         major_label_text_align='left',
                         major_label_text_baseline='middle',
                         title='e/s',
                         margin=0)
    fig.add_layout(color_bar, 'right')

    color_bar.formatter = PrintfTickFormatter(format="%14u")

    if tpf_source is not None:
        fig.rect('xx',
                 'yy',
                 1,
                 1,
                 source=tpf_source,
                 fill_color='gray',
                 fill_alpha=0.4,
                 line_color='white')

    # Configure the stretch slider and its callback function
    stretch_slider = RangeSlider(start=np.log10(vlo),
                                 end=np.log10(vhi),
                                 step=vstep,
                                 title='Screen Stretch (log)',
                                 value=(np.log10(lo), np.log10(hi)),
                                 orientation='horizontal',
                                 width=200,
                                 height=10,
                                 direction='ltr',
                                 show_value=True,
                                 sizing_mode='fixed',
                                 name='tpfstretch')

    def stretch_change_callback(attr, old, new):
        """TPF stretch slider callback."""
        fig.select('tpfimg')[0].glyph.color_mapper.high = 10**new[1]
        fig.select('tpfimg')[0].glyph.color_mapper.low = 10**new[0]

    stretch_slider.on_change('value', stretch_change_callback)

    return fig, stretch_slider
def make_tracks_figure(doc):
    """
    Create a Bokeh app for visualization of the tracks of hurricanes
    """

    df = pd.read_csv('files/df_full_tracks_bokeh.csv', index_col=0, parse_dates=['Time'])

    # Remove last entry for each hurricane, add steps numbering, year_start, year_end, zone start
    df.dropna(subset=['x_end'], inplace=True)

    df.sort_values(by=['ID', 'Time'], inplace=True)

    steps = df.groupby(by='ID').Time.count()
    times = df.groupby(by='ID').Time.first()
    zones = df.groupby(by='ID').Zones.first()

    df['Step'] = [i for hur in steps.index for i in range(steps[hur])]
    df['Year_start'] = [times[hur].year for hur in steps.index for i in range(steps[hur])]
    df['Month_start'] = [times[hur].month for hur in steps.index for i in range(steps[hur])]
    df['Zones_start'] = [zones[hur]for hur in steps.index for i in range(steps[hur])]

    # Convert knots to km/h
    df['Max_Speed'] = df['Max_Speed'] * 1.852

    # -----------------------------------------------------
    # FIGURE
    # -----------------------------------------------------
    year_min, year_max, lon_boundaries, lat_boundaries = get_boundaries(df)

    gulf_stream_lon1, gulf_stream_lon2, gulf_stream_lat1, gulf_stream_lat2 = get_gulf_stream()

    # credits of the map
    url = 'http://a.basemaps.cartocdn.com/rastertiles/voyager/{Z}/{X}/{Y}.png'
    attribution = "Tiles by Carto, under CC BY 3.0. Data by OSM, under ODbL"

    add_paragraph = additional_legend(loc='spawns')

    # -----------------------------------------------------
    # WIDGETS
    # -----------------------------------------------------

    # definition and configuration of the number selection
    options_number = ['-1'] + [str(x) for x in list(np.arange(1, 21))]
    select_number = Select(title='Number of hurricanes:', value='5', options=options_number)

    # definition and configuration of the zone selection
    options_zone = ['All', 'Mexico_Caribbean', 'Atlantic']
    select_zone = Select(title='Spawning Zone:', value='All', options=options_zone)

    # definition and configuration of the year and month sliders
    slider_year = RangeSlider(start=year_min, end=year_max,
                              value=(year_min, year_max), step=1, title="Years")

    slider_month = RangeSlider(start=1, end=12,
                               value=(1, 12), step=1, title="Months")

    # definition and configuration of the number selection
    # select_number_season = Select(title='Number of hurricanes:', value='5',
    #                              options=options_number)

    # definition and configuration of the zone selection
    # select_zone_season = Select(title='Spawning Zone:', value='All', options=options_zone)

    # definition and configuration of the year and sliders
    # slider_year_season = RangeSlider(start=year_min, end=year_max,
    #                                 value=(year_min, year_max), step=1, title="Years")

    # definition and configuration of the season selection
    # options_season = ['All', 'Winter', 'Spring', 'Summer', 'Autumn']
    # select_season = Select(title='Season:', value='All', options=options_season)

    # -------------------------------------------------------
    # DATA SOURCE AND RANDOMIZATION
    # -------------------------------------------------------
    np.random.seed(42)
    n = 5

    select_list = list(np.random.choice(df.ID.unique(), size=n, replace=False))
    filtr = df.ID.map(lambda x: x in select_list)

    source = ColumnDataSource(data=df[filtr])

    # Initialization of the map
    p = figure(tools='pan, wheel_zoom', x_range=(lon_boundaries[0], lon_boundaries[1]),
               y_range=(lat_boundaries[0], lat_boundaries[1]),
               x_axis_type="mercator", y_axis_type="mercator")

    p.add_tile(WMTSTileSource(url=url, attribution=attribution))

    # Add data points
    # - Start
    # - End
    # - Start with size adjusted to the traveled distance
    c1 = p.circle(x='x_start', y='y_start', fill_color='green', size=5, source=source)

    c2 = p.circle(x='x_end', y='y_end', fill_color='green', size=5, source=source)

    # Line between start and end points
    s1 = p.segment(x0='x_start', y0='y_start', x1='x_end', y1='y_end',
                   line_dash='dashed', source=source)

    # Configuration of the hovertool
    hover = HoverTool(tooltips=[("ID", "@ID"), ("Step", "@Step"), ("Distance", "@Distance")], renderers=[c1])
    p.tools.append(hover)

    # Draw the Gulf Stream
    p.segment(x0=gulf_stream_lon1[:-1], y0=gulf_stream_lat1[:-1],
              x1=gulf_stream_lon1[1:], y1=gulf_stream_lat1[1:],
              legend_label='Gulf Stream', color='red', line_alpha=0.5, line_width=2)

    p.segment(x0=gulf_stream_lon2[:-1], y0=gulf_stream_lat2[:-1],
              x1=gulf_stream_lon2[1:], y1=gulf_stream_lat2[1:],
              color='red', line_alpha=0.5, line_width=2)

    p.legend.location = "top_left"

    # DataFrame display
    no_cols = ['x_start', 'x_end', 'y_start', 'y_end', 'Zones_start', 'ID', 'Time']
    cols = ([TableColumn(field='ID', title='ID')]
            + [TableColumn(field='Time', title='Time', formatter=DateFormatter(format="%d/%m/%Y %H:%M"))]
            + [TableColumn(field=col, title=col) for col in df.columns if col not in no_cols])
    data_table = DataTable(columns=cols, source=source, width=1100, selectable=False)

    # updating process of the data underlying the map depending on user actions.
    def update_map_se(attr, old, new):

        yr = slider_year.value
        month = slider_month.value
        zone = select_zone.value
        n = select_number.value
        n = int(n)

        if zone == 'All':
            df_temp = df.loc[(df['Year_start'] >= yr[0])
                             & (df['Year_start'] <= yr[1])
                             & (df['Month_start'] >= month[0])
                             & (df['Month_start'] <= month[1])]

        else:
            df_temp = df.loc[(df.Zones_start == zone)
                             & (df['Year_start'] >= yr[0])
                             & (df['Year_start'] <= yr[1])
                             & (df['Month_start'] >= month[0])
                             & (df['Month_start'] <= month[1])]

        if n == -1:

            source.data = ColumnDataSource.from_df(df_temp)
        else:

            if n > len(df_temp):  # For cases where there are not enough data points
                n = int(len(df_temp))

            np.random.seed(42)

            select_list = list(np.random.choice(df_temp.ID.unique(), size=n, replace=False))

            filtr = df_temp.ID.map(lambda x: x in select_list)

            source.data = ColumnDataSource.from_df(df_temp.loc[filtr])

    # activation of the changes on user action
    select_number.on_change('value', update_map_se)
    slider_year.on_change('value', update_map_se)
    slider_month.on_change('value', update_map_se)
    select_zone.on_change('value', update_map_se)

    layout = column(row(column(slider_year, slider_month, select_number, select_zone),
                        p, add_paragraph), data_table)

    # Make document
    doc.add_root(layout)
    doc.title = 'Hurricanes_Tracks'
    doc.theme = Theme(filename="theme.yaml")
Beispiel #32
0
def make_tpf_figure_elements(tpf,
                             tpf_source,
                             pedestal=None,
                             fiducial_frame=None,
                             plot_width=370,
                             plot_height=340,
                             scale='log',
                             vmin=None,
                             vmax=None,
                             cmap='Viridis256',
                             tools='tap,box_select,wheel_zoom,reset'):
    """Returns the lightcurve figure elements.

    Parameters
    ----------
    tpf : TargetPixelFile
        TPF to show.
    tpf_source : bokeh.plotting.ColumnDataSource
        TPF data source.
    pedestal: float
        A scalar value to be added to the TPF flux values, often to avoid
        taking the log of a negative number in colorbars.
        Defaults to `-min(tpf.flux) + 1`
    fiducial_frame: int
        The tpf slice to start with by default, it is assumed the WCS
        is exact for this frame.
    scale: str
        Color scale for tpf figure. Default is 'log'
    vmin: int [optional]
        Minimum color scale for tpf figure
    vmax: int [optional]
        Maximum color scale for tpf figure
    cmap: str
        Colormap to use for tpf plot. Default is 'Viridis256'
    tools: str
        Bokeh tool list
    Returns
    -------
    fig, stretch_slider : bokeh.plotting.figure.Figure, RangeSlider
    """
    if pedestal is None:
        pedestal = -np.nanmin(tpf.flux.value) + 1
    if scale == 'linear':
        pedestal = 0

    if tpf.mission in ['Kepler', 'K2']:
        title = 'Pixel data (CCD {}.{})'.format(tpf.module, tpf.output)
    elif tpf.mission == 'TESS':
        title = 'Pixel data (Camera {}.{})'.format(tpf.camera, tpf.ccd)
    else:
        title = "Pixel data"

    # We subtract 0.5 from the range below because pixel coordinates refer to
    # the middle of a pixel, e.g. (col, row) = (10.0, 20.0) is a pixel center.
    fig = figure(plot_width=plot_width,
                 plot_height=plot_height,
                 x_range=(tpf.column - 0.5, tpf.column + tpf.shape[2] - 0.5),
                 y_range=(tpf.row - 0.5, tpf.row + tpf.shape[1] - 0.5),
                 title=title,
                 tools=tools,
                 toolbar_location="below",
                 border_fill_color="whitesmoke")

    fig.yaxis.axis_label = 'Pixel Row Number'
    fig.xaxis.axis_label = 'Pixel Column Number'

    vlo, lo, hi, vhi = np.nanpercentile(tpf.flux.value + pedestal,
                                        [0.2, 1, 95, 99.8])
    if vmin is not None:
        vlo, lo = vmin, vmin
    if vmax is not None:
        vhi, hi = vmax, vmax

    if scale == 'log':
        vstep = (np.log10(vhi) -
                 np.log10(vlo)) / 300.0  # assumes counts >> 1.0!
    if scale == 'linear':
        vstep = (vhi - vlo) / 300.0  # assumes counts >> 1.0!

    if scale == 'log':
        color_mapper = LogColorMapper(palette=cmap, low=lo, high=hi)
    elif scale == 'linear':
        color_mapper = LinearColorMapper(palette=cmap, low=lo, high=hi)
    else:
        raise ValueError(
            'Please specify either `linear` or `log` scale for color.')

    fig.image([tpf.flux.value[fiducial_frame, :, :] + pedestal],
              x=tpf.column - 0.5,
              y=tpf.row - 0.5,
              dw=tpf.shape[2],
              dh=tpf.shape[1],
              dilate=True,
              color_mapper=color_mapper,
              name="tpfimg")

    # The colorbar will update with the screen stretch slider
    # The colorbar margin increases as the length of the tick labels grows.
    # This colorbar share of the plot window grows, shrinking plot area.
    # This effect is known, some workarounds might work to fix the plot area:
    # https://github.com/bokeh/bokeh/issues/5186

    if scale == 'log':
        ticker = LogTicker(desired_num_ticks=8)
    elif scale == 'linear':
        ticker = BasicTicker(desired_num_ticks=8)

    color_bar = ColorBar(color_mapper=color_mapper,
                         ticker=ticker,
                         label_standoff=-10,
                         border_line_color=None,
                         location=(0, 0),
                         background_fill_color='whitesmoke',
                         major_label_text_align='left',
                         major_label_text_baseline='middle',
                         title='e/s',
                         margin=0)
    fig.add_layout(color_bar, 'right')

    color_bar.formatter = PrintfTickFormatter(format="%14i")

    if tpf_source is not None:
        fig.rect('xx',
                 'yy',
                 1,
                 1,
                 source=tpf_source,
                 fill_color='gray',
                 fill_alpha=0.4,
                 line_color='white')

    # Configure the stretch slider and its callback function
    if scale == 'log':
        start, end = np.log10(vlo), np.log10(vhi)
        values = (np.log10(lo), np.log10(hi))
    elif scale == 'linear':
        start, end = vlo, vhi
        values = (lo, hi)

    stretch_slider = RangeSlider(start=start,
                                 end=end,
                                 step=vstep,
                                 title='Screen Stretch ({})'.format(scale),
                                 value=values,
                                 orientation='horizontal',
                                 width=200,
                                 direction='ltr',
                                 show_value=True,
                                 sizing_mode='fixed',
                                 height=15,
                                 name='tpfstretch')

    def stretch_change_callback_log(attr, old, new):
        """TPF stretch slider callback."""
        fig.select('tpfimg')[0].glyph.color_mapper.high = 10**new[1]
        fig.select('tpfimg')[0].glyph.color_mapper.low = 10**new[0]

    def stretch_change_callback_linear(attr, old, new):
        """TPF stretch slider callback."""
        fig.select('tpfimg')[0].glyph.color_mapper.high = new[1]
        fig.select('tpfimg')[0].glyph.color_mapper.low = new[0]

    if scale == 'log':
        stretch_slider.on_change('value', stretch_change_callback_log)
    if scale == 'linear':
        stretch_slider.on_change('value', stretch_change_callback_linear)

    return fig, stretch_slider
Beispiel #33
0
class Samples(object):
    def __init__(
        self,
        ydeg,
        npix,
        npts,
        nmaps,
        throttle_time,
        nosmooth,
        gp,
        sample_function,
    ):
        # Settings
        self.ydeg = ydeg
        self.npix = npix
        self.npts = npts
        self.throttle_time = throttle_time
        self.nosmooth = nosmooth
        self.nmaps = nmaps
        self.gp = gp

        # Design matrices
        self.A_I = get_intensity_design_matrix(ydeg, npix)
        self.A_F = get_flux_design_matrix(ydeg, npts)

        def sample_ylm(r, mu_l, sigma_l, c, n):
            # Avoid issues at the boundaries
            if mu_l == 0:
                mu_l = 1e-2
            elif mu_l == 90:
                mu_l = 90 - 1e-2
            a, b = gauss2beta(mu_l, sigma_l)
            return sample_function(r, a, b, c, n)

        self.sample_ylm = sample_ylm

        # Draw three samples from the default distr
        self.ylm = self.sample_ylm(
            params["size"]["r"]["value"],
            params["latitude"]["mu"]["value"],
            params["latitude"]["sigma"]["value"],
            params["contrast"]["c"]["value"],
            params["contrast"]["n"]["value"],
        )[0]

        # Plot the GP ylm samples
        self.color_mapper = LinearColorMapper(palette="Plasma256",
                                              nan_color="white",
                                              low=0.5,
                                              high=1.2)
        self.moll_plot = [None for i in range(self.nmaps)]
        self.moll_source = [
            ColumnDataSource(data=dict(image=[
                1.0 +
                (self.A_I @ self.ylm[i]).reshape(self.npix, 2 * self.npix)
            ])) for i in range(self.nmaps)
        ]
        eps = 0.1
        epsp = 0.02
        xe = np.linspace(-2, 2, 300)
        ye = 0.5 * np.sqrt(4 - xe**2)
        for i in range(self.nmaps):
            self.moll_plot[i] = figure(
                plot_width=280,
                plot_height=130,
                toolbar_location=None,
                x_range=(-2 - eps, 2 + eps),
                y_range=(-1 - eps / 2, 1 + eps / 2),
            )
            self.moll_plot[i].axis.visible = False
            self.moll_plot[i].grid.visible = False
            self.moll_plot[i].outline_line_color = None
            self.moll_plot[i].image(
                image="image",
                x=-2,
                y=-1,
                dw=4 + epsp,
                dh=2 + epsp / 2,
                color_mapper=self.color_mapper,
                source=self.moll_source[i],
            )
            self.moll_plot[i].toolbar.active_drag = None
            self.moll_plot[i].toolbar.active_scroll = None
            self.moll_plot[i].toolbar.active_tap = None

        # Plot lat/lon grid
        lat_lines = get_latitude_lines()
        lon_lines = get_longitude_lines()
        for i in range(self.nmaps):
            for x, y in lat_lines:
                self.moll_plot[i].line(x,
                                       y,
                                       line_width=1,
                                       color="black",
                                       alpha=0.25)
            for x, y in lon_lines:
                self.moll_plot[i].line(x,
                                       y,
                                       line_width=1,
                                       color="black",
                                       alpha=0.25)
            self.moll_plot[i].line(xe,
                                   ye,
                                   line_width=3,
                                   color="black",
                                   alpha=1)
            self.moll_plot[i].line(xe,
                                   -ye,
                                   line_width=3,
                                   color="black",
                                   alpha=1)

        # Colorbar slider
        self.slider = RangeSlider(
            start=0,
            end=1.5,
            step=0.01,
            value=(0.5, 1.2),
            orientation="horizontal",
            show_value=False,
            css_classes=["colorbar-slider"],
            direction="ltr",
            title="cmap",
        )
        self.slider.on_change("value", self.slider_callback)

        # Buttons
        self.seed_button = Button(
            label="re-seed",
            button_type="default",
            css_classes=["seed-button"],
            sizing_mode="fixed",
            height=30,
            width=75,
        )
        self.seed_button.on_click(self.seed_callback)

        self.smooth_button = Toggle(
            label="smooth",
            button_type="default",
            css_classes=["smooth-button"],
            sizing_mode="fixed",
            height=30,
            width=75,
            active=False,
        )
        self.smooth_button.disabled = bool(self.nosmooth)
        self.smooth_button.on_click(self.smooth_callback)

        self.auto_button = Toggle(
            label="auto",
            button_type="default",
            css_classes=["auto-button"],
            sizing_mode="fixed",
            height=30,
            width=75,
            active=True,
        )

        self.reset_button = Button(
            label="reset",
            button_type="default",
            css_classes=["reset-button"],
            sizing_mode="fixed",
            height=30,
            width=75,
        )
        self.reset_button.on_click(self.reset_callback)

        # Light curve samples
        self.flux_plot = [None for i in range(self.nmaps)]
        self.flux_source = [
            ColumnDataSource(data=dict(
                xs=[np.linspace(0, 2, npts) for j in range(6)],
                ys=[fluxnorm(self.A_F[j] @ self.ylm[i]) for j in range(6)],
                color=[Plasma6[5 - j] for j in range(6)],
                inc=[15, 30, 45, 60, 75, 90],
            )) for i in range(self.nmaps)
        ]
        for i in range(self.nmaps):
            self.flux_plot[i] = figure(
                toolbar_location=None,
                x_range=(0, 2),
                y_range=None,
                min_border_left=50,
                plot_height=400,
            )
            if i == 0:
                self.flux_plot[i].yaxis.axis_label = "flux [ppt]"
                self.flux_plot[i].yaxis.axis_label_text_font_style = "normal"
            self.flux_plot[i].xaxis.axis_label = "rotational phase"
            self.flux_plot[i].xaxis.axis_label_text_font_style = "normal"
            self.flux_plot[i].outline_line_color = None
            self.flux_plot[i].multi_line(
                xs="xs",
                ys="ys",
                line_color="color",
                source=self.flux_source[i],
            )
            self.flux_plot[i].toolbar.active_drag = None
            self.flux_plot[i].toolbar.active_scroll = None
            self.flux_plot[i].toolbar.active_tap = None
            self.flux_plot[i].yaxis.major_label_orientation = np.pi / 4
            self.flux_plot[i].xaxis.axis_label_text_font_size = "8pt"
            self.flux_plot[i].xaxis.major_label_text_font_size = "8pt"
            self.flux_plot[i].yaxis.axis_label_text_font_size = "8pt"
            self.flux_plot[i].yaxis.major_label_text_font_size = "8pt"

        # Javascript callback to update light curves & images
        self.A_F_source = ColumnDataSource(data=dict(A_F=self.A_F))
        self.A_I_source = ColumnDataSource(data=dict(A_I=self.A_I))
        self.ylm_source = ColumnDataSource(data=dict(ylm=self.ylm))
        callback = CustomJS(
            args=dict(
                A_F_source=self.A_F_source,
                A_I_source=self.A_I_source,
                ylm_source=self.ylm_source,
                flux_source=self.flux_source,
                moll_source=self.moll_source,
            ),
            code="""
            var A_F = A_F_source.data['A_F'];
            var A_I = A_I_source.data['A_I'];
            var ylm = ylm_source.data['ylm'];
            var i, j, k, l, m, n;
            for (n = 0; n < {nmax}; n++) {{

                // Update the light curves
                var flux = flux_source[n].data['ys'];
                for (l = 0; l < {lmax}; l++) {{
                    for (m = 0; m < {mmax}; m++) {{
                        flux[l][m] = 0.0;
                        for (k = 0; k < {kmax}; k++) {{
                            flux[l][m] += A_F[{kmax} * ({mmax} * l + m) + k] * ylm[{kmax} * n + k];
                        }}
                    }}
                    // Normalize
                    var mean = flux[l].reduce((previous, current) => current += previous) / {mmax};
                    for (m = 0; m < {mmax}; m++) {{
                        flux[l][m] = 1e3 * ((1 + flux[l][m]) / (1 + mean) - 1)
                    }}
                }}
                flux_source[n].change.emit();

                // Update the images
                var image = moll_source[n].data['image'][0];
                for (i = 0; i < {imax}; i++) {{
                    for (j = 0; j < {jmax}; j++) {{
                        image[{jmax} * i + j] = 1.0;
                        for (k = 0; k < {kmax}; k++) {{
                            image[{jmax} * i + j] += A_I[{kmax} * ({jmax} * i + j) + k] * ylm[{kmax} * n + k];
                        }}
                    }}
                }}
                moll_source[n].change.emit();

            }}
            """.format(
                imax=self.npix,
                jmax=2 * self.npix,
                kmax=(self.ydeg + 1)**2,
                nmax=self.nmaps,
                lmax=self.A_F.shape[0],
                mmax=self.npts,
            ),
        )
        self.js_dummy = self.flux_plot[0].circle(x=0, y=0, size=1, alpha=0)
        self.js_dummy.glyph.js_on_change("size", callback)

        # Full layout
        self.plots = row(
            *[
                column(m, f, sizing_mode="scale_both")
                for m, f in zip(self.moll_plot, self.flux_plot)
            ],
            margin=(10, 30, 10, 30),
            sizing_mode="scale_both",
            css_classes=["samples"],
        )
        self.layout = grid([[self.plots]])

    def slider_callback(self, attr, old, new):
        self.color_mapper.low, self.color_mapper.high = self.slider.value

    def seed_callback(self, event):
        self.gp.random.seed(np.random.randint(0, 99999))
        tmp = self.auto_button.active
        self.callback(None, None, None)
        self.auto_button.active = tmp

    def reset_callback(self, event):
        self.Size.sliders[0].value = params["size"]["r"]["value"]
        self.Latitude.sliders[0].value = params["latitude"]["mu"]["value"]
        self.Latitude.sliders[1].value = params["latitude"]["sigma"]["value"]
        self.Contrast.sliders[0].value = params["contrast"]["c"]["value"]
        self.Contrast.sliders[1].value = params["contrast"]["n"]["value"]
        self.Size.callback(None, None, None)
        self.Latitude.callback(None, None, None)
        self.gp.random.seed(0)
        self.slider.value = (0.5, 1.2)
        self.slider_callback(None, None, None)
        self.smooth_button.active = False
        self.smooth_callback(None)
        self.auto_button.active = True
        self.callback(None, None, None)

    def smooth_callback(self, event):
        if self.smooth_button.active:
            self.Latitude.throttle_time = self.throttle_time
            self.Size.throttle_time = self.throttle_time
            self.Contrast.throttle_time = self.throttle_time
        else:
            self.Latitude.throttle_time = 0
            self.Size.throttle_time = 0
            self.Contrast.throttle_time = 0

    def callback(self, attr, old, new):
        try:

            if self.auto_button.active:
                self.gp.random.seed(np.random.randint(0, 99999))

            # Draw the samples
            self.ylm = self.sample_ylm(
                self.Size.sliders[0].value,
                self.Latitude.sliders[0].value,
                self.Latitude.sliders[1].value,
                self.Contrast.sliders[0].value,
                self.Contrast.sliders[1].value,
            )[0]

            # HACK: Trigger the JS callback by modifying
            # a property of the `js_dummy` glyph
            self.ylm_source.data["ylm"] = self.ylm
            self.js_dummy.glyph.size = 3 - self.js_dummy.glyph.size

            # If everything worked, ensure the sliders are active
            for slider in (self.Size.sliders + self.Latitude.sliders +
                           self.Contrast.sliders):
                slider.bar_color = "white"

        except Exception as e:

            # Something went wrong inverting the covariance!
            for slider in (self.Size.sliders + self.Latitude.sliders +
                           self.Contrast.sliders):
                slider.bar_color = "firebrick"

            print("An error occurred when computing the covariance:")
            print(e)