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 = DateSlider(start=start, end=end, value=value, css_classes=["foo"], width=300, bar_color="red") 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): plot = Plot(height=400, width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) slider = DateSlider(start=start, end=end, value=value, css_classes=["foo"], width=300) def cb(attr, old, new): slider.title = "baz" 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(height=400, 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 = DateSlider(start=start, end=end, value=value, css_classes=["foo"], width=300, step=24*3600*1000) def cb(attr, old, new): source.data['val'] = [slider.value_as_date.isoformat()] slider.on_change('value', cb) doc.add_root(column(slider, plot))
def test_js_on_change_executes(self, bokeh_model_page) -> None: slider = DateSlider(start=start, end=end, value=value, css_classes=["foo"], width=300) slider.js_on_change('value', CustomJS(code=RECORD("value", "cb_obj.value"))) page = bokeh_model_page(slider) drag_slider(page.driver, ".foo", 150) results = page.results assert datetime.fromtimestamp(results['value']/1000) > datetime(*date.fromisoformat("2017-08-04").timetuple()[:3]) assert page.has_no_console_errors()
def test_server_bar_color_updates( self, bokeh_server_page: BokehServerPage) -> None: slider = DateSlider(start=start, end=end, value=value, width=300, bar_color="red") def modify_doc(doc): plot = Plot(height=400, width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) def cb(attr, old, new): slider.bar_color = "rgba(255, 255, 0, 1)" slider.on_change('value', cb) doc.add_root(column(slider, plot)) page = bokeh_server_page(modify_doc) drag_slider(page.driver, slider, 150) sleep(1) # noUiSlider does a transition that takes some time assert get_slider_bar_color(page.driver, slider) == "rgba(255, 255, 0, 1)"
def test_display(self, bokeh_model_page: BokehModelPage) -> None: slider = DateSlider(start=start, end=end, value=value, width=300) page = bokeh_model_page(slider) children = find_elements_for(page.driver, slider, "div.bk-input-group > div") assert len(children) == 2 assert page.has_no_console_errors()
def test_display(self, bokeh_model_page) -> None: slider = DateSlider(start=start, end=end, value=value, css_classes=["foo"], width=300) page = bokeh_model_page(slider) el = page.driver.find_element_by_css_selector('.foo') children = el.find_elements_by_css_selector('div.bk-input-group > div') assert len(children) == 2 assert page.has_no_console_errors()
def test_displays_bar_color(self, bokeh_model_page) -> None: slider = DateSlider(start=start, end=end, value=value, css_classes=["foo"], width=300, bar_color="red") page = bokeh_model_page(slider) el = page.driver.find_element_by_css_selector('.foo') assert len(el.find_elements_by_css_selector('div.bk-input-group > div')) == 2 assert get_slider_bar_color(page.driver, ".foo") == "rgba(255, 0, 0, 1)" assert page.has_no_console_errors()
def test_displays_title(self, bokeh_model_page) -> None: slider = DateSlider(start=start, end=end, value=value, css_classes=["foo"], width=300) page = bokeh_model_page(slider) el = page.driver.find_element_by_css_selector('.foo') assert len(el.find_elements_by_css_selector('div.bk-input-group > div')) == 2 assert get_slider_title_text(page.driver, ".foo") == "04 Aug 2017" assert get_slider_title_value(page.driver, ".foo") == "04 Aug 2017" assert page.has_no_console_errors()
def test_title_updates(self, bokeh_model_page: BokehModelPage) -> None: slider = DateSlider(start=start, end=end, value=value, width=300) page = bokeh_model_page(slider) assert get_slider_title_value(page.driver, slider) == "04 Aug 2017" drag_slider(page.driver, slider, 50) assert get_slider_title_value(page.driver, slider) > "04 Aug 2017" drag_slider(page.driver, slider, -70) assert get_slider_title_value(page.driver, slider) == "03 Aug 2017" assert page.has_no_console_errors()
def modify_doc(doc): plot = Plot(height=400, width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) slider = DateSlider(start=start, end=end, value=value, css_classes=["foo"], width=300) def cbv(attr, old, new): junk['v'] += 1 def cbvt(attr, old, new): junk['vt'] += 1 slider.on_change('value', cbv) slider.on_change('value_throttled', cbvt) doc.add_root(column(slider, plot))
def construct(pgcd, controller=None) : df_column = "Confirmed" lastday = pgcd.lastday() firstday = pgcd.firstday() mapper = "Log" # Make carto title = 'Coronavirus map : Day ' + str(lastday) tooltips = lutils.tooltips() tools = [PanTool(), WheelZoomTool(), ResetTool()] carto = WMap(pgcd, lastday, df_column, title=title, mkind=mapper, tooltips=tooltips, aspect_ratio=2, sizing_mode="scale_both", tools=tools) # Make a slider object: slider slider = DateSlider(title="Date", start=firstday, end=lastday, value=lastday, step=1, format="%Y-%d-%m", sizing_mode="stretch_width") carto.link_on_change("date", slider, postfun=convert_slider_date) # Make buttons lambda_callback_bleft = lambda : carto_shift_day(False, carto, slider) bleft = Button(label="Day -1", button_type="success", width=200) bleft.on_click(lambda_callback_bleft) lambda_callback_bright = lambda : carto_shift_day(True, carto, slider) bright = Button(label="Day +1", button_type="success", width=200) bright.on_click(lambda_callback_bright) # Select for carto options = [df_column for df_column in lutils.columns_description() if df_column not in ["Date"]] scol = Select(title="", options=options, value=df_column, width=200) rdesc_column = lambda column : lutils.description(column, reverse=True) carto.link_on_change("field", scol, postfun=rdesc_column) smap = Select(title="", options=list(COLOR_MAPPER_NAME.values()), value=COLOR_MAPPER_NAME[mapper], width=200) rdesc_cmapper = lambda name : lutils.reverse_mapping(COLOR_MAPPER_NAME, name) carto.link_on_change("mkind", smap, postfun=rdesc_cmapper) if controller : fun = lambda : update(slider, carto) controller.add_receiver("update", fun) new_signal = lambda country : controller.emit_signal("select_country", country) carto.add_receiver("doubletap", new_signal) return column( carto.figure, slider, row(bleft, bright, scol, smap, sizing_mode="stretch_width"), sizing_mode="stretch_both")
def init_widgets(data_start_date, data_end_date, source): """Initializes the widgets to be displayed adjacent the plot Args: data_start_date: the first date given in the data data_end_date: the last date given in the data source: data for the current day that is displayed by the widgets initially """ date_slider = DateSlider(title="Date Range: ", start=date.fromisoformat(data_start_date.split("T")[0]), end=date.fromisoformat(data_end_date.split("T")[0]), value=date.fromisoformat(data_end_date.split("T")[0]), step=86400000, sizing_mode="stretch_width") radio_button_group = RadioButtonGroup(labels=["New Positives", "Cumulative Number of Positives", "Total Number of Tests", "Cumulative Number of Tests"], active=0, sizing_mode="stretch_width") button = Button(label="Play", button_type="primary") columns = [ TableColumn(field="name", title="County"), TableColumn(field="new_positives", title="New Positives"), ] data_table = DataTable(source=source, columns=columns, sizing_mode="stretch_both", index_position=None) return date_slider, radio_button_group, button, data_table
def test_server_on_change_round_trip( self, bokeh_server_page: BokehServerPage) -> None: slider = DateSlider(start=start, end=end, value=value, width=300, step=24 * 3600 * 1000) def modify_doc(doc): source = ColumnDataSource(dict(x=[1, 2], y=[1, 1], val=["a", "b"])) plot = Plot(height=400, 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.tags.append( CustomJS(name="custom-action", args=dict(s=source), code=RECORD("data", "s.data"))) def cb(attr, old, new): iso_date = slider.value_as_date.isoformat() source.data['val'] = [iso_date, iso_date] slider.on_change('value', cb) doc.add_root(column(slider, plot)) page = bokeh_server_page(modify_doc) drag_slider(page.driver, slider, 50) page.eval_custom_action() results = page.results new = results['data']['val'] assert new[0] > '2017-08-04' drag_slider(page.driver, slider, -70) page.eval_custom_action() results = page.results new = results['data']['val'] assert new[0] == '2017-08-03'
def add_slider(self): """Build slider """ self.controls['slider'] = DateSlider(start=self.meta['dates'][-1].date(), end=self.meta['dates'][0].date(), value=self.meta['dates'][0].date(), width=self.plot.plot_width-40-84, title='Reported Date') _callback = CustomJS(args=dict(source=self.srcs['counties'], date=self.controls['slider']), code=""" // javascript code var data = source.data; var cur_day = data['day']; // from DateSlider var day = Math.floor((date.end - date.value)/(1000*60*60*24)); // create column names var ci = 'c'.concat(day.toString()); var di = 'd'.concat(day.toString()); var mi = 'm'.concat(day.toString()); // change data if (cur_day[0] != day){ for (var i=0; i < cur_day.length; i++){ data['c'][i] = data[ci][i]; data['d'][i] = data[di][i]; data['m'][i] = data[mi][i]; cur_day[0] = day; } } source.change.emit(); """) self.controls['slider'].js_on_change('value', _callback) log.debug('slider added')
def test_server_callback_value_vs_value_throttled( self, bokeh_server_page: BokehServerPage) -> None: junk = dict(v=0, vt=0) slider = DateSlider(start=start, end=end, value=value, width=300) def modify_doc(doc): plot = Plot(height=400, width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) def cbv(attr, old, new): junk['v'] += 1 def cbvt(attr, old, new): junk['vt'] += 1 slider.on_change('value', cbv) slider.on_change('value_throttled', cbvt) doc.add_root(column(slider, plot)) page = bokeh_server_page(modify_doc) drag_slider(page.driver, slider, 30, release=False) sleep(1) # noUiSlider does a transition that takes some time drag_slider(page.driver, slider, 30, release=False) sleep(1) # noUiSlider does a transition that takes some time drag_slider(page.driver, slider, 30, release=False) sleep(1) # noUiSlider does a transition that takes some time drag_slider(page.driver, slider, 30, release=True) sleep(1) # noUiSlider does a transition that takes some time assert junk['v'] == 4 assert junk['vt'] == 1
# Define a function to update color mapper used in both patches and colorbar def update_bar(new): for i, d in enumerate(labels): if i == new: color_bar.color_mapper = mappers[d]["transform"] color_bar.title = d cantons.glyph.fill_color = mappers[d] buttons.on_click(update_bar) # T2.5 Add a dateslider to control which per capita daily new cases information to display # Define a dateslider using maximum and mimimum dates, set value to be the latest date timeslider = DateSlider(title='Date', start=dates.min(), end=dates.max(), value=dates.max()) # Complete the callback function # Hints: # convert the timestamp value from the slider to datetime and format it in the form of '%Y-%m-%d' # update columns 'size', 'dnc' with the column named '%Y-%m-%d' in merged # update geosource with new merged def callback(attr, old, new): # Convert timestamp to datetime # https://stackoverflow.com/questions/9744775/how-to-convert-integer-timestamp-to-python-datetime date = datetime.fromtimestamp(new / 1e3) i = date.strftime('%Y-%m-%d') merged.size = merged[i] * 1e5 / 5 + 10
fill_color={ 'field': 'temp_anomalies', 'transform': color_mapper }, fill_alpha=0.5, line_color=None) color_bar = ColorBar(color_mapper=color_mapper, label_standoff=12, border_line_color=None, location=(0, 0)) p.add_layout(color_bar, 'right') # Make a slider object: slider slider = DateSlider(title="Date", value=min(climate_data.index), start=min(climate_data.index), end=max(climate_data.index), step=1, width=900) # Attach the callback to the 'value' property of slider slider.on_change('value', update_plot) # Make a row layout of widgetbox(slider) and plot and add it to the current document layout = column(widgetbox(slider, sizing_mode='scale_width'), p) # Add the plot to the current document and add a title curdoc().add_root(layout) curdoc().title = 'Global Warming'
max(df_map[plot_var[3]]), max(df_map[plot_var[4]]), max(df_map[plot_var[5]]), max(df_map[plot_var[6]]), max(df_map[plot_var[7]]), max(df_map[plot_var[8]]), max(df_map[plot_var[9]]), max(df_map[plot_var[10]]), max(df_map[plot_var[11]]) ] # Make a selection of the date to plot slider = DateSlider(title='Date', start=first_dt, end=last_dt, step=1, value=last_dt, height=20, margin=(20, 50, 20, 50), sizing_mode="stretch_width") slider.on_change('value_throttled', update_map) # Make a span to show current date in plots dt_span = Span(location=slider.value_as_date, dimension='height', line_color='red', line_dash='solid', line_width=2) # Update timeseries plots based on selection source_map.selected.on_change('indices', update_plot)
def create_html_page(html_page_name, df): del states["HI"] del states["AK"] EXCLUDED = ("ak", "hi", "pr", "gu", "vi", "mp", "as") state_xs = [states[code]["lons"] for code in states] state_ys = [states[code]["lats"] for code in states] county_xs = [ counties[code]["lons"] for code in counties if counties[code]["state"] not in EXCLUDED ] county_ys = [ counties[code]["lats"] for code in counties if counties[code]["state"] not in EXCLUDED ] county_names = [ counties[code]["name"] for code in counties if counties[code]["state"] not in EXCLUDED ] col_names = list(df.columns.values) len_col = len(col_names) last_day_str = col_names[len_col - 1] last_day = datetime.strptime(last_day_str, '%Y-%m-%d %H:%M:%S').date() first_day_str = col_names[4] # first 4 colums contain names etc first_day = datetime.strptime(first_day_str, '%Y-%m-%d %H:%M:%S').date() a_dict = create_dict_forJS(df) source_new = ColumnDataSource(data=a_dict) source_visible = ColumnDataSource( data={ 'x': county_xs, 'y': county_ys, 'name': county_names, 'rate': a_dict[str(last_day)] }) ''' c_dict = create_colors_forJS(df) hex_color = rgb_to_hex((255, 255, 255)) source_visible = ColumnDataSource(data={'x': county_xs, 'y': county_ys, 'name': county_names, 'rate': a_dict[str(last_day)], 'color': [hex_color]}) ''' # Define a sequential multi-hue color palette. palette = brewer['YlGnBu'][6] palette = palette[::-1] # TODO: get the high value from median? color_mapper = LinearColorMapper(palette=palette, low=0, high=100) # TODO: add agenda? TOOLS = "pan,zoom_in,zoom_out,wheel_zoom,box_zoom,reset,hover,save" p = figure(title="US density", toolbar_location="right", output_backend="webgl", plot_width=1100, plot_height=700, tools=TOOLS, tooltips=[("County", "@name"), ("Confirmed cases", "@rate"), ("(Long, Lat)", "($x, $y)")]) # hide grid and axes p.axis.visible = None p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None p.hover.point_policy = "follow_mouse" # p.patches(county_xs, county_ys, # fill_alpha=0.7, # line_color="white", line_width=0.5) p.patches(state_xs, state_ys, fill_alpha=0.7, line_color="white", line_width=2, line_alpha=0.3) p.patches( 'x', 'y', source=source_visible, fill_color={ 'field': 'rate', 'transform': color_mapper }, #fill_color='color', fill_alpha=0.7, line_color="white", line_width=0.2) date_slider = DateSlider(title="Date:", start=first_day, end=last_day, value=last_day, step=1) callback = CustomJS(args=dict(source=source_new, ts=source_visible), code=""" var data=ts.data; var data1=source.data; var f=cb_obj.value; //this is the selection value of slider var event = new Date(f); var date_selected = event.toISOString().substring(0,10); // converting date from python to JS //ts.data['color'] = '#ffffff' //color_dict.data[date_selected]; data['rate']=data1[date_selected]; ts.change.emit(); """) date_slider.js_on_change('value', callback) layout = row(column(date_slider), p) output_file(html_page_name, title="Interactive USA density map") show(layout)
def bkapp_page(): ###-----------------------------------------------------------------------### ###------------------------PREPARING DATA---------------------------------### ### This section contains getting and preparing data for this plot------ ### ###-----------------------------------------------------------------------### ### Load dataset rat interventions bait_interventions_to_save = pd.read_pickle('development/bait_interventions_to_save_pitch_night.pickle') ### Load indices of rows for each month for bait dataset indices_bait_df = pd.read_pickle('development/indices_bait_df_pitch_night.pickle') #has 2 columns: 'from_index' and 'to_index' ### Load dataset rat sighting dataset_sightings_locations_to_save = pd.read_pickle('development/dataset_sightings_locations_to_save_pitch_night.pickle') ### Load indices of rows for each month for sightings dataset indices_sight_df = pd.read_pickle('development/indices_sight_df_pitch_night.pickle') #has 2 columns: 'from_index' and 'to_index' ### Load dataset by zipcodes by_zipcodes_df = pd.read_pickle('development/dataset_by_zipcodes_pitch_night.pickle') ### PREDICTIONS datasets df = pd.read_pickle('development/locations_prediction_df_pitch_night.pickle') prophet_fit_all_nyc = pd.read_pickle('development/prophet_fit_all_nyc_pitch_night.pickle') prophet_prediction_all_nyc = pd.read_pickle('development/prophet_prediction_all_nyc_pitch_night.pickle') ### Read the nyc map data nyc_df = pd.read_pickle('development/nyc_converted_to_save.pickle') nyc_by_zips = pd.read_pickle('development/dataset_map_by_zipcodes_pitch_night.pickle') zip_hm = pd.read_pickle('development/zip_heatmaps_pitch_night.pickle') ### Read existing year-month strings in dataset with open('development/timepoints_pitch_night.pickle', "rb") as f: timepoints = pickle.load(f) timepoints = timepoints[:-1] ### list of zipcodes in dataset with open('development/all_zips.pickle', "rb") as f: all_zips = pickle.load(f) ### Read predicted months with open('development/predicted_months_pitch_night.pickle', "rb") as f: predicted_months = pickle.load(f) ### prepare data for bokeh bait_source = ColumnDataSource(bait_interventions_to_save) indices_bait_source = ColumnDataSource(indices_bait_df) sight_source = ColumnDataSource(dataset_sightings_locations_to_save) indices_sight_source = ColumnDataSource(indices_sight_df) nyc_source = ColumnDataSource(nyc_df) timepoints_cds = ColumnDataSource(pd.DataFrame({'timepoints':timepoints})) predicted_months_cds = ColumnDataSource(pd.DataFrame({'predicted_months':predicted_months})) by_zipcodes_source = ColumnDataSource(by_zipcodes_df) nyc_by_zips_source = ColumnDataSource(nyc_by_zips) zip_hm_first = ColumnDataSource(zip_hm.loc[:,['ZIPCODE','x','y','sightings']]) zip_hm_original = ColumnDataSource(zip_hm) ### bokeh data source for initial plot rendered: first_source_bait = ColumnDataSource(bait_interventions_to_save.iloc[indices_bait_df['from_index'][51]:indices_bait_df['to_index'][51],:]) first_source_sight = ColumnDataSource(dataset_sightings_locations_to_save.iloc[indices_sight_df['from_index'][51]:indices_sight_df['to_index'][51],:]) ###-----------------------------------------------------------------------### ###----------------------GRAPHICAL USER INTERFACE-------------------------### ### This code defines the Bokeh controls that are used for the user ### ### interface. ---------------------------------------------------------- ### ###-----------------------------------------------------------------------### ### Initialize plot figure p = figure(x_range=(-74.2, -73.7), y_range=(40.53, 40.915), tools= 'box_zoom,pan,save,reset', active_drag="box_zoom", min_border_right = 40, min_border_top = 5, min_border_bottom = 5, border_fill_color = "black", background_fill_color = "black", toolbar_location="left") p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None p.axis.visible = False p.outline_line_color = "black" ###-----------------------------------------------------------------------### ###------------------------PREDICTED locations----------------------------### ###-------------------------heatmap---------------------------------------### ###-----------------------------------------------------------------------### colors = ['#000000'] + brewer["Reds"][9] binsize = 0.5/80 hm_source = ColumnDataSource(pd.read_pickle('development/df_mock_pitch_practice.pickle')) # hm_source = ColumnDataSource(df) hm_source_original = ColumnDataSource(df) ## not nomalized count mapper = LinearColorMapper(palette=colors, low=df.rat_count.min(), high=df.rat_count.max()) prediction_location = p.rect(x="level_0", y="level_1", width=binsize, height=binsize, source=hm_source, fill_color={'field': 'start', 'transform': mapper}, line_color=None) ###-----------------------------------------------------------------------### ###---------------------------NYC map-------------------------------------### ###------------------------and events from data---------------------------### ###-----------------------------------------------------------------------### ### Add nyc map p.patches('x', 'y', source=nyc_source, color='black', line_width=1, fill_color={'field': 'colors'}, fill_alpha = 0.4) ### Add my bait points baits = p.circle('LONGITUDE', 'LATITUDE', source=first_source_bait, fill_color='#4dc6e0', line_color = '#4dc6e0', line_width=3, line_alpha=0.6, legend="Rat Interventions") ### Add my sights points sights = p.circle('LONGITUDE', 'LATITUDE', source=first_source_sight, fill_color = '#d96c82',line_color = '#d96c82',line_width=3, line_alpha=0.6, legend="Rat Sightings") p.legend.location = "top_left" p.legend.label_text_color = 'white' p.legend.border_line_color = "white" p.legend.background_fill_color = "black" ### Add slider date_slider = DateSlider(title="Date", start=dt.date(2010, 1, 1), end=dt.date(2018, 9, 1),value=dt.date(2014, 4, 1), step=1, format = "%B %Y") ### Add hovers bait_hover = HoverTool(tooltips = """ <div> <div> <span style="font-size: 14px; font-weight:bold; color: #00BFFF">Location:</span> <span style="font-size: 15px; color: #000000">@HOUSE_NUMBER @STREET_NAME</span><br> <span style="font-size: 14px; font-weight:bold; color: #00BFFF;">Zip Code:</span> <span style="font-size: 15px; color: #000000"> @ZIP_CODE </span><br> <span style="font-size: 14px; font-weight:bold; color: #00BFFF;">Intervention Date: </span> <span style="font-size: 15px; color: #000000">@Inspection_Date</span><br> <span style="font-size: 14px; font-weight:bold; color: #00BFFF;">Intervention Type: </span> <span style="font-size: 15px; color: #000000">@RESULT</span> </div> </div> """, renderers=[baits]) p.add_tools(bait_hover) sight_hover = HoverTool(tooltips = """ <div> <div> <span style="font-size: 14px; font-weight:bold; color: #F08080">Location:</span> <span style="font-size: 15px; color: #000000">@ADDRESS</span><br> <span style="font-size: 14px; font-weight:bold; color: #F08080;">Zip Code:</span> <span style="font-size: 15px; color: #000000"> @ZIP_CODE </span><br> <span style="font-size: 14px; font-weight:bold; color: #F08080;">Rat Sighting Date: </span> <span style="font-size: 15px; color: #000000">@Sighting_Date</span> </div> </div> """, renderers=[sights]) p.add_tools(sight_hover) prediction_hover = HoverTool(tooltips = """ <div> <div> <span style="font-size: 14px; font-weight:bold; color: #F08080">Longitude:</span> <span style="font-size: 15px; color: #000000">@level_0</span><br> <span style="font-size: 14px; font-weight:bold; color: #F08080;">Latitude:</span> <span style="font-size: 15px; color: #000000"> @level_1 </span><br> <span style="font-size: 14px; font-weight:bold; color: #F08080;">Predicted monthly sightings: </span> <span style="font-size: 15px; color: #000000">@start</span> </div> </div> """, renderers=[prediction_location]) p.add_tools(prediction_hover) ### Add a Zip Code selection option zip_select = Select(title="Selected Zipcode:", value="all zipcodes", options= all_zips) ###-----------------------------------------------------------------------### ###------------------------PLOT of whole----------------------------------### ###----------------------city sightings numbers---------------------------### ###-----------------------------------------------------------------------### fit_source = ColumnDataSource(prophet_fit_all_nyc) prediction_source = ColumnDataSource(prophet_prediction_all_nyc) p_right = figure(title = 'CITY-WIDE MONTHLY PREDICTIONS',tools= 'box_zoom,pan,save,reset', min_border_top = 250, min_border_left = 100, border_fill_color = "black", background_fill_color = "black", width = 600, height = 550, active_drag="box_zoom", x_axis_type="datetime") # interval shading glyph: lowerband = prophet_prediction_all_nyc['yhat_lower'].values upperband = prophet_prediction_all_nyc['yhat_upper'].values band_x = np.append(prophet_prediction_all_nyc['ds'].values, prophet_prediction_all_nyc['ds'].values[::-1]) band_y = np.append(lowerband, upperband[::-1]) p_right.patch(band_x, band_y, color='white', fill_alpha=0.5, alpha = 0.5) p_right.line(x = 'ds', y = 'y', source = fit_source, color = '#d96c82', line_width=2.6, legend = 'monthly rat sightings') p_right.circle(x = 'ds', y = 'y', source = fit_source, color = '#d96c82', size = 7, alpha = 0.5, legend = 'monthly rat sightings') p_right.line(x = 'ds', y = 'yhat', source = prophet_fit_all_nyc, line_width=2, color = 'white', legend = 'FBprophet fit/prediction') p_right.circle(x = 'ds', y = 'yhat', source = prophet_fit_all_nyc, color = 'white', size = 5, alpha = 0.5, legend = 'FBprophet fit/prediction') p_right.line(x = 'ds', y = 'yhat', source = prophet_prediction_all_nyc, line_width=2, color = 'white', line_dash="4 4") p_right.circle(x = 'ds', y = 'yhat', source = prophet_prediction_all_nyc, size = 5, color = 'white', alpha = 0.5, line_dash="4 4") p_right.line([prophet_fit_all_nyc.iloc[-1,0], prophet_prediction_all_nyc.iloc[0,0]], [prophet_fit_all_nyc.iloc[-1,2], prophet_prediction_all_nyc.iloc[0,1]], line_dash="4 4", line_width=2, color='white') p_right.legend.location = "top_left" p_right.xaxis.major_label_text_font_size = "14pt" p_right.yaxis.major_label_text_font_size = "14pt" p_right.title.text_font_size = '16pt' p_right.legend.label_text_font_size = '9pt' p_right.legend.location = "top_left" p_right.xaxis.axis_label = 'Date' p_right.yaxis.axis_label = 'monthly rat sightings' p_right.xaxis.axis_label_text_font_size = "14pt" p_right.yaxis.axis_label_text_font_size = "14pt" p_right.xaxis.axis_label_text_color = '#909090' p_right.xaxis.axis_line_color = '#909090' p_right.xaxis.major_label_text_color = '#909090' p_right.yaxis.axis_label_text_color = '#909090' p_right.yaxis.axis_line_color = '#909090' p_right.yaxis.major_label_text_color = '#909090' p_right.title.text_color = '#909090' p_right.legend.label_text_color = '#909090' p_right.legend.border_line_color = "#909090" p_right.outline_line_color = "#909090" p_right.legend.background_fill_color = "black" ###-----------------------------------------------------------------------### ###----------------------------CALLBACKS----------------------------------### ### This section defines the behavior of the GUI as the user interacts ### ### with the controls. --------------------------------------------------### ###-----------------------------------------------------------------------### ### Slider callback function callback = CustomJS(args=dict(date_slider = date_slider, zip_select = zip_select, first_source_bait = first_source_bait, original_source_bait = bait_source, bait_indices = indices_bait_source, first_source_sight = first_source_sight, original_source_sight = sight_source, hm_source_original = hm_source_original, hm_source = hm_source, sight_indices = indices_sight_source, timepoints_cds = timepoints_cds, predicted_months_cds = predicted_months_cds), code=""" var date_slider = new Date(date_slider.value); var timepoints_cds = timepoints_cds.data; var predicted_months_cds = predicted_months_cds.data; var zip_selected = parseFloat(zip_select.value); var data_bait = first_source_bait.data; var whole_data_bait = original_source_bait.data; var bait_indices = bait_indices.data; var data_sight = first_source_sight.data; var whole_data_sight = original_source_sight.data; var sight_indices = sight_indices.data; var data_hm = hm_source.data; var data_hm_original = hm_source_original.data; const monthNames = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]; var year_month = (date_slider.getUTCFullYear()).toString() +'-'+ monthNames[date_slider.getUTCMonth()]; console.log(year_month) var g = timepoints_cds['timepoints'].indexOf(year_month) var test = 0; data_hm['start'] = []; data_hm['level_0'] = []; data_hm['level_1'] = []; if(predicted_months_cds['predicted_months'].indexOf(year_month) >= 0 ) { for (k = 0; k < 80*80; k++) { data_hm['start'].push(data_hm_original['predicted_'+ year_month][k]) data_hm['level_0'].push(data_hm_original['level_0'][k]) data_hm['level_1'].push(data_hm_original['level_1'][k]) test = k; } } console.log(data_hm['start'][test]) data_bait['LONGITUDE'] = [] data_bait['LATITUDE'] = [] data_bait['HOUSE_NUMBER'] = [] data_bait['STREET_NAME'] = [] data_bait['ZIP_CODE'] = [] data_bait['Inspection_Date'] = [] data_bait['RESULT'] = [] for (i = bait_indices['from_index'][g]; i < bait_indices['to_index'][g] + 1; i++) { if(whole_data_bait['ZIP_CODE'][i] == zip_selected || zip_selected == "all zipcodes" || isNaN(zip_selected)) { data_bait['LONGITUDE'].push(whole_data_bait['LONGITUDE'][i]) data_bait['LATITUDE'].push(whole_data_bait['LATITUDE'][i]) data_bait['HOUSE_NUMBER'].push(whole_data_bait['HOUSE_NUMBER'][i]) data_bait['STREET_NAME'].push(whole_data_bait['STREET_NAME'][i]) data_bait['ZIP_CODE'].push(whole_data_bait['ZIP_CODE'][i]) data_bait['Inspection_Date'].push(whole_data_bait['Inspection_Date'][i]) data_bait['RESULT'].push(whole_data_bait['RESULT'][i]) } } data_sight['LONGITUDE'] = [] data_sight['LATITUDE'] = [] data_sight['ADDRESS'] = [] data_sight['ZIP_CODE'] = [] data_sight['Sighting_Date'] = [] for (j = sight_indices['from_index'][g]; j < sight_indices['to_index'][g] + 1; j++) { if(whole_data_sight['ZIP_CODE'][j] == zip_selected || zip_selected == "all zipcodes" || isNaN(zip_selected)) { data_sight['LONGITUDE'].push(whole_data_sight['LONGITUDE'][j]) data_sight['LATITUDE'].push(whole_data_sight['LATITUDE'][j]) data_sight['ADDRESS'].push(whole_data_sight['ADDRESS'][j]) data_sight['ZIP_CODE'].push(whole_data_sight['ZIP_CODE'][j]) data_sight['Sighting_Date'].push(whole_data_sight['Sighting_Date'][j]) } } hm_source.change.emit(); first_source_sight.change.emit(); first_source_bait.change.emit(); """) ### Zip code select callback function zip_callback = CustomJS(args=dict(zip_select = zip_select, nyc_source = nyc_source, date_slider = date_slider, first_source_bait = first_source_bait, original_source_bait = bait_source, bait_indices = indices_bait_source, first_source_sight = first_source_sight, original_source_sight = sight_source, sight_indices = indices_sight_source, timepoints_cds = timepoints_cds), code=""" var zip_selected = parseFloat(zip_select.value); var date_slider = new Date(date_slider.value); var timepoints_cds = timepoints_cds.data; var nyc_source_data = nyc_source.data; var zip_color_selected = "black"; if (zip_selected == "all zipcodes" || isNaN(zip_selected)) { zip_color_selected = "white"; } var zip_color_rest = "white"; var data_bait = first_source_bait.data; var whole_data_bait = original_source_bait.data; var bait_indices = bait_indices.data; var data_sight = first_source_sight.data; var whole_data_sight = original_source_sight.data; var sight_indices = sight_indices.data; nyc_source_data['colors'] = [] for (i = 0; i <nyc_source_data['ZIPCODE'].length; i++) { if (nyc_source_data['ZIPCODE'][i] == zip_selected || zip_selected == "all zipcodes" || isNaN(zip_selected)) { nyc_source_data['colors'].push(zip_color_selected); } else { nyc_source_data['colors'].push(zip_color_rest); } } const monthNames = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]; var year_month = (date_slider.getUTCFullYear()).toString() +'-'+ monthNames[date_slider.getUTCMonth()]; console.log(year_month) console.log(zip_selected) var g = timepoints_cds['timepoints'].indexOf(year_month) data_bait['LONGITUDE'] = [] data_bait['LATITUDE'] = [] data_bait['HOUSE_NUMBER'] = [] data_bait['STREET_NAME'] = [] data_bait['ZIP_CODE'] = [] data_bait['Inspection_Date'] = [] data_bait['RESULT'] = [] for (i = bait_indices['from_index'][g]; i < bait_indices['to_index'][g] + 1; i++) { if(whole_data_bait['ZIP_CODE'][i] == zip_selected || zip_selected == "all zipcodes" || isNaN(zip_selected)) { data_bait['LONGITUDE'].push(whole_data_bait['LONGITUDE'][i]) data_bait['LATITUDE'].push(whole_data_bait['LATITUDE'][i]) data_bait['HOUSE_NUMBER'].push(whole_data_bait['HOUSE_NUMBER'][i]) data_bait['STREET_NAME'].push(whole_data_bait['STREET_NAME'][i]) data_bait['ZIP_CODE'].push(whole_data_bait['ZIP_CODE'][i]) data_bait['Inspection_Date'].push(whole_data_bait['Inspection_Date'][i]) data_bait['RESULT'].push(whole_data_bait['RESULT'][i]) } } data_sight['LONGITUDE'] = [] data_sight['LATITUDE'] = [] data_sight['ADDRESS'] = [] data_sight['ZIP_CODE'] = [] data_sight['Sighting_Date'] = [] for (j = sight_indices['from_index'][g]; j < sight_indices['to_index'][g] + 1; j++) { if(whole_data_sight['ZIP_CODE'][j] == zip_selected || zip_selected == "all zipcodes" || isNaN(zip_selected)) { data_sight['LONGITUDE'].push(whole_data_sight['LONGITUDE'][j]) data_sight['LATITUDE'].push(whole_data_sight['LATITUDE'][j]) data_sight['ADDRESS'].push(whole_data_sight['ADDRESS'][j]) data_sight['ZIP_CODE'].push(whole_data_sight['ZIP_CODE'][j]) data_sight['Sighting_Date'].push(whole_data_sight['Sighting_Date'][j]) } } first_source_sight.change.emit(); first_source_bait.change.emit(); nyc_source.change.emit(); """) zip_select.js_on_change('value', zip_callback) date_slider.js_on_change('value', callback) layout = row(column(row(date_slider, zip_select), p), p_right) # layout = gridplot([[p, p_right]]) the_script, the_div = components(layout) ###-----------------------------------------------------------------------### ###-----------------------------------------------------------------------### ###-----------------------BY ZIPCODES PLOT--------------------------------### ###-----------------------------------------------------------------------### ###-----------------------------------------------------------------------### colors = ['#f27991', '#f493a7', '#f7aebd', '#fce4e9'] + ['#FFFFFF'] + ['#ddf8fd','#ccf4fd', '#bbf1fc','#aaedfc','#99eafb','#88e6fa', '#77e3fa', '#66dff9', '#56dcf9'] mapper = LinearColorMapper(palette=colors, low=by_zipcodes_df.dev.min(), high=by_zipcodes_df.dev.max()) color_bar = ColorBar(color_mapper=mapper, location=(0, 0), label_standoff=10, major_label_text_font_size='14pt', major_label_text_color = '#909090', background_fill_color = 'black', scale_alpha = 0.7) mp = figure(x_range=(-74.2, -73.7), y_range=(40.53, 40.915), width = 600, height =630, tools= 'box_zoom,pan,save,reset', active_drag="box_zoom", background_fill_color = "black", min_border_right = 40, min_border_top = 5, min_border_bottom = 5, border_fill_color = "black") mp.xgrid.grid_line_color = None mp.ygrid.grid_line_color = None mp.axis.visible = False mp.outline_line_color = "black" zips = mp.patches('x', 'y', source=nyc_by_zips_source, color='black', line_width=1, fill_color={'field': 'dev', 'transform': mapper}, alpha = 0.7) zips_hover = HoverTool(tooltips = """ <div> <div> <span style="font-size: 14px; font-weight:bold; color: #000000;">Zip Code: </span> <span style="font-size: 15px; color: #000000">@ZIPCODE</span><br> <span style="font-size: 14px; font-weight:bold; color: #000000">Average number of rat sightings per year:</span> <span style="font-size: 15px; color: #000000">@sightings</span><br> <span style="font-size: 14px; font-weight:bold; color: #000000;">Average number of interventions per year:</span> <span style="font-size: 15px; color: #000000"> @interventions </span><br> <span style="font-size: 14px; font-weight:bold; color: #000000;">Number of interventions above expectation:</span> <span style="font-size: 15px; color: #000000"> @dev </span> </div> </div> """, renderers=[zips]) mp.add_tools(zips_hover) p_zips = figure(title = 'Sightings and interventions by zipcode',tools= 'box_zoom,pan,save,reset', active_drag="box_zoom", background_fill_color = "black", min_border_right = 40, min_border_top = 5, min_border_bottom = 5, border_fill_color = "black") points = p_zips.circle(x = 'sightings', y = 'interventions', source = by_zipcodes_source, size=12, fill_color={'field': 'dev', 'transform': mapper}, alpha = 0.7, line_color = 'black') p_zips.line(x = 'sightings', y = 'lin_fit', source = by_zipcodes_source, color = 'white') p_zips.add_layout(color_bar, 'left') points_hover = HoverTool(tooltips = """ <div> <div> <span style="font-size: 14px; font-weight:bold; color: #000000;">Zip Code: </span> <span style="font-size: 15px; color: #000000">@ZIP_CODE</span><br> <span style="font-size: 14px; font-weight:bold; color: #000000">Average number of rat sightings per year:</span> <span style="font-size: 15px; color: #000000">@sightings</span><br> <span style="font-size: 14px; font-weight:bold; color: #000000;">Average number of interventions per year:</span> <span style="font-size: 15px; color: #000000"> @interventions </span><br> <span style="font-size: 14px; font-weight:bold; color: #000000;">Number of interventions above expectation:</span> <span style="font-size: 15px; color: #000000"> @dev </span> </div> </div> """, renderers=[points]) p_zips.add_tools(points_hover) p_zips.xaxis.major_label_text_font_size = "14pt" p_zips.yaxis.major_label_text_font_size = "14pt" p_zips.title.text_font_size = '16pt' p_zips.xaxis.axis_label = 'average number of rat sightings per year' p_zips.yaxis.axis_label = 'average number of interventions per year' p_zips.xaxis.axis_label_text_font_size = "14pt" p_zips.yaxis.axis_label_text_font_size = "14pt" p_zips.xaxis.axis_label_text_color = '#909090' p_zips.xaxis.axis_line_color = '#909090' p_zips.xaxis.major_label_text_color = '#909090' p_zips.yaxis.axis_label_text_color = '#909090' p_zips.yaxis.axis_line_color = '#909090' p_zips.yaxis.major_label_text_color = '#909090' p_zips.title.text_color = '#909090' layout_zips = row(mp,p_zips) the_script_zips, the_div_zips = components(layout_zips) ###-----------------------------------------------------------------------### ###-----------------------------------------------------------------------### ###--------------------------HEATMAPS PLOT--------------------------------### ###------------------------- BY ZIPCODE----------------------------------### ###-----------------------------------------------------------------------### colors_hm = ['#fdf1f4', '#fce4e9', '#fbd6de', '#f9c9d3', '#f8bcc8', '#f7aebd', '#f5a1b2','#f493a7', '#f3869c', '#f27991'] mapper_hm = LinearColorMapper(palette=colors_hm, low=0, high=50) hm_color_bar = ColorBar(color_mapper=mapper_hm, location=(0, 0), label_standoff=10, major_label_text_font_size='14pt', major_label_text_color = '#909090', background_fill_color = 'black', scale_alpha = 0.7) heatmap = figure(x_range=(-74.2, -73.7), y_range=(40.53, 40.915), width = 500, height =500, tools= 'box_zoom,pan,save,reset', active_drag="box_zoom", background_fill_color = "black", min_border_top = 5, min_border_bottom = 5, border_fill_color = "black", toolbar_location="left") heatmap.xgrid.grid_line_color = None heatmap.ygrid.grid_line_color = None heatmap.axis.visible = False heatmap.outline_line_color = "black" zips_hm = heatmap.patches('x', 'y', source=zip_hm_first, color='black', line_width=1, fill_color={'field': 'sightings', 'transform': mapper_hm}, alpha = 0.7) zips_hm_hover = HoverTool(tooltips = """ <div> <div> <span style="font-size: 14px; font-weight:bold; color: #000000;">Zip Code: </span> <span style="font-size: 15px; color: #000000">@ZIPCODE</span><br> <span style="font-size: 14px; font-weight:bold; color: #000000">Number of sightings this month:</span> <span style="font-size: 15px; color: #000000">@sightings</span><br> </div> </div> """, renderers=[zips_hm]) heatmap.add_tools(zips_hm_hover) dummy = figure(height=500, width=150, toolbar_location=None, min_border=0, outline_line_color=None, background_fill_color = "black", min_border_top = 5, min_border_bottom = 5, border_fill_color = "black") dummy.add_layout(hm_color_bar, 'right') ### Add slider date_slider_hm = DateSlider(title="Date", start=dt.date(2010, 1, 1), end=dt.date(2018, 4, 1),value=dt.date(2014, 7, 1), step=1, format = "%B %Y") ### Slider callback function hm_callback = CustomJS(args=dict(date_slider = date_slider_hm, zip_hm_first = zip_hm_first, zip_hm_original = zip_hm_original), code=""" var date_slider = new Date(date_slider.value); var data_hm = zip_hm_first.data; var data_hm_original = zip_hm_original.data; const monthNames = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]; var year_month = (date_slider.getUTCFullYear()).toString() +'-'+ monthNames[date_slider.getUTCMonth()]; console.log(year_month) var test = 0; data_hm['sightings'] = []; for (k = 0; k < 263; k++) { data_hm['sightings'].push(data_hm_original[year_month][k]) } zip_hm_first.change.emit(); """) date_slider_hm.js_on_change('value', hm_callback) layout_hm = column(date_slider_hm,row(heatmap, dummy)) the_script_hm, the_div_hm = components(layout_hm) return render_template('myindex-pitch-night.html', div = the_div, script=the_script, the_script_zips = the_script_zips, the_div_zips = the_div_zips, the_script_hm = the_script_hm, the_div_hm = the_div_hm)
def bokehTile(tileFile, jsonFile, TT=[0, 0, 0], DD=[2019, 10, 1], dynamic=False, plotTitle=''): citls, h = fitsio.read(tileFile, header=True) w = (np.where(citls['IN_DESI'] == 1)[0]) inci = citls[w] if jsonFile is not None: with open(jsonFile, "r") as read_file: data = json.load(read_file) ## Coloring scheme palette = ['green', 'red', 'white'] dye = [] for tile in citls['TILEID']: rang = 2 # 'orange' if jsonFile is not None: if str(tile) in data: rang = 0 # 'green' #green default if len(data[str(tile)] ['unassigned']) > 0: # not assigned (red) rang = 1 # 'red' #'red' if (0 in data[str(tile)]['gfa_stars_percam']): print(data[str(tile)]['gfa_stars_percam']) rang = 1 # 'cyan' else: rang = 0 # green if qa.json is not provided dye.append(rang) dye = np.asarray(dye) w = (np.where(dye < 2)[0]) citls = citls[w] dye = dye[w] mapper = linear_cmap(field_name='DYE', palette=palette, low=0, high=2) ######################################################### TOOLS = [ 'pan', 'tap', 'wheel_zoom', 'box_zoom', 'reset', 'save', 'box_select' ] obsTime = dt(DD[0], DD[1], DD[2], TT[0], TT[1], TT[2]) # print(get_kp_twilights(TT,DD)) if plotTitle == '' or plotTitle is None: PTITLE = '' else: PTITLE = 'Program: ' + plotTitle p = figure(tools=TOOLS, toolbar_location="right", plot_width=800, plot_height=450, title=PTITLE, active_drag='box_select') # str(DD[1])+" - 2019") p.title.text_font_size = '16pt' p.title.text_color = 'black' p.grid.grid_line_color = "gainsboro" ############################### adding ecliptic plane+ hour grid ####################3 add_plane(p, color='red', plane='ecliptic', projection='equatorial') tiledata = dict( RA=citls['RA'], DEC=citls['DEC'], TILEID=citls['TILEID'], BRIGHTRA=citls['BRIGHTRA'][:, 0], BRIGHTDEC=citls['BRIGHTDEC'][:, 0], BRIGHTVTMAG=citls['BRIGHTVTMAG'][:, 0], EBV_MED=np.round(citls['EBV_MED'], 3), STAR_DENSITY=citls['STAR_DENSITY'], DYE=dye, program=citls['PROGRAM'], selected=np.ones(len(citls), dtype=bool), ) for colname in ['STAR_DENSITY', 'EBV_MED']: if colname in citls.dtype.names: tiledata[colname] = citls[colname] tiles = ColumnDataSource(data=tiledata) colformat = bktables.NumberFormatter(format='0,0.00') columns = [ bktables.TableColumn(field='TILEID', title='TILEID', width=80), bktables.TableColumn(field='RA', title='RA', formatter=colformat), bktables.TableColumn(field='DEC', title='DEC', formatter=colformat), ] for colname in ['STAR_DENSITY', 'EBV_MED']: if colname in tiledata: columns.append( bktables.TableColumn(field=colname, title=colname, formatter=colformat)) columns.append(bktables.TableColumn(field='selected', title='Selected')) tiletable = bktables.DataTable(columns=columns, source=tiles, width=800) tiles.selected.js_on_change( 'indices', CustomJS(args=dict(s1=tiles), code=""" var inds = cb_obj.indices; var d1 = s1.data; for (var i=0; i<d1['selected'].length; i++) { d1['selected'][i] = false; } for (var i = 0; i < inds.length; i++) { d1['selected'][inds[i]] = true; } s1.change.emit(); """)) render = p.circle( 'RA', 'DEC', source=tiles, size=9, line_color='chocolate', color=mapper, alpha=0.4, hover_color='orange', hover_alpha=1, hover_line_color='red', # set visual properties for selected glyphs selection_fill_color='orange', selection_line_color='white', # set visual properties for non-selected glyphs nonselection_fill_alpha=0.4, nonselection_fill_color=mapper) p.xaxis.axis_label = 'RA [deg]' p.yaxis.axis_label = 'Dec. [deg]' p.xaxis.axis_label_text_font_size = "14pt" p.yaxis.axis_label_text_font_size = "14pt" p.grid.grid_line_color = "gainsboro" p.yaxis.major_label_text_font_size = "12pt" p.xaxis.major_label_text_font_size = "12pt" p.x_range = Range1d(360, 0) p.y_range = Range1d(-40, 95) p.toolbar.logo = None p.toolbar_location = None # mytext = Label(x=180, y=-35, text="S", text_color='gray', text_font_size='12pt') ; p.add_layout(mytext) # mytext = Label(x=180, y=88, text="N", text_color='gray', text_font_size='12pt') ; p.add_layout(mytext) # mytext = Label(x=350, y=45, text="E", text_color='gray', text_font_size='12pt', angle=np.pi/2) ; p.add_layout(mytext) # mytext = Label(x=4, y=45, text="W", text_color='gray', text_font_size='12pt', angle=np.pi/2) ; p.add_layout(mytext) ## Javascript code to open up custom html pages, once user click on a tile code = """ var index_selected = source.selected['1d']['indices'][0]; var tileID = source.data['TILEID'][index_selected]; if (tileID!==undefined) { var win = window.open("http://www.astro.utah.edu/~u6022465/cmx/ALL_SKY/dr8/allSKY_ci_tiles/sub_pages/tile-"+tileID+".html", " "); try {win.focus();} catch (e){} } """ taptool = p.select(type=TapTool) taptool.callback = CustomJS(args=dict(source=tiles), code=code) ## The html code for the hover window that contain tile infrormation ttp = """ <div> <div> <span style="font-size: 14px; color: blue;">Tile ID:</span> <span style="font-size: 14px; font-weight: bold;">@TILEID{int}</span> </div> <div> <span style="font-size: 14px; color: blue;">RA:</span> <span style="font-size: 14px; font-weight: bold;">@RA</span> </div> <div> <span style="font-size: 14px; color: blue;">Dec:</span> <span style="font-size: 14px; font-weight: bold;">@DEC</span> </div> <div> <span style="font-size: 14px; color: blue;">EBV_MED:</span> <span style="font-size: 14px; font-weight: bold;">@EBV_MED{0.000}</span> </div> <div> <span style="font-size: 14px; color: blue;">STAR_DENSITY:</span> <span style="font-size: 14px; font-weight: bold;">@STAR_DENSITY{0}</span> </div> <div> <span style="font-size: 14px; color: blue;">BRIGHTEST_STAR_VTMAG:</span> <span style="font-size: 14px; font-weight: bold;">@BRIGHTVTMAG</span> </div> <div> <span style="font-size: 14px; color: blue;">BRIGHTEST_STAR_LOC:</span> <span style="font-size: 14px; font-weight: bold;">(@BRIGHTRA, @BRIGHTDEC)</span> </div> </div> """ hover = HoverTool(tooltips=ttp, renderers=[render]) hover.point_policy = 'snap_to_data' hover.line_policy = 'nearest' # hover.mode='vline' p.add_tools(hover) cross = CrosshairTool() # cross.dimensions='height' cross.line_alpha = 0.3 cross.line_color = 'gray' p.add_tools(cross) # Setting the second y axis range name and range p.extra_y_ranges = {"foo": p.y_range} p.extra_x_ranges = {"joo": p.x_range} # Adding the second axis to the plot. p.add_layout(LinearAxis(y_range_name="foo"), 'right') p.add_layout(LinearAxis(x_range_name="joo"), 'above') p.xaxis.major_label_text_font_size = "12pt" p.yaxis.major_label_text_font_size = "12pt" if dynamic: # twilight_source = get_kp_twilights(TT,DD) # evening and morning twilights at every TT and DD circleSource_1 = skyCircle(TT, DD, 1.5) p.circle('RA', 'DEC', source=circleSource_1, size=1.5, color='black') circleSource_2 = skyCircle(TT, DD, 2.0) p.circle('RA', 'DEC', source=circleSource_2, size=0.5, color='gray') else: circleSource = skyCircle(TT, DD, 1.5) p.circle('RA', 'DEC', source=circleSource, size=1.5, color=None) ### Dealing with the Moon and Jupiter inFile = 'moonLoc_jupLoc_fracPhase.csv' # 'moon_loc_jup_loc_fracPhase_namePhase.csv' tbl_moon_jup = np.genfromtxt(inFile, delimiter=',', filling_values=-1, names=True, dtype=None) # , dtype=np.float) loc = EarthLocation.of_site('Kitt Peak') kp_lat = 31, 57, 48 kp_lon = -111, 36, 00 mooninfo_obj = pylunar.MoonInfo((kp_lat), (kp_lon)) m_ra, m_dec, frac_phase, name_phase = moonLoc(TT, DD, loc, mooninfo_obj) j_ra, j_dec = jupLoc(TT, DD, loc) #moonSource = ColumnDataSource({"moon_RAS": tbl_moon_jup['moon_ra'], "moon_DECS": tbl_moon_jup['moon_dec'], # "Phase_frac": tbl_moon_jup['moon_phase_frac']}) moonSource = ColumnDataSource({ "moon_RAS": tbl_moon_jup['moon_ra'], "moon_DECS": tbl_moon_jup['moon_dec'], "Phase_frac": np.round(100 * tbl_moon_jup['moon_phase_frac']) }) ####moon_RADEC = ColumnDataSource({"moon_ra": [m_ra.deg], "moon_dec": [m_dec.deg], "phase_frac": [frac_phase]}) moon_RADEC_ = ColumnDataSource({ "moon_ra": [m_ra.deg - 360], "moon_dec": [m_dec.deg], "phase_frac": [frac_phase] }) moon_RADEC = ColumnDataSource({ "moon_ra": [m_ra.deg], "moon_dec": [m_dec.deg], "phase_frac": [frac_phase] }) render_moon = p.circle('moon_ra', 'moon_dec', source=moon_RADEC, size=170, color='cyan', alpha=0.2) render_moon = p.circle('moon_ra', 'moon_dec', source=moon_RADEC, size=4, color='blue') render_moon = p.circle('moon_ra', 'moon_dec', source=moon_RADEC_, size=170, color='cyan', alpha=0.2) render_moon = p.circle('moon_ra', 'moon_dec', source=moon_RADEC_, size=4, color='blue') jupSource = ColumnDataSource({ "jup_RAS": tbl_moon_jup['jup_ra'], "jup_DECS": tbl_moon_jup['jup_dec'] }) jup_RADEC = ColumnDataSource({ "jup_ra": [j_ra.deg], "jup_dec": [j_dec.deg] }) twilight = get_kp_twilights( TT, DD) # evening and morning twilights at every TT and DD twilight_source = ColumnDataSource({ "eve_twilight": [twilight[0]], "mor_twilight": [twilight[1]] }) render_jup = p.circle('jup_ra', 'jup_dec', source=jup_RADEC, size=5, color='blue') render_jup = p.circle('jup_ra', 'jup_dec', source=jup_RADEC, size=4, color='gold') from bokeh.models.glyphs import Text TXTsrc = ColumnDataSource( dict(x=[350], y=[85], text=['Moon Phase: ' + "%.0f" % (frac_phase * 100) + "%"])) glyph = Text(x="x", y="y", text="text", angle=0, text_color="black") p.add_glyph(TXTsrc, glyph) TXTsrc_moon = ColumnDataSource( dict(x=[m_ra.deg + 10], y=[m_dec.deg - 10], text=['Moon'])) glyph = Text(x="x", y="y", text="text", angle=0, text_color="blue", text_alpha=0.3, text_font_size='10pt') p.add_glyph(TXTsrc_moon, glyph) TXTsrc_jup = ColumnDataSource( dict(x=[j_ra.deg + 5], y=[j_dec.deg - 8], text=['Jup.'])) glyph = Text(x="x", y="y", text="text", angle=0, text_color="black", text_alpha=0.3, text_font_size='10pt') p.add_glyph(TXTsrc_jup, glyph) callback = CustomJS(args=dict(source_sky1=circleSource_1, source_sky2=circleSource_2, source_moon=moonSource, source_moon_RADEC=moon_RADEC, source_moon_RADEC_=moon_RADEC_, source_jup=jupSource, source_jup_RADEC=jup_RADEC, sourceTXT=TXTsrc, sourceTXTmoon=TXTsrc_moon, sourceTXTjup=TXTsrc_jup), code=""" // First set times as if they were UTC var t = new Date(time_slider.value); var d = new Date(date_slider.value); var data1 = source_sky1.data; var ra_1 = data1['RA']; var ra0_1 = data1['RA0']; var data2 = source_sky2.data; var ra_2 = data2['RA']; var ra0_2 = data2['RA0']; var data_moon = source_moon.data; var ras_moon = data_moon['moon_RAS']; var decs_moon = data_moon['moon_DECS']; var phase_frac = data_moon['Phase_frac']; var moonRADEC = source_moon_RADEC.data; var moon_ra = moonRADEC['moon_ra']; var moon_dec = moonRADEC['moon_dec']; var moonRADEC_ = source_moon_RADEC_.data; var moon_ra_ = moonRADEC_['moon_ra']; var moon_dec_ = moonRADEC_['moon_dec']; var data_jup = source_jup.data; var ras_jup = data_jup['jup_RAS']; var decs_jup = data_jup['jup_DECS']; var jupRADEC = source_jup_RADEC.data; var jup_ra = jupRADEC['jup_ra']; var jup_dec = jupRADEC['jup_dec']; var Hour = t.getUTCHours(); var Day = d.getDate(); var Month = d.getMonth(); var Year = new Array(31,28,31,30,31,30,31,31,30,31,30,31); var all_FULdays = 0; for (var i = 0; i < Month; i++) all_FULdays=all_FULdays+Year[i]; all_FULdays = all_FULdays + (Day-1); if (Hour<12) all_FULdays=all_FULdays+1; var all_minutes = all_FULdays*24+Hour; if (all_minutes<8800) { moon_ra[0] = ras_moon[all_minutes]; moon_dec[0] = decs_moon[all_minutes]; moon_ra_[0] = ras_moon[all_minutes]-360.; moon_dec_[0] = decs_moon[all_minutes]; } var jupTXTdata = sourceTXTjup.data; var x_jup = jupTXTdata['x']; var y_jup = jupTXTdata['y']; var text_jup = jupTXTdata['text']; if (all_minutes<8800) { jup_ra[0] = ras_jup[all_minutes]; jup_dec[0] = decs_jup[all_minutes]; x_jup[0] = jup_ra[0]+5; y_jup[0] = jup_dec[0]-8; } if (t.getUTCHours() < 12) { d.setTime(date_slider.value + 24*3600*1000); } else { d.setTime(date_slider.value); } d.setUTCHours(t.getUTCHours()); d.setUTCMinutes(t.getUTCMinutes()); d.setUTCSeconds(0); // Correct to KPNO local time // d object still thinks in UTC, which is 7 hours ahead of KPNO d.setTime(d.getTime() + 7*3600*1000); // noon UT on 2000-01-01 var reftime = new Date(); reftime.setUTCFullYear(2000); reftime.setUTCMonth(0); // Months are 0-11 (!) reftime.setUTCDate(1); // Days are 1-31 (!) reftime.setUTCHours(12); reftime.setUTCMinutes(0); reftime.setUTCSeconds(0); // time difference in days (starting from milliseconds) var dt = (d.getTime() - reftime.getTime()) / (24*3600*1000); // Convert to LST var mayall_longitude_degrees = -(111 + 35/60. + 59.6/3600); var LST_hours = ((18.697374558 + 24.06570982441908 * dt) + mayall_longitude_degrees/15) % 24; var LST_degrees = LST_hours * 15; for (var i = 0; i < ra_1.length; i++) { ra_1[i] = (ra0_1[i] + LST_degrees) % 360; } for (var i = 0; i < ra_2.length; i++) { ra_2[i] = (ra0_2[i] + LST_degrees) % 360; } //// Here we gtake care of the moon phasde text var TXTdata = sourceTXT.data; var x = TXTdata['x']; var y = TXTdata['y']; var text = TXTdata['text']; var moonTXTdata = sourceTXTmoon.data; var x_moon = moonTXTdata['x']; var y_moon = moonTXTdata['y']; var text_moon = moonTXTdata['text']; // x[0] = 1; // y[0] = 40; if (all_minutes<8800) { text[0] = 'Moon Phase: ' + phase_frac[all_minutes]+'%'; x_moon[0] = moon_ra[0]+10; y_moon[0] = moon_dec[0]-10; } sourceTXT.change.emit(); /////////////////////////////// Moon phase code ends. source_sky1.change.emit(); source_sky2.change.emit(); //source_moon_RADEC.change.emit(); //source_moon_RADEC_.change.emit(); //source_jup_RADEC.change.emit(); sourceTXTmoon.change.emit(); sourceTXTjup.change.emit(); //alert(d); """) if dynamic: ### TIME Timeslider = DateSlider(start=dt(2019, 9, 1, 16, 0, 0), end=dt(2019, 9, 2, 8, 0, 0), value=dt(2019, 9, 1, 16, 0, 0), step=1, title="KPNO local time(hh:mm)", format="%H:%M", width=800) ## DATE Dateslider = DateSlider(start=dt(2019, 9, 1, 16, 0, 0), end=dt(2020, 8, 31, 8, 0, 0), value=dt(2019, 10, 1, 16, 0, 0), step=1, title="Date of sunset(4pm-8am)", format="%B:%d", width=800) callback.args['time_slider'] = Timeslider callback.args['date_slider'] = Dateslider Dateslider.js_on_change('value', callback) Timeslider.js_on_change('value', callback) layout = column(p, Dateslider, Timeslider, tiletable) # show(p) return layout return p
def update_plot(attr, old, new): selectedDate = str(datepicker.value_as_date) new_data = filtered_data(selectedDate) new_data['date'] = new_data['date'].to_string() new_json = new_data.to_json() geosource.geojson = new_json #Datepicker datepicker = DateSlider(start="2020-12-13", end=current_date, step=1, value=current_date, width=200, align="center", title="Currently Displaying") datepicker.on_change('value', update_plot) # Last Updated on Current Date Text update_text = "Last Updated on " + str(current_date) p.add_layout(Title(text=update_text, align="center", text_alpha=0.5), "below") #Authorship p.add_layout(Title(text="Made by Frank Hoang", align="center", text_alpha=0.5), "below") # Make a column layout of widgetbox(slider) and plot, and add it to the current document layout = Column(datepicker, p)
def direction_plot(dataframe: object, ti: str) -> object: """ :param dataframe: pandas dataframe :param ti: string defining 'week', 'month'... :return: """ # use data in percent => transform db_data to percent df = (dataframe.transpose().iloc[2:, 0:] / dataframe['sum']) * 100 df.columns = dataframe['tstamp'] db_datadictstr = { str(int(time.mktime(item.timetuple()) * 1000)): list(df[item]) for item in df.columns } maxlist = df.max(1) hist = df.mean(1) # maxhist = sorted(maxlist)[-3] maxhist = mean( maxlist ) * 0.8 # don't use real max of dataset, too many discordant values sumhist = sum(hist) start = [-radians((i * 10) - 85) for i in list(range(0, 36))] end = [-radians((i * 10) - 75) for i in list(range(0, 36))] pdstart = [-radians((i * 10) - 95) for i in list(range(0, 36))] pdend = start # pdend = [-radians((i * 10) - 85) for i in list(range(0, 36))] labeltext = ("Selection of " + ti + "ly histograms") titletext = (ti + 'ly median and sum of all histograms').capitalize() # need two different sources for callback in Bokeh pdsource = ColumnDataSource( data=dict(radius=hist, start=pdstart, end=pdend)) jssource = ColumnDataSource(data=db_datadictstr) mainplot = figure(title=titletext, plot_width=400, plot_height=400, x_axis_type=None, y_axis_type=None, tools="save", min_border=0, outline_line_color=None) mainplot.title.text_font_size = "14pt" # simple rose plot mainplot.wedge(radius=hist, start_angle=start, end_angle=end, x=0, y=0, direction='clock', line_color='blue', fill_color='lightblue', alpha=0.5, legend_label='Whole dataset') # plot connected to slider mainplot.wedge(radius='radius', start_angle='start', end_angle='end', source=pdsource, x=0, y=0, alpha=0.5, direction='clock', line_color='darkred', fill_color='lightsalmon', legend_label=labeltext) # create slider day = 1000 * 3600 * 24 stepsize = day if ti == 'week': stepsize = day elif ti == 'month': stepsize = 7 * day elif ti == 'year': stepsize = 30 * day slider = DateSlider(start=min(df.columns), end=max(df.columns), value=min(df.columns), step=stepsize, title="date within histogram") callback = CustomJS(args=dict(source=pdsource, data=jssource, slid=slider), code=""" const S = slid.value; let radius = source.data.radius; const radii = Object.keys(data.data) let slidestop = radii.reduce(function(prev, curr) { (Math.abs(curr - S) < Math.abs(prev - S) ? curr : prev) return (Math.abs(curr - S) < Math.abs(prev - S) ? curr : prev); }); source.data.radius = data.data[slidestop] source.change.emit(); """) slider.js_on_change('value', callback) # create range slider rslider = DateRangeSlider(start=min(df.columns), end=max(df.columns), value=(min(df.columns), max(df.columns)), step=stepsize, title="Data within date range from ") rcallback = CustomJS(args=dict(source=pdsource, data=jssource, rslid=rslider), code=""" const smin = rslid.value[0] const smax = rslid.value[1] let radius = source.data.radius; const radii = Object.keys(data.data) let lstop = radii.reduce(function(prev, curr) { return (Math.abs(curr - smin) < Math.abs(prev - smin) ? curr : prev); }); let rstop = radii.reduceRight(function(prev, curr) { return (Math.abs(curr - smax) < Math.abs(prev - smax) ? curr : prev); }); let keylist = []; for (let k in data.data) keylist.push(k); let fromkey = keylist.indexOf(lstop); let tokey = keylist.indexOf(rstop); let rangekeys = keylist.slice(fromkey, tokey) var dataavg = Array(36).fill(0) var count = 0; for (let k of rangekeys) { dataavg = dataavg.map(function (num, idx) {return num + data.data[k][idx];}); count += 1 } dataavg = dataavg.map(function (num, idx) {return num/count;}); source.data.radius = dataavg; source.change.emit(); """) rslider.js_on_change('value', rcallback) # create grid rund_perc = ceil(maxhist / sumhist * 100) labels = list(range(0, rund_perc, 2)) labels.append(rund_perc) rad_pos = [i * sumhist / 100 for i in labels] out_rim = rad_pos[-1] label_pos = [sqrt(((i - 1)**2) / 2) for i in rad_pos] mainplot.text(label_pos[1:], label_pos[1:], [str(r) + ' %' for r in labels[1:]], text_font_size="10pt", text_align="left", text_baseline="top") for rad in rad_pos: mainplot.circle(x=0, y=0, radius=rad, fill_color=None, line_color='grey', line_width=0.5, line_alpha=0.8) diagonal = sqrt((out_rim**2) / 2) mainplot.multi_line(xs=[[diagonal, -diagonal], [-diagonal, diagonal], [-out_rim, out_rim], [0, 0]], ys=[[diagonal, -diagonal], [diagonal, -diagonal], [0, 0], [-out_rim, out_rim]], line_color="grey", line_width=0.5, line_alpha=0.8) mainplot.x_range = Range1d(-out_rim * 1.1, out_rim * 1.1) mainplot.y_range = Range1d(-out_rim * 1.1, out_rim * 1.1) mainplot.legend.location = "top_left" mainplot.legend.click_policy = "hide" # plot bars for the number of values in each group as secondary 'by' plot mapper = linear_cmap(field_name='count', palette=Oranges9, low=0, high=max(dataframe['sum'])) bin_width = df.columns[0] - df.columns[1] source = ColumnDataSource({ 'date': dataframe['tstamp'], 'count': dataframe['sum'] }) distriplot = distribution_plot(source, mapper, bin_width, 'Number of values per cluster', 400) script, div = components(column(distriplot, mainplot, slider, rslider), wrap_script=False) return {'div': div, 'script': script}
completions = ["aaa", "aab", "aac", "baa", "caa"] autocomplete_input = AutocompleteInput(placeholder="Enter value (auto-complete) ...", completions=completions) text_area = TextAreaInput(placeholder="Enter text ...", cols=20, rows=10, value="uuu") select = Select(options=["Option 1", "Option 2", "Option 3"]) multi_select = MultiSelect(options=["Option %d" % (i+1) for i in range(16)], size=6) multi_choice = MultiChoice(options=["Option %d" % (i+1) for i in range(16)]) slider = Slider(value=10, start=0, end=100, step=0.5) range_slider = RangeSlider(value=[10, 90], start=0, end=100, step=0.5) date_slider = DateSlider(value=date(2016, 1, 1), start=date(2015, 1, 1), end=date(2017, 12, 31)) date_range_slider = DateRangeSlider(value=(date(2016, 1, 1), date(2016, 12, 31)), start=date(2015, 1, 1), end=date(2017, 12, 31)) spinner = Spinner(value=100) color_picker = ColorPicker(color="red", title="Choose color:") date_picker = DatePicker(value=date(2017, 8, 1)) paragraph = Paragraph(text="some text") div = Div(text="some <b>text</b>") pre_text = PreText(text="some text")
def update_date(attr, old, new): yr = date_slider.value new_data = json_data(yr) geosource.geojson = new_data p.title.text = 'covid 19 deaths, %s' %yr def update_color(attr, old, new): color_mapper.high = color_slider.value merged = read_all_data() geosource = GeoJSONDataSource(geojson = json_data(str(date(2020, 4,25)))) palette = brewer['YlGnBu'][8] palette = palette[::-1] color_cap_deaths = round(np.nanmax(merged["Deaths"]) + 500, -3) color_mapper = LinearColorMapper(palette = palette, low = 0, high = color_cap_deaths, nan_color = '#d9d9d9') hover = HoverTool(tooltips = [ ('Country/region','@country'),('deaths', '@Deaths')]) color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8,width = 900, height = 20, border_line_color=None,location = (0,0), orientation = 'horizontal') p = figure(title = 'Covid 19 deaths', plot_height = 900 , plot_width = 1600, tools = [BoxZoomTool(), ResetTool(), hover]) p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None p.patches('xs','ys', source = geosource,fill_color = {'field' :'Deaths', 'transform' : color_mapper}, line_color = 'black', line_width = 0.25, fill_alpha = 1) p.add_layout(color_bar, 'below') date_slider = DateSlider(title="Date Range: ", start=date(2020, 1, 31), end=date(2020, 4, 25), value=date(2020, 4, 25), step=1) date_slider.on_change('value', update_date) color_slider = Slider(title="Max value", start=0, end=color_cap_deaths, value=color_cap_deaths, step=100) color_slider.on_change('value', update_color) layout = column(p,widgetbox(date_slider), widgetbox(color_slider)) curdoc().add_root(layout) show(layout)
def build_time_evolution_tab(): # Importing geographical shapefile s3_root = 'https://covid19-bokeh-app.s3.eu-west-2.amazonaws.com' geo_data_gdf = gpd.read_file(f'{s3_root}/data/_geo_data/ne_50m_land.zip') geosource = GeoJSONDataSource(geojson=geo_data_gdf.to_json()) # Importing geo-evolutions cases/deaths data time_evol_df = pd.read_csv(f'{s3_root}/data/geo_time_evolution.csv') # Selecting earliest snapshot time_evol_df.date = pd.to_datetime(time_evol_df.date, format="%Y-%m-%d") snapshot_df = time_evol_df[time_evol_df.date == min(time_evol_df.date)] global_by_day_df = pd.read_csv(f'{s3_root}/data/global_by_day.csv') global_by_day_df.date = pd.to_datetime(global_by_day_df.date, format="%Y-%m-%d") global_totals_df = global_by_day_df.loc[global_by_day_df.date == min( time_evol_df.date)] global_cases = int(global_totals_df.iloc[0]['cases']) global_deaths = int(global_totals_df.iloc[0]['deaths']) # Applying bubble-size mapping bubble_size = snapshot_df['cases'].apply(lambda x: 0.5 * math.log(x, 1.1) if x > 0 else 0) snapshot_df = snapshot_df.assign(size=bubble_size.values) # Creating ColumnDataSource for visualisation cases_cds = ColumnDataSource(snapshot_df) # Adding figure and geographical patches from shapefile geo_plot = figure(plot_height=450, plot_width=720, x_range=(-180, 180), y_range=(-90, 90), name="time_evolution_geo_plot", sizing_mode="scale_width") geo_patches = geo_plot.patches('xs', 'ys', source=geosource, alpha=0.5) # Adding circle glyph to create bubble plot cases_circles = geo_plot.circle(x='long', y='lat', size='size', source=cases_cds, color='red', alpha=0.2) # Adding hover tool hover = HoverTool(tooltips=[('Country/Region', '@region'), ('Province/State', '@province'), ('Cases', '@cases')], renderers=[cases_circles]) geo_plot.add_tools(hover) # Adding hbar countries_df = snapshot_df.loc[:, ['date', 'region', 'cases']] countries_df.rename(columns={"cases": "value"}, inplace=True) countries_df = countries_df.groupby(['date', 'region']).sum().reset_index() countries_df.sort_values(by='value', ascending=False, inplace=True) countries_df = countries_df.reset_index(drop=True) countries_cds = ColumnDataSource(countries_df) hbar_plot = figure(plot_height=450, plot_width=475, y_range=(10.5, -0.5), x_range=(0, countries_df.value.max() * 1.2), name="time_evolution_hbar_plot", sizing_mode="scale_width") hbar = hbar_plot.hbar(left=0, right='value', y='index', source=countries_cds, height=0.5, line_color='white') labels = LabelSet(x='value', y='index', text='region', text_font_size='10pt', text_color='white', x_offset=5, y_offset=0, source=countries_cds, level='glyph', render_mode='canvas') hbar_plot.add_layout(labels) # Adding hover tool hover_hbar = HoverTool(tooltips=[('Country/Region', '@region'), ('Cases', '@value')], renderers=[hbar]) hbar_plot.add_tools(hover_hbar) # Adding callback for updating data def data_view_callback(attr, old, new): """Callback function to update data source: - Updates source data to selected data view (cases/deaths/new cases/new deaths) and selected snapshot date on date slider. - Updates HoverTool to reflect data view change - Updates Divs for total cases/deaths """ # Determine data view selection if cases_deaths_button.active == 0: data_view = "cases" elif cases_deaths_button.active == 1: data_view = "deaths" if total_new_button.active == 1: data_view = f"new_{data_view}" # Determine date selection slider_date = date_slider.value_as_datetime.date() # Filter data for selected date snapshot_df = time_evol_df[time_evol_df.date == pd.Timestamp( slider_date)] # Map bubble size on selected data view bubble_size = snapshot_df[data_view].apply( lambda x: 0.5 * math.log(x, 1.1) if x > 0 else 0) snapshot_df = snapshot_df.assign(size=bubble_size.values) cases_cds.data = snapshot_df hover.tooltips = [('Country/Region', '@region'), ('Province/State', '@province'), (data_view.replace('_', ' ').title(), f'@{data_view}')] # Update hbar data countries_df = snapshot_df.loc[:, ['date', 'region', data_view]] countries_df.rename(columns={data_view: "value"}, inplace=True) countries_df = countries_df.groupby(['date', 'region']).sum().reset_index() countries_df.sort_values(by="value", ascending=False, inplace=True) countries_df = countries_df.reset_index(drop=True) countries_cds.data = countries_df hbar_plot.x_range.end = countries_df.value.max() * 1.2 hover_hbar.tooltips = [('Country/Region', '@region'), (data_view.replace('_', ' ').title(), '@value')] # Filter for totals global_totals_df = global_by_day_df.loc[( global_by_day_df.date == pd.Timestamp(slider_date))] global_cases = int(global_totals_df.iloc[0]['cases']) global_deaths = int(global_totals_df.iloc[0]['deaths']) cases_div.text = (f'<h3 class="card-text">' f'{global_cases:,}</h3>') deaths_div.text = (f'<h3 class="card-text">' f'{global_deaths:,}</h3>') # Adding Date slider date_range = [ pd.Timestamp(date_val) for date_val in time_evol_df.date.unique() ] date_slider = DateSlider(title="Date", start=min(date_range), end=max(date_range), value=min(date_range), sizing_mode="scale_width") date_slider.on_change('value', data_view_callback) # Adding Cases/Deaths toggle cases_deaths_button = RadioButtonGroup(labels=["Cases", "Deaths"], active=0, sizing_mode="scale_width") cases_deaths_button.on_change('active', data_view_callback) # Adding Total/New toggle total_new_button = RadioButtonGroup(labels=["Total", "New"], active=0, sizing_mode="scale_width") total_new_button.on_change('active', data_view_callback) # Adding callback for zooming into a selected continent def continent_zoom_callback(attr, old, new): continent_map_ref = { # Worldwide 0: { 'x_range': [-200, 200], 'y_range': [-100, 100] }, # Europe 1: { 'x_range': [-30, 50], 'y_range': [30, 70] }, # North America 2: { 'x_range': [-175, -15], 'y_range': [0, 80] }, # South America 3: { 'x_range': [-140, 10], 'y_range': [-60, 15] }, # Africa 4: { 'x_range': [-55, 105], 'y_range': [-40, 40] }, # Asia 5: { 'x_range': [40, 140], 'y_range': [-5, 45] }, # Oceania 6: { 'x_range': [80, 200], 'y_range': [-55, 5] } } map_ref = continent_map_ref[continent_button.active] geo_plot.x_range.start = map_ref['x_range'][0] geo_plot.x_range.end = map_ref['x_range'][1] geo_plot.y_range.start = map_ref['y_range'][0] geo_plot.y_range.end = map_ref['y_range'][1] # Adding continent toggle continent_button = RadioGroup(labels=[ "Worldwide", "Europe", "North America", "South America", "Africa", "Asia", "Oceania" ], active=0) continent_button.on_change('active', continent_zoom_callback) # Adding animation with Play/Pause button callback_id = None def animate(): def animate_update(): date = date_slider.value_as_datetime.date() + timedelta(days=1) date = pd.Timestamp(date) if date >= max(date_range): date = min(date_range) date_slider.value = date global callback_id if play_button.label == '► Play': play_button.label = '❚❚ Pause' callback_id = curdoc().add_periodic_callback(animate_update, 300) else: play_button.label = '► Play' curdoc().remove_periodic_callback(callback_id) play_button = Button(label='► Play', width=60, button_type="success") play_button.on_click(animate) # Adding Cases/Deaths count cases_div = Div(text=f'<h3 class="card-text">' f'{global_cases:,}</h3>', sizing_mode="scale_width", name="cases_div") deaths_div = Div(text=f'<h3 class="card-text">' f'{global_deaths:,}</h3>', sizing_mode="scale_width", name="deaths_div") # Defining layout of tab widgets = widgetbox(date_slider, cases_deaths_button, total_new_button, play_button, continent_button, name="time_evolution_widgetbox", sizing_mode="scale_width") # Add the plot to the current document curdoc().add_root(geo_plot) curdoc().add_root(hbar_plot) curdoc().add_root(widgets) curdoc().add_root(cases_div) curdoc().add_root(deaths_div)
def create_world_map_tab(): "Factory for creating first tab of app." ## Data Sources source_df, source_CDS = get_time_series_confirmed_data() ## Map color_mapper = log_cmap(field_name='number', palette=Spectral6, low=1, high=1e6) TOOLTIPS = [('Region', '@full_name'), ('Num. Cases', '@number{0,0}')] map_figure = figure(title='Confirmed COVID-19 Cases by Region', tooltips=TOOLTIPS, x_range=(-16697923.62, 18924313), y_range=(-8399737.89, 8399737.89), x_axis_type='mercator', y_axis_type='mercator', active_scroll='wheel_zoom') tile_provider = get_provider(CARTODBPOSITRON) map_figure.add_tile(tile_provider) map_figure.circle(x='web_mercator_x', y='web_mercator_y', source=source_CDS, size='sizes', color=color_mapper) ## Colorbar color_bar = ColorBar(title='Num. Cases', title_standoff=20, color_mapper=color_mapper['transform'], label_standoff=20, width=8, location=(0, 0), ticker=LogTicker()) color_bar.formatter.use_scientific = False map_figure.add_layout(color_bar, 'right') ## Slider def slider_callback(attr, old, new): delta = datetime.timedelta(milliseconds=new) date = datetime.date(1970, 1, 1) + delta date_string = date.strftime('%Y-%m-%d') try: source_CDS.data['number'] = source_df[date_string] source_CDS.data['sizes'] = source_df[date_string].apply(scale) except KeyError: pass slider = DateSlider(title='Date', start=START_DATE, end=datetime.date.today(), step=1, value=START_DATE) slider.on_change('value', slider_callback) ## Data Table columns = [ TableColumn(field='full_name', title='Region'), TableColumn(field='number', title='Cases') ] data_table = DataTable( source=source_CDS, columns=columns, ) ## Cancel Selection Button def cancel_selection_callback(): source_CDS.selected.indices = [] cancel_selection_button = Button(label='Clear Selection', button_type='warning') cancel_selection_button.on_click(cancel_selection_callback) child = row([ column([slider, map_figure]), column([data_table, cancel_selection_button]), ]) return Panel(child=child, title='World Map')
def create_html_page(html_page_name, df): del states["HI"] del states["AK"] EXCLUDED = ("ak", "hi", "pr", "gu", "vi", "mp", "as") state_xs = [states[code]["lons"] for code in states] state_ys = [states[code]["lats"] for code in states] county_xs = [ counties[code]["lons"] for code in counties if counties[code]["state"] not in EXCLUDED ] county_ys = [ counties[code]["lats"] for code in counties if counties[code]["state"] not in EXCLUDED ] county_names = [ counties[code]["name"] for code in counties if counties[code]["state"] not in EXCLUDED ] county_rates = [] col_names = list(df.columns.values) len_col = len(col_names) for county_id in counties: if counties[county_id]["state"] in EXCLUDED: continue fips = str(county_id[0]).zfill(2) + str(county_id[1]).zfill(3) # len_col - 1 = its the last day that we have rate = df.loc[df['FIPS'] == fips][col_names[len_col - 1]].values if len(rate) == 0: county_rates.append(0.0) else: county_rates.append(rate[0]) source_visible = ColumnDataSource(data={ 'x': county_xs, 'y': county_ys, 'name': county_names, 'rate': county_rates }) source_new = create_dict_forJS(df) print(np.shape(source_new), type(source_new)) # Define a sequential multi-hue color palette. #palette = brewer['YlGnBu'][9] palette = Magma256 # palette = big_palette(200, bokeh.palettes.plasma) palette = palette[::-1] color_mapper = LinearColorMapper(palette=palette, low=0, high=100) #color_mapper = LogColorMapper(palette=palette) TOOLS = "pan,wheel_zoom,reset,hover,save" p = figure(title="US density", toolbar_location="left", plot_width=1100, plot_height=700, tools=TOOLS, tooltips=[("County", "@name"), ("Infection rate", "@rate"), ("(Long, Lat)", "($x, $y)")]) # hide grid and axes p.axis.visible = None p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None p.hover.point_policy = "follow_mouse" p.patches( county_xs, county_ys, # fill_alpha=0.7, line_color="white", line_width=0.5) p.patches(state_xs, state_ys, fill_alpha=0.0, line_color="#884444", line_width=2, line_alpha=0.3) p.patches('x', 'y', source=source_visible, fill_color={ 'field': 'rate', 'transform': color_mapper }, fill_alpha=0.7, line_color="white", line_width=0.5) # Make a slider object: slider last_day_str = col_names[len_col - 1] last_day = datetime.strptime( last_day_str, '%Y-%m-%d %H:%M:%S').date() # + timedelta(days=1) first_day_str = col_names[4] # first 4 colums contain names etc first_day = datetime.strptime(first_day_str, '%Y-%m-%d %H:%M:%S').date() print(last_day) date_slider = DateSlider(title="Date:", start=first_day, end=last_day, value=last_day, step=1) callback = CustomJS(args=dict(source=source_new, ts=source_visible), code=""" var data=ts.data; var rate=data['rate']; var name=data['name']; var data1=source.data; var f=cb_obj.value; //this is the selection value of slider const event = new Date(f); var date_selected = event.toISOString().substring(0,10); // converting date from python to JS //console.log(typeof data1[0]); data['rate']=data1[date_selected]; ts.change.emit(); """) date_slider.js_on_change('value', callback) #layout = column(p, widgetbox(slider),widgetbox(date_slider)) layout = column(p, date_slider) output_file(html_page_name, title="Interactive USA density map") show(layout)
def create_us_map_tab(): "Factory for creating second tab of app: US Only Data" ## Data Sources source_df_confirmed, source_CDS = get_time_series_confirmed_US_data() source_CDS.data['number_per_capita'] = source_df_confirmed[ START_DATE_STRING] / source_df_confirmed['population'] ## Map color_mapper = log_cmap(field_name='number', palette=Spectral6, low=1, high=1e6) TOOLTIPS = [('County/Region', '@county'), ('State/Province', '@region'), ('Population', '@population'), ('Cases', '@number'), ('Cases Per Capita', '@number_per_capita')] map_figure = figure( title='Confirmed COVID-19 Cases in the United States', tooltips=TOOLTIPS, x_range=(-18367715, -6901808.43), y_range=(0, 13377019.78), x_axis_type='mercator', y_axis_type='mercator', active_scroll='wheel_zoom', ) tile_provider = get_provider(CARTODBPOSITRON) map_figure.add_tile(tile_provider) map_figure.circle(x='web_mercator_x', y='web_mercator_y', source=source_CDS, size='sizes', color=color_mapper) ## Colorbar color_bar = ColorBar(title='Num. Cases', title_standoff=20, color_mapper=color_mapper['transform'], label_standoff=20, width=8, location=(0, 0), ticker=LogTicker()) color_bar.formatter.use_scientific = False map_figure.add_layout(color_bar, 'right') ## Slider def slider_callback(attr, old, new): delta = datetime.timedelta(milliseconds=new) date = datetime.date(1970, 1, 1) + delta date_string = date.strftime('%Y-%m-%d') try: source_CDS.data['number'] = source_df_confirmed[date_string] source_CDS.data['sizes'] = source_df_confirmed[date_string].apply( scale) source_CDS.data['number_per_capita'] = source_df_confirmed[ date_string] / source_df_confirmed['population'] except KeyError: pass slider = DateSlider(title='Date', start=START_DATE, end=datetime.date.today(), step=1, value=START_DATE) slider.on_change('value', slider_callback) ## Data Table columns = [ TableColumn(field='county', title='County/Region'), TableColumn(field='region', title='State/Province'), TableColumn(field='population', title='Population'), TableColumn(field='number', title='Cases'), TableColumn(field='number_per_capita', title='Cases Per Capita'), ] data_table = DataTable( source=source_CDS, columns=columns, ) ## Cancel Selection Button def cancel_selection_callback(): source_CDS.selected.indices = [] cancel_selection_button = Button(label='Clear Selection', button_type='warning') cancel_selection_button.on_click(cancel_selection_callback) child = row([ column([slider, map_figure]), column([data_table, cancel_selection_button]) ]) return Panel(child=child, title='United States Map')